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