Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqc2qstyle.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qqc2qstyle_p.h"
7
8#include <qpa/qplatformtheme.h>
9
10#include <private/qguiapplication_p.h>
11#include <private/qqc2qstyleoption_p.h>
12
13#include <QtGui/qpainter.h>
14#include <QtGui/qbitmap.h>
15#include <QtGui/qpixmapcache.h>
16
17#ifndef QT_NO_DEBUG
18# include <QtCore/qdebug.h>
19#endif
20
21#include <limits.h>
22#include <algorithm>
23
24QT_BEGIN_NAMESPACE
25
26namespace QQC2 {
27
28/*!
29 \internal
30 Constructs a style object.
31*/
34{
35 Q_D(QStyle);
36 d->proxyStyle = this;
37}
38
39/*!
40 \internal
41
42 Constructs a style object.
43*/
45 : QObject(dd)
46{
47 Q_D(QStyle);
48 d->proxyStyle = this;
49}
50
51/*!
52 \internal
53 Destroys the style object.
54*/
56{
57}
58
59/*!
60 \internal
61
62 Returns the area within the given \a rectangle in which to draw
63 the provided \a text according to the specified font \a metrics
64 and \a alignment. The \a enabled parameter indicates whether or
65 not the associated item is enabled.
66
67 If the given \a rectangle is larger than the area needed to render
68 the \a text, the rectangle that is returned will be offset within
69 \a rectangle according to the specified \a alignment. For
70 example, if \a alignment is Qt::AlignCenter, the returned
71 rectangle will be centered within \a rectangle. If the given \a
72 rectangle is smaller than the area needed, the returned rectangle
73 will be the smallest rectangle large enough to render the \a text.
74
75 \sa Qt::Alignment
76*/
77QRect QStyle::itemTextRect(const QFontMetrics &metrics, const QRect &rect, int alignment, bool enabled,
78 const QString &text) const
79{
80 QRect result;
81 int x, y, w, h;
82 rect.getRect(&x, &y, &w, &h);
83 if (!text.isEmpty()) {
84 result = metrics.boundingRect(x, y, w, h, alignment, text);
85 if (!enabled && proxy()->styleHint(SH_EtchDisabledText)) {
86 result.setWidth(result.width()+1);
87 result.setHeight(result.height()+1);
88 }
89 } else {
90 result = QRect(x, y, w, h);
91 }
92 return result;
93}
94
95/*!
96 \internal
97
98 Returns the area within the given \a rectangle in which to draw
99 the specified \a pixmap according to the defined \a alignment.
100*/
101QRect QStyle::itemPixmapRect(const QRect &rect, int alignment, const QPixmap &pixmap) const
102{
103 QRect result;
104 int x, y, w, h;
105 rect.getRect(&x, &y, &w, &h);
106
107 const int pixmapWidth = pixmap.width()/pixmap.devicePixelRatio();
108 const int pixmapHeight = pixmap.height()/pixmap.devicePixelRatio();
109
110 if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter)
111 y += h/2 - pixmapHeight/2;
112 else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom)
113 y += h - pixmapHeight;
114 if ((alignment & Qt::AlignRight) == Qt::AlignRight)
115 x += w - pixmapWidth;
116 else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter)
117 x += w/2 - pixmapWidth/2;
118 else if ((alignment & Qt::AlignLeft) != Qt::AlignLeft && QGuiApplication::isRightToLeft())
119 x += w - pixmapWidth;
120 result = QRect(x, y, pixmapWidth, pixmapHeight);
121 return result;
122}
123
124/*!
125 \internal
126
127 Draws the given \a text in the specified \a rectangle using the
128 provided \a painter and \a palette.
129
130 The text is drawn using the painter's pen, and aligned and wrapped
131 according to the specified \a alignment. If an explicit \a
132 textRole is specified, the text is drawn using the \a palette's
133 color for the given role. The \a enabled parameter indicates
134 whether or not the item is enabled; when reimplementing this
135 function, the \a enabled parameter should influence how the item is
136 drawn.
137
138 \sa Qt::Alignment, drawItemPixmap()
139*/
140void QStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal,
141 bool enabled, const QString& text, QPalette::ColorRole textRole) const
142{
143 if (text.isEmpty())
144 return;
145 QPen savedPen;
146 if (textRole != QPalette::NoRole) {
147 savedPen = painter->pen();
148 painter->setPen(QPen(pal.brush(textRole), savedPen.widthF()));
149 }
150 if (!enabled) {
151 if (proxy()->styleHint(SH_DitherDisabledText)) {
152 QRect br;
153 painter->drawText(rect, alignment, text, &br);
154 painter->fillRect(br, QBrush(painter->background().color(), Qt::Dense5Pattern));
155 return;
156 } else if (proxy()->styleHint(SH_EtchDisabledText)) {
157 QPen pen = painter->pen();
158 painter->setPen(pal.light().color());
159 painter->drawText(rect.adjusted(1, 1, 1, 1), alignment, text);
160 painter->setPen(pen);
161 }
162 }
163 painter->drawText(rect, alignment, text);
164 if (textRole != QPalette::NoRole)
165 painter->setPen(savedPen);
166}
167
168/*!
169 \internal
170
171 Draws the given \a pixmap in the specified \a rectangle, according
172 to the specified \a alignment, using the provided \a painter.
173
174 \sa drawItemText()
175*/
176
177void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
178 const QPixmap &pixmap) const
179{
180 qreal scale = pixmap.devicePixelRatio();
181 QRect aligned = alignedRect(QGuiApplication::layoutDirection(), QFlag(alignment), pixmap.size() / scale, rect);
182 QRect inter = aligned.intersected(rect);
183
184 painter->drawPixmap(inter.x(), inter.y(), pixmap, inter.x() - aligned.x(), inter.y() - aligned.y(), inter.width() * scale, inter.height() *scale);
185}
186
187/*!
188 \internal
189
190 Returns the given \a logicalRectangle converted to screen
191 coordinates based on the specified \a direction. The \a
192 boundingRectangle is used when performing the translation.
193
194 This function is provided to support right-to-left desktops, and
195 is typically used in implementations of the subControlRect()
196 function.
197
198 \sa QWidget::layoutDirection
199*/
200QRect QStyle::visualRect(Qt::LayoutDirection direction, const QRect &boundingRect, const QRect &logicalRect)
201{
202 if (direction == Qt::LeftToRight)
203 return logicalRect;
204 QRect rect = logicalRect;
205 rect.translate(2 * (boundingRect.right() - logicalRect.right()) +
206 logicalRect.width() - boundingRect.width(), 0);
207 return rect;
208}
209
210/*!
211 \internal
212
213 Returns the given \a logicalPosition converted to screen
214 coordinates based on the specified \a direction. The \a
215 boundingRectangle is used when performing the translation.
216
217 \sa QWidget::layoutDirection
218*/
219QPoint QStyle::visualPos(Qt::LayoutDirection direction, const QRect &boundingRect, const QPoint &logicalPos)
220{
221 if (direction == Qt::LeftToRight)
222 return logicalPos;
223 return QPoint(boundingRect.right() - logicalPos.x(), logicalPos.y());
224}
225
226/*!
227 \internal
228 Returns a new rectangle of the specified \a size that is aligned to the given \a
229 rectangle according to the specified \a alignment and \a direction.
230 */
231QRect QStyle::alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment, const QSize &size, const QRect &rectangle)
232{
233 alignment = visualAlignment(direction, alignment);
234 int x = rectangle.x();
235 int y = rectangle.y();
236 int w = size.width();
237 int h = size.height();
238 if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter)
239 y += rectangle.size().height()/2 - h/2;
240 else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom)
241 y += rectangle.size().height() - h;
242 if ((alignment & Qt::AlignRight) == Qt::AlignRight)
243 x += rectangle.size().width() - w;
244 else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter)
245 x += rectangle.size().width()/2 - w/2;
246 return QRect(x, y, w, h);
247}
248
249/*!
250 \internal
251
252 Transforms an \a alignment of Qt::AlignLeft or Qt::AlignRight
253 without Qt::AlignAbsolute into Qt::AlignLeft or Qt::AlignRight with
254 Qt::AlignAbsolute according to the layout \a direction. The other
255 alignment flags are left untouched.
256
257 If no horizontal alignment was specified, the function returns the
258 default alignment for the given layout \a direction.
259
260 QWidget::layoutDirection
261*/
262Qt::Alignment QStyle::visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment)
263{
264 return QGuiApplicationPrivate::visualAlignment(direction, alignment);
265}
266
267/*!
268 \internal
269
270 Converts the given \a logicalValue to a pixel position. The \a min
271 parameter maps to 0, \a max maps to \a span and other values are
272 distributed evenly in-between.
273
274 This function can handle the entire integer range without
275 overflow, providing that \a span is less than 4096.
276
277 By default, this function assumes that the maximum value is on the
278 right for horizontal items and on the bottom for vertical items.
279 Set the \a upsideDown parameter to true to reverse this behavior.
280
281 \sa sliderValueFromPosition()
282*/
283
284int QStyle::sliderPositionFromValue(int min, int max, int logicalValue, int span, bool upsideDown)
285{
286 if (span <= 0 || logicalValue < min || max <= min)
287 return 0;
288 if (logicalValue > max)
289 return upsideDown ? span : min;
290
291 uint range = max - min;
292 uint p = upsideDown ? max - logicalValue : logicalValue - min;
293
294 if (range > (uint)INT_MAX/4096) {
295 double dpos = (double(p))/(double(range)/span);
296 return int(dpos);
297 } else if (range > (uint)span) {
298 return (2 * p * span + range) / (2*range);
299 } else {
300 uint div = span / range;
301 uint mod = span % range;
302 return p * div + (2 * p * mod + range) / (2 * range);
303 }
304 // equiv. to (p * span) / range + 0.5
305 // no overflow because of this implicit assumption:
306 // span <= 4096
307}
308
309/*!
310 \internal
311
312 Converts the given pixel \a position to a logical value. 0 maps to
313 the \a min parameter, \a span maps to \a max and other values are
314 distributed evenly in-between.
315
316 This function can handle the entire integer range without
317 overflow.
318
319 By default, this function assumes that the maximum value is on the
320 right for horizontal items and on the bottom for vertical
321 items. Set the \a upsideDown parameter to true to reverse this
322 behavior.
323
324 \sa sliderPositionFromValue()
325*/
326
327int QStyle::sliderValueFromPosition(int min, int max, int pos, int span, bool upsideDown)
328{
329 if (span <= 0 || pos <= 0)
330 return upsideDown ? max : min;
331 if (pos >= span)
332 return upsideDown ? min : max;
333
334 uint range = max - min;
335
336 if ((uint)span > range) {
337 int tmp = (2 * pos * range + span) / (2 * span);
338 return upsideDown ? max - tmp : tmp + min;
339 } else {
340 uint div = range / span;
341 uint mod = range % span;
342 int tmp = pos * div + (2 * pos * mod + span) / (2 * span);
343 return upsideDown ? max - tmp : tmp + min;
344 }
345 // equiv. to min + (pos*range)/span + 0.5
346 // no overflow because of this implicit assumption:
347 // pos <= span < sqrt(INT_MAX+0.0625)+0.25 ~ sqrt(INT_MAX)
348}
349
350/*!
351 \internal
352
353 Returns the style's standard palette.
354
355 Note that on systems that support system colors, the style's
356 standard palette is not used. In particular, the Windows
357 Vista and Mac styles do not use the standard palette, but make
358 use of native theme engines. With these styles, you should not set
359 the palette with QApplication::setPalette().
360
361 \sa QApplication::setPalette()
362 */
364{
365 QColor background = QColor(0xd4, 0xd0, 0xc8); // win 2000 grey
366
367 QColor light(background.lighter());
368 QColor dark(background.darker());
369 QColor mid(Qt::gray);
370 QPalette palette(Qt::black, background, light, dark, mid, Qt::black, Qt::white);
371 palette.setBrush(QPalette::Disabled, QPalette::WindowText, dark);
372 palette.setBrush(QPalette::Disabled, QPalette::Text, dark);
373 palette.setBrush(QPalette::Disabled, QPalette::ButtonText, dark);
374 palette.setBrush(QPalette::Disabled, QPalette::Base, background);
375 return palette;
376}
377
378//Windows and KDE allow menus to cover the taskbar, while GNOME and macOS don't
379bool QStylePrivate::useFullScreenForPopup()
380{
381 auto theme = QGuiApplicationPrivate::platformTheme();
382 return theme && theme->themeHint(QPlatformTheme::UseFullScreenForPopupMenu).toBool();
383}
384
385} // namespace QQC2
386
387QT_END_NAMESPACE
388
389#include "moc_qqc2qstyle_p.cpp"
const QStyle * proxy() const
virtual QRect itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const
virtual QPalette standardPalette() const
virtual ~QStyle()
virtual void drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, const QPixmap &pixmap) const
static int sliderPositionFromValue(int min, int max, int val, int space, bool upsideDown=false)
static int sliderValueFromPosition(int min, int max, int pos, int space, bool upsideDown=false)
virtual void drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled, const QString &text, QPalette::ColorRole textRole=QPalette::NoRole) const