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
49QT_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
78void 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 = 0;
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*/
115QProxyStyle::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*/
134QProxyStyle::QProxyStyle(const QString &key)
135 : QProxyStyle(QStyleFactory::create(key))
136{
137}
138
139/*!
140 Destroys the QProxyStyle object.
141*/
142QProxyStyle::~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*/
153QStyle *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 zero, a desktop-dependant style will be
166 assigned automatically.
167*/
168void 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 */
185void 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 */
195void 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 */
204void 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 */
213void 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 */
223void 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 */
232QSize 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 */
241QRect 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 */
250QRect 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 */
259QRect 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 */
268QRect 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 */
277QStyle::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 */
286int 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 */
295int 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 */
304QPixmap 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 */
313QPixmap 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 */
322QPalette QProxyStyle::standardPalette() const
323{
324 Q_D (const QProxyStyle);
325 d->ensureBaseStyle();
326 return d->baseStyle->standardPalette();
327}
328
329/*! \reimp
330 */
331void QProxyStyle::polish(QWidget *widget)
332{
333 Q_D (QProxyStyle);
334 d->ensureBaseStyle();
335 d->baseStyle->polish(widget);
336}
337
338/*! \reimp
339 */
340void QProxyStyle::polish(QPalette &pal)
341{
342 Q_D (QProxyStyle);
343 d->ensureBaseStyle();
344 d->baseStyle->polish(pal);
345}
346
347/*! \reimp
348 */
349void QProxyStyle::polish(QApplication *app)
350{
351 Q_D (QProxyStyle);
352 d->ensureBaseStyle();
353 d->baseStyle->polish(app);
354}
355
356/*! \reimp
357 */
358void QProxyStyle::unpolish(QWidget *widget)
359{
360 Q_D (QProxyStyle);
361 d->ensureBaseStyle();
362 d->baseStyle->unpolish(widget);
363}
364
365/*! \reimp
366 */
367void QProxyStyle::unpolish(QApplication *app)
368{
369 Q_D (QProxyStyle);
370 d->ensureBaseStyle();
371 d->baseStyle->unpolish(app);
372}
373
374/*! \reimp
375 */
376bool 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 */
391QIcon 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 0.
407
408 The default implementation returns -1.
409
410 \sa combinedLayoutSpacing()
411 */
412int 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
423QT_END_NAMESPACE
424
425#include "moc_qproxystyle.cpp"
426
427#endif // QT_NO_STYLE_PROXY
428