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