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 | */ |
107 | QPixmapStyle::QPixmapStyle() |
108 | : QCommonStyle(*new QPixmapStylePrivate) |
109 | { |
110 | } |
111 | |
112 | /*! |
113 | Destroys the QPixmapStyle object. |
114 | */ |
115 | QPixmapStyle::~QPixmapStyle() |
116 | { |
117 | } |
118 | |
119 | /*! |
120 | \reimp |
121 | */ |
122 | void QPixmapStyle::polish(QApplication *application) |
123 | { |
124 | QCommonStyle::polish(app: application); |
125 | } |
126 | |
127 | /*! |
128 | \reimp |
129 | */ |
130 | void QPixmapStyle::polish(QPalette &palette) |
131 | { |
132 | palette = proxy()->standardPalette(); |
133 | } |
134 | |
135 | /*! |
136 | \reimp |
137 | */ |
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*>(object: widget)) { |
145 | QPalette p = widget->palette(); |
146 | p.setBrush(acr: QPalette::Base, abrush: Qt::NoBrush); |
147 | widget->setPalette(p); |
148 | } |
149 | #endif |
150 | #if QT_CONFIG(progressbar) |
151 | if (QProgressBar *pb = qobject_cast<QProgressBar*>(object: 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(akey: PB_HBackground).size.height()/2); |
157 | pb->setFont(font); |
158 | } |
159 | #endif |
160 | #if QT_CONFIG(slider) |
161 | if (qobject_cast<QSlider*>(object: widget)) |
162 | widget->installEventFilter(filterObj: this); |
163 | #endif |
164 | #if QT_CONFIG(combobox) |
165 | if (QComboBox *cb = qobject_cast<QComboBox*>(object: widget)) { |
166 | widget->installEventFilter(filterObj: 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(name: "_pixmap_combobox_list" , value: true); |
171 | list->setItemDelegate(new QStyledItemDelegate(list)); |
172 | QPalette p = list->palette(); |
173 | p.setBrush(cg: QPalette::Active, cr: QPalette::Base, brush: QBrush(Qt::transparent) ); |
174 | p.setBrush(cg: QPalette::Active, cr: QPalette::AlternateBase, brush: QBrush(Qt::transparent) ); |
175 | p.setBrush(cg: QPalette::Inactive, cr: QPalette::Base, brush: QBrush(Qt::transparent) ); |
176 | p.setBrush(cg: QPalette::Inactive, cr: QPalette::AlternateBase, brush: QBrush(Qt::transparent) ); |
177 | p.setBrush(cg: QPalette::Disabled, cr: QPalette::Base, brush: QBrush(Qt::transparent) ); |
178 | p.setBrush(cg: QPalette::Disabled, cr: QPalette::AlternateBase, brush: QBrush(Qt::transparent) ); |
179 | list->setPalette(p); |
180 | |
181 | QFrame *frame = qobject_cast<QFrame*>(object: list->parent()); |
182 | if (frame) { |
183 | const QPixmapStyleDescriptor &desc = d->descriptors.value(akey: DD_PopupDown); |
184 | const QPixmapStylePixmap &pix = d->pixmaps.value(akey: DD_ItemSeparator); |
185 | frame->setContentsMargins(left: pix.margins.left(), top: desc.margins.top(), |
186 | right: pix.margins.right(), bottom: desc.margins.bottom()); |
187 | frame->setAttribute(Qt::WA_TranslucentBackground); |
188 | } |
189 | } |
190 | #endif // QT_CONFIG(combobox) |
191 | if (qstrcmp(str1: widget->metaObject()->className(),str2: "QComboBoxPrivateContainer" ) == 0) |
192 | widget->installEventFilter(filterObj: this); |
193 | |
194 | #if QT_CONFIG(scrollarea) |
195 | if (QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea*>(object: widget)) { |
196 | scrollArea->viewport()->setAutoFillBackground(false); |
197 | #if QT_CONFIG(itemviews) |
198 | if (QAbstractItemView *view = qobject_cast<QAbstractItemView*>(object: 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(target: scrollArea->viewport(), gestureType: QScroller::LeftMouseButtonGesture); |
205 | #endif |
206 | } |
207 | #endif // QT_CONFIG(scrollarea) |
208 | #if QT_CONFIG(scrollbar) |
209 | if (qobject_cast<QScrollBar*>(object: widget)) |
210 | widget->setAttribute(Qt::WA_OpaquePaintEvent, on: 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 | */ |
221 | void QPixmapStyle::unpolish(QApplication *application) |
222 | { |
223 | QCommonStyle::unpolish(application); |
224 | } |
225 | |
226 | /*! |
227 | \reimp |
228 | */ |
229 | void QPixmapStyle::unpolish(QWidget *widget) |
230 | { |
231 | if ( |
232 | #if QT_CONFIG(slider) |
233 | qobject_cast<QSlider*>(object: widget) |
234 | #else |
235 | false |
236 | #endif |
237 | #if QT_CONFIG(combobox) |
238 | || qobject_cast<QComboBox*>(object: widget) |
239 | #endif |
240 | ) { |
241 | widget->removeEventFilter(obj: this); |
242 | } |
243 | |
244 | if (qstrcmp(str1: widget->metaObject()->className(),str2: "QComboBoxPrivateContainer" ) == 0) |
245 | widget->removeEventFilter(obj: this); |
246 | |
247 | #if QT_CONFIG(gestures) && QT_CONFIG(scrollarea) && QT_CONFIG(scroller) |
248 | if (QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea*>(object: widget)) |
249 | QScroller::ungrabGesture(target: scrollArea->viewport()); |
250 | #endif |
251 | |
252 | QCommonStyle::unpolish(widget); |
253 | } |
254 | |
255 | /*! |
256 | \reimp |
257 | */ |
258 | 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*>(object: 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*>(object: widget)) |
288 | drawPanelItemViewItem(option, painter, widget); |
289 | else |
290 | #endif |
291 | QCommonStyle::drawPrimitive(pe: element, opt: option, p: painter, w: widget); |
292 | break; |
293 | default: |
294 | QCommonStyle::drawPrimitive(pe: element, opt: option, p: painter, w: widget); |
295 | } |
296 | } |
297 | |
298 | /*! |
299 | \reimp |
300 | */ |
301 | 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(str1: widget->metaObject()->className(),str2: "QComboBoxPrivateContainer" ) == 0) { |
319 | const QPixmapStyleDescriptor &desc = d->descriptors.value(akey: DD_PopupDown); |
320 | const QPixmapStylePixmap &pix = d->pixmaps.value(akey: DD_ItemSeparator); |
321 | QRect rect = option->rect; |
322 | rect.adjust(dx1: -pix.margins.left(), dy1: -desc.margins.top(), |
323 | dx2: pix.margins.right(), dy2: desc.margins.bottom()); |
324 | bool up = widget->property(name: "_pixmapstyle_combobox_up" ).toBool(); |
325 | drawCachedPixmap(control: up ? DD_PopupUp : DD_PopupDown, rect, p: painter); |
326 | } |
327 | else { |
328 | QCommonStyle::drawControl(element, opt: option, p: painter, w: widget); |
329 | } |
330 | break; |
331 | default: |
332 | QCommonStyle::drawControl(element, opt: option, p: painter, w: widget); |
333 | } |
334 | } |
335 | |
336 | /*! |
337 | \reimp |
338 | */ |
339 | 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, opt: option, p: painter, w: widget); |
354 | } |
355 | } |
356 | |
357 | /*! |
358 | \reimp |
359 | */ |
360 | 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(ct: type, opt: option, contentsSize, widget); |
380 | } |
381 | |
382 | /*! |
383 | \reimp |
384 | */ |
385 | 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(r: element, opt: option, widget); |
394 | const QPixmapStyleDescriptor &desc = d->descriptors.value(akey: LE_Enabled); |
395 | rect.adjust(dx1: desc.margins.left(), dy1: desc.margins.top(), |
396 | dx2: -desc.margins.right(), dy2: -desc.margins.bottom()); |
397 | rect = visualRect(direction: option->direction, boundingRect: option->rect, logicalRect: rect); |
398 | return rect; |
399 | } |
400 | default: ; |
401 | } |
402 | |
403 | return QCommonStyle::subElementRect(r: element, opt: option, widget); |
404 | } |
405 | |
406 | /*! |
407 | \reimp |
408 | */ |
409 | 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, opt: option, sc, w: widget); |
421 | } |
422 | |
423 | /*! |
424 | \reimp |
425 | */ |
426 | 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*>(object: widget)) { |
438 | const QPixmapStyleDescriptor &desc = d->descriptors.value(akey: LE_Enabled); |
439 | return qMax(a: qMax(a: desc.margins.left(), b: desc.margins.right()), |
440 | b: qMax(a: desc.margins.top(), b: desc.margins.bottom())); |
441 | } |
442 | #endif |
443 | return 0; |
444 | case PM_IndicatorWidth: |
445 | return d->pixmaps.value(akey: CB_Enabled).pixmap.width(); |
446 | case PM_IndicatorHeight: |
447 | return d->pixmaps.value(akey: CB_Enabled).pixmap.height(); |
448 | case PM_CheckBoxLabelSpacing: |
449 | { |
450 | const QPixmapStylePixmap &pix = d->pixmaps.value(akey: CB_Enabled); |
451 | return qMax(a: qMax(a: pix.margins.left(), b: pix.margins.right()), |
452 | b: qMax(a: pix.margins.top(), b: pix.margins.bottom())); |
453 | } |
454 | case PM_ExclusiveIndicatorWidth: |
455 | return d->pixmaps.value(akey: RB_Enabled).pixmap.width(); |
456 | case PM_ExclusiveIndicatorHeight: |
457 | return d->pixmaps.value(akey: RB_Enabled).pixmap.height(); |
458 | case PM_RadioButtonLabelSpacing: |
459 | { |
460 | const QPixmapStylePixmap &pix = d->pixmaps.value(akey: RB_Enabled); |
461 | return qMax(a: qMax(a: pix.margins.left(), b: pix.margins.right()), |
462 | b: qMax(a: pix.margins.top(), b: pix.margins.bottom())); |
463 | } |
464 | #if QT_CONFIG(slider) |
465 | case PM_SliderThickness: |
466 | if (const QStyleOptionSlider *slider = |
467 | qstyleoption_cast<const QStyleOptionSlider*>(opt: option)) { |
468 | const QPixmapStyleDescriptor desc = |
469 | d->descriptors.value(akey: 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*>(opt: option)) { |
478 | const QPixmapStylePixmap pix = |
479 | d->pixmaps.value(akey: 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*>(opt: option)) { |
488 | const QPixmapStylePixmap pix = |
489 | d->pixmaps.value(akey: 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*>(opt: option)) { |
498 | const QPixmapStyleDescriptor desc = |
499 | d->descriptors.value(akey: 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(m: metric, opt: option, widget); |
512 | } |
513 | |
514 | /*! |
515 | \reimp |
516 | */ |
517 | 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(sh: hint, opt: option, w: widget, shret: returnData); |
529 | } |
530 | |
531 | /*! |
532 | \reimp |
533 | */ |
534 | 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(cc: control, opt: option, pt: pos, w: 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 | */ |
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*>(object: 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*>(object: watched)) { |
570 | switch (event->type()) { |
571 | case QEvent::MouseButtonPress: |
572 | event->ignore(); |
573 | comboBox->setProperty(name: "_pixmapstyle_combobox_pressed" , value: true); |
574 | comboBox->repaint(); |
575 | return true; |
576 | case QEvent::MouseButtonRelease: |
577 | comboBox->setProperty(name: "_pixmapstyle_combobox_pressed" , value: 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(str1: watched->metaObject()->className(),str2: "QComboBoxPrivateContainer" ) == 0) { |
592 | if (event->type() == QEvent::Show) { |
593 | QWidget *widget = qobject_cast<QWidget*>(o: watched); |
594 | int = 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(akey: DD_ButtonEnabled); |
598 | const bool up = yPopup < yCombo; |
599 | geom.moveTop(pos: geom.top() + (up ? desc.margins.top() : -desc.margins.bottom())); |
600 | widget->setGeometry(geom); |
601 | widget->setProperty(name: "_pixmapstyle_combobox_up" , value: up); |
602 | widget->parentWidget()->setProperty(name: "_pixmapstyle_combobox_up" , value: 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 | */ |
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 | |
650 | void QPixmapStyle::copyDescriptor(QPixmapStyle::ControlDescriptor source, |
651 | QPixmapStyle::ControlDescriptor dest) |
652 | { |
653 | Q_D(QPixmapStyle); |
654 | d->descriptors[dest] = d->descriptors.value(akey: 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 | */ |
662 | 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(akey: control); |
667 | if (descriptor == d->descriptors.constEnd()) |
668 | return; |
669 | const QPixmap pix = d->getCachedPixmap(control, desc: descriptor.value(), size: rect.size()); |
670 | Q_ASSERT(!pix.isNull()); |
671 | p->drawPixmap(r: rect, pm: 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 | */ |
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 | */ |
705 | void QPixmapStyle::copyPixmap(QPixmapStyle::ControlPixmap source, QPixmapStyle::ControlPixmap dest) |
706 | { |
707 | Q_D(QPixmapStyle); |
708 | d->pixmaps[dest] = d->pixmaps.value(akey: source); |
709 | } |
710 | |
711 | /*! |
712 | \internal |
713 | |
714 | Constructs a QPixmapStyle object. |
715 | */ |
716 | QPixmapStyle::QPixmapStyle(QPixmapStylePrivate &dd) |
717 | : QCommonStyle(dd) |
718 | {} |
719 | |
720 | 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, rect: option->rect, p: painter); |
733 | } |
734 | |
735 | 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*>(object: 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, rect: option->rect, p: painter); |
749 | } |
750 | |
751 | 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, rect: option->rect, p: painter); |
758 | } |
759 | |
760 | 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*>(opt: 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(r: button->rect, pm: d->pixmaps.value(akey: control).pixmap); |
777 | } |
778 | |
779 | 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*>(opt: 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(r: button->rect, pm: d->pixmaps.value(akey: control).pixmap); |
796 | } |
797 | |
798 | 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(name: "_pixmap_combobox_list" ).toBool()) { |
807 | cp = DD_ItemSeparator; |
808 | cd = DD_ItemSelected; |
809 | } |
810 | |
811 | QPixmap pix = d->pixmaps.value(akey: cp).pixmap; |
812 | QRect rect = option->rect; |
813 | rect.setBottom(rect.top() + pix.height()-1); |
814 | painter->drawPixmap(r: rect, pm: pix); |
815 | if (option->state & QStyle::State_Selected) { |
816 | rect = option->rect; |
817 | rect.setTop(rect.top() + pix.height()); |
818 | drawCachedPixmap(control: cd, rect, p: painter); |
819 | } |
820 | } |
821 | |
822 | 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 *>(opt: option)) { |
828 | vertical = pb->orientation == Qt::Vertical; |
829 | } |
830 | drawCachedPixmap(control: vertical ? PB_VBackground : PB_HBackground, rect: option->rect, p: painter); |
831 | } |
832 | |
833 | void QPixmapStyle::drawProgressBarLabel(const QStyleOption *option, |
834 | QPainter *painter, const QWidget *) const |
835 | { |
836 | if (const QStyleOptionProgressBar *pb = |
837 | qstyleoption_cast<const QStyleOptionProgressBar *>(opt: option)) { |
838 | const bool vertical = pb->orientation == Qt::Vertical; |
839 | if (!vertical) { |
840 | QPalette::ColorRole textRole = QPalette::ButtonText; |
841 | proxy()->drawItemText(painter, rect: pb->rect, |
842 | flags: Qt::AlignCenter | Qt::TextSingleLine, pal: pb->palette, |
843 | enabled: pb->state & State_Enabled, text: pb->text, textRole); |
844 | } |
845 | } |
846 | } |
847 | |
848 | void QPixmapStyle::drawProgressBarFill(const QStyleOption *option, |
849 | QPainter *painter, const QWidget *) const |
850 | { |
851 | const QStyleOptionProgressBar *pbar = |
852 | qstyleoption_cast<const QStyleOptionProgressBar*>(opt: 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(control: vertical ? PB_VComplete : PB_HComplete, rect: option->rect, p: 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(control: vertical ? PB_VContent : PB_HContent, rect: optRect, p: painter); |
883 | } |
884 | } |
885 | |
886 | 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*>(opt: 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: CC_Slider, opt: option, sc: SC_SliderHandle, widget); |
901 | if (option->subControls & SC_SliderGroove) { |
902 | QRect groove = proxy()->subControlRect(cc: CC_Slider, opt: option, sc: 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, rect: groove, p: 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(akey: control); |
921 | const QPixmap pix = d->getCachedPixmap(control, desc, size: groove.size()); |
922 | if (!pix.isNull()) { |
923 | groove.setRight(orient == Qt::Horizontal |
924 | ? handle.center().x() : handle.center().y()); |
925 | painter->drawPixmap(targetRect: groove, pixmap: pix, sourceRect: 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(r: handle, pm: d->pixmaps.value(akey: 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 | |
946 | 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(name: "_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, rect: option->rect, p: painter); |
958 | |
959 | ControlPixmap cp = enabled ? (opened ? DD_ArrowOpen |
960 | : (pressed ? DD_ArrowPressed : DD_ArrowEnabled)) |
961 | : DD_ArrowDisabled; |
962 | QPixmapStylePixmap pix = d->pixmaps.value(akey: cp); |
963 | QRect rect = comboBoxSubControlRect(option, sc: SC_ComboBoxArrow, widget); |
964 | painter->drawPixmap(r: rect, pm: pix.pixmap); |
965 | } |
966 | |
967 | 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*>(opt: option)) { |
973 | // Do not draw the scrollbar |
974 | if (slider->minimum == slider->maximum) |
975 | return; |
976 | |
977 | QRect rect = scrollBarSubControlRect(option, sc: SC_ScrollBarSlider, widget); |
978 | ControlDescriptor control = slider->orientation == Qt::Horizontal |
979 | ? SB_Horizontal : SB_Vertical; |
980 | drawCachedPixmap(control, rect, p: painter); |
981 | } |
982 | #else |
983 | Q_UNUSED(option); |
984 | Q_UNUSED(painter); |
985 | Q_UNUSED(widget); |
986 | #endif // QT_CONFIG(slider) |
987 | } |
988 | |
989 | 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(akey: PB_Enabled); |
996 | const int bm = proxy()->pixelMetric(metric: 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, width: w, height: h); |
1004 | } |
1005 | |
1006 | 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(akey: LE_Enabled); |
1012 | const int border = 2 * proxy()->pixelMetric(metric: 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, width: w, height: h); |
1018 | } |
1019 | |
1020 | 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 *>(opt: option)) { |
1029 | vertical = pb->orientation == Qt::Vertical; |
1030 | } |
1031 | QSize result = QCommonStyle::sizeFromContents(ct: CT_Slider, opt: option, contentsSize, widget); |
1032 | if (vertical) { |
1033 | const QPixmapStyleDescriptor desc = d->descriptors.value(akey: PB_VBackground); |
1034 | return QSize(desc.size.height(), result.height()); |
1035 | } else { |
1036 | const QPixmapStyleDescriptor desc = d->descriptors.value(akey: PB_HBackground); |
1037 | return QSize(result.width(), desc.size.height()); |
1038 | } |
1039 | } |
1040 | |
1041 | 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*>(opt: option); |
1049 | if (!slider) |
1050 | return QSize(); |
1051 | |
1052 | QSize result = QCommonStyle::sizeFromContents(ct: CT_Slider, opt: option, contentsSize, widget); |
1053 | |
1054 | const QPixmapStyleDescriptor desc = d->descriptors.value(akey: 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 | |
1069 | 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(akey: DD_ButtonEnabled); |
1076 | |
1077 | QSize result = QCommonStyle::sizeFromContents(ct: CT_ComboBox, opt: option, contentsSize, widget); |
1078 | return d->computeSize(desc, width: result.width(), height: result.height()); |
1079 | } |
1080 | |
1081 | 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: CT_ItemViewItem, opt: option, contentsSize, widget); |
1088 | |
1089 | ControlPixmap cp = ID_Separator; |
1090 | ControlDescriptor cd = ID_Selected; |
1091 | if (widget && widget->property(name: "_pixmap_combobox_list" ).toBool()) { |
1092 | cp = DD_ItemSeparator; |
1093 | cd = DD_ItemSelected; |
1094 | } |
1095 | |
1096 | const QPixmapStyleDescriptor &desc = d->descriptors.value(akey: cd); |
1097 | const QPixmapStylePixmap &pix = d->pixmaps.value(akey: cp); |
1098 | size.setHeight(qMax(a: size.height(), |
1099 | b: desc.size.height() + pix.pixmap.height())); |
1100 | return size; |
1101 | } |
1102 | |
1103 | 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(akey: DD_ArrowEnabled); |
1110 | const QPixmapStyleDescriptor &desc = d->descriptors.value(akey: DD_ButtonEnabled); |
1111 | |
1112 | switch (sc) { |
1113 | case SC_ComboBoxArrow: |
1114 | r.setRect(ax: r.right() - pix.margins.right() - pix.pixmap.width(), |
1115 | ay: r.top() + pix.margins.top(), |
1116 | aw: pix.pixmap.width(), ah: pix.pixmap.height()); |
1117 | break; |
1118 | case SC_ComboBoxEditField: |
1119 | r.adjust(dx1: desc.margins.left(), dy1: desc.margins.right(), |
1120 | dx2: -desc.margins.right(), dy2: -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(direction: option->direction, boundingRect: option->rect, logicalRect: r); |
1128 | return r; |
1129 | } |
1130 | |
1131 | 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*>(opt: 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(a: pos+page, b: 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 | |
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( fillColor: transparent ); |
1194 | QPainter p( &result ); |
1195 | const QMargins margins = desc.margins; |
1196 | qDrawBorderPixmap(painter: &p, targetRect: result.rect(), targetMargins: margins, pixmap, |
1197 | sourceRect: pixmap.rect(), sourceMargins: margins, rules: desc.tileRules); |
1198 | } |
1199 | return result; |
1200 | } |
1201 | |
1202 | 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, pixmap: &result)) { |
1216 | QPixmap source(desc.fileName); |
1217 | result = scale(w: size.width(), h: size.height(), pixmap: source, desc); |
1218 | QPixmapCache::insert(key, pixmap: result); |
1219 | } |
1220 | return result; |
1221 | } |
1222 | |
1223 | QSize QPixmapStylePrivate::computeSize(const QPixmapStyleDescriptor &desc, int width, int height) const |
1224 | { |
1225 | if (desc.tileRules.horizontal != Qt::RepeatTile) |
1226 | width = qMax(a: width, b: desc.size.width()); |
1227 | if (desc.tileRules.vertical != Qt::RepeatTile) |
1228 | height = qMax(a: height, b: desc.size.height()); |
1229 | return QSize(width, height); |
1230 | } |
1231 | |
1232 | QT_END_NAMESPACE |
1233 | |