1 /***************************************************************************
2 **
3 ** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
4 ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
5 ** Copyright (C) 2016 The Qt Company Ltd.
6 ** Contact: https://www.qt.io/licensing/
7 **
8 ** This file is part of the QtWidgets module of the Qt Toolkit.
9 **
10 ** $QT_BEGIN_LICENSE:LGPL$
11 ** Commercial License Usage
12 ** Licensees holding valid commercial Qt licenses may use this file in
13 ** accordance with the commercial license agreement provided with the
14 ** Software or, alternatively, in accordance with the terms contained in
15 ** a written agreement between you and The Qt Company. For licensing terms
16 ** and conditions see https://www.qt.io/terms-conditions. For further
17 ** information use the contact form at https://www.qt.io/contact-us.
18 **
19 ** GNU Lesser General Public License Usage
20 ** Alternatively, this file may be used under the terms of the GNU Lesser
21 ** General Public License version 3 as published by the Free Software
22 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
23 ** packaging of this file. Please review the following information to
24 ** ensure the GNU Lesser General Public License version 3 requirements
25 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
26 **
27 ** GNU General Public License Usage
28 ** Alternatively, this file may be used under the terms of the GNU
29 ** General Public License version 2.0 or (at your option) the GNU General
30 ** Public license version 3 or any later version approved by the KDE Free
31 ** Qt Foundation. The licenses are as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
33 ** included in the packaging of this file. Please review the following
34 ** information to ensure the GNU General Public License requirements will
35 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
36 ** https://www.gnu.org/licenses/gpl-3.0.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qpixmapstyle_p.h"
43 #include "qpixmapstyle_p_p.h"
44 
45 #include <QDebug>
46 #if QT_CONFIG(textedit)
47 #include <QTextEdit>
48 #endif
49 #include <QStringBuilder>
50 #include <QPainter>
51 #include <QPixmapCache>
52 #include <QStyleOption>
53 #include <QString>
54 #if QT_CONFIG(progressbar)
55 #include <QProgressBar>
56 #endif
57 #if QT_CONFIG(slider)
58 #include <QSlider>
59 #endif
60 #include <QEvent>
61 #if QT_CONFIG(combobox)
62 #include <QComboBox>
63 #endif
64 #if QT_CONFIG(itemviews)
65 #include <QAbstractItemView>
66 #include <QStyledItemDelegate>
67 #endif
68 #if QT_CONFIG(listview)
69 #include <QListView>
70 #endif
71 #include <QAbstractScrollArea>
72 #if QT_CONFIG(scrollbar)
73 #include <QScrollBar>
74 #endif
75 #if QT_CONFIG(scroller)
76 #include <qscroller.h>
77 #endif
78 
79 QT_BEGIN_NAMESPACE
80 
81 /*!
82     \class QPixmapStyle
83     \brief The QPixmapStyle class provides mechanism for writing pixmap based styles.
84 
85     \since 5.7
86     \ingroup appearance
87     \inmodule QtWidgets
88     \internal
89 
90     This is a convenience class that enables the implementation of a widget style using
91     pixmaps, on the same fashion used by the \l{BorderImage} QML type.
92 
93     In order to style a QWidget, one simply needs to call QPixmapStyle::addDescriptor()
94     or QPixmapStyle::addPixmap() with the id of the component to be styled, the path of
95     the image to be used, the margins and the tiling rules:
96 
97     \snippet styles/qcustompixmapstyle.cpp 0
98 
99     \sa QStyle, QCommonStyle
100 */
101 
102 /*!
103     \internal
104 
105     Constructs a QPixmapStyle object.
106 */
QPixmapStyle()107 QPixmapStyle::QPixmapStyle()
108     : QCommonStyle(*new QPixmapStylePrivate)
109 {
110 }
111 
112 /*!
113     Destroys the QPixmapStyle object.
114 */
~QPixmapStyle()115 QPixmapStyle::~QPixmapStyle()
116 {
117 }
118 
119 /*!
120     \reimp
121 */
polish(QApplication * application)122 void QPixmapStyle::polish(QApplication *application)
123 {
124     QCommonStyle::polish(application);
125 }
126 
127 /*!
128     \reimp
129 */
polish(QPalette & palette)130 void QPixmapStyle::polish(QPalette &palette)
131 {
132     palette = proxy()->standardPalette();
133 }
134 
135 /*!
136     \reimp
137 */
polish(QWidget * widget)138 void QPixmapStyle::polish(QWidget *widget)
139 {
140     Q_D(QPixmapStyle);
141 
142     // Don't fill the interior of the QTextEdit
143 #if QT_CONFIG(textedit)
144     if (qobject_cast<QTextEdit*>(widget)) {
145         QPalette p = widget->palette();
146         p.setBrush(QPalette::Base, Qt::NoBrush);
147         widget->setPalette(p);
148     }
149 #endif
150 #if QT_CONFIG(progressbar)
151     if (QProgressBar *pb = qobject_cast<QProgressBar*>(widget)) {
152         // Center the text in the progress bar
153         pb->setAlignment(Qt::AlignCenter);
154         // Change the font size if needed, as it's used to compute the minimum size
155         QFont font = pb->font();
156         font.setPixelSize(d->descriptors.value(PB_HBackground).size.height()/2);
157         pb->setFont(font);
158     }
159 #endif
160 #if QT_CONFIG(slider)
161     if (qobject_cast<QSlider*>(widget))
162         widget->installEventFilter(this);
163 #endif
164 #if QT_CONFIG(combobox)
165     if (QComboBox *cb = qobject_cast<QComboBox*>(widget)) {
166         widget->installEventFilter(this);
167         // NOTE: This will break if the private API of QComboBox changes drastically
168         // Make sure the popup is created so we can change the frame style
169         QAbstractItemView *list = cb->view();
170         list->setProperty("_pixmap_combobox_list", true);
171         list->setItemDelegate(new QStyledItemDelegate(list));
172         QPalette p = list->palette();
173         p.setBrush(QPalette::Active, QPalette::Base, QBrush(Qt::transparent) );
174         p.setBrush(QPalette::Active, QPalette::AlternateBase, QBrush(Qt::transparent) );
175         p.setBrush(QPalette::Inactive, QPalette::Base, QBrush(Qt::transparent) );
176         p.setBrush(QPalette::Inactive, QPalette::AlternateBase, QBrush(Qt::transparent) );
177         p.setBrush(QPalette::Disabled, QPalette::Base, QBrush(Qt::transparent) );
178         p.setBrush(QPalette::Disabled, QPalette::AlternateBase, QBrush(Qt::transparent) );
179         list->setPalette(p);
180 
181         QFrame *frame = qobject_cast<QFrame*>(list->parent());
182         if (frame) {
183             const QPixmapStyleDescriptor &desc = d->descriptors.value(DD_PopupDown);
184             const QPixmapStylePixmap &pix = d->pixmaps.value(DD_ItemSeparator);
185             frame->setContentsMargins(pix.margins.left(), desc.margins.top(),
186                                       pix.margins.right(), desc.margins.bottom());
187             frame->setAttribute(Qt::WA_TranslucentBackground);
188         }
189     }
190 #endif // QT_CONFIG(combobox)
191     if (qstrcmp(widget->metaObject()->className(),"QComboBoxPrivateContainer") == 0)
192         widget->installEventFilter(this);
193 
194 #if QT_CONFIG(scrollarea)
195     if (QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea*>(widget)) {
196         scrollArea->viewport()->setAutoFillBackground(false);
197 #if QT_CONFIG(itemviews)
198         if (QAbstractItemView *view = qobject_cast<QAbstractItemView*>(scrollArea)) {
199             view->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
200             view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
201         }
202 #endif
203 #if QT_CONFIG(gestures) && QT_CONFIG(scroller)
204         QScroller::grabGesture(scrollArea->viewport(), QScroller::LeftMouseButtonGesture);
205 #endif
206     }
207 #endif // QT_CONFIG(scrollarea)
208 #if QT_CONFIG(scrollbar)
209     if (qobject_cast<QScrollBar*>(widget))
210         widget->setAttribute(Qt::WA_OpaquePaintEvent, false);
211 #endif
212 #if !QT_CONFIG(progressbar) && !QT_CONFIG(combobox)
213     Q_UNUSED(d);
214 #endif
215     QCommonStyle::polish(widget);
216 }
217 
218 /*!
219     \reimp
220 */
unpolish(QApplication * application)221 void QPixmapStyle::unpolish(QApplication *application)
222 {
223     QCommonStyle::unpolish(application);
224 }
225 
226 /*!
227     \reimp
228 */
unpolish(QWidget * widget)229 void QPixmapStyle::unpolish(QWidget *widget)
230 {
231     if (
232 #if QT_CONFIG(slider)
233         qobject_cast<QSlider*>(widget)
234 #else
235         false
236 #endif
237 #if QT_CONFIG(combobox)
238           ||  qobject_cast<QComboBox*>(widget)
239 #endif
240         ) {
241         widget->removeEventFilter(this);
242     }
243 
244     if (qstrcmp(widget->metaObject()->className(),"QComboBoxPrivateContainer") == 0)
245         widget->removeEventFilter(this);
246 
247 #if QT_CONFIG(gestures) && QT_CONFIG(scrollarea) && QT_CONFIG(scroller)
248     if (QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea*>(widget))
249         QScroller::ungrabGesture(scrollArea->viewport());
250 #endif
251 
252     QCommonStyle::unpolish(widget);
253 }
254 
255 /*!
256     \reimp
257 */
drawPrimitive(PrimitiveElement element,const QStyleOption * option,QPainter * painter,const QWidget * widget) const258 void QPixmapStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
259                                  QPainter *painter, const QWidget *widget) const
260 {
261     switch (element) {
262     case PE_FrameFocusRect: //disable focus rectangle
263         break;
264     case PE_PanelButtonBevel:
265     case PE_PanelButtonCommand:
266         drawPushButton(option, painter, widget);
267         break;
268     case PE_PanelLineEdit:
269     case PE_FrameLineEdit:
270         drawLineEdit(option, painter, widget);
271         break;
272     case PE_Frame:
273 #if QT_CONFIG(textedit)
274     case PE_FrameDefaultButton:
275         if (qobject_cast<const QTextEdit*>(widget))
276             drawTextEdit(option, painter, widget);
277         break;
278 #endif
279     case PE_IndicatorCheckBox:
280         drawCheckBox(option, painter, widget);
281         break;
282     case PE_IndicatorRadioButton:
283         drawRadioButton(option, painter, widget);
284         break;
285     case PE_PanelItemViewItem:
286 #if QT_CONFIG(listview)
287         if (qobject_cast<const QListView*>(widget))
288             drawPanelItemViewItem(option, painter, widget);
289         else
290 #endif
291             QCommonStyle::drawPrimitive(element, option, painter, widget);
292         break;
293     default:
294         QCommonStyle::drawPrimitive(element, option, painter, widget);
295     }
296 }
297 
298 /*!
299     \reimp
300 */
drawControl(ControlElement element,const QStyleOption * option,QPainter * painter,const QWidget * widget) const301 void QPixmapStyle::drawControl(ControlElement element, const QStyleOption *option,
302                                QPainter *painter, const QWidget *widget) const
303 {
304     Q_D(const QPixmapStyle);
305 
306     switch (element) {
307     case CE_ProgressBarGroove:
308         drawProgressBarBackground(option, painter, widget);
309         break;
310     case CE_ProgressBarLabel:
311         drawProgressBarLabel(option, painter, widget);
312         break;
313     case CE_ProgressBarContents:
314         drawProgressBarFill(option, painter, widget);
315         break;
316     case CE_ShapedFrame:
317         // NOTE: This will break if the private API of QComboBox changes drastically
318         if (qstrcmp(widget->metaObject()->className(),"QComboBoxPrivateContainer") == 0) {
319             const QPixmapStyleDescriptor &desc = d->descriptors.value(DD_PopupDown);
320             const QPixmapStylePixmap &pix = d->pixmaps.value(DD_ItemSeparator);
321             QRect rect = option->rect;
322             rect.adjust(-pix.margins.left(), -desc.margins.top(),
323                         pix.margins.right(), desc.margins.bottom());
324             bool up = widget->property("_pixmapstyle_combobox_up").toBool();
325             drawCachedPixmap(up ? DD_PopupUp : DD_PopupDown, rect, painter);
326         }
327         else {
328             QCommonStyle::drawControl(element, option, painter, widget);
329         }
330         break;
331     default:
332         QCommonStyle::drawControl(element, option, painter, widget);
333     }
334 }
335 
336 /*!
337     \reimp
338 */
drawComplexControl(ComplexControl cc,const QStyleOptionComplex * option,QPainter * painter,const QWidget * widget) const339 void QPixmapStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *option,
340                                       QPainter *painter, const QWidget *widget) const
341 {
342     switch (cc) {
343     case CC_Slider:
344         drawSlider(option, painter, widget);
345         break;
346     case CC_ComboBox:
347         drawComboBox(option, painter, widget);
348         break;
349     case CC_ScrollBar:
350         drawScrollBar(option, painter, widget);
351         break;
352     default:
353         QCommonStyle::drawComplexControl(cc, option, painter, widget);
354     }
355 }
356 
357 /*!
358     \reimp
359 */
sizeFromContents(ContentsType type,const QStyleOption * option,const QSize & contentsSize,const QWidget * widget) const360 QSize QPixmapStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
361                                      const QSize &contentsSize, const QWidget *widget) const
362 {
363     switch (type) {
364     case CT_PushButton:
365         return pushButtonSizeFromContents(option, contentsSize, widget);
366     case CT_LineEdit:
367         return lineEditSizeFromContents(option, contentsSize, widget);
368     case CT_ProgressBar:
369         return progressBarSizeFromContents(option, contentsSize, widget);
370     case CT_Slider:
371         return sliderSizeFromContents(option, contentsSize, widget);
372     case CT_ComboBox:
373         return comboBoxSizeFromContents(option, contentsSize, widget);
374     case CT_ItemViewItem:
375         return itemViewSizeFromContents(option, contentsSize, widget);
376     default: ;
377     }
378 
379     return QCommonStyle::sizeFromContents(type, option, contentsSize, widget);
380 }
381 
382 /*!
383     \reimp
384 */
subElementRect(SubElement element,const QStyleOption * option,const QWidget * widget) const385 QRect QPixmapStyle::subElementRect(SubElement element, const QStyleOption *option,
386                                    const QWidget *widget) const
387 {
388     Q_D(const QPixmapStyle);
389 
390     switch (element) {
391     case SE_LineEditContents:
392     {
393         QRect rect = QCommonStyle::subElementRect(element, option, widget);
394         const QPixmapStyleDescriptor &desc = d->descriptors.value(LE_Enabled);
395         rect.adjust(desc.margins.left(), desc.margins.top(),
396                     -desc.margins.right(), -desc.margins.bottom());
397         rect = visualRect(option->direction, option->rect, rect);
398         return rect;
399     }
400     default: ;
401     }
402 
403     return QCommonStyle::subElementRect(element, option, widget);
404 }
405 
406 /*!
407     \reimp
408 */
subControlRect(ComplexControl cc,const QStyleOptionComplex * option,SubControl sc,const QWidget * widget) const409 QRect QPixmapStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *option,
410                                    SubControl sc, const QWidget *widget) const
411 {
412     switch (cc) {
413     case CC_ComboBox:
414         return comboBoxSubControlRect(option, sc, widget);
415     case CC_ScrollBar:
416         return scrollBarSubControlRect(option, sc, widget);
417     default: ;
418     }
419 
420     return QCommonStyle::subControlRect(cc, option, sc, widget);
421 }
422 
423 /*!
424     \reimp
425 */
pixelMetric(PixelMetric metric,const QStyleOption * option,const QWidget * widget) const426 int QPixmapStyle::pixelMetric(PixelMetric metric, const QStyleOption *option,
427                               const QWidget *widget) const
428 {
429     Q_D(const QPixmapStyle);
430 
431     switch (metric) {
432     case PM_ButtonShiftHorizontal:
433     case PM_ButtonShiftVertical:
434         return 0;
435     case PM_DefaultFrameWidth:
436 #if QT_CONFIG(textedit)
437         if (qobject_cast<const QTextEdit*>(widget)) {
438             const QPixmapStyleDescriptor &desc = d->descriptors.value(LE_Enabled);
439             return qMax(qMax(desc.margins.left(), desc.margins.right()),
440                         qMax(desc.margins.top(), desc.margins.bottom()));
441         }
442 #endif
443         return 0;
444     case PM_IndicatorWidth:
445         return d->pixmaps.value(CB_Enabled).pixmap.width();
446     case PM_IndicatorHeight:
447         return d->pixmaps.value(CB_Enabled).pixmap.height();
448     case PM_CheckBoxLabelSpacing:
449     {
450         const QPixmapStylePixmap &pix = d->pixmaps.value(CB_Enabled);
451         return qMax(qMax(pix.margins.left(), pix.margins.right()),
452                     qMax(pix.margins.top(), pix.margins.bottom()));
453     }
454     case PM_ExclusiveIndicatorWidth:
455         return d->pixmaps.value(RB_Enabled).pixmap.width();
456     case PM_ExclusiveIndicatorHeight:
457         return d->pixmaps.value(RB_Enabled).pixmap.height();
458     case PM_RadioButtonLabelSpacing:
459     {
460         const QPixmapStylePixmap &pix = d->pixmaps.value(RB_Enabled);
461         return qMax(qMax(pix.margins.left(), pix.margins.right()),
462                     qMax(pix.margins.top(), pix.margins.bottom()));
463     }
464 #if QT_CONFIG(slider)
465     case PM_SliderThickness:
466         if (const QStyleOptionSlider *slider =
467                     qstyleoption_cast<const QStyleOptionSlider*>(option)) {
468             const QPixmapStyleDescriptor desc =
469                 d->descriptors.value(slider->orientation == Qt::Horizontal
470                                      ? SG_HEnabled : SG_VEnabled);
471             return slider->orientation == Qt::Horizontal
472                                                 ? desc.size.height() : desc.size.width();
473         }
474         break;
475     case PM_SliderControlThickness:
476         if (const QStyleOptionSlider *slider =
477                     qstyleoption_cast<const QStyleOptionSlider*>(option)) {
478             const QPixmapStylePixmap pix =
479                     d->pixmaps.value(slider->orientation == Qt::Horizontal
480                                      ? SH_HEnabled : SH_VEnabled);
481             return slider->orientation == Qt::Horizontal
482                                                 ? pix.pixmap.height() : pix.pixmap.width();
483         }
484         break;
485     case PM_SliderLength:
486         if (const QStyleOptionSlider *slider =
487                     qstyleoption_cast<const QStyleOptionSlider*>(option)) {
488             const QPixmapStylePixmap pix =
489                     d->pixmaps.value(slider->orientation == Qt::Horizontal
490                                      ? SH_HEnabled : SH_VEnabled);
491             return slider->orientation == Qt::Horizontal
492                                                 ? pix.pixmap.width() : pix.pixmap.height();
493         }
494         break;
495     case PM_ScrollBarExtent:
496         if (const QStyleOptionSlider *slider =
497                     qstyleoption_cast<const QStyleOptionSlider*>(option)) {
498             const QPixmapStyleDescriptor desc =
499                     d->descriptors.value(slider->orientation == Qt::Horizontal
500                                          ? SB_Horizontal : SB_Vertical);
501             return slider->orientation == Qt::Horizontal
502                                                 ? desc.size.height() : desc.size.width();
503         }
504         break;
505 #endif // QT_CONFIG(slider)
506     case PM_ScrollBarSliderMin:
507         return 0;
508     default: ;
509     }
510 
511     return QCommonStyle::pixelMetric(metric, option, widget);
512 }
513 
514 /*!
515     \reimp
516 */
styleHint(StyleHint hint,const QStyleOption * option,const QWidget * widget,QStyleHintReturn * returnData) const517 int QPixmapStyle::styleHint(StyleHint hint, const QStyleOption *option,
518                             const QWidget *widget, QStyleHintReturn *returnData) const
519 {
520     switch (hint) {
521     case SH_EtchDisabledText:
522         return false;
523     case SH_ComboBox_Popup:
524         return false;
525     default: ;
526     }
527 
528     return QCommonStyle::styleHint(hint, option, widget, returnData);
529 }
530 
531 /*!
532     \reimp
533 */
hitTestComplexControl(QStyle::ComplexControl control,const QStyleOptionComplex * option,const QPoint & pos,const QWidget * widget) const534 QStyle::SubControl QPixmapStyle::hitTestComplexControl(QStyle::ComplexControl control,
535                                                        const QStyleOptionComplex *option,
536                                                        const QPoint &pos,
537                                                        const QWidget *widget) const
538 {
539     const SubControl sc = QCommonStyle::hitTestComplexControl(control, option, pos, widget);
540     if (control == CC_ScrollBar) {
541         if (sc == SC_ScrollBarAddLine)
542             return SC_ScrollBarAddPage;
543         else if (sc == SC_ScrollBarSubLine)
544             return SC_ScrollBarSubPage;
545     }
546 
547     return sc;
548 }
549 
550 /*!
551     \reimp
552 */
eventFilter(QObject * watched,QEvent * event)553 bool QPixmapStyle::eventFilter(QObject *watched, QEvent *event)
554 {
555     Q_D(QPixmapStyle);
556 #if QT_CONFIG(slider)
557     if (QSlider *slider = qobject_cast<QSlider*>(watched)) {
558         switch (event->type()) {
559         case QEvent::MouseButtonPress:
560         case QEvent::MouseButtonRelease:
561         case QEvent::MouseMove:
562             slider->update();
563             break;
564         default: ;
565         }
566     }
567 #endif // QT_CONFIG(slider)
568 #if QT_CONFIG(combobox)
569     if (QComboBox *comboBox = qobject_cast<QComboBox*>(watched)) {
570         switch (event->type()) {
571         case QEvent::MouseButtonPress:
572             event->ignore();
573             comboBox->setProperty("_pixmapstyle_combobox_pressed", true);
574             comboBox->repaint();
575             return true;
576         case QEvent::MouseButtonRelease:
577             comboBox->setProperty("_pixmapstyle_combobox_pressed", false);
578             comboBox->repaint();
579             if ( comboBox->view() ) {
580                 if ( comboBox->view()->isVisible() || (!comboBox->isEnabled()))
581                     comboBox->hidePopup();
582                 else
583                     comboBox->showPopup();
584             }
585             break;
586         default: ;
587         }
588     }
589 #endif // QT_CONFIG(combobox)
590 
591     if (qstrcmp(watched->metaObject()->className(),"QComboBoxPrivateContainer") == 0) {
592         if (event->type() == QEvent::Show) {
593             QWidget *widget = qobject_cast<QWidget*>(watched);
594             int yPopup = widget->geometry().top();
595             int yCombo = widget->parentWidget()->mapToGlobal(QPoint(0, 0)).y();
596             QRect geom = widget->geometry();
597             const QPixmapStyleDescriptor &desc = d->descriptors.value(DD_ButtonEnabled);
598             const bool up = yPopup < yCombo;
599             geom.moveTop(geom.top() + (up ? desc.margins.top() : -desc.margins.bottom()));
600             widget->setGeometry(geom);
601             widget->setProperty("_pixmapstyle_combobox_up", up);
602             widget->parentWidget()->setProperty("_pixmapstyle_combobox_up", up);
603         }
604     }
605 
606     return QCommonStyle::eventFilter(watched, event);
607 }
608 
609 /*!
610     \fn void QPixmapStyle::addDescriptor(QPixmapStyle::ControlDescriptor control, const QString &fileName, QMargins margins, QTileRules tileRules)
611 
612     Associates the pixmap having the given \a fileName with the given \a control. The \a margins parameter describe the boundaries
613     of the pixmap's top-left, top-right, bottom-left and bottom-right corners, as well as the left, right, top and bottorm segments
614     and the middle. The \a tileRules parameter describes how QPixmapStyle is supposed to handle the scaling of the center of the  pixmap.
615 
616     Use QPixmapStyle::addPixmap() for controls that are not resizable.
617 
618     \snippet styles/qcustompixmapstyle.cpp 1
619 
620     \sa addPixmap, copyDescriptor
621 
622 */
addDescriptor(QPixmapStyle::ControlDescriptor control,const QString & fileName,QMargins margins,QTileRules tileRules)623 void QPixmapStyle::addDescriptor(QPixmapStyle::ControlDescriptor control, const QString &fileName,
624                                  QMargins margins, QTileRules tileRules)
625 {
626     Q_D(QPixmapStyle);
627 
628     QPixmapStyleDescriptor desc;
629     QImage image(fileName);
630 
631     if (image.isNull())
632         return;
633 
634     desc.fileName = fileName;
635     desc.margins = margins;
636     desc.tileRules = tileRules;
637     desc.size = image.size();
638 
639     d->descriptors[control] = desc;
640 }
641 
642 /*!
643     \fn void QPixmapStyle::copyDescriptor(QPixmapStyle::ControlDescriptor source, QPixmapStyle::ControlDescriptor dest)
644 
645     Copies the data associated with the \a source descriptor to the \a dest descriptor.
646 
647     \snippet styles/qcustompixmapstyle.cpp 2
648 */
649 
copyDescriptor(QPixmapStyle::ControlDescriptor source,QPixmapStyle::ControlDescriptor dest)650 void QPixmapStyle::copyDescriptor(QPixmapStyle::ControlDescriptor source,
651                                   QPixmapStyle::ControlDescriptor dest)
652 {
653     Q_D(QPixmapStyle);
654     d->descriptors[dest] = d->descriptors.value(source);
655 }
656 
657 /*!
658     \fn void QPixmapStyle::drawCachedPixmap(QPixmapStyle::ControlDescriptor control, const QRect &rect, QPainter *painter) const
659 
660     Draws the image associated with the current \a control on the given \a rect using the given \a painter.
661 */
drawCachedPixmap(QPixmapStyle::ControlDescriptor control,const QRect & rect,QPainter * p) const662 void QPixmapStyle::drawCachedPixmap(QPixmapStyle::ControlDescriptor control, const QRect &rect,
663                                     QPainter *p) const
664 {
665     Q_D(const QPixmapStyle);
666     auto descriptor = d->descriptors.constFind(control);
667     if (descriptor == d->descriptors.constEnd())
668         return;
669     const QPixmap pix = d->getCachedPixmap(control, descriptor.value(), rect.size());
670     Q_ASSERT(!pix.isNull());
671     p->drawPixmap(rect, pix);
672 }
673 
674 /*!
675     \fn void QPixmapStyle::addPixmap(ControlPixmap control, const QString &fileName, QMargins margins)
676 
677     Use this function to style statically sized controls such as check boxes.
678 
679     \sa addDescriptor, copyPixmap
680 */
addPixmap(ControlPixmap control,const QString & fileName,QMargins margins)681 void QPixmapStyle::addPixmap(ControlPixmap control, const QString &fileName,
682                              QMargins margins)
683 {
684     Q_D(QPixmapStyle);
685 
686     QPixmapStylePixmap pix;
687     QPixmap image(fileName);
688 
689     if (image.isNull())
690         return;
691 
692     pix.pixmap = image;
693     pix.margins = margins;
694 
695     d->pixmaps[control] = pix;
696 }
697 
698 /*
699     \fn void QPixmapStyle::copyPixmap(QPixmapStyle::ControlPixmap source, QPixmapStyle::ControlPixmap dest)
700 
701     Copies the data associated with the \a source pixmap to the \a dest pixmap.
702 
703     \sa addPixmap, addDescriptor, copyDescriptor
704 */
copyPixmap(QPixmapStyle::ControlPixmap source,QPixmapStyle::ControlPixmap dest)705 void QPixmapStyle::copyPixmap(QPixmapStyle::ControlPixmap source, QPixmapStyle::ControlPixmap dest)
706 {
707     Q_D(QPixmapStyle);
708     d->pixmaps[dest] = d->pixmaps.value(source);
709 }
710 
711 /*!
712     \internal
713 
714     Constructs a QPixmapStyle object.
715 */
QPixmapStyle(QPixmapStylePrivate & dd)716 QPixmapStyle::QPixmapStyle(QPixmapStylePrivate &dd)
717     : QCommonStyle(dd)
718 {}
719 
drawPushButton(const QStyleOption * option,QPainter * painter,const QWidget *) const720 void QPixmapStyle::drawPushButton(const QStyleOption *option,
721                                   QPainter *painter, const QWidget *) const
722 {
723     const bool checked = option->state & State_On;
724     const bool pressed = option->state & State_Sunken;
725     const bool enabled = option->state & State_Enabled;
726 
727     ControlDescriptor control = PB_Enabled;
728     if (enabled)
729         control = pressed ? PB_Pressed : (checked ? PB_Checked : PB_Enabled);
730     else
731         control = checked ? PB_PressedDisabled : PB_Disabled;
732     drawCachedPixmap(control, option->rect, painter);
733 }
734 
drawLineEdit(const QStyleOption * option,QPainter * painter,const QWidget * widget) const735 void QPixmapStyle::drawLineEdit(const QStyleOption *option,
736                                 QPainter *painter, const QWidget *widget) const
737 {
738     // Don't draw for the line edit inside a combobox
739 #if QT_CONFIG(combobox)
740     if (widget && qobject_cast<const QComboBox*>(widget->parentWidget()))
741         return;
742 #else
743     Q_UNUSED(widget);
744 #endif
745     const bool enabled = option->state & State_Enabled;
746     const bool focused = option->state & State_HasFocus;
747     ControlDescriptor control = enabled ? (focused ? LE_Focused : LE_Enabled) : LE_Disabled;
748     drawCachedPixmap(control, option->rect, painter);
749 }
750 
drawTextEdit(const QStyleOption * option,QPainter * painter,const QWidget *) const751 void QPixmapStyle::drawTextEdit(const QStyleOption *option,
752                                 QPainter *painter, const QWidget *) const
753 {
754     const bool enabled = option->state & State_Enabled;
755     const bool focused = option->state & State_HasFocus;
756     ControlDescriptor control = enabled ? (focused ? TE_Focused : TE_Enabled) : TE_Disabled;
757     drawCachedPixmap(control, option->rect, painter);
758 }
759 
drawCheckBox(const QStyleOption * option,QPainter * painter,const QWidget *) const760 void QPixmapStyle::drawCheckBox(const QStyleOption *option,
761                                 QPainter *painter, const QWidget *) const
762 {
763     Q_D(const QPixmapStyle);
764 
765     const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton*>(option);
766 
767     const bool down = button->state & State_Sunken;
768     const bool enabled = button->state & State_Enabled;
769     const bool on = button->state & State_On;
770 
771     ControlPixmap control;
772     if (enabled)
773         control = on ? (down ? CB_PressedChecked : CB_Checked) : (down ? CB_Pressed : CB_Enabled);
774     else
775         control = on ? CB_DisabledChecked : CB_Disabled;
776     painter->drawPixmap(button->rect, d->pixmaps.value(control).pixmap);
777 }
778 
drawRadioButton(const QStyleOption * option,QPainter * painter,const QWidget *) const779 void QPixmapStyle::drawRadioButton(const QStyleOption *option,
780                                    QPainter *painter, const QWidget *) const
781 {
782     Q_D(const QPixmapStyle);
783 
784     const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton*>(option);
785 
786     const bool down = button->state & State_Sunken;
787     const bool enabled = button->state & State_Enabled;
788     const bool on = button->state & State_On;
789 
790     ControlPixmap control;
791     if (enabled)
792         control = on ? RB_Checked : (down ? RB_Pressed : RB_Enabled);
793     else
794         control = on ? RB_DisabledChecked : RB_Disabled;
795     painter->drawPixmap(button->rect, d->pixmaps.value(control).pixmap);
796 }
797 
drawPanelItemViewItem(const QStyleOption * option,QPainter * painter,const QWidget * widget) const798 void QPixmapStyle::drawPanelItemViewItem(const QStyleOption *option, QPainter *painter,
799                                          const QWidget *widget) const
800 {
801     Q_D(const QPixmapStyle);
802 
803     ControlPixmap cp = ID_Separator;
804     ControlDescriptor cd = ID_Selected;
805 
806     if (widget && widget->property("_pixmap_combobox_list").toBool()) {
807         cp = DD_ItemSeparator;
808         cd = DD_ItemSelected;
809     }
810 
811     QPixmap pix = d->pixmaps.value(cp).pixmap;
812     QRect rect = option->rect;
813     rect.setBottom(rect.top() + pix.height()-1);
814     painter->drawPixmap(rect, pix);
815     if (option->state & QStyle::State_Selected) {
816         rect = option->rect;
817         rect.setTop(rect.top() + pix.height());
818         drawCachedPixmap(cd, rect, painter);
819     }
820 }
821 
drawProgressBarBackground(const QStyleOption * option,QPainter * painter,const QWidget *) const822 void QPixmapStyle::drawProgressBarBackground(const QStyleOption *option,
823                                              QPainter *painter, const QWidget *) const
824 {
825     bool vertical = false;
826     if (const QStyleOptionProgressBar *pb =
827             qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
828         vertical = pb->orientation == Qt::Vertical;
829     }
830     drawCachedPixmap(vertical ? PB_VBackground : PB_HBackground, option->rect, painter);
831 }
832 
drawProgressBarLabel(const QStyleOption * option,QPainter * painter,const QWidget *) const833 void QPixmapStyle::drawProgressBarLabel(const QStyleOption *option,
834                                         QPainter *painter, const QWidget *) const
835 {
836     if (const QStyleOptionProgressBar *pb =
837                     qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
838         const bool vertical = pb->orientation == Qt::Vertical;
839         if (!vertical) {
840             QPalette::ColorRole textRole = QPalette::ButtonText;
841             proxy()->drawItemText(painter, pb->rect,
842                                   Qt::AlignCenter | Qt::TextSingleLine, pb->palette,
843                                   pb->state & State_Enabled, pb->text, textRole);
844         }
845     }
846 }
847 
drawProgressBarFill(const QStyleOption * option,QPainter * painter,const QWidget *) const848 void QPixmapStyle::drawProgressBarFill(const QStyleOption *option,
849                                        QPainter *painter, const QWidget *) const
850 {
851     const QStyleOptionProgressBar *pbar =
852                 qstyleoption_cast<const QStyleOptionProgressBar*>(option);
853     const bool vertical = pbar->orientation == Qt::Vertical;
854     const bool flip = (pbar->direction == Qt::RightToLeft) ^ pbar->invertedAppearance;
855 
856     if (pbar->progress == pbar->maximum) {
857         drawCachedPixmap(vertical ? PB_VComplete : PB_HComplete, option->rect, painter);
858 
859     } else {
860         if (pbar->progress == pbar->minimum)
861             return;
862         const auto totalSteps = qint64(pbar->maximum) - pbar->minimum;
863         const auto progressSteps = qint64(pbar->progress) - pbar->minimum;
864         const auto availablePixels = vertical ? option->rect.height() : option->rect.width();
865         const auto pixelsPerStep = double(availablePixels) / totalSteps;
866 
867         const auto progress = static_cast<int>(progressSteps * pixelsPerStep); // width in pixels
868 
869         QRect optRect = option->rect;
870         if (vertical) {
871             if (flip)
872                 optRect.setBottom(optRect.top()+progress-1);
873             else
874                 optRect.setTop(optRect.bottom()-progress+1);
875         } else {
876             if (flip)
877                 optRect.setLeft(optRect.right()-progress+1);
878             else
879                 optRect.setRight(optRect.left()+progress-1);
880         }
881 
882         drawCachedPixmap(vertical ? PB_VContent : PB_HContent, optRect, painter);
883     }
884 }
885 
drawSlider(const QStyleOptionComplex * option,QPainter * painter,const QWidget * widget) const886 void QPixmapStyle::drawSlider(const QStyleOptionComplex *option,
887                               QPainter *painter, const QWidget *widget) const
888 {
889 #if QT_CONFIG(slider)
890     Q_D(const QPixmapStyle);
891 
892     const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider*>(option);
893     if (!slider)
894         return;
895 
896     const bool enabled = option->state & State_Enabled;
897     const bool pressed = option->state & State_Sunken;
898     const Qt::Orientation orient = slider->orientation;
899 
900     const QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
901     if (option->subControls & SC_SliderGroove) {
902         QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
903         if (groove.isValid()) {
904             // Draw the background
905             ControlDescriptor control;
906             if (orient == Qt::Horizontal)
907                 control = enabled ? SG_HEnabled : SG_HDisabled;
908             else
909                 control = enabled ? SG_VEnabled : SG_VDisabled;
910             drawCachedPixmap(control, groove, painter);
911 
912             // Draw the active part
913             if (orient == Qt::Horizontal) {
914                 control = enabled ? (pressed ? SG_HActivePressed : SG_HActiveEnabled )
915                                   : SG_HActiveDisabled;
916             } else {
917                 control = enabled ? (pressed ? SG_VActivePressed : SG_VActiveEnabled )
918                                   : SG_VActiveDisabled;
919             }
920             const QPixmapStyleDescriptor &desc = d->descriptors.value(control);
921             const QPixmap pix = d->getCachedPixmap(control, desc, groove.size());
922             if (!pix.isNull()) {
923                 groove.setRight(orient == Qt::Horizontal
924                                ? handle.center().x() : handle.center().y());
925                 painter->drawPixmap(groove, pix, groove);
926             }
927         }
928     }
929     if (option->subControls & SC_SliderHandle) {
930         if (handle.isValid()) {
931             ControlPixmap pix;
932             if (orient == Qt::Horizontal)
933                 pix = enabled ? (pressed ? SH_HPressed : SH_HEnabled) : SH_HDisabled;
934             else
935                 pix = enabled ? (pressed ? SH_VPressed : SH_VEnabled) : SH_VDisabled;
936             painter->drawPixmap(handle, d->pixmaps.value(pix).pixmap);
937         }
938     }
939 #else
940     Q_UNUSED(option);
941     Q_UNUSED(painter);
942     Q_UNUSED(widget);
943 #endif // QT_CONFIG(slider)
944 }
945 
drawComboBox(const QStyleOptionComplex * option,QPainter * painter,const QWidget * widget) const946 void QPixmapStyle::drawComboBox(const QStyleOptionComplex *option,
947                                 QPainter *painter, const QWidget *widget) const
948 {
949     Q_D(const QPixmapStyle);
950 
951     const bool enabled = option->state & State_Enabled;
952     const bool pressed = widget->property("_pixmapstyle_combobox_pressed").toBool();
953     const bool opened = option->state & State_On;
954 
955     ControlDescriptor control =
956         enabled ? (pressed ? DD_ButtonPressed : DD_ButtonEnabled) : DD_ButtonDisabled;
957     drawCachedPixmap(control, option->rect, painter);
958 
959     ControlPixmap cp = enabled ? (opened ? DD_ArrowOpen
960                                     : (pressed ? DD_ArrowPressed : DD_ArrowEnabled))
961                                     : DD_ArrowDisabled;
962     QPixmapStylePixmap pix = d->pixmaps.value(cp);
963     QRect rect = comboBoxSubControlRect(option, SC_ComboBoxArrow, widget);
964     painter->drawPixmap(rect, pix.pixmap);
965 }
966 
drawScrollBar(const QStyleOptionComplex * option,QPainter * painter,const QWidget * widget) const967 void QPixmapStyle::drawScrollBar(const QStyleOptionComplex *option,
968                                  QPainter *painter, const QWidget *widget) const
969 {
970 #if QT_CONFIG(slider)
971     if (const QStyleOptionSlider *slider =
972                     qstyleoption_cast<const QStyleOptionSlider*>(option)) {
973         // Do not draw the scrollbar
974         if (slider->minimum == slider->maximum)
975             return;
976 
977         QRect rect = scrollBarSubControlRect(option, SC_ScrollBarSlider, widget);
978         ControlDescriptor control = slider->orientation == Qt::Horizontal
979                 ? SB_Horizontal : SB_Vertical;
980         drawCachedPixmap(control, rect, painter);
981     }
982 #else
983     Q_UNUSED(option);
984     Q_UNUSED(painter);
985     Q_UNUSED(widget);
986 #endif // QT_CONFIG(slider)
987 }
988 
pushButtonSizeFromContents(const QStyleOption * option,const QSize & contentsSize,const QWidget * widget) const989 QSize QPixmapStyle::pushButtonSizeFromContents(const QStyleOption *option,
990                                                const QSize &contentsSize,
991                                                const QWidget *widget) const
992 {
993     Q_D(const QPixmapStyle);
994 
995     const QPixmapStyleDescriptor &desc = d->descriptors.value(PB_Enabled);
996     const int bm = proxy()->pixelMetric(PM_ButtonMargin, option, widget);
997 
998     int w = contentsSize.width();
999     int h = contentsSize.height();
1000     w += desc.margins.left() + desc.margins.right() + bm;
1001     h += desc.margins.top() + desc.margins.bottom() + bm;
1002 
1003     return d->computeSize(desc, w, h);
1004 }
1005 
lineEditSizeFromContents(const QStyleOption * option,const QSize & contentsSize,const QWidget *) const1006 QSize QPixmapStyle::lineEditSizeFromContents(const QStyleOption *option,
1007                                              const QSize &contentsSize, const QWidget *) const
1008 {
1009     Q_D(const QPixmapStyle);
1010 
1011     const QPixmapStyleDescriptor &desc = d->descriptors.value(LE_Enabled);
1012     const int border = 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, option);
1013 
1014     int w = contentsSize.width() + border + desc.margins.left() + desc.margins.right();
1015     int h = contentsSize.height() + border + desc.margins.top() + desc.margins.bottom();
1016 
1017     return d->computeSize(desc, w, h);
1018 }
1019 
progressBarSizeFromContents(const QStyleOption * option,const QSize & contentsSize,const QWidget * widget) const1020 QSize QPixmapStyle::progressBarSizeFromContents(const QStyleOption *option,
1021                                                 const QSize &contentsSize,
1022                                                 const QWidget *widget) const
1023 {
1024     Q_D(const QPixmapStyle);
1025 
1026     bool vertical = false;
1027     if (const QStyleOptionProgressBar *pb =
1028                     qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
1029         vertical = pb->orientation == Qt::Vertical;
1030     }
1031     QSize result = QCommonStyle::sizeFromContents(CT_Slider, option, contentsSize, widget);
1032     if (vertical) {
1033         const QPixmapStyleDescriptor desc = d->descriptors.value(PB_VBackground);
1034         return QSize(desc.size.height(), result.height());
1035     } else {
1036         const QPixmapStyleDescriptor desc = d->descriptors.value(PB_HBackground);
1037         return QSize(result.width(), desc.size.height());
1038     }
1039 }
1040 
sliderSizeFromContents(const QStyleOption * option,const QSize & contentsSize,const QWidget * widget) const1041 QSize QPixmapStyle::sliderSizeFromContents(const QStyleOption *option,
1042                                            const QSize &contentsSize,
1043                                            const QWidget *widget) const
1044 {
1045 #if QT_CONFIG(slider)
1046     Q_D(const QPixmapStyle);
1047 
1048     const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider*>(option);
1049     if (!slider)
1050         return QSize();
1051 
1052     QSize result = QCommonStyle::sizeFromContents(CT_Slider, option, contentsSize, widget);
1053 
1054     const QPixmapStyleDescriptor desc = d->descriptors.value(slider->orientation == Qt::Horizontal
1055                                                 ? SG_HEnabled : SG_VEnabled);
1056 
1057     if (slider->orientation == Qt::Horizontal)
1058         return QSize(result.width(), desc.size.height());
1059     else
1060         return QSize(desc.size.width(), result.height());
1061 #else // QT_CONFIG(slider)
1062     Q_UNUSED(option);
1063     Q_UNUSED(contentsSize);
1064     Q_UNUSED(widget);
1065     return QSize();
1066 #endif // QT_CONFIG(slider)
1067 }
1068 
comboBoxSizeFromContents(const QStyleOption * option,const QSize & contentsSize,const QWidget * widget) const1069 QSize QPixmapStyle::comboBoxSizeFromContents(const QStyleOption *option,
1070                                              const QSize &contentsSize,
1071                                              const QWidget *widget) const
1072 {
1073     Q_D(const QPixmapStyle);
1074 
1075     const QPixmapStyleDescriptor &desc = d->descriptors.value(DD_ButtonEnabled);
1076 
1077     QSize result = QCommonStyle::sizeFromContents(CT_ComboBox, option, contentsSize, widget);
1078     return d->computeSize(desc, result.width(), result.height());
1079 }
1080 
itemViewSizeFromContents(const QStyleOption * option,const QSize & contentsSize,const QWidget * widget) const1081 QSize QPixmapStyle::itemViewSizeFromContents(const QStyleOption *option,
1082                                              const QSize &contentsSize,
1083                                              const QWidget *widget) const
1084 {
1085     Q_D(const QPixmapStyle);
1086 
1087     QSize size = QCommonStyle::sizeFromContents(CT_ItemViewItem, option, contentsSize, widget);
1088 
1089     ControlPixmap cp = ID_Separator;
1090     ControlDescriptor cd = ID_Selected;
1091     if (widget && widget->property("_pixmap_combobox_list").toBool()) {
1092         cp = DD_ItemSeparator;
1093         cd = DD_ItemSelected;
1094     }
1095 
1096     const QPixmapStyleDescriptor &desc = d->descriptors.value(cd);
1097     const QPixmapStylePixmap &pix = d->pixmaps.value(cp);
1098     size.setHeight(qMax(size.height(),
1099                         desc.size.height() + pix.pixmap.height()));
1100     return size;
1101 }
1102 
comboBoxSubControlRect(const QStyleOptionComplex * option,QStyle::SubControl sc,const QWidget *) const1103 QRect QPixmapStyle::comboBoxSubControlRect(const QStyleOptionComplex *option,
1104                                            QStyle::SubControl sc, const QWidget *) const
1105 {
1106     Q_D(const QPixmapStyle);
1107 
1108     QRect r = option->rect; // Default size
1109     const QPixmapStylePixmap &pix = d->pixmaps.value(DD_ArrowEnabled);
1110     const QPixmapStyleDescriptor &desc = d->descriptors.value(DD_ButtonEnabled);
1111 
1112     switch (sc) {
1113     case SC_ComboBoxArrow:
1114         r.setRect(r.right() - pix.margins.right() - pix.pixmap.width(),
1115                     r.top() + pix.margins.top(),
1116                     pix.pixmap.width(), pix.pixmap.height());
1117         break;
1118     case SC_ComboBoxEditField:
1119         r.adjust(desc.margins.left(), desc.margins.right(),
1120                  -desc.margins.right(), -desc.margins.bottom());
1121         r.setRight(r.right() - pix.margins.right() - pix.margins.left() - pix.pixmap.width());
1122         break;
1123     default:
1124         break;
1125     }
1126 
1127     r = visualRect(option->direction, option->rect, r);
1128     return r;
1129 }
1130 
scrollBarSubControlRect(const QStyleOptionComplex * option,QStyle::SubControl sc,const QWidget *) const1131 QRect QPixmapStyle::scrollBarSubControlRect(const QStyleOptionComplex *option,
1132                                             QStyle::SubControl sc, const QWidget *) const
1133 {
1134 #if QT_CONFIG(slider)
1135     if (const QStyleOptionSlider *slider =
1136                 qstyleoption_cast<const QStyleOptionSlider*>(option)) {
1137         int length = (slider->orientation == Qt::Horizontal)
1138                 ? slider->rect.width() : slider->rect.height();
1139         int page = length * slider->pageStep
1140                 / (slider->maximum - slider->minimum + slider->pageStep);
1141         int pos = length * slider->sliderValue
1142                 / (slider->maximum - slider->minimum + slider->pageStep);
1143         pos = qMin(pos+page, length) - page;
1144 
1145         QRect rect = slider->rect;
1146 
1147         if (slider->orientation == Qt::Horizontal) {
1148             switch (sc) {
1149             case SC_ScrollBarAddPage:
1150                 rect.setLeft(pos+page);
1151                 return rect;
1152             case SC_ScrollBarSubPage:
1153                 rect.setRight(pos);
1154                 return rect;
1155             case SC_ScrollBarGroove:
1156                 return rect;
1157             case SC_ScrollBarSlider:
1158                 rect.setLeft(pos);
1159                 rect.setRight(pos+page);
1160                 return rect;
1161             default: ;
1162             }
1163         } else {
1164             switch (sc) {
1165             case SC_ScrollBarAddPage:
1166                 rect.setTop(pos+page);
1167                 return rect;
1168             case SC_ScrollBarSubPage:
1169                 rect.setBottom(pos);
1170                 return rect;
1171             case SC_ScrollBarGroove:
1172                 return rect;
1173             case SC_ScrollBarSlider:
1174                 rect.setTop(pos);
1175                 rect.setBottom(pos+page);
1176                 return rect;
1177             default: ;
1178             }
1179         }
1180     }
1181 #else
1182     Q_UNUSED(option);
1183     Q_UNUSED(sc);
1184 #endif // QT_CONFIG(slider)
1185     return QRect();
1186 }
1187 
scale(int w,int h,const QPixmap & pixmap,const QPixmapStyleDescriptor & desc)1188 QPixmap QPixmapStylePrivate::scale(int w, int h, const QPixmap &pixmap, const QPixmapStyleDescriptor &desc)
1189 {
1190     QPixmap result(w, h);
1191     {
1192         const QColor transparent(0, 0, 0, 0);
1193         result.fill( transparent );
1194         QPainter p( &result );
1195         const QMargins margins = desc.margins;
1196         qDrawBorderPixmap(&p, result.rect(), margins, pixmap,
1197                           pixmap.rect(), margins, desc.tileRules);
1198     }
1199     return result;
1200 }
1201 
getCachedPixmap(QPixmapStyle::ControlDescriptor control,const QPixmapStyleDescriptor & desc,const QSize & size) const1202 QPixmap QPixmapStylePrivate::getCachedPixmap(QPixmapStyle::ControlDescriptor control,
1203                                              const QPixmapStyleDescriptor &desc,
1204                                              const QSize &size) const
1205 {
1206     Q_Q(const QPixmapStyle);
1207 
1208     const QString sizeString = QString::number(size.width()) % QLatin1Char('*')
1209             % QString::number(size.height());
1210     const QString key = QLatin1String(q->metaObject()->className()) % QString::number(control)
1211             % QLatin1Char('@') % sizeString;
1212 
1213     QPixmap result;
1214 
1215     if (!QPixmapCache::find( key, &result)) {
1216         QPixmap source(desc.fileName);
1217         result = scale(size.width(), size.height(), source, desc);
1218         QPixmapCache::insert(key, result);
1219     }
1220     return result;
1221 }
1222 
computeSize(const QPixmapStyleDescriptor & desc,int width,int height) const1223 QSize QPixmapStylePrivate::computeSize(const QPixmapStyleDescriptor &desc, int width, int height) const
1224 {
1225     if (desc.tileRules.horizontal != Qt::RepeatTile)
1226         width = qMax(width, desc.size.width());
1227     if (desc.tileRules.vertical != Qt::RepeatTile)
1228         height = qMax(height, desc.size.height());
1229     return QSize(width, height);
1230 }
1231 
1232 QT_END_NAMESPACE
1233