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 
ensureBaseStyle() const78 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 */
QProxyStyle(QStyle * style)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 */
QProxyStyle(const QString & key)134 QProxyStyle::QProxyStyle(const QString &key)
135     : QProxyStyle(QStyleFactory::create(key))
136 {
137 }
138 
139 /*!
140     Destroys the QProxyStyle object.
141 */
~QProxyStyle()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 */
baseStyle() const153 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 */
setBaseStyle(QStyle * style)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  */
drawPrimitive(PrimitiveElement element,const QStyleOption * option,QPainter * painter,const QWidget * widget) const185 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  */
drawControl(ControlElement element,const QStyleOption * option,QPainter * painter,const QWidget * widget) const195 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  */
drawComplexControl(ComplexControl control,const QStyleOptionComplex * option,QPainter * painter,const QWidget * widget) const204 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  */
drawItemText(QPainter * painter,const QRect & rect,int flags,const QPalette & pal,bool enabled,const QString & text,QPalette::ColorRole textRole) const213 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  */
drawItemPixmap(QPainter * painter,const QRect & rect,int alignment,const QPixmap & pixmap) const223 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  */
sizeFromContents(ContentsType type,const QStyleOption * option,const QSize & size,const QWidget * widget) const232 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  */
subElementRect(SubElement element,const QStyleOption * option,const QWidget * widget) const241 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  */
subControlRect(ComplexControl cc,const QStyleOptionComplex * option,SubControl sc,const QWidget * widget) const250 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  */
itemTextRect(const QFontMetrics & fm,const QRect & r,int flags,bool enabled,const QString & text) const259 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  */
itemPixmapRect(const QRect & r,int flags,const QPixmap & pixmap) const268 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  */
hitTestComplexControl(ComplexControl control,const QStyleOptionComplex * option,const QPoint & pos,const QWidget * widget) const277 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  */
styleHint(StyleHint hint,const QStyleOption * option,const QWidget * widget,QStyleHintReturn * returnData) const286 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  */
pixelMetric(PixelMetric metric,const QStyleOption * option,const QWidget * widget) const295 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  */
standardPixmap(StandardPixmap standardPixmap,const QStyleOption * opt,const QWidget * widget) const304 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  */
generatedIconPixmap(QIcon::Mode iconMode,const QPixmap & pixmap,const QStyleOption * opt) const313 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  */
standardPalette() const322 QPalette QProxyStyle::standardPalette() const
323 {
324     Q_D (const QProxyStyle);
325     d->ensureBaseStyle();
326     return d->baseStyle->standardPalette();
327 }
328 
329 /*! \reimp
330  */
polish(QWidget * widget)331 void QProxyStyle::polish(QWidget *widget)
332 {
333     Q_D (QProxyStyle);
334     d->ensureBaseStyle();
335     d->baseStyle->polish(widget);
336 }
337 
338 /*! \reimp
339  */
polish(QPalette & pal)340 void QProxyStyle::polish(QPalette &pal)
341 {
342     Q_D (QProxyStyle);
343     d->ensureBaseStyle();
344     d->baseStyle->polish(pal);
345 }
346 
347 /*! \reimp
348  */
polish(QApplication * app)349 void QProxyStyle::polish(QApplication *app)
350 {
351     Q_D (QProxyStyle);
352     d->ensureBaseStyle();
353     d->baseStyle->polish(app);
354 }
355 
356 /*! \reimp
357  */
unpolish(QWidget * widget)358 void QProxyStyle::unpolish(QWidget *widget)
359 {
360     Q_D (QProxyStyle);
361     d->ensureBaseStyle();
362     d->baseStyle->unpolish(widget);
363 }
364 
365 /*! \reimp
366  */
unpolish(QApplication * app)367 void QProxyStyle::unpolish(QApplication *app)
368 {
369     Q_D (QProxyStyle);
370     d->ensureBaseStyle();
371     d->baseStyle->unpolish(app);
372 }
373 
374 /*! \reimp
375  */
event(QEvent * e)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  */
standardIcon(StandardPixmap standardIcon,const QStyleOption * option,const QWidget * widget) const391 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  */
layoutSpacing(QSizePolicy::ControlType control1,QSizePolicy::ControlType control2,Qt::Orientation orientation,const QStyleOption * option,const QWidget * widget) const412 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