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