1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui 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 http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://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 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include <qstyle.h>
43 #include <private/qproxystyle_p.h>
44 #include <private/qapplication_p.h>
45 #include "qproxystyle.h"
46 #include "qstylefactory.h"
47 #include <private/qstyle_p.h>
48 
49 #if !defined(QT_NO_STYLE_PROXY) || defined(QT_PLUGIN)
50 
51 QT_BEGIN_NAMESPACE
52 
53 /*!
54     \class QProxyStyle
55 
56     \brief The QProxyStyle class is a convenience class that simplifies
57     dynamically overriding QStyle elements.
58 
59     \since 4.6
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 doc/src/snippets/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 = 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 \a style
110   or in the current application \l{QStyle}{style} if \a style is 0
111   (default). Normally \a style is 0, because you want to override
112   behavior in the system style.
113 
114   Ownership of \a style is transferred to QProxyStyle.
115 */
QProxyStyle(QStyle * style)116 QProxyStyle::QProxyStyle(QStyle *style) :
117     QCommonStyle(*new QProxyStylePrivate())
118 {
119     Q_D(QProxyStyle);
120     if (style) {
121         style->setProxy(this);
122         style->setParent(this); // Take ownership
123         d->baseStyle = style;
124     }
125 }
126 
127 /*!
128     Destroys the QProxyStyle object.
129 */
~QProxyStyle()130 QProxyStyle::~QProxyStyle()
131 {
132 }
133 
134 /*!
135     Returns the proxy base style object. If no base style
136     is set on the proxy style, QProxyStyle will create
137     an instance of the application style instead.
138 
139     \sa setBaseStyle(), QStyle
140 */
baseStyle() const141 QStyle *QProxyStyle::baseStyle() const
142 {
143     Q_D (const QProxyStyle);
144     d->ensureBaseStyle();
145     return d->baseStyle;
146 }
147 
148 /*!
149     Sets the base style that should be proxied.
150 
151     Ownership of \a style is transferred to QProxyStyle.
152 
153     If style is zero, a desktop-dependant style will be
154     assigned automatically.
155 */
setBaseStyle(QStyle * style)156 void QProxyStyle::setBaseStyle(QStyle *style)
157 {
158     Q_D (QProxyStyle);
159 
160     if (d->baseStyle && d->baseStyle->parent() == this)
161         d->baseStyle->deleteLater();
162 
163     d->baseStyle = style;
164 
165     if (d->baseStyle) {
166         d->baseStyle->setProxy(this);
167         d->baseStyle->setParent(this);
168     }
169 }
170 
171 /*! \reimp
172  */
drawPrimitive(PrimitiveElement element,const QStyleOption * option,QPainter * painter,const QWidget * widget) const173 void QProxyStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
174 {
175     Q_D (const QProxyStyle);
176     d->ensureBaseStyle();
177     d->baseStyle->drawPrimitive(element, option, painter, widget);
178 }
179 
180 /*!
181   \reimp
182  */
drawControl(ControlElement element,const QStyleOption * option,QPainter * painter,const QWidget * widget) const183 void QProxyStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
184 {
185     Q_D (const QProxyStyle);
186     d->ensureBaseStyle();
187     d->baseStyle->drawControl(element, option, painter, widget);
188 }
189 
190 /*! \reimp
191  */
drawComplexControl(ComplexControl control,const QStyleOptionComplex * option,QPainter * painter,const QWidget * widget) const192 void QProxyStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const
193 {
194     Q_D (const QProxyStyle);
195     d->ensureBaseStyle();
196     d->baseStyle->drawComplexControl(control, option, painter, widget);
197 }
198 
199 /*! \reimp
200  */
drawItemText(QPainter * painter,const QRect & rect,int flags,const QPalette & pal,bool enabled,const QString & text,QPalette::ColorRole textRole) const201 void QProxyStyle::drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled,
202                                const QString &text, QPalette::ColorRole textRole) const
203 {
204     Q_D (const QProxyStyle);
205     d->ensureBaseStyle();
206     d->baseStyle->drawItemText(painter, rect, flags, pal, enabled, text, textRole);
207 }
208 
209 /*! \reimp
210  */
drawItemPixmap(QPainter * painter,const QRect & rect,int alignment,const QPixmap & pixmap) const211 void QProxyStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, const QPixmap &pixmap) const
212 {
213     Q_D (const QProxyStyle);
214     d->ensureBaseStyle();
215     d->baseStyle->drawItemPixmap(painter, rect, alignment, pixmap);
216 }
217 
218 /*! \reimp
219  */
sizeFromContents(ContentsType type,const QStyleOption * option,const QSize & size,const QWidget * widget) const220 QSize QProxyStyle::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const
221 {
222     Q_D (const QProxyStyle);
223     d->ensureBaseStyle();
224     return d->baseStyle->sizeFromContents(type, option, size, widget);
225 }
226 
227 /*! \reimp
228  */
subElementRect(SubElement element,const QStyleOption * option,const QWidget * widget) const229 QRect QProxyStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
230 {
231     Q_D (const QProxyStyle);
232     d->ensureBaseStyle();
233     return d->baseStyle->subElementRect(element, option, widget);
234 }
235 
236 /*! \reimp
237  */
subControlRect(ComplexControl cc,const QStyleOptionComplex * option,SubControl sc,const QWidget * widget) const238 QRect QProxyStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *option, SubControl sc, const QWidget *widget) const
239 {
240     Q_D (const QProxyStyle);
241     d->ensureBaseStyle();
242     return d->baseStyle->subControlRect(cc, option, sc, widget);
243 }
244 
245 /*! \reimp
246  */
itemTextRect(const QFontMetrics & fm,const QRect & r,int flags,bool enabled,const QString & text) const247 QRect QProxyStyle::itemTextRect(const QFontMetrics &fm, const QRect &r, int flags, bool enabled, const QString &text) const
248 {
249     Q_D (const QProxyStyle);
250     d->ensureBaseStyle();
251     return d->baseStyle->itemTextRect(fm, r, flags, enabled, text);
252 }
253 
254 /*! \reimp
255  */
itemPixmapRect(const QRect & r,int flags,const QPixmap & pixmap) const256 QRect QProxyStyle::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const
257 {
258     Q_D (const QProxyStyle);
259     d->ensureBaseStyle();
260     return d->baseStyle->itemPixmapRect(r, flags, pixmap);
261 }
262 
263 /*! \reimp
264  */
hitTestComplexControl(ComplexControl control,const QStyleOptionComplex * option,const QPoint & pos,const QWidget * widget) const265 QStyle::SubControl QProxyStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget) const
266 {
267     Q_D (const QProxyStyle);
268     d->ensureBaseStyle();
269     return d->baseStyle->hitTestComplexControl(control, option, pos, widget);
270 }
271 
272 /*! \reimp
273  */
styleHint(StyleHint hint,const QStyleOption * option,const QWidget * widget,QStyleHintReturn * returnData) const274 int QProxyStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const
275 {
276     Q_D (const QProxyStyle);
277     d->ensureBaseStyle();
278     return d->baseStyle->styleHint(hint, option, widget, returnData);
279 }
280 
281 /*! \reimp
282  */
pixelMetric(PixelMetric metric,const QStyleOption * option,const QWidget * widget) const283 int QProxyStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
284 {
285     Q_D (const QProxyStyle);
286     d->ensureBaseStyle();
287     return d->baseStyle->pixelMetric(metric, option, widget);
288 }
289 
290 /*! \reimp
291  */
standardPixmap(StandardPixmap standardPixmap,const QStyleOption * opt,const QWidget * widget) const292 QPixmap QProxyStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const
293 {
294     Q_D (const QProxyStyle);
295     d->ensureBaseStyle();
296     return d->baseStyle->standardPixmap(standardPixmap, opt, widget);
297 }
298 
299 /*! \reimp
300  */
generatedIconPixmap(QIcon::Mode iconMode,const QPixmap & pixmap,const QStyleOption * opt) const301 QPixmap QProxyStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const
302 {
303     Q_D (const QProxyStyle);
304     d->ensureBaseStyle();
305     return d->baseStyle->generatedIconPixmap(iconMode, pixmap, opt);
306 }
307 
308 /*! \reimp
309  */
standardPalette() const310 QPalette QProxyStyle::standardPalette() const
311 {
312     Q_D (const QProxyStyle);
313     d->ensureBaseStyle();
314     return d->baseStyle->standardPalette();
315 }
316 
317 /*! \reimp
318  */
polish(QWidget * widget)319 void QProxyStyle::polish(QWidget *widget)
320 {
321     Q_D (QProxyStyle);
322     d->ensureBaseStyle();
323     d->baseStyle->polish(widget);
324 }
325 
326 /*! \reimp
327  */
polish(QPalette & pal)328 void QProxyStyle::polish(QPalette &pal)
329 {
330     Q_D (QProxyStyle);
331     d->ensureBaseStyle();
332     d->baseStyle->polish(pal);
333 }
334 
335 /*! \reimp
336  */
polish(QApplication * app)337 void QProxyStyle::polish(QApplication *app)
338 {
339     Q_D (QProxyStyle);
340     d->ensureBaseStyle();
341     d->baseStyle->polish(app);
342 }
343 
344 /*! \reimp
345  */
unpolish(QWidget * widget)346 void QProxyStyle::unpolish(QWidget *widget)
347 {
348     Q_D (QProxyStyle);
349     d->ensureBaseStyle();
350     d->baseStyle->unpolish(widget);
351 }
352 
353 /*! \reimp
354  */
unpolish(QApplication * app)355 void QProxyStyle::unpolish(QApplication *app)
356 {
357     Q_D (QProxyStyle);
358     d->ensureBaseStyle();
359     d->baseStyle->unpolish(app);
360 }
361 
362 /*! \reimp
363  */
event(QEvent * e)364 bool QProxyStyle::event(QEvent *e)
365 {
366     Q_D (QProxyStyle);
367     d->ensureBaseStyle();
368     return d->baseStyle->event(e);
369 }
370 
371 /*!
372   Returns an icon for the given \a standardIcon.
373 
374   Reimplement this slot to provide your own icons in a QStyle
375   subclass. The \a option argument can be used to pass extra
376   information required to find the appropriate icon. The \a widget
377   argument is optional and can also be used to help find the icon.
378 
379   \note Because of binary compatibility constraints, standardIcon()
380   introduced in Qt 4.1 is not virtual. Therefore it must dynamically
381   detect and call \e this slot.  This default implementation simply
382   calls standardIcon() with the given parameters.
383 
384   \sa standardIcon()
385  */
standardIconImplementation(StandardPixmap standardIcon,const QStyleOption * option,const QWidget * widget) const386 QIcon QProxyStyle::standardIconImplementation(StandardPixmap standardIcon,
387                                               const QStyleOption *option,
388                                               const QWidget *widget) const
389 {
390     Q_D (const QProxyStyle);
391     d->ensureBaseStyle();
392     return d->baseStyle->standardIcon(standardIcon, option, widget);
393 }
394 
395 /*!
396   This slot is called by layoutSpacing() to determine the spacing that
397   should be used between \a control1 and \a control2 in a layout. \a
398   orientation specifies whether the controls are laid out side by side
399   or stacked vertically. The \a option parameter can be used to pass
400   extra information about the parent widget.  The \a widget parameter
401   is optional and can also be used if \a option is 0.
402 
403   The default implementation returns -1.
404 
405   \sa layoutSpacing(), combinedLayoutSpacing()
406  */
layoutSpacingImplementation(QSizePolicy::ControlType control1,QSizePolicy::ControlType control2,Qt::Orientation orientation,const QStyleOption * option,const QWidget * widget) const407 int QProxyStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1,
408                                              QSizePolicy::ControlType control2,
409                                              Qt::Orientation orientation,
410                                              const QStyleOption *option,
411                                              const QWidget *widget) const
412 {
413     Q_D (const QProxyStyle);
414     d->ensureBaseStyle();
415     return d->baseStyle->layoutSpacing(control1, control2, orientation, option, widget);
416 }
417 
418 QT_END_NAMESPACE
419 
420 #endif // QT_NO_STYLE_PROXY
421