1 | // Copyright (C) 2016 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 | |
4 | #include <qstyle.h> |
5 | #include <private/qproxystyle_p.h> |
6 | #include <private/qapplication_p.h> |
7 | #include "qproxystyle.h" |
8 | #include "qstylefactory.h" |
9 | #include <private/qstyle_p.h> |
10 | |
11 | #if !defined(QT_NO_STYLE_PROXY) || defined(QT_PLUGIN) |
12 | |
13 | QT_BEGIN_NAMESPACE |
14 | |
15 | using namespace Qt::StringLiterals; |
16 | |
17 | /*! |
18 | \class QProxyStyle |
19 | |
20 | \brief The QProxyStyle class is a convenience class that simplifies |
21 | dynamically overriding QStyle elements. |
22 | |
23 | \since 4.6 |
24 | |
25 | \inmodule QtWidgets |
26 | |
27 | A QProxyStyle wraps a QStyle (usually the default system style) for the |
28 | purpose of dynamically overriding painting or other specific style behavior. |
29 | |
30 | The following example shows how to override the shortcut underline |
31 | behavior on any platform: |
32 | |
33 | \snippet code/src_gui_qproxystyle.cpp 1 |
34 | |
35 | Warning: The \l {QCommonStyle} {common styles} provided by Qt will |
36 | respect this hint, because they call QStyle::proxy(), but there is |
37 | no guarantee that QStyle::proxy() will be called for user defined |
38 | or system controlled styles. It would not work on a Mac, for |
39 | example, where menus are handled by the operating system. |
40 | |
41 | When a proxy style should be set on a specific widget only, you have |
42 | to make sure to not set the proxy on the global application style which |
43 | is returned by QWidget::style(). You have to create a separate custom style |
44 | for the widget similar to: |
45 | |
46 | \snippet code/src_gui_qproxystyle.cpp 2 |
47 | |
48 | \sa QStyle |
49 | */ |
50 | |
51 | void QProxyStylePrivate::ensureBaseStyle() const |
52 | { |
53 | Q_Q(const QProxyStyle); |
54 | |
55 | if (baseStyle) |
56 | return; |
57 | |
58 | if (!baseStyle && !QApplicationPrivate::styleOverride.isEmpty()) { |
59 | baseStyle = QStyleFactory::create(QApplicationPrivate::styleOverride); |
60 | if (baseStyle) { |
61 | // If baseStyle is an instance of the same proxyStyle |
62 | // we destroy it and fall back to the desktop style |
63 | if (qstrcmp(str1: baseStyle->metaObject()->className(), |
64 | str2: q->metaObject()->className()) == 0) { |
65 | delete baseStyle; |
66 | baseStyle = nullptr; |
67 | } |
68 | } |
69 | } |
70 | |
71 | if (!baseStyle) // Use application desktop style |
72 | baseStyle = QStyleFactory::create(QApplicationPrivate::desktopStyleKey()); |
73 | |
74 | if (!baseStyle) // Fallback to windows style |
75 | baseStyle = QStyleFactory::create("windows"_L1 ); |
76 | |
77 | baseStyle->setProxy(const_cast<QProxyStyle*>(q)); |
78 | baseStyle->setParent(const_cast<QProxyStyle*>(q)); // Take ownership |
79 | } |
80 | |
81 | /*! |
82 | Constructs a QProxyStyle object for overriding behavior in the |
83 | specified \a style, or in the default native \l{QApplication::style()} |
84 | {style} if \a style is not specified. |
85 | |
86 | Ownership of \a style is transferred to QProxyStyle. |
87 | */ |
88 | QProxyStyle::QProxyStyle(QStyle *style) : |
89 | QCommonStyle(*new QProxyStylePrivate()) |
90 | { |
91 | Q_D(QProxyStyle); |
92 | if (style) { |
93 | d->baseStyle = style; |
94 | style->setProxy(this); |
95 | style->setParent(this); // Take ownership |
96 | } |
97 | } |
98 | |
99 | /*! |
100 | Constructs a QProxyStyle object for overriding behavior in |
101 | the base style specified by style \a key, or in the current |
102 | \l{QApplication::style()}{application style} if the specified |
103 | style \a key is unrecognized. |
104 | |
105 | \sa QStyleFactory::create() |
106 | */ |
107 | QProxyStyle::QProxyStyle(const QString &key) |
108 | : QProxyStyle(QStyleFactory::create(key)) |
109 | { |
110 | } |
111 | |
112 | /*! |
113 | Destroys the QProxyStyle object. |
114 | */ |
115 | QProxyStyle::~QProxyStyle() |
116 | { |
117 | } |
118 | |
119 | /*! |
120 | Returns the proxy base style object. If no base style |
121 | is set on the proxy style, QProxyStyle will create |
122 | an instance of the application style instead. |
123 | |
124 | \sa setBaseStyle(), QStyle |
125 | */ |
126 | QStyle *QProxyStyle::baseStyle() const |
127 | { |
128 | Q_D (const QProxyStyle); |
129 | d->ensureBaseStyle(); |
130 | return d->baseStyle; |
131 | } |
132 | |
133 | /*! |
134 | Sets the base style that should be proxied. |
135 | |
136 | Ownership of \a style is transferred to QProxyStyle. |
137 | |
138 | If style is \nullptr, a desktop-dependent style will be |
139 | assigned automatically. |
140 | */ |
141 | void QProxyStyle::setBaseStyle(QStyle *style) |
142 | { |
143 | Q_D (QProxyStyle); |
144 | |
145 | if (d->baseStyle && d->baseStyle->parent() == this) |
146 | d->baseStyle->deleteLater(); |
147 | |
148 | d->baseStyle = style; |
149 | |
150 | if (d->baseStyle) { |
151 | d->baseStyle->setProxy(this); |
152 | d->baseStyle->setParent(this); |
153 | } |
154 | } |
155 | |
156 | /*! \reimp |
157 | */ |
158 | void QProxyStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const |
159 | { |
160 | Q_D (const QProxyStyle); |
161 | d->ensureBaseStyle(); |
162 | d->baseStyle->drawPrimitive(pe: element, opt: option, p: painter, w: widget); |
163 | } |
164 | |
165 | /*! |
166 | \reimp |
167 | */ |
168 | void QProxyStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const |
169 | { |
170 | Q_D (const QProxyStyle); |
171 | d->ensureBaseStyle(); |
172 | d->baseStyle->drawControl(element, opt: option, p: painter, w: widget); |
173 | } |
174 | |
175 | /*! \reimp |
176 | */ |
177 | void QProxyStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const |
178 | { |
179 | Q_D (const QProxyStyle); |
180 | d->ensureBaseStyle(); |
181 | d->baseStyle->drawComplexControl(cc: control, opt: option, p: painter, widget); |
182 | } |
183 | |
184 | /*! \reimp |
185 | */ |
186 | void QProxyStyle::drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled, |
187 | const QString &text, QPalette::ColorRole textRole) const |
188 | { |
189 | Q_D (const QProxyStyle); |
190 | d->ensureBaseStyle(); |
191 | d->baseStyle->drawItemText(painter, rect, flags, pal, enabled, text, textRole); |
192 | } |
193 | |
194 | /*! \reimp |
195 | */ |
196 | void QProxyStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, const QPixmap &pixmap) const |
197 | { |
198 | Q_D (const QProxyStyle); |
199 | d->ensureBaseStyle(); |
200 | d->baseStyle->drawItemPixmap(painter, rect, alignment, pixmap); |
201 | } |
202 | |
203 | /*! \reimp |
204 | */ |
205 | QSize QProxyStyle::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const |
206 | { |
207 | Q_D (const QProxyStyle); |
208 | d->ensureBaseStyle(); |
209 | return d->baseStyle->sizeFromContents(ct: type, opt: option, contentsSize: size, w: widget); |
210 | } |
211 | |
212 | /*! \reimp |
213 | */ |
214 | QRect QProxyStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const |
215 | { |
216 | Q_D (const QProxyStyle); |
217 | d->ensureBaseStyle(); |
218 | return d->baseStyle->subElementRect(subElement: element, option, widget); |
219 | } |
220 | |
221 | /*! \reimp |
222 | */ |
223 | QRect QProxyStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *option, SubControl sc, const QWidget *widget) const |
224 | { |
225 | Q_D (const QProxyStyle); |
226 | d->ensureBaseStyle(); |
227 | return d->baseStyle->subControlRect(cc, opt: option, sc, widget); |
228 | } |
229 | |
230 | /*! \reimp |
231 | */ |
232 | QRect QProxyStyle::itemTextRect(const QFontMetrics &fm, const QRect &r, int flags, bool enabled, const QString &text) const |
233 | { |
234 | Q_D (const QProxyStyle); |
235 | d->ensureBaseStyle(); |
236 | return d->baseStyle->itemTextRect(fm, r, flags, enabled, text); |
237 | } |
238 | |
239 | /*! \reimp |
240 | */ |
241 | QRect QProxyStyle::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const |
242 | { |
243 | Q_D (const QProxyStyle); |
244 | d->ensureBaseStyle(); |
245 | return d->baseStyle->itemPixmapRect(r, flags, pixmap); |
246 | } |
247 | |
248 | /*! \reimp |
249 | */ |
250 | QStyle::SubControl QProxyStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget) const |
251 | { |
252 | Q_D (const QProxyStyle); |
253 | d->ensureBaseStyle(); |
254 | return d->baseStyle->hitTestComplexControl(cc: control, opt: option, pt: pos, widget); |
255 | } |
256 | |
257 | /*! \reimp |
258 | */ |
259 | int QProxyStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const |
260 | { |
261 | Q_D (const QProxyStyle); |
262 | d->ensureBaseStyle(); |
263 | return d->baseStyle->styleHint(stylehint: hint, opt: option, widget, returnData); |
264 | } |
265 | |
266 | /*! \reimp |
267 | */ |
268 | int QProxyStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const |
269 | { |
270 | Q_D (const QProxyStyle); |
271 | d->ensureBaseStyle(); |
272 | return d->baseStyle->pixelMetric(metric, option, widget); |
273 | } |
274 | |
275 | /*! \reimp |
276 | */ |
277 | QPixmap QProxyStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const |
278 | { |
279 | Q_D (const QProxyStyle); |
280 | d->ensureBaseStyle(); |
281 | return d->baseStyle->standardPixmap(standardPixmap, opt, widget); |
282 | } |
283 | |
284 | /*! \reimp |
285 | */ |
286 | QPixmap QProxyStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const |
287 | { |
288 | Q_D (const QProxyStyle); |
289 | d->ensureBaseStyle(); |
290 | return d->baseStyle->generatedIconPixmap(iconMode, pixmap, opt); |
291 | } |
292 | |
293 | /*! \reimp |
294 | */ |
295 | QPalette QProxyStyle::standardPalette() const |
296 | { |
297 | Q_D (const QProxyStyle); |
298 | d->ensureBaseStyle(); |
299 | return d->baseStyle->standardPalette(); |
300 | } |
301 | |
302 | /*! \reimp |
303 | */ |
304 | void QProxyStyle::polish(QWidget *widget) |
305 | { |
306 | Q_D (QProxyStyle); |
307 | d->ensureBaseStyle(); |
308 | d->baseStyle->polish(widget); |
309 | } |
310 | |
311 | /*! \reimp |
312 | */ |
313 | void QProxyStyle::polish(QPalette &pal) |
314 | { |
315 | Q_D (QProxyStyle); |
316 | d->ensureBaseStyle(); |
317 | d->baseStyle->polish(palette&: pal); |
318 | } |
319 | |
320 | /*! \reimp |
321 | */ |
322 | void QProxyStyle::polish(QApplication *app) |
323 | { |
324 | Q_D (QProxyStyle); |
325 | d->ensureBaseStyle(); |
326 | d->baseStyle->polish(application: app); |
327 | } |
328 | |
329 | /*! \reimp |
330 | */ |
331 | void QProxyStyle::unpolish(QWidget *widget) |
332 | { |
333 | Q_D (QProxyStyle); |
334 | d->ensureBaseStyle(); |
335 | d->baseStyle->unpolish(widget); |
336 | } |
337 | |
338 | /*! \reimp |
339 | */ |
340 | void QProxyStyle::unpolish(QApplication *app) |
341 | { |
342 | Q_D (QProxyStyle); |
343 | d->ensureBaseStyle(); |
344 | d->baseStyle->unpolish(application: app); |
345 | } |
346 | |
347 | /*! \reimp |
348 | */ |
349 | bool QProxyStyle::event(QEvent *e) |
350 | { |
351 | Q_D (QProxyStyle); |
352 | |
353 | switch (e->type()) { |
354 | // The Mac style relies on these events in order to set the focus frame |
355 | case QEvent::FocusIn: |
356 | case QEvent::FocusOut: |
357 | d->ensureBaseStyle(); |
358 | return QApplication::sendEvent(receiver: d->baseStyle, event: e); |
359 | default: |
360 | break; |
361 | } |
362 | |
363 | return QCommonStyle::event(event: e); |
364 | } |
365 | |
366 | /*! |
367 | Returns an icon for the given \a standardIcon. |
368 | |
369 | Reimplement this slot to provide your own icons in a QStyle |
370 | subclass. The \a option argument can be used to pass extra |
371 | information required to find the appropriate icon. The \a widget |
372 | argument is optional and can also be used to help find the icon. |
373 | */ |
374 | QIcon QProxyStyle::standardIcon(StandardPixmap standardIcon, |
375 | const QStyleOption *option, |
376 | const QWidget *widget) const |
377 | { |
378 | Q_D (const QProxyStyle); |
379 | d->ensureBaseStyle(); |
380 | return d->baseStyle->standardIcon(standardIcon, option, widget); |
381 | } |
382 | |
383 | /*! |
384 | This slot is called by layoutSpacing() to determine the spacing that |
385 | should be used between \a control1 and \a control2 in a layout. \a |
386 | orientation specifies whether the controls are laid out side by side |
387 | or stacked vertically. The \a option parameter can be used to pass |
388 | extra information about the parent widget. The \a widget parameter |
389 | is optional and can also be used if \a option is \nullptr. |
390 | |
391 | The default implementation returns -1. |
392 | |
393 | \sa combinedLayoutSpacing() |
394 | */ |
395 | int QProxyStyle::layoutSpacing(QSizePolicy::ControlType control1, |
396 | QSizePolicy::ControlType control2, |
397 | Qt::Orientation orientation, |
398 | const QStyleOption *option, |
399 | const QWidget *widget) const |
400 | { |
401 | Q_D (const QProxyStyle); |
402 | d->ensureBaseStyle(); |
403 | return d->baseStyle->layoutSpacing(control1, control2, orientation, option, widget); |
404 | } |
405 | |
406 | QT_END_NAMESPACE |
407 | |
408 | #include "moc_qproxystyle.cpp" |
409 | |
410 | #endif // QT_NO_STYLE_PROXY |
411 | |