7#include <QtWidgets/qstyleoption.h>
8#include <QtWidgets/qstyle.h>
9#include <QtWidgets/qapplication.h>
10#if QT_CONFIG(scrollarea)
11# include <QtWidgets/qabstractscrollarea.h>
13#if QT_CONFIG(itemviews)
14# include <QtWidgets/qabstractitemview.h>
16#if QT_CONFIG(lineedit)
17# include <QtWidgets/qlineedit.h>
19#if QT_CONFIG(pushbutton)
20# include <QtWidgets/qpushbutton.h>
22#if QT_CONFIG(checkbox)
23# include <QtWidgets/qcheckbox.h>
25#if QT_CONFIG(radiobutton)
26# include <QtWidgets/qradiobutton.h>
28#if QT_CONFIG(combobox)
29# include <QtWidgets/qcombobox.h>
32# include <QtWidgets/qslider.h>
35# include <QtWidgets/qdial.h>
37#if QT_CONFIG(scrollbar)
38# include <QtWidgets/qscrollbar.h>
41# include <QtWidgets/qspinbox.h>
43#if QT_CONFIG(progressbar)
44# include <QtWidgets/qprogressbar.h>
46#if QT_CONFIG(textedit)
47# include <QtWidgets/qtextedit.h>
48# include <QtWidgets/qplaintextedit.h>
51# include <QtWidgets/qtabbar.h>
53#if QT_CONFIG(tabwidget)
54# include <QtWidgets/qtabwidget.h>
57# include <QtWidgets/qtoolbar.h>
59#if QT_CONFIG(toolbutton)
60# include <QtWidgets/qtoolbutton.h>
62#if QT_CONFIG(groupbox)
63# include <QtWidgets/qgroupbox.h>
66# include <QtWidgets/qmenu.h>
67# include <QtWidgets/qmenubar.h>
70# include <QtWidgets/qlabel.h>
72#include <QtWidgets/private/qwidget_p.h>
73#include <QtCore/private/qobject_p.h>
74#include <QtGui/qpainter.h>
75#include <QtGui/qpainterpath.h>
76#include <QtGui/qpainterstateguard.h>
77#include <QtGui/qstylehints.h>
78#include <QtCore/qloggingcategory.h>
79#include <QtCore/qnumeric.h>
80#include <QtQml/private/qqmlcomponent_p.h>
81#include <QtQml/qqmlengine.h>
82#include <QtQuick/private/qquicktransition_p.h>
83#include <QtLabsStyleKit/private/qqstylekit_p.h>
84#include <QtLabsStyleKit/private/qqstylekitcontrolproperties_p.h>
85#include <QtLabsStyleKit/private/qqstylekitstyle_p.h>
89Q_STATIC_LOGGING_CATEGORY(lcStyleKit,
"qt.labs.stylekit")
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
300
301
302
303
304
305
306
307
308
309
310
313
314
315
316
317
318
319
320
321
322
323
326
327
328
329
330
331
332
333
336
337
338
339
340
341
342
343
344
346static QQStyleKitReader::ControlType controlTypeForWidget(
const QWidget *widget)
349 return QQStyleKitReader::Control;
351#if QT_CONFIG(pushbutton)
352 if (qobject_cast<
const QPushButton *>(widget))
353 return QQStyleKitReader::Button;
355#if QT_CONFIG(checkbox)
356 if (qobject_cast<
const QCheckBox *>(widget))
357 return QQStyleKitReader::CheckBox;
359#if QT_CONFIG(radiobutton)
360 if (qobject_cast<
const QRadioButton *>(widget))
361 return QQStyleKitReader::RadioButton;
363#if QT_CONFIG(combobox)
364 if (qobject_cast<
const QComboBox *>(widget))
365 return QQStyleKitReader::ComboBox;
368 if (qobject_cast<
const QSlider *>(widget))
369 return QQStyleKitReader::Slider;
371#if QT_CONFIG(scrollbar)
372 if (qobject_cast<
const QScrollBar *>(widget))
373 return QQStyleKitReader::ScrollBar;
375#if QT_CONFIG(spinbox)
376 if (qobject_cast<
const QSpinBox *>(widget) || qobject_cast<
const QDoubleSpinBox *>(widget))
377 return QQStyleKitReader::SpinBox;
379#if QT_CONFIG(itemviews)
380 if (qobject_cast<
const QAbstractItemView *>(widget))
381 return QQStyleKitReader::ItemDelegate;
383#if QT_CONFIG(progressbar)
384 if (qobject_cast<
const QProgressBar *>(widget))
385 return QQStyleKitReader::ProgressBar;
387#if QT_CONFIG(lineedit)
388 if (qobject_cast<
const QLineEdit *>(widget))
389 return QQStyleKitReader::TextField;
391#if QT_CONFIG(textedit)
392 if (qobject_cast<
const QTextEdit *>(widget) || qobject_cast<
const QPlainTextEdit *>(widget))
393 return QQStyleKitReader::TextArea;
396 if (qobject_cast<
const QTabBar *>(widget))
397 return QQStyleKitReader::TabBar;
399#if QT_CONFIG(tabwidget)
400 if (qobject_cast<
const QTabWidget *>(widget))
401 return QQStyleKitReader::Page;
403#if QT_CONFIG(toolbar)
404 if (qobject_cast<
const QToolBar *>(widget))
405 return QQStyleKitReader::ToolBar;
407#if QT_CONFIG(toolbutton)
408 if (qobject_cast<
const QToolButton *>(widget))
409 return QQStyleKitReader::ToolButton;
411#if QT_CONFIG(groupbox)
412 if (qobject_cast<
const QGroupBox *>(widget))
413 return QQStyleKitReader::GroupBox;
416 if (qobject_cast<
const QMenuBar *>(widget))
417 return QQStyleKitReader::MenuBar;
418 if (qobject_cast<
const QMenu *>(widget))
419 return QQStyleKitReader::Menu;
421 if (widget->windowType() == Qt::Popup)
422 return QQStyleKitReader::Popup;
423 if (widget->windowType() == Qt::Dialog)
424 return QQStyleKitReader::Dialog;
425 if (widget->windowType() == Qt::Window)
426 return QQStyleKitReader::ApplicationWindow;
428 if (qobject_cast<
const QFrame *>(widget))
429 return QQStyleKitReader::Frame;
432 if (qobject_cast<
const QDial *>(widget))
433 return QQStyleKitReader::Dial;
435 return QQStyleKitReader::Control;
438#if QT_CONFIG(itemviews)
439static QQStyleKitReader::ControlType itemViewControlType(
const QStyleOption *opt)
441 const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt);
442 return itemViewOption && (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator)
443 ? QQStyleKitReader::ControlType::CheckDelegate
444 : QQStyleKitReader::ControlType::ItemDelegate;
453#if QT_CONFIG(scrollarea)
454 if (
const auto *area = qobject_cast<
const QAbstractScrollArea *>(widget))
455 return area->viewport();
457 return const_cast<QWidget *>(widget);
466 || qobject_cast<
const QLabel *>(widget)
468#if QT_CONFIG(textedit)
469 || qobject_cast<
const QTextEdit *>(widget)
470 || qobject_cast<
const QPlainTextEdit *>(widget)
472#if QT_CONFIG(lineedit)
473 || qobject_cast<
const QLineEdit *>(widget)
480#if QT_CONFIG(textedit)
481 if (
auto *textEdit = qobject_cast<QTextEdit *>(widget))
482 return textEdit->viewport();
483 if (
auto *plainTextEdit = qobject_cast<QPlainTextEdit *>(widget))
484 return plainTextEdit->viewport();
486#if QT_CONFIG(itemviews) && QT_CONFIG(combobox)
487 if (
auto *view = qobject_cast<QAbstractItemView *>(widget)) {
488 if (
auto *p = view->parentWidget(); p && p->inherits(
"QComboBoxPrivateContainer"))
489 return view->viewport();
498 const uint h = raw & Qt::AlignHorizontal_Mask;
499 const uint v = raw & Qt::AlignVertical_Mask;
500 result |= h ? h : uint(hDefault);
501 result |= v ? v : uint(vDefault);
507 return qMax(0.0, element->fillWidth() ? availableW : element->width());
512 return qMax(0.0, element->fillHeight() ? availableH : element->height());
517 using QtPrivate::qSaturateRound;
518 return QMargins(qSaturateRound(element->leftMargin()),
519 qSaturateRound(element->topMargin()),
520 qSaturateRound(element->rightMargin()),
521 qSaturateRound(element->bottomMargin()));
525
526
527
529 const QQStyleKitDelegateProperties *element,
535 const qreal scale = element->scale();
536 if (qFuzzyIsNull(scale))
539 const qreal rotation = element->rotation();
540 if (qFuzzyIsNull(rotation) && qFuzzyCompare(scale, 1.0))
543 const QPointF center = box.center();
544 painter->translate(center);
545 if (!qFuzzyIsNull(rotation))
546 painter->rotate(rotation);
547 if (!qFuzzyCompare(scale, 1.0))
548 painter->scale(scale, scale);
549 painter->translate(-center);
554static qreal dialAngle(
const QStyleOptionSlider *dial)
556 const qreal range = dial->maximum - dial->minimum;
557 qreal position = range > 0 ? (dial->sliderPosition - dial->minimum) / range : 0;
558 if (!dial->upsideDown)
559 position = 1 - position;
560 const qreal start = dial->dialWrapping ? -180 : -150;
561 return start + position * -2 * start;
564static QPointF dialHandleOffset(
const QRectF &backgroundRect,
const QQStyleKitDelegateProperties *handle)
567 return QPointF(handle->leftMargin() - handle->rightMargin(),
568 -qMin(backgroundRect.width(), backgroundRect.height()) / 2 + handle->height() / 2
569 + handle->topMargin() - handle->bottomMargin());
576#if QT_CONFIG(lineedit)
577 if (qobject_cast<
const QLineEdit *>(w)) {
579 QWidget *parent = w->parentWidget();
581# if QT_CONFIG(combobox)
582 || qobject_cast<
const QComboBox *>(parent)
584# if QT_CONFIG(spinbox)
585 || qobject_cast<
const QAbstractSpinBox *>(parent)
593#if QT_CONFIG(scrollarea)
594 if (
const QAbstractScrollArea *sa =
595 qobject_cast<
const QAbstractScrollArea *>(w->parentWidget())) {
596 if (sa->viewport() == w)
597 return w->parentWidget();
605 : QCommonStylePrivate()
611 if (filePath.startsWith(QLatin1Char(
':')))
612 return QUrl(QLatin1String(
"qrc") + filePath);
613 if (filePath.startsWith(QLatin1String(
"qrc:")) || filePath.startsWith(QLatin1String(
"file:")))
614 return QUrl(filePath);
615 return QUrl::fromLocalFile(filePath);
622 qmlEngine =
new QQmlEngine(q);
625 qWarning(
"QStyleKitStyle: No QML engine available to load style.");
628 const QUrl url = stylePath.isEmpty() ? QUrl() : urlFromStylePath(stylePath);
629 if (stylePath.isEmpty() || !url.isValid()) {
630 qWarning(
"QStyleKitStyle: No valid style path provided: %s", qPrintable(stylePath));
633 QQmlComponent component(qmlEngine, url);
634 if (component.isError()) {
635 qWarning(
"QStyleKitStyle: Failed to load style from %s: %s", qPrintable(stylePath),
636 qPrintable(component.errorString()));
641 QQmlComponentPrivate *componentPrivate = QQmlComponentPrivate::get(&component);
642 const auto compilationUnit = componentPrivate->compilationUnit();
643 const auto propertyCache = compilationUnit ? compilationUnit->rootPropertyCache() :
nullptr;
644 const auto firstMetaObject = propertyCache ? propertyCache->firstCppMetaObject() :
nullptr;
645 if (!firstMetaObject || !firstMetaObject->inherits(&QQStyleKitStyle::staticMetaObject)) {
646 qWarning(
"QStyleKitStyle: Failed to load style from %s: component is not a StyleKit Style.",
647 qPrintable(stylePath));
650 QQStyleKitStyle *styleObject = qobject_cast<QQStyleKitStyle *>(component.create());
652 qWarning(
"QStyleKitStyle: Failed to create style object from %s: "
653 "component is not a StyleKit style.",
654 qPrintable(stylePath));
657 const bool isReload = style !=
nullptr;
663 QObject::connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, q,
665 if (style && style->themeName() == QLatin1String(
"System")) {
666 style->recreateTheme();
673 QQStyleKitReader::resetReadersForStyle(style);
679
680
681
689 qmlEngine =
new QQmlEngine(q);
691 QQmlComponent component(qmlEngine);
692 component.loadFromModule(
"Qt.labs.StyleKit",
"Style");
693 if (component.isError()) {
694 qWarning(
"QStyleKitStyle: Failed to create default fallback style: %s",
695 qPrintable(component.errorString()));
698 defaultStyle = qobject_cast<QQStyleKitStyle *>(component.create());
700 defaultStyle->setParent(q);
702 "No style set; using a default fallback style. "
703 "Set stylePath to load a StyleKit Style.");
709
710
711
714 return style ? style : defaultStyle;
721 QQStyleKitStyle *effective = effectiveStyle();
723 if (sharedReader && sharedReader->style() != effective)
724 sharedReader->setExplicitStyle(effective);
726 if (subElementReader && subElementReader->style() != effective)
727 subElementReader->setExplicitStyle(effective);
729 clearAllSubElements();
731 for (
auto *wr : std::as_const(widgetReaders)) {
732 if (wr->style() != effective)
733 wr->setExplicitStyle(effective);
736 if (!QWidgetPrivate::allWidgets)
739 for (
auto *widget : std::as_const(*QWidgetPrivate::allWidgets)) {
740 if (customFontWidgets.contains(widget))
741 unsetStyleFont(widget);
742 refreshStyleFont(widget);
743 if (customPaletteWidgets.contains(widget))
744 unsetStylePalette(widget);
745 refreshStylePalette(widget);
746 refreshStyleMinimumSize(widget);
749 QEvent styleChange(QEvent::StyleChange);
750 for (
auto *widget : std::as_const(*QWidgetPrivate::allWidgets)) {
751 QApplication::sendEvent(widget, &styleChange);
761 if (!qobject_cast<QDial *>(widget))
763 const auto resolved = resolveLayout(QQStyleKitReader::ControlType::Dial, QStyle::State_Enabled);
764 if (!resolved.isValid())
766 const auto &m = *resolved.metrics;
767 const QSize styleSize(m.bgImplicitSize.width() + m.margins.left() + m.margins.right(),
768 m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom());
770 auto it = customMinimumSizeWidgets.find(widget);
771 if (it == customMinimumSizeWidgets.end()) {
772 it = customMinimumSizeWidgets.insert(widget, widget->minimumSize());
773 QObject::connect(widget, &QObject::destroyed, widget,
774 [
this, widget]() { customMinimumSizeWidgets.remove(widget); });
776 widget->setMinimumSize(it.value().expandedTo(styleSize));
784 const auto it = customMinimumSizeWidgets.constFind(widget);
785 if (it == customMinimumSizeWidgets.cend())
787 const QSize original = it.value();
788 customMinimumSizeWidgets.erase(it);
789 widget->setMinimumSize(original);
795 auto it = customFontWidgets.find(widget);
796 if (it == customFontWidgets.end())
799 auto customFont =
std::move(*it);
800 customFontWidgets.erase(it);
801 widget->setFont(
std::move(customFont).reverted(QWidgetPrivate::get(widget)->localFont()));
806 if (!effectiveStyle() || !widget)
809 const auto styleMask = styleFont.resolveMask();
810 auto it = customFontWidgets.find(widget);
812 if (it == customFontWidgets.end()) {
815 it = customFontWidgets.insert(widget, { QWidgetPrivate::get(widget)->localFont(), 0 });
816 QObject::connect(widget, &QObject::destroyed, widget,
817 [
this, widget]() { customFontWidgets.remove(widget); });
820 it->resolveMask = styleMask;
822 const QFont &baseline = it->oldWidgetValue;
823 QFont merged = styleFont.resolve(baseline);
824 merged.setResolveMask(baseline.resolveMask() | styleMask);
825 widget->setFont(merged);
830 if (!effectiveStyle() || !widget)
833 const QWidget *targetWidget = containerWidget(widget);
834 QQStyleKitReader::ControlType controlType = controlTypeForWidget(targetWidget);
836 auto *shared = ensureSharedReader();
841 opt.initFrom(targetWidget);
842 const QQSK::State currentState = resolvedStateFor(controlType, opt.state, targetWidget);
844 shared->setControlTypeAndState(controlType, currentState,
false);
845 setStyleFont(widget, shared->font());
850 auto it = customPaletteWidgets.find(widget);
851 if (it == customPaletteWidgets.end())
854 auto customPalette =
std::move(*it);
855 customPaletteWidgets.erase(it);
856 widget->setPalette(
std::move(customPalette).reverted(widget->palette()));
861 if (!effectiveStyle() || !widget)
864 const quint64 styleMask = stylePalette.resolveMask();
868 if (!customPaletteWidgets.contains(widget)) {
869 customPaletteWidgets.insert(widget, { widget->palette(), 0 });
870 QObject::connect(widget, &QObject::destroyed, widget,
871 [
this, widget]() { customPaletteWidgets.remove(widget); });
874 customPaletteWidgets[widget].resolveMask |= styleMask;
875 QPalette merged = stylePalette.resolve(widget->palette());
876 merged.setResolveMask(widget->palette().resolveMask() | styleMask);
877 widget->setPalette(merged);
884 if (!effectiveStyle() || !widget)
887 const bool isWindow = widget->windowType() & (Qt::Popup | Qt::Window | Qt::Dialog);
888 const bool isPaletteManaged = isSelfPaintingWidget(widget) || isWindow;
889 if (!isPaletteManaged)
892 const QWidget *targetWidget = containerWidget(widget);
893 QQStyleKitReader::ControlType controlType = controlTypeForWidget(targetWidget);
895 auto *shared = ensureSharedReader();
900 opt.initFrom(targetWidget);
901 const QQSK::State currentState = resolvedStateFor(controlType, opt.state, targetWidget);
903 QPalette stylePalette;
906 shared->setControlTypeAndState(controlType, currentState,
false);
907 if (
const auto *bg = shared->global()->background();
908 bg && bg->isDefined(QQSK::Property::Color)) {
909 stylePalette.setColor(QPalette::Window, bg->color());
911 shared->setControlTypeAndState(controlType, QQSK::StateFlag::Disabled,
false);
912 if (
const auto *dbg = shared->global()->background();
913 dbg && dbg->isDefined(QQSK::Property::Color)) {
914 stylePalette.setColor(QPalette::Disabled, QPalette::Window, dbg->color());
919 shared->setControlTypeAndState(controlType, currentState,
false);
920 if (
const auto *text = shared->global()->text();
921 text && text->isDefined(QQSK::Property::Color)) {
922 stylePalette.setColor(QPalette::Text, text->color());
923 stylePalette.setColor(QPalette::WindowText, text->color());
925 shared->setControlTypeAndState(controlType, QQSK::StateFlag::Disabled,
false);
926 if (
const auto *dt = shared->global()->text();
927 dt && dt->isDefined(QQSK::Property::Color)) {
928 stylePalette.setColor(QPalette::Disabled, QPalette::Text, dt->color());
929 stylePalette.setColor(QPalette::Disabled, QPalette::WindowText, dt->color());
933 setStylePalette(widget, stylePalette);
937
938
941 Q_Q(
const QStyleKitStyle);
942 QQStyleKitStyle *effective = effectiveStyle();
943 if (!effective || !widget)
946 if (
auto it = widgetReaders.find(widget); it != widgetReaders.end())
949 auto *widgetReader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
950 widgetReader->setExplicitStyle(effective);
951 widgetReader->setTarget(paintTarget(widget));
952 widgetReader->setControlType(controlTypeForWidget(widget));
953 widgetReader->setCompleted(
true);
954 widgetReaders.insert(widget, widgetReader);
955 QObjectPrivate::connect(widget, &QObject::destroyed,
this,
956 &QStyleKitStylePrivate::onWidgetDestroyed, Qt::UniqueConnection);
962 if (
auto *reader = widgetReaders.take(widget))
963 reader->deleteLater();
964 cleanupSubElements(widget);
969 cleanupWidgetReader(
static_cast<QWidget *>(w));
973
974
975
976
984#if QT_CONFIG(itemviews)
985 if (
const auto *viewOpt = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
986 const QModelIndex &idx = viewOpt->index;
990 key.id = SubElementKey::ItemViewCell{ idx.model(), idx.internalId(), idx.row(),
996 if (
const auto *menuOpt = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
997 if (menuOpt->menuItemType == QStyleOptionMenuItem::Separator)
999 QAction *action =
nullptr;
1000 if (
const auto *menu = qobject_cast<
const QMenu *>(widget))
1001 action = menu->actionAt(menuOpt->rect.center());
1002 else if (
const auto *menuBar = qobject_cast<
const QMenuBar *>(widget))
1003 action = menuBar->actionAt(menuOpt->rect.center());
1005 key.widget = widget;
1006 key.id = SubElementKey::Action{ action };
1011#if QT_CONFIG(tabbar)
1012 if (
const auto *tabOpt = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
1013 if (tabOpt->tabIndex < 0)
1015 key.widget = widget;
1016 key.id = SubElementKey::Tab{ tabOpt->tabIndex };
1024
1025
1026
1027
1029 const SubElementKey &key, QQStyleKitReader::ControlType type, QQSK::State fromState,
1030 QQSK::State toState, QQuickTransition *transition)
const
1032 Q_Q(
const QStyleKitStyle);
1033 QQStyleKitStyle *effective = effectiveStyle();
1039 for (
auto it = subElementAnimationReaders.begin(); it != subElementAnimationReaders.end();) {
1040 const QQuickTransition *t = it.value()->transition();
1041 if (!t || !t->running()) {
1042 it.value()->deleteLater();
1043 it = subElementAnimationReaders.erase(it);
1050 if (subElementAnimationReaders.size() >= kMaxSubElementAnimationReaders) {
1051 const auto it = subElementAnimationReaders.begin();
1052 if (
const QWidget *widget = it.key().widget)
1053 paintTarget(widget)->update();
1054 it.value()->deleteLater();
1055 subElementAnimationReaders.erase(it);
1058 auto *reader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
1059 reader->setExplicitStyle(effective);
1060 reader->setTarget(paintTarget(key.widget));
1062 reader->setControlTypeAndState(type, fromState);
1063 reader->setCompleted(
true);
1067 reader->background();
1068 auto *indicator = reader->indicator();
1069 indicator->first()->foreground();
1070 indicator->second()->foreground();
1072 reader->setControlTypeAndState(type, toState);
1073 if (!transition || !transition->running()) {
1074 reader->deleteLater();
1077 subElementAnimationReaders.insert(key, reader);
1082
1083
1086 for (
auto it = subElementStates.begin(); it != subElementStates.end();) {
1087 if (it.key().widget == widget)
1088 it = subElementStates.erase(it);
1092 for (
auto it = subElementAnimationReaders.begin(); it != subElementAnimationReaders.end();) {
1093 if (it.key().widget == widget) {
1094 it.value()->deleteLater();
1095 it = subElementAnimationReaders.erase(it);
1103
1104
1107 subElementStates.clear();
1108 for (QQStyleKitReader *reader : std::as_const(subElementAnimationReaders))
1109 reader->deleteLater();
1110 subElementAnimationReaders.clear();
1114
1115
1116
1118 QStyle::State state,
1119 const QWidget *widget)
const
1122 flags.setFlag(QQSK::StateFlag::Hovered, (state & QStyle::State_MouseOver));
1123 flags.setFlag(QQSK::StateFlag::Pressed, state & QStyle::State_Sunken);
1124 flags.setFlag(QQSK::StateFlag::Checked, state & QStyle::State_On);
1125 flags.setFlag(QQSK::StateFlag::Focused, state & QStyle::State_HasFocus);
1126 flags.setFlag(QQSK::StateFlag::Highlighted, state & QStyle::State_Selected);
1128 bool hasOrientation =
false;
1130 case QQStyleKitReader::ProgressBar:
1131 case QQStyleKitReader::ScrollBar:
1132 case QQStyleKitReader::ScrollIndicator:
1133 case QQStyleKitReader::Slider:
1134 case QQStyleKitReader::ToolBar:
1135 case QQStyleKitReader::ToolSeparator:
1136 hasOrientation =
true;
1142 flags.setFlag(QQSK::StateFlag::Vertical, !(state & QStyle::State_Horizontal));
1146 const bool enabled = (state & QStyle::State_Enabled) || (widget && widget->isEnabled());
1147 flags.setFlag(QQSK::StateFlag::Disabled, !enabled);
1151 if (type == QQStyleKitReader::ControlType::ComboBox)
1152 flags.setFlag(QQSK::StateFlag::Checked,
false);
1155 if (type == QQStyleKitReader::ControlType::Popup)
1156 flags.setFlag(QQSK::StateFlag::Hovered,
false);
1159 if (type == QQStyleKitReader::ControlType::TabButton) {
1160 flags.setFlag(QQSK::StateFlag::Checked, state & QStyle::State_Selected);
1161 flags.setFlag(QQSK::StateFlag::Highlighted,
false);
1168
1169
1170
1171const QStyleKitStylePrivate::ControlMetrics &
1174 if (
auto it = metricsCache.find({ type, state }); it != metricsCache.end())
1177 auto *reader = ensureSharedReader();
1179 reader->setControlTypeAndState(type, state,
false);
1180 return *metricsCache.insert({ type, state }, metricsForReader(reader));
1184
1185
1186
1189 QStyle::State state)
const
1191 QQStyleKitResolved out;
1194 auto *reader = readerForWidget(w);
1198 const QQSK::State resolvedState = resolvedStateFor(type, state, w);
1199 reader->setControlTypeAndState(type, resolvedState);
1201 out.reader = reader;
1202 out.metrics = &metricsFor(type, resolvedState);
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1220 QQStyleKitReader::ControlType type, QStyle::State state,
1223 QQStyleKitResolved out;
1226 auto *steadyReader = ensureSubElementReader();
1230 const QQSK::State newState = resolvedStateFor(type, state, w);
1231 const SubElementKey key = subElementKeyForOption(opt, w);
1233 QQStyleKitReader *reader =
nullptr;
1234 if (track && key.isValid()) {
1235 QQStyleKitReader *animReader = subElementAnimationReaders.value(key);
1236 const auto it = subElementStates.constFind(key);
1237 const bool seen = it != subElementStates.cend();
1241 constexpr QQSK::State InteractiveStates = QQSK::State(QQSK::StateFlag::Hovered)
1242 | QQSK::StateFlag::Pressed | QQSK::StateFlag::Checked
1243 | QQSK::StateFlag::Focused | QQSK::StateFlag::Highlighted;
1244 const auto baseState = newState & ~InteractiveStates;
1245 const QQSK::State prevState = seen ? *it : baseState;
1246 if (prevState != newState) {
1251 animReader->setControlTypeAndState(type, newState);
1256 const bool shouldAnimate = seen || newState.testFlag(QQSK::StateFlag::Hovered)
1257 || newState.testFlag(QQSK::StateFlag::Pressed);
1258 if (shouldAnimate) {
1259 steadyReader->setControlTypeAndState(type, newState);
1260 if (QQuickTransition *transition = steadyReader->transition())
1261 animReader = startSubElementTransition(key, type, prevState,
1262 newState, transition);
1266 if (!seen || prevState != newState) {
1267 QObjectPrivate::connect(w, &QObject::destroyed,
this,
1268 &QStyleKitStylePrivate::onWidgetDestroyed,
1269 Qt::UniqueConnection);
1270 if (subElementStates.size() >= kMaxSubElementStates)
1271 subElementStates.clear();
1272 subElementStates.insert(key, newState);
1274 reader = animReader;
1278 reader = steadyReader;
1279 reader->setControlTypeAndState(type, newState);
1281 out.reader = reader;
1282 out.metrics = &metricsFor(type, newState);
1288 return reader ? reader->text() :
nullptr;
1293 return reader ? reader->background() :
nullptr;
1298 return reader ? reader->handle() :
nullptr;
1303 return reader ? reader->indicator() :
nullptr;
1308 return reader ? reader->font() : QFont();
1314 return sharedReader;
1316 Q_Q(
const QStyleKitStyle);
1317 QQStyleKitStyle *effective = effectiveStyle();
1320 sharedReader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
1322 sharedReader->setTransitionsEnabled(
false);
1323 sharedReader->setExplicitStyle(effective);
1324 sharedReader->setCompleted(
true);
1325 return sharedReader;
1330 if (subElementReader)
1331 return subElementReader;
1333 Q_Q(
const QStyleKitStyle);
1334 QQStyleKitStyle *effective = effectiveStyle();
1337 subElementReader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
1340 subElementReader->setTransitionsEnabled(
false);
1341 subElementReader->setExplicitStyle(effective);
1342 subElementReader->setCompleted(
true);
1343 return subElementReader;
1347
1348
1349
1350
1354 QQStyleKitLayoutResolved out;
1355 auto *reader = ensureSharedReader();
1359 const QQSK::State resolvedState = resolvedStateFor(type, state);
1360 out.metrics = &metricsFor(type, resolvedState);
1364 reader->setControlTypeAndState(type, resolvedState,
false);
1365 out.staticProps = reader->global();
1366 out.staticFont = reader->font();
1372 return staticProps ? staticProps->text() :
nullptr;
1375const QQStyleKitDelegateProperties *
1378 return staticProps ? staticProps->background() :
nullptr;
1383 return staticProps ? staticProps->handle() :
nullptr;
1389 return staticProps ? staticProps->indicator() :
nullptr;
1394 metricsCache.clear();
1398 const QRectF &rect, QPainter *painter)
const
1400 if (!indicator || !indicator->visible() || indicator->opacity() <= 0 || !rect.isValid())
1406 QPainterStateGuard stateGuard(painter);
1407 if (!applyDelegateTransform(painter, indicator, rect))
1411 QRectF indicatorRect = rect;
1412 drawStyledItemContents(indicator, indicatorRect, painter);
1414 const QQStyleKitDelegateProperties *foreground =
nullptr;
1415 if (
auto *indicatorWithSubTypes =
1416 qobject_cast<
const QQStyleKitIndicatorWithSubTypes *>(indicator)) {
1417 foreground = indicatorWithSubTypes->foreground();
1418 }
else if (
auto *indicatorProps =
1419 qobject_cast<
const QQStyleKitIndicatorProperties *>(indicator)) {
1420 foreground = indicatorProps->foreground();
1424 if (!foreground || !foreground->visible() || foreground->opacity() <= 0)
1428 QRectF foregroundRect;
1429 const uint foregroundAlign = resolvedAlignment(foreground->alignment(), Qt::AlignHCenter,
1431 const auto foregroundW = resolvedWidth(
1432 foreground, indicatorRect.width() - foreground->leftMargin() - foreground->rightMargin());
1433 const auto foregroundH = resolvedHeight(
1434 foreground, indicatorRect.height() - foreground->topMargin() - foreground->bottomMargin());
1435 foregroundRect.setSize(QSizeF(foregroundW, foregroundH));
1436 if (foregroundAlign & Qt::AlignLeft)
1437 foregroundRect.moveLeft(indicatorRect.left() + foreground->leftMargin());
1438 else if (foregroundAlign & Qt::AlignHCenter)
1439 foregroundRect.moveLeft(indicatorRect.left() + (indicatorRect.width() - foregroundW) / 2.0);
1440 else if (foregroundAlign & Qt::AlignRight)
1441 foregroundRect.moveLeft(indicatorRect.right() - foreground->rightMargin() - foregroundW);
1442 if (foregroundAlign & Qt::AlignTop)
1443 foregroundRect.moveTop(indicatorRect.top() + foreground->topMargin());
1444 else if (foregroundAlign & Qt::AlignVCenter)
1445 foregroundRect.moveTop(indicatorRect.top() + (indicatorRect.height() - foregroundH) / 2.0);
1446 else if (foregroundAlign & Qt::AlignBottom)
1447 foregroundRect.moveTop(indicatorRect.bottom() - foreground->bottomMargin() - foregroundH);
1448 drawStyledItemRect(foreground, foregroundRect, painter);
1452 const QFont &font,
const QRect &rect,
1453 const QString &text, uint textFlags, QPainter *p,
1454 Qt::Alignment defaultAlignment)
const
1456 uint flags = textFlags;
1458 ? resolvedAlignment(textProps->alignment(), defaultAlignment & Qt::AlignHorizontal_Mask,
1459 defaultAlignment & Qt::AlignVertical_Mask)
1460 : uint(defaultAlignment);
1462 const QFont oldFont = p->font();
1463 p->setFont(font.resolve(oldFont));
1464 p->setBrush(Qt::NoBrush);
1465 p->setPen(textProps ? textProps->color() : QColor());
1466 p->drawText(rect, flags, text,
nullptr);
1470 const QRectF &rect, QPainter *painter)
const
1472 if (!props || !props->visible() || props->opacity() <= 0 || !rect.isValid())
1475 QPainterStateGuard stateGuard(painter);
1476 if (!applyDelegateTransform(painter, props, rect))
1478 drawStyledItemContents(props, rect, painter);
1482 const QRectF &rect, QPainter *painter)
const
1484 if (!props || !props->visible() || props->opacity() <= 0 || !rect.isValid())
1487 QPainterStateGuard stateGuard(painter);
1488 painter->setRenderHint(QPainter::Antialiasing,
true);
1490 painter->setClipping(
true);
1493 const auto opacity = props->opacity();
1496 const auto *border = props->border();
1497 auto borderWidth = 0;
1501 borderWidth = border->width();
1502 borderColor = border->color();
1503 inset = borderWidth / 2.0;
1505 if (borderWidth > 0 && borderColor.isValid() && borderColor.alpha() > 0) {
1506 QPen pen(borderColor, borderWidth);
1507 painter->setPen(pen);
1509 painter->setPen(Qt::NoPen);
1514 const qreal minDimension = qMin(rect.width(), rect.height());
1515 const qreal xRadius = qMax(0.0, qMin(props->topLeftRadius() - inset, minDimension / 2.0));
1516 const qreal yRadius = qMax(0.0, qMin(props->bottomLeftRadius() - inset, minDimension / 2.0));
1518 QRectF adjustedRect = rect.adjusted(inset, inset, -inset, -inset);
1522 QColor color = props->color();
1523 QBrush colorBrush(color);
1524 painter->setBrush(colorBrush);
1525 if (color.isValid()) {
1526 painter->setOpacity(opacity);
1527 painter->drawRoundedRect(adjustedRect, xRadius, yRadius, Qt::AbsoluteSize);
1529 if (QQuickGradient *gradient = props->gradient()) {
1530 QLinearGradient linearGradient(rect.topLeft(), rect.bottomLeft());
1531 QQmlListProperty<QQuickGradientStop> stops = gradient->stops();
1532 const int stopCount = stops.count(&stops);
1533 for (
int i = 0; i < stopCount; i++) {
1534 QQuickGradientStop *stop =
static_cast<QQuickGradientStop *>(stops.at(&stops, i));
1535 linearGradient.setColorAt(stop->position(), stop->color());
1537 QBrush gradientBrush(linearGradient);
1538 painter->setBrush(gradientBrush);
1539 painter->setOpacity(opacity);
1540 painter->drawRoundedRect(adjustedRect, xRadius, yRadius, Qt::AbsoluteSize);
1544 drawStyledItemImage(props->image(), adjustedRect, opacity, painter);
1548 const QRectF &rect, qreal opacity,
1549 QPainter *painter)
const
1551 if (!image || image->source().isEmpty() || image->color().alpha() <= 0)
1554 QString imageSource = image->source().toString();
1555 if (imageSource.startsWith(QLatin1String(
"qrc:/")))
1556 imageSource = imageSource.mid(3);
1557 QUrl imageUrl(imageSource);
1558 QString imagePath = imageUrl.isLocalFile() ? imageUrl.toLocalFile() : imageSource;
1559 QPixmap pixmap(imagePath);
1560 if (pixmap.isNull())
1563 if (image->color().isValid()) {
1564 QImage coloredImage = pixmap.toImage();
1565 QPainter imagePainter(&coloredImage);
1566 imagePainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
1567 imagePainter.fillRect(coloredImage.rect(), image->color());
1569 pixmap = QPixmap::fromImage(coloredImage);
1571 painter->setOpacity(opacity);
1572 const QSizeF pixmapSize = pixmap.deviceIndependentSize();
1574 switch (image->fillMode()) {
1575 case QQuickImage::PreserveAspectFit: {
1576 const QSize scaled = pixmapSize.scaled(rect.size(), Qt::KeepAspectRatio).toSize();
1577 const QPointF topLeft(rect.x() + (rect.width() - scaled.width()) / 2.0,
1578 rect.y() + (rect.height() - scaled.height()) / 2.0);
1579 painter->drawPixmap(QRectF(topLeft, scaled), pixmap, QRectF(QPointF(0, 0), pixmapSize));
1582 case QQuickImage::PreserveAspectCrop: {
1583 const QSize scaled = pixmapSize
1584 .scaled(rect.size(), Qt::KeepAspectRatioByExpanding)
1586 const QPointF topLeft(rect.x() + (rect.width() - scaled.width()) / 2.0,
1587 rect.y() + (rect.height() - scaled.height()) / 2.0);
1588 QPainterStateGuard stateGuard(painter);
1589 painter->setClipRect(rect);
1590 painter->drawPixmap(QRectF(topLeft, scaled), pixmap, QRectF(QPointF(0, 0), pixmapSize));
1594 case QQuickImage::Stretch:
1596 painter->drawPixmap(rect, pixmap, QRectF(QPointF(0, 0), pixmapSize));
1602 uint alignment,
const QMargins &padding,
1603 const QMargins &margins)
const
1605 QRect r(QPoint(0, 0), size);
1607 if (alignment & Qt::AlignLeft)
1608 r.moveLeft(container.x() + padding.left() + margins.left());
1609 else if (alignment & Qt::AlignHCenter)
1610 r.moveLeft(container.x() + (container.width() - size.width()) / 2);
1612 r.moveLeft(container.right() + 1 - padding.right() - margins.right() - size.width());
1614 if (alignment & Qt::AlignTop)
1615 r.moveTop(container.y() + padding.top() + margins.top());
1616 else if (alignment & Qt::AlignVCenter)
1617 r.moveTop(container.y() + (container.height() - size.height()) / 2);
1619 r.moveTop(container.bottom() + 1 - padding.bottom() - margins.bottom() - size.height());
1624QStyleKitStylePrivate::ControlMetrics
1628 using QtPrivate::qSaturateRound;
1629 const QQStyleKitControlProperties *props = reader->global();
1630 ControlMetrics metrics;
1631 metrics.bgImplicitSize = QSize(0, 0);
1632 metrics.textPadding = QMargins(0, 0, 0, 0);
1633 metrics.padding = QMargins(qSaturateRound(props->leftPadding()),
1634 qSaturateRound(props->topPadding()),
1635 qSaturateRound(props->rightPadding()),
1636 qSaturateRound(props->bottomPadding()));
1637 metrics.spacing = qSaturateRound(props->spacing());
1638 metrics.margins = QMargins(0, 0, 0, 0);
1639 metrics.indicatorImplicitSize = QSize(0, 0);
1640 metrics.indicatorMargins = QMargins(0, 0, 0, 0);
1641 const auto *background = props->background();
1644 const auto elementSize = [](qreal w, qreal h) {
1645 constexpr qreal zero(.0);
1646 return QSizeF(std::max(zero, w), std::max(zero, h)).toSize();
1650 metrics.bgImplicitSize = elementSize(background->width(), background->height());
1651 metrics.margins = elementMargins(background);
1653 const auto *textProps = props->text();
1655 metrics.textPadding = QMargins(qSaturateRound(textProps->leftPadding()),
1656 qSaturateRound(textProps->topPadding()),
1657 qSaturateRound(textProps->rightPadding()),
1658 qSaturateRound(textProps->bottomPadding()));
1660 const auto *indicator = props->indicator();
1662 metrics.indicatorMargins = elementMargins(indicator);
1663 metrics.indicatorImplicitSize = elementSize(indicator->width(), indicator->height());
1665 const auto *handle = props->handle();
1667 metrics.handleImplicitSize = elementSize(handle->width(), handle->height());
1668 metrics.handleMargins = elementMargins(handle);
1674
1675
1676
1677
1678
1679QStyleKitStyle::QStyleKitStyle()
1680 : QCommonStyle(*
new QStyleKitStylePrivate())
1685
1686
1687
1688
1689
1690
1691
1692QStyleKitStyle::QStyleKitStyle(
const QString &filePath)
1693 : QCommonStyle(*
new QStyleKitStylePrivate())
1695 Q_D(QStyleKitStyle);
1696 d->stylePath = filePath;
1697 if (!d->loadStyle()) {
1698 d->stylePath.clear();
1699 qWarning(
"QStyleKitStyle: Failed to load style from %s", qPrintable(filePath));
1704
1705
1706QStyleKitStyle::~QStyleKitStyle()
1711
1712
1713
1714
1715QString QStyleKitStyle::stylePath()
const
1717 Q_D(
const QStyleKitStyle);
1718 return d->stylePath;
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733void QStyleKitStyle::setStylePath(
const QString &filePath)
1735 Q_D(QStyleKitStyle);
1736 if (d->stylePath == filePath)
1739 const QString oldThemeName = themeName();
1740 const QStringList oldThemeNames = availableThemeNames();
1741 const QStringList oldCustomThemeNames = customThemeNames();
1743 const QString previousPath = d->stylePath;
1744 d->stylePath = filePath;
1745 if (!d->loadStyle()) {
1746 d->stylePath = previousPath;
1750 if (
const QStringList names = availableThemeNames(); names != oldThemeNames)
1751 emit availableThemeNamesChanged(names);
1752 if (
const QStringList names = customThemeNames(); names != oldCustomThemeNames)
1753 emit customThemeNamesChanged(names);
1754 emit stylePathChanged(d->stylePath);
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767QString QStyleKitStyle::themeName()
const
1769 Q_D(
const QStyleKitStyle);
1770 return d->style ? d->style->themeName() : QString();
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787void QStyleKitStyle::setThemeName(
const QString &themeName)
1789 Q_D(QStyleKitStyle);
1791 qWarning(
"QStyleKitStyle: No style loaded, cannot set theme name.");
1794 if (d->style->themeName() == themeName)
1796 d->style->setThemeName(themeName);
1798 emit themeNameChanged(d->style->themeName());
1802
1803
1804
1805
1806
1807
1808
1809
1810QStringList QStyleKitStyle::availableThemeNames()
const
1812 Q_D(
const QStyleKitStyle);
1813 return d->style ? d->style->availableThemeNames() : QStringList();
1817
1818
1819
1820
1821
1822
1823QStringList QStyleKitStyle::customThemeNames()
const
1825 Q_D(
const QStyleKitStyle);
1826 return d->style ? d->style->customThemeNames() : QStringList();
1830void QStyleKitStyle::drawPrimitive(PrimitiveElement pe,
const QStyleOption *opt, QPainter *p,
1831 const QWidget *w)
const
1833 Q_D(
const QStyleKitStyle);
1837 case PE_PanelMenu: {
1838 const auto controlType = w && w->inherits(
"QComboBoxPrivateContainer")
1839 ? QQStyleKitReader::ControlType::Popup
1840 : QQStyleKitReader::ControlType::Menu;
1841 const auto r = d->resolve(w, controlType, opt->state);
1844 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
1851#if QT_CONFIG(menubar)
1852 case PE_PanelMenuBar: {
1853 const auto r = d->resolve(w, QQStyleKitReader::ControlType::MenuBar, opt->state);
1856 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
1860 case PE_FrameButtonBevel:
1861 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1862 const auto controlType = btn->features & QStyleOptionButton::Flat
1863 ? QQStyleKitReader::ControlType::FlatButton
1864 : QQStyleKitReader::ControlType::Button;
1865 const auto r = d->resolve(w, controlType, btn->state);
1868 d->drawStyledItemRect(r.background(), opt->rect, p);
1873 QQStyleKitReader::ControlType controlType;
1874 const bool isPopup = w
1876#if QT_CONFIG(combobox)
1877 || w->inherits(
"QComboBoxPrivateContainer")
1881 controlType = QQStyleKitReader::ControlType::Popup;
1882#if QT_CONFIG(lineedit)
1883 else if (qobject_cast<
const QLineEdit *>(w))
1884 controlType = QQStyleKitReader::ControlType::TextField;
1887 controlType = QQStyleKitReader::ControlType::Frame;
1888 const auto r = d->resolve(w, controlType, opt->state);
1891 d->drawStyledItemRect(r.background(), opt->rect, p);
1894#if QT_CONFIG(lineedit)
1895 case PE_PanelLineEdit:
1896 if (
const auto *lineEdit = qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
1899 QStyleOption lineEditOpt(*lineEdit);
1900 lineEditOpt.state &= ~QStyle::State_Sunken;
1901 const auto r = d->resolve(w, QQStyleKitReader::ControlType::TextField,
1907 if (
auto *le = qobject_cast<
const QLineEdit *>(w)) {
1908 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
1909 QPalette stylePalette;
1910 stylePalette.setColor(QPalette::Text, txt->color());
1911 d->setStylePalette(
const_cast<QLineEdit *>(le), stylePalette);
1913 const_cast<QStyleKitStylePrivate *>(d)->setStyleFont(
const_cast<QLineEdit *>(le),
1917 const QObject *parent = w ? w->parent() :
nullptr;
1918# if QT_CONFIG(spinbox)
1919 const bool isInSpinBox = qobject_cast<
const QAbstractSpinBox *>(parent);
1921 const bool isInSpinBox =
false;
1923# if QT_CONFIG(combobox)
1924 const bool isInComboBox = qobject_cast<
const QComboBox *>(parent);
1926 const bool isInComboBox =
false;
1929 if (isInSpinBox || isInComboBox)
1932 d->drawStyledItemRect(r.background(), opt->rect, p);
1937#if QT_CONFIG(itemviews)
1938 case PE_PanelItemViewItem: {
1939 const auto r = d->resolveSubElement(w, opt, itemViewControlType(opt), opt->state);
1942 d->drawStyledItemRect(r.background(), opt->rect, p);
1946 case PE_IndicatorCheckBox:
1947 case PE_IndicatorRadioButton: {
1948 const auto controlType = pe == PE_IndicatorCheckBox
1949 ? QQStyleKitReader::ControlType::CheckBox
1950 : QQStyleKitReader::ControlType::RadioButton;
1951 const auto r = d->resolve(w, controlType, opt->state);
1954 d->drawControlIndicator(r.indicator(), opt->rect, p);
1957 case PE_IndicatorArrowDown: {
1958 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, opt->state);
1961 d->drawControlIndicator(r.indicator(), opt->rect, p);
1964 case PE_IndicatorItemViewItemCheck: {
1966 const auto r = d->resolveSubElement(w, opt, itemViewControlType(opt), opt->state,
false);
1969 d->drawControlIndicator(r.indicator(), opt->rect, p);
1972#if QT_CONFIG(spinbox)
1973 case PE_IndicatorSpinUp:
1974 case PE_IndicatorSpinDown: {
1975 const auto r = d->resolve(w, QQStyleKitReader::ControlType::SpinBox, opt->state);
1978 const auto *indicator = r.indicator();
1979 const auto *upDownIndicator = indicator
1980 ? (pe == PE_IndicatorSpinUp ? indicator->first() : indicator->second())
1982 d->drawControlIndicator(upDownIndicator, opt->rect, p);
1986#if QT_CONFIG(groupbox)
1987 case PE_FrameGroupBox: {
1988 const auto r = d->resolve(w, QQStyleKitReader::ControlType::GroupBox, opt->state);
1991 d->drawStyledItemRect(r.background(), opt->rect, p);
1995#if QT_CONFIG(tabwidget)
1996 case PE_FrameTabWidget: {
1997 const auto r = d->resolve(w, QQStyleKitReader::ControlType::Page, opt->state);
2000 d->drawStyledItemRect(r.background(), opt->rect, p);
2004#if QT_CONFIG(tabbar)
2006 case PE_IndicatorTabClose:
2007 case PE_IndicatorTabTearRight:
2008 case PE_IndicatorTabTearLeft:
2011#if QT_CONFIG(toolbutton)
2012 case PE_FrameButtonTool:
2013 case PE_PanelButtonTool: {
2014 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolButton, opt->state);
2017 d->drawStyledItemRect(r.background(), opt->rect, p);
2021#if QT_CONFIG(toolbar)
2022 case PE_IndicatorToolBarHandle:
2024 case PE_IndicatorToolBarSeparator: {
2025 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolSeparator, opt->state);
2028 const auto &metrics = *r.metrics;
2030 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
2031 d->drawStyledItemRect(r.background(), frameRect, p);
2033 const auto *indicator = r.indicator();
2034 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2036 QRect contentRect = frameRect.marginsRemoved(metrics.padding);
2037 const int iw = QtPrivate::qSaturateRound(
2038 resolvedWidth(indicator,
2040 - metrics.indicatorMargins.left()
2041 - metrics.indicatorMargins.right()));
2042 const int ih = QtPrivate::qSaturateRound(
2043 resolvedHeight(indicator,
2044 contentRect.height()
2045 - metrics.indicatorMargins.top()
2046 - metrics.indicatorMargins.bottom()));
2047 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignHCenter,
2049 const QRect indicatorRect = d->getAlignedRectInContainer(
2050 contentRect, QSize(iw, ih), alignment, QMargins(), metrics.indicatorMargins);
2051 d->drawControlIndicator(indicator, visualRect(opt->direction, contentRect, indicatorRect),
2059 QCommonStyle::drawPrimitive(pe, opt, p, w);
2063void QStyleKitStyle::drawControl(ControlElement element,
const QStyleOption *opt, QPainter *p,
2064 const QWidget *w)
const
2066 Q_D(
const QStyleKitStyle);
2070 if (
const QStyleOptionButton *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2071 proxy()->drawControl(CE_PushButtonBevel, btn, p, w);
2072 QStyleOptionButton btnContent(*btn);
2073 btnContent.rect = subElementRect(SE_PushButtonContents, btn, w);
2074 proxy()->drawControl(CE_PushButtonLabel, &btnContent, p, w);
2077 case CE_PushButtonBevel:
2078 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2079 QStyleOptionButton btnBg(*btn);
2080 btnBg.rect = subElementRect(SE_PushButtonBevel, btn, w);
2081 proxy()->drawPrimitive(PE_FrameButtonBevel, &btnBg, p, w);
2084 case CE_PushButtonLabel:
2085 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2086 const auto controlType = btn->features & QStyleOptionButton::Flat
2087 ? QQStyleKitReader::ControlType::FlatButton
2088 : QQStyleKitReader::ControlType::Button;
2089 const auto r = d->resolve(w, controlType, btn->state);
2092 const auto metrics = r.metrics;
2094 QRect textRect = opt->rect;
2095 uint textFlags = Qt::TextShowMnemonic;
2096 if (!styleHint(SH_UnderlineShortcut, opt, w))
2097 textFlags |= Qt::TextHideMnemonic;
2100 const QIcon icon = btn->icon;
2101 if (!icon.isNull()) {
2102 const auto *textProps = r.text();
2103 uint iconTextFlags = textFlags;
2104 iconTextFlags |= textProps
2105 ? resolvedAlignment(textProps->alignment(), Qt::AlignHCenter, Qt::AlignVCenter)
2106 : uint(Qt::AlignHCenter | Qt::AlignVCenter);
2107 QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
2108 if (mode == QIcon::Normal && btn->state & State_HasFocus)
2109 mode = QIcon::Active;
2110 QIcon::State iconState = btn->state & State_On ? QIcon::On : QIcon::Off;
2111 const auto paintDeviceDpr = p->device()->devicePixelRatio();
2112 QPixmap pixmap = icon.pixmap(btn->iconSize, paintDeviceDpr, mode, iconState);
2113 int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
2114 int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
2115 int labelWidth = pixmapWidth;
2116 int iconSpacing = metrics->spacing;
2117 int textWidth = btn->fontMetrics
2118 .boundingRect(opt->rect, iconTextFlags, btn->text)
2120 if (!btn->text.isEmpty()) {
2121 labelWidth += (textWidth
2122 + iconSpacing + textProps->leftPadding() + textProps->rightPadding());
2126 if (iconTextFlags & Qt::AlignLeft) {
2127 iconRect = QRect(textRect.x(),
2128 textRect.y() + (textRect.height() - pixmapHeight) / 2,
2129 pixmapWidth, pixmapHeight);
2130 }
else if (iconTextFlags & Qt::AlignHCenter) {
2131 iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
2132 textRect.y() + (textRect.height() - pixmapHeight) / 2,
2133 pixmapWidth, pixmapHeight);
2135 iconRect = QRect(textRect.x() + textRect.width() - labelWidth,
2136 textRect.y() + (textRect.height() - pixmapHeight) / 2,
2137 pixmapWidth, pixmapHeight);
2139 iconRect = visualRect(btn->direction, textRect, iconRect);
2142 textFlags &= ~Qt::AlignHorizontal_Mask;
2143 textFlags |= Qt::AlignLeft;
2144 if (btn->direction == Qt::RightToLeft)
2145 textRect.setRight(iconRect.left() - iconSpacing);
2147 textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing);
2149 p->drawPixmap(iconRect, pixmap);
2152 if (btn->features & QStyleOptionButton::HasMenu) {
2153 int indicatorSize = pixelMetric(PM_MenuButtonIndicator, btn, w);
2154 if (btn->direction == Qt::LeftToRight)
2155 textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
2157 textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
2159 d->drawControlText(r.text(), r.font(), textRect, btn->text, textFlags, p);
2164 case CE_RadioButton:
2165 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2166 const auto controlType = element == CE_CheckBox
2167 ? QQStyleKitReader::ControlType::CheckBox
2168 : QQStyleKitReader::ControlType::RadioButton;
2169 const auto r = d->resolve(w, controlType, btn->state);
2172 QRect backgroundRect = btn->rect.marginsRemoved(r.metrics->margins);
2174 d->drawStyledItemRect(r.background(), backgroundRect, p);
2176 QStyleOptionButton btnContent(*btn);
2177 const auto contentElement = element == CE_CheckBox
2178 ? SE_CheckBoxContents
2179 : SE_RadioButtonContents;
2180 btnContent.rect = subElementRect(contentElement, btn, w);
2181 const auto labelElement = element == CE_CheckBox
2183 : CE_RadioButtonLabel;
2184 proxy()->drawControl(labelElement, &btnContent, p, w);
2186 QStyleOptionButton indicator(*btn);
2187 const auto indicatorElement = element == CE_CheckBox
2188 ? SE_CheckBoxIndicator
2189 : SE_RadioButtonIndicator;
2190 indicator.rect = subElementRect(indicatorElement, btn, w);
2191 const auto primitiveElement = element == CE_CheckBox
2192 ? PE_IndicatorCheckBox
2193 : PE_IndicatorRadioButton;
2194 proxy()->drawPrimitive(primitiveElement, &indicator, p, w);
2198 case CE_CheckBoxLabel:
2199 case CE_RadioButtonLabel:
2200 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2201 const auto controlType = element == CE_CheckBoxLabel
2202 ? QQStyleKitReader::ControlType::CheckBox
2203 : QQStyleKitReader::ControlType::RadioButton;
2204 const auto r = d->resolve(w, controlType, btn->state);
2207 uint textFlags = Qt::TextShowMnemonic;
2208 if (!styleHint(SH_UnderlineShortcut, opt, w))
2209 textFlags |= Qt::TextHideMnemonic;
2210 d->drawControlText(r.text(), r.font(), opt->rect, btn->text, textFlags, p);
2214#if QT_CONFIG(combobox)
2215 case CE_ComboBoxLabel:
2216 if (
const auto *comboBox = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
2217 if (comboBox->editable)
2219 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, comboBox->state);
2222 const QRect textRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, w)
2223 .marginsRemoved(r.metrics->textPadding);
2224 uint textFlags = Qt::TextShowMnemonic;
2225 if (!styleHint(SH_UnderlineShortcut, opt, w))
2226 textFlags |= Qt::TextHideMnemonic;
2227 d->drawControlText(r.text(), r.font(), textRect, comboBox->currentText, textFlags, p);
2232#if QT_CONFIG(progressbar)
2233 case CE_ProgressBar:
2234 if (
const QStyleOptionProgressBar *progressBar =
2235 qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
2236 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar,
2237 progressBar->state);
2240 QRect backgroundRect = progressBar->rect.marginsRemoved(r.metrics->margins);
2242 d->drawStyledItemRect(r.background(), backgroundRect, p);
2244 QStyleOptionProgressBar contents(*progressBar);
2245 contents.rect = subElementRect(SE_ProgressBarGroove, progressBar, w);
2246 const QRect grooveRect = contents.rect;
2247 proxy()->drawControl(CE_ProgressBarGroove, &contents, p, w);
2249 contents.rect = subElementRect(SE_ProgressBarContents, progressBar, w);
2252 QPainterStateGuard stateGuard(p);
2253 if (applyDelegateTransform(p, r.indicator(), grooveRect))
2254 proxy()->drawControl(CE_ProgressBarContents, &contents, p, w);
2259 case CE_ProgressBarGroove: {
2261 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar, opt->state);
2264 d->drawStyledItemRect(r.indicator(), opt->rect, p);
2267 case CE_ProgressBarContents:
2269 if (
const auto *progressBar = qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
2270 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar,
2271 progressBar->state);
2274 const auto progress = progressBar->progress;
2275 const auto ratio = progressBar->maximum > progressBar->minimum
2276 ? (progress - progressBar->minimum)
2277 /
static_cast<qreal>(progressBar->maximum - progressBar->minimum)
2279 const auto width =
static_cast<
int>(progressBar->rect.width() * ratio);
2280 const auto x = progressBar->invertedAppearance
2281 ? progressBar->rect.right() - width
2282 : progressBar->rect.left();
2283 const auto contentsRect = QRect(x, progressBar->rect.y(),
2284 width, progressBar->rect.height());
2285 const auto *foreground = r.indicator() ? r.indicator()->foreground() :
nullptr;
2286 if (foreground && foreground->visible() && foreground->opacity() > 0) {
2287 QPainterStateGuard stateGuard(p);
2288 if (applyDelegateTransform(p, foreground, progressBar->rect))
2289 d->drawStyledItemContents(foreground, contentsRect, p);
2295#if QT_CONFIG(itemviews)
2296 case CE_ItemViewItem:
2297 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
2298 const auto r = d->resolveSubElement(w, opt, itemViewControlType(opt), opt->state);
2301 QStyleOptionViewItem optBg(*itemViewOption);
2302 optBg.rect = optBg.rect.marginsRemoved(r.metrics->margins);
2303 QRect indicatorRect = subElementRect(SE_ItemViewItemCheckIndicator, itemViewOption, w);
2304 QRect iconRect = subElementRect(SE_ItemViewItemDecoration, itemViewOption, w);
2305 QRect textRect = subElementRect(SE_ItemViewItemText, itemViewOption, w);
2308 const auto *itemTextProps = r.text();
2309 const QFont itemFont = r.font();
2312 proxy()->drawPrimitive(PE_PanelItemViewItem, &optBg, p, w);
2315 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator) {
2316 QStyleOptionViewItem option(*itemViewOption);
2317 option.rect = indicatorRect;
2318 option.state = option.state & ~QStyle::State_HasFocus;
2320 switch (itemViewOption->checkState) {
2322 option.state |= QStyle::State_Off;
2324 case Qt::PartiallyChecked:
2325 option.state |= QStyle::State_NoChange;
2328 option.state |= QStyle::State_On;
2331 proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, p, w);
2335 QIcon::Mode mode = QIcon::Normal;
2336 if (!(itemViewOption->state & QStyle::State_Enabled))
2337 mode = QIcon::Disabled;
2338 else if (itemViewOption->state & QStyle::State_Selected)
2339 mode = QIcon::Selected;
2340 QIcon::State state = itemViewOption->state & QStyle::State_Open
2343 itemViewOption->icon.paint(p, iconRect, itemViewOption->decorationAlignment, mode,
2347 uint textFlags = Qt::TextShowMnemonic;
2348 if (!styleHint(SH_UnderlineShortcut, opt, w))
2349 textFlags |= Qt::TextHideMnemonic;
2350 d->drawControlText(itemTextProps, itemFont, textRect, itemViewOption->text, textFlags,
2351 p, Qt::AlignLeft | Qt::AlignVCenter);
2357 case CE_ShapedFrame: {
2358# if QT_CONFIG(scrollarea)
2359 if (qobject_cast<
const QAbstractScrollArea *>(w))
2363 auto controlType = QQStyleKitReader::ControlType::Frame;
2364# if QT_CONFIG(combobox)
2365 if (w && w->inherits(
"QComboBoxPrivateContainer"))
2366 controlType = QQStyleKitReader::ControlType::Popup;
2368# if QT_CONFIG(textedit)
2369 else if (w && qobject_cast<
const QTextEdit *>(w))
2370 controlType = QQStyleKitReader::ControlType::TextArea;
2372# if QT_CONFIG(label)
2373 else if (w && qobject_cast<
const QLabel *>(w))
2374 controlType = QQStyleKitReader::ControlType::Label;
2377 if (qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
2378 const auto r = d->resolve(w, controlType, opt->state);
2381 QRect backgroundRect = opt->rect.marginsRemoved(r.metrics->margins);
2382 d->drawStyledItemRect(r.background(), backgroundRect, p);
2388#if QT_CONFIG(scrollbar)
2389 case CE_ScrollBarSlider: {
2390 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ScrollBar, opt->state);
2393 d->drawControlIndicator(r.indicator(), opt->rect, p);
2397#if QT_CONFIG(toolbutton)
2398 case CE_ToolButtonLabel:
2399 if (
const auto *tool = qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
2400 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolButton, tool->state);
2403 const auto *metrics = r.metrics;
2404 QRect rect = tool->rect.marginsRemoved(metrics->textPadding);
2406 uint textFlags = Qt::TextShowMnemonic;
2407 if (!styleHint(SH_UnderlineShortcut, opt, w))
2408 textFlags |= Qt::TextHideMnemonic;
2410 const bool hasArrow = tool->features & QStyleOptionToolButton::Arrow;
2411 if ((!hasArrow && tool->icon.isNull() && !tool->text.isEmpty())
2412 || tool->toolButtonStyle == Qt::ToolButtonTextOnly) {
2413 d->drawControlText(r.text(), r.font(), rect, tool->text, textFlags, p);
2419 if (!hasArrow && !tool->icon.isNull()) {
2420 const QIcon::State iconState = tool->state & State_On ? QIcon::On : QIcon::Off;
2422 if (!(tool->state & State_Enabled))
2423 mode = QIcon::Disabled;
2424 else if ((tool->state & State_MouseOver) && (tool->state & State_AutoRaise))
2425 mode = QIcon::Active;
2427 mode = QIcon::Normal;
2428 pm = tool->icon.pixmap(tool->iconSize, p->device()->devicePixelRatio(), mode,
2430 pmSize = pm.size() / pm.devicePixelRatio();
2433 if (tool->toolButtonStyle == Qt::ToolButtonIconOnly || tool->text.isEmpty()) {
2435 p->drawPixmap(visualRect(tool->direction, rect,
2436 QRect(rect.x() + (rect.width() - pmSize.width()) / 2,
2437 rect.y() + (rect.height() - pmSize.height()) / 2,
2438 pmSize.width(), pmSize.height())),
2444 if (tool->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
2446 const QRect pr(rect.x() + (rect.width() - pmSize.width()) / 2, rect.y(),
2447 pmSize.width(), pmSize.height());
2448 p->drawPixmap(visualRect(tool->direction, rect, pr), pm);
2450 tr.setTop(rect.y() + pmSize.height() + metrics->spacing);
2451 d->drawControlText(r.text(), r.font(), visualRect(tool->direction, rect, tr),
2452 tool->text, textFlags, p, Qt::AlignCenter);
2454 d->drawControlText(r.text(), r.font(), rect, tool->text, textFlags, p,
2459 const QRect pr(rect.x(), rect.y() + (rect.height() - pmSize.height()) / 2,
2460 pmSize.width(), pmSize.height());
2461 p->drawPixmap(visualRect(tool->direction, rect, pr), pm);
2463 tr.setLeft(rect.x() + pmSize.width() + metrics->spacing);
2464 d->drawControlText(r.text(), r.font(), visualRect(tool->direction, rect, tr),
2465 tool->text, textFlags, p, Qt::AlignLeft | Qt::AlignVCenter);
2467 d->drawControlText(r.text(), r.font(), rect, tool->text, textFlags, p,
2468 Qt::AlignLeft | Qt::AlignVCenter);
2477 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
2478 using QtPrivate::qSaturateRound;
2480 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
2481 const auto r = d->resolve(w, QQStyleKitReader::ControlType::MenuSeparator,
2485 const auto metrics = r.metrics;
2486 QRect contentRect = opt->rect
2487 .marginsRemoved(metrics->margins)
2488 .marginsRemoved(metrics->padding);
2489 const auto *indicator = r.indicator();
2490 if (indicator && indicator->visible() && indicator->opacity() > 0) {
2491 const int w = qSaturateRound(resolvedWidth(
2493 contentRect.width() - indicator->leftMargin() - indicator->rightMargin()));
2494 const int h = qSaturateRound(resolvedHeight(
2496 contentRect.height() - indicator->topMargin() - indicator->bottomMargin()));
2497 const uint align = resolvedAlignment(indicator->alignment(), Qt::AlignHCenter,
2499 const QRect indicatorRect = d->getAlignedRectInContainer(
2500 contentRect, QSize(w, h), align, QMargins(), elementMargins(indicator));
2501 d->drawControlIndicator(
2502 indicator, visualRect(opt->direction, contentRect, indicatorRect), p);
2507 QStyle::State adjustedState = menuItem->state;
2508 if (adjustedState & State_Selected)
2509 adjustedState |= State_MouseOver;
2511 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::MenuItem,
2517 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
2520 const QRect contentRect = opt->rect.marginsRemoved(r.metrics->padding);
2521 const auto *indicator = r.indicator();
2522 const auto *first = indicator ? indicator->first() :
nullptr;
2523 const auto *second = indicator ? indicator->second() :
nullptr;
2524 int leftOffset = 0, rightOffset = 0;
2525 const int spacing = r.metrics->spacing;
2526 QRect firstDrawRect, secondDrawRect;
2527 auto placeSubIndicator = [&](
const QQStyleKitIndicatorProperties *sub,
2531 const QSize sz(qSaturateRound(sub->width()), qSaturateRound(sub->height()));
2532 const QMargins subMargins = elementMargins(sub);
2533 const int slotW = qSaturateRound(sub->leftMargin() + sub->width() + sub->rightMargin());
2534 if (sub->alignment() & Qt::AlignRight) {
2535 const QRect slot(contentRect.right() - rightOffset - slotW, contentRect.top(),
2536 slotW, contentRect.height());
2537 drawRect = d->getAlignedRectInContainer(
2538 slot, sz, Qt::AlignRight | Qt::AlignVCenter, { }, subMargins);
2539 rightOffset += slotW + spacing;
2541 const QRect slot(contentRect.left() + leftOffset, contentRect.top(), slotW,
2542 contentRect.height());
2543 drawRect = d->getAlignedRectInContainer(
2544 slot, sz, Qt::AlignLeft | Qt::AlignVCenter, { }, subMargins);
2545 leftOffset += slotW + spacing;
2548 placeSubIndicator(first, firstDrawRect);
2549 placeSubIndicator(second, secondDrawRect);
2551 if (first && menuItem->checkType != QStyleOptionMenuItem::NotCheckable
2552 && menuItem->checked) {
2553 d->drawControlIndicator(
2554 first, visualRect(menuItem->direction, contentRect, firstDrawRect), p);
2557 if (second && menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {
2558 d->drawControlIndicator(
2559 second, visualRect(menuItem->direction, contentRect, secondDrawRect), p);
2563 QRect textRect = contentRect
2564 .adjusted(leftOffset, 0, -rightOffset, 0)
2565 .marginsRemoved(r.metrics->textPadding);
2566 if (!menuItem->icon.isNull()) {
2567 const int iconW = menuItem->maxIconWidth;
2568 const QIcon::Mode mode = (menuItem->state & State_Enabled)
2571 const int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt, w);
2572 const QPixmap pm = menuItem->icon.pixmap(
2573 QSize(iconExtent, iconExtent), p->device()->devicePixelRatio(), mode);
2574 const QSize pmSize = pm.size() / pm.devicePixelRatio();
2575 const int pmW = pmSize.width();
2576 const int pmH = pmSize.height();
2578 visualRect(menuItem->direction, textRect,
2579 QRect(textRect.left(),
2580 textRect.top() + (textRect.height() - pmH) / 2, pmW, pmH)),
2582 textRect.setLeft(textRect.left() + iconW + r.metrics->spacing);
2585 const int tabIdx = menuItem->text.indexOf(QLatin1Char(
'\t'));
2586 const QString label = tabIdx >= 0 ? menuItem->text.left(tabIdx) : menuItem->text;
2587 const QString shortcut = tabIdx >= 0 ? menuItem->text.mid(tabIdx + 1) : QString();
2588 uint textFlags = Qt::TextShowMnemonic;
2589 if (!styleHint(SH_UnderlineShortcut, opt, w))
2590 textFlags |= Qt::TextHideMnemonic;
2591 QRect labelRect = textRect;
2592 if (!shortcut.isEmpty() && menuItem->reservedShortcutWidth > 0) {
2593 const QRect shortcutRect(textRect.right() - menuItem->reservedShortcutWidth + 1,
2594 textRect.top(), menuItem->reservedShortcutWidth,
2596 labelRect.setRight(shortcutRect.left() - r.metrics->spacing - 1);
2597 const int shortcutFlags =
2598 int(QStyle::visualAlignment(menuItem->direction,
2599 Qt::AlignRight | Qt::AlignVCenter))
2602 p->setFont(r.font().resolve(p->font()));
2603 p->setBrush(Qt::NoBrush);
2604 if (
const auto *shortcutText = r.text())
2605 p->setPen(shortcutText->color());
2606 p->drawText(visualRect(menuItem->direction, textRect, shortcutRect), shortcutFlags,
2610 d->drawControlText(r.text(), r.font(),
2611 visualRect(menuItem->direction, textRect, labelRect), label,
2612 textFlags, p, Qt::AlignLeft | Qt::AlignVCenter);
2618 case CE_MenuScroller:
2619 case CE_MenuTearoff:
2621 case CE_MenuEmptyArea:
2624#if QT_CONFIG(menubar)
2625 case CE_MenuBarEmptyArea:
2627 case CE_MenuBarItem:
2628 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
2629 QStyle::State adjustedState = menuItem->state;
2630 if (adjustedState & State_Selected)
2631 adjustedState |= State_MouseOver;
2632 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::MenuBarItem,
2636 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
2637 const QRect textRect = opt->rect.marginsRemoved(
2638 r.metrics->margins + r.metrics->padding + r.metrics->textPadding);
2639 uint textFlags = Qt::TextShowMnemonic;
2640 if (!styleHint(SH_UnderlineShortcut, opt, w))
2641 textFlags |= Qt::TextHideMnemonic;
2642 d->drawControlText(r.text(), r.font(), textRect, menuItem->text, textFlags, p);
2647#if QT_CONFIG(tabbar)
2649 if (
const auto *tab = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
2650 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::TabButton,
2654 const auto &m = *r.metrics;
2656 const QRect backgroundRect = opt->rect.marginsRemoved(m.margins);
2657 d->drawStyledItemRect(r.background(), backgroundRect, p);
2659 const QRect contentRect = backgroundRect.marginsRemoved(m.padding);
2660 uint textFlags = Qt::TextShowMnemonic;
2661 if (!styleHint(SH_UnderlineShortcut, opt, w))
2662 textFlags |= Qt::TextHideMnemonic;
2664 if (!tab->icon.isNull()) {
2665 const QIcon::Mode mode = (tab->state & State_Enabled)
2668 const QIcon::State iconState = (tab->state & State_Selected)
2671 const QPixmap pm = tab->icon.pixmap(tab->iconSize, p->device()->devicePixelRatio(),
2673 const QSize pmSize = pm.size() / pm.devicePixelRatio();
2674 const QRect pr(contentRect.x(),
2675 contentRect.y() + (contentRect.height() - pmSize.height()) / 2,
2676 pmSize.width(), pmSize.height());
2677 p->drawPixmap(visualRect(tab->direction, contentRect, pr), pm);
2678 QRect tr = contentRect;
2679 tr.setLeft(contentRect.x() + pmSize.width() + m.spacing);
2680 d->drawControlText(r.text(), r.font(), visualRect(tab->direction, contentRect, tr),
2681 tab->text, textFlags, p, Qt::AlignCenter);
2683 d->drawControlText(r.text(), r.font(), contentRect, tab->text, textFlags, p,
2690#if QT_CONFIG(toolbar)
2692 if (
const auto *toolBar = qstyleoption_cast<
const QStyleOptionToolBar *>(opt)) {
2693 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolBar, toolBar->state);
2696 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
2704 QCommonStyle::drawControl(element, opt, p, w);
2708QRect QStyleKitStyle::subElementRect(SubElement r,
const QStyleOption *opt,
2709 const QWidget *widget)
const
2711 using QtPrivate::qSaturateRound;
2712 Q_D(
const QStyleKitStyle);
2715 case SE_PushButtonBevel:
2716 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2717 const auto controlType = btn->features & QStyleOptionButton::Flat
2718 ? QQStyleKitReader::ControlType::FlatButton
2719 : QQStyleKitReader::ControlType::Button;
2720 const auto resolved = d->resolveLayout(controlType, opt->state);
2721 if (!resolved.isValid())
2723 const auto &metrics = *resolved.metrics;
2724 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2725 return visualRect(opt->direction, opt->rect, rect);
2728 case SE_PushButtonContents:
2729 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2730 const auto controlType = btn->features & QStyleOptionButton::Flat
2731 ? QQStyleKitReader::ControlType::FlatButton
2732 : QQStyleKitReader::ControlType::Button;
2733 const auto resolved = d->resolveLayout(controlType, opt->state);
2734 if (!resolved.isValid())
2736 const auto &metrics = *resolved.metrics;
2737 QRect rect = opt->rect.marginsRemoved(
2738 metrics.margins + metrics.padding + metrics.textPadding);
2739 return visualRect(opt->direction, opt->rect, rect);
2742 case SE_CheckBoxContents:
2743 case SE_RadioButtonContents: {
2744 const auto controlType = r == SE_CheckBoxContents
2745 ? QQStyleKitReader::ControlType::CheckBox
2746 : QQStyleKitReader::ControlType::RadioButton;
2747 const auto resolved = d->resolveLayout(controlType, opt->state);
2748 if (!resolved.isValid())
2750 const auto &metrics = *resolved.metrics;
2751 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
2752 const auto subElement = r == SE_CheckBoxContents
2753 ? SE_CheckBoxIndicator
2754 : SE_RadioButtonIndicator;
2755 QRect indicatorRect = visualRect(opt->direction, opt->rect,
2756 subElementRect(subElement, opt, widget));
2757 const int spacing = metrics.spacing;
2758 const auto *indicator = resolved.indicator();
2759 const uint alignment = indicator
2760 ? resolvedAlignment(indicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
2761 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2762 if (alignment & Qt::AlignLeft) {
2763 contentsRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
2764 }
else if (alignment & Qt::AlignHCenter) {
2765 contentsRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
2766 contentsRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
2768 contentsRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
2770 return visualRect(opt->direction, opt->rect, contentsRect);
2772 case SE_CheckBoxIndicator:
2773 case SE_RadioButtonIndicator: {
2774 const auto controlType = r == SE_CheckBoxIndicator
2775 ? QQStyleKitReader::ControlType::CheckBox
2776 : QQStyleKitReader::ControlType::RadioButton;
2777 const auto resolved = d->resolveLayout(controlType, opt->state);
2778 if (!resolved.isValid())
2780 const auto &metrics = *resolved.metrics;
2781 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2782 const auto *indicator = resolved.indicator();
2783 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2786 const int w = qSaturateRound(resolvedWidth(
2788 rect.width() - metrics.padding.left() - metrics.padding.right()
2789 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right()));
2790 const int h = qSaturateRound(resolvedHeight(
2793 - metrics.padding.top() - metrics.padding.bottom()
2794 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom()));
2795 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft,
2797 const QRect indicatorRect = d->getAlignedRectInContainer(
2798 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
2799 return visualRect(opt->direction, rect, indicatorRect);
2801#if QT_CONFIG(itemviews)
2802 case SE_ItemViewItemCheckIndicator: {
2803 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
2804 if (!resolved.isValid())
2806 const auto &metrics = *resolved.metrics;
2807 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2808 const auto *indicator = resolved.indicator();
2809 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2812 const int w = qSaturateRound(resolvedWidth(
2815 - metrics.padding.left() - metrics.padding.right()
2816 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right()));
2817 const int h = qSaturateRound(resolvedHeight(
2819 rect.height() - metrics.padding.top() - metrics.padding.bottom()
2820 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom()));
2821 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft,
2823 const QRect indicatorRect = d->getAlignedRectInContainer(
2824 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
2825 return visualRect(opt->direction, rect, indicatorRect);
2827 case SE_ItemViewItemDecoration:
2828 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
2829 if (!(itemViewOption->features & QStyleOptionViewItem::HasDecoration))
2831 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
2832 if (!resolved.isValid())
2834 const auto &metrics = *resolved.metrics;
2835 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
2836 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator) {
2837 const QRect indicatorRect = subElementRect(
2838 SE_ItemViewItemCheckIndicator, opt, widget);
2839 const auto *checkIndicator = resolved.indicator();
2840 const uint checkAlign = checkIndicator
2841 ? resolvedAlignment(checkIndicator->alignment(), Qt::AlignLeft,
2843 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2844 if (checkAlign & Qt::AlignLeft) {
2845 contentsRect.setLeft(indicatorRect.right()
2846 + metrics.indicatorMargins.right() + metrics.spacing);
2847 }
else if (checkAlign & Qt::AlignRight) {
2848 contentsRect.setRight(indicatorRect.left()
2849 - metrics.indicatorMargins.left() - metrics.spacing);
2853 const QSize decorationSize = itemViewOption->decorationSize
2854 .boundedTo(contentsRect.size());
2855 QRect decorationRect;
2856 switch (itemViewOption->decorationPosition) {
2857 case QStyleOptionViewItem::Top:
2858 decorationRect = QRect(contentsRect.left(), contentsRect.top(),
2859 contentsRect.width(), decorationSize.height());
2861 case QStyleOptionViewItem::Bottom:
2862 decorationRect = QRect(contentsRect.left(),
2863 contentsRect.bottom() - decorationSize.height() + 1,
2864 contentsRect.width(), decorationSize.height());
2866 case QStyleOptionViewItem::Right:
2867 decorationRect = QRect(contentsRect.right() - decorationSize.width() + 1,
2868 contentsRect.top(), decorationSize.width(),
2869 contentsRect.height());
2871 case QStyleOptionViewItem::Left:
2873 decorationRect = QRect(contentsRect.left(), contentsRect.top(),
2874 decorationSize.width(), contentsRect.height());
2877 const uint decorationAlign = resolvedAlignment(itemViewOption->decorationAlignment,
2878 Qt::AlignLeft, Qt::AlignVCenter);
2879 decorationRect = d->getAlignedRectInContainer(
2880 decorationRect, decorationSize, decorationAlign, QMargins(0, 0, 0, 0),
2881 QMargins(0, 0, 0, 0));
2882 return visualRect(opt->direction, opt->rect, decorationRect);
2885 case SE_ItemViewItemText:
2886 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
2887 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
2888 if (!resolved.isValid())
2890 const auto &metrics = *resolved.metrics;
2891 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
2892 const int spacing = metrics.spacing;
2894 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator) {
2895 const QRect indicatorRect = subElementRect(
2896 SE_ItemViewItemCheckIndicator, opt, widget);
2897 const auto *checkIndicator = resolved.indicator();
2898 const uint checkAlign = checkIndicator
2899 ? resolvedAlignment(checkIndicator->alignment(), Qt::AlignLeft,
2901 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2902 if (checkAlign & Qt::AlignLeft) {
2903 contentsRect.setLeft(
2904 indicatorRect.right() + metrics.indicatorMargins.right() + spacing);
2905 }
else if (checkAlign & Qt::AlignRight) {
2906 contentsRect.setRight(
2907 indicatorRect.left() - metrics.indicatorMargins.left() - spacing);
2911 QRect textRect = contentsRect;
2912 if (itemViewOption->features & QStyleOptionViewItem::HasDecoration) {
2913 const QRect decorationRect = subElementRect(
2914 SE_ItemViewItemDecoration, opt, widget);
2915 switch (itemViewOption->decorationPosition) {
2916 case QStyleOptionViewItem::Top:
2917 textRect.setTop(decorationRect.bottom() + spacing);
2919 case QStyleOptionViewItem::Bottom:
2920 textRect.setBottom(decorationRect.top() - spacing);
2922 case QStyleOptionViewItem::Right:
2923 textRect.setRight(decorationRect.left() - spacing);
2925 case QStyleOptionViewItem::Left:
2927 textRect.setLeft(decorationRect.right() + spacing);
2932 const auto *textProps = resolved.text();
2933 const uint textAlign = textProps
2934 ? resolvedAlignment(textProps->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
2935 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2936 if (textAlign & Qt::AlignLeft) {
2937 textRect.setLeft(textRect.left() + metrics.textPadding.left());
2938 }
else if (textAlign & Qt::AlignHCenter) {
2939 textRect.setLeft(textRect.left() + metrics.textPadding.left() / 2);
2940 textRect.setRight(textRect.right() - metrics.textPadding.right() / 2);
2942 textRect.setRight(textRect.right() - metrics.textPadding.right());
2944 if (textAlign & Qt::AlignTop) {
2945 textRect.setTop(textRect.top() + metrics.textPadding.top());
2946 }
else if (textAlign & Qt::AlignVCenter) {
2947 textRect.setTop(textRect.top() + metrics.textPadding.top() / 2);
2948 textRect.setBottom(textRect.bottom() - metrics.textPadding.bottom() / 2);
2950 textRect.setBottom(textRect.bottom() - metrics.textPadding.bottom());
2952 return visualRect(opt->direction, opt->rect, textRect);
2956 case SE_PushButtonFocusRect:
2957 case SE_CheckBoxClickRect:
2958 case SE_RadioButtonClickRect:
2960#if QT_CONFIG(progressbar)
2961 case SE_ProgressBarGroove: {
2962 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar,
2964 if (!resolved.isValid())
2966 const auto &metrics = *resolved.metrics;
2967 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2968 const auto *indicator = resolved.indicator();
2969 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2972 const int w = qSaturateRound(resolvedWidth(
2974 rect.width() - metrics.padding.left() - metrics.padding.right()
2975 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right()));
2976 const int h = qSaturateRound(resolvedHeight(
2978 rect.height() - metrics.padding.top() - metrics.padding.bottom()
2979 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom()));
2980 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft,
2982 const QRect indicatorRect = d->getAlignedRectInContainer(
2983 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
2984 return visualRect(opt->direction, rect, indicatorRect);
2986 case SE_ProgressBarContents: {
2987 if (qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
2988 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar,
2990 if (!resolved.isValid())
2992 const auto *foreground = resolved.indicator()
2993 ? resolved.indicator()->foreground()
2995 if (!foreground || !foreground->visible() || foreground->opacity() == 0)
2998 QRect indicatorRect = subElementRect(SE_ProgressBarGroove, opt, widget);
2999 const int foregroundW = qSaturateRound(resolvedWidth(
3001 indicatorRect.width() - foreground->leftMargin() - foreground->rightMargin()));
3002 const int foregroundH = qSaturateRound(resolvedHeight(
3004 indicatorRect.height() - foreground->topMargin() - foreground->bottomMargin()));
3005 const uint foregroundAlign = resolvedAlignment(foreground->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
3006 const QMargins foregroundMargins = elementMargins(foreground);
3007 const QRect foregroundRect = d->getAlignedRectInContainer(
3008 indicatorRect, QSize(foregroundW, foregroundH), foregroundAlign,
3009 QMargins(0, 0, 0, 0), foregroundMargins);
3010 return visualRect(opt->direction, opt->rect, foregroundRect);
3015 case SE_LineEditContents:
3016 if (qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
3017#if QT_CONFIG(spinbox)
3018 const bool isInSpinBox = widget && qobject_cast<
const QSpinBox *>(widget->parentWidget());
3020 const bool isInSpinBox =
false;
3022 const auto controlType = isInSpinBox ? QQStyleKitReader::ControlType::SpinBox
3023 : QQStyleKitReader::ControlType::TextField;
3024 const auto resolved = d->resolveLayout(controlType, opt->state);
3025 if (!resolved.isValid())
3027 const auto &metrics = *resolved.metrics;
3028 QRect contentsRect = opt->rect.marginsRemoved(metrics.padding);
3029 const auto *textProps = resolved.text();
3030 const uint textAlign = resolvedAlignment(textProps ? textProps->alignment() : 0u,
3031 Qt::AlignLeft, Qt::AlignVCenter);
3032 if (textAlign & Qt::AlignLeft)
3033 contentsRect.setLeft(contentsRect.left() + metrics.textPadding.left());
3034 else if (textAlign & Qt::AlignHCenter) {
3035 contentsRect.setLeft(contentsRect.left() + metrics.textPadding.left() / 2);
3036 contentsRect.setRight(contentsRect.right() - metrics.textPadding.right() / 2);
3038 contentsRect.setRight(contentsRect.right() - metrics.textPadding.right());
3040 if (textAlign & Qt::AlignTop)
3041 contentsRect.setTop(contentsRect.top() + metrics.textPadding.top());
3042 else if (textAlign & Qt::AlignVCenter) {
3043 contentsRect.setTop(contentsRect.top() + metrics.textPadding.top() / 2);
3044 contentsRect.setBottom(contentsRect.bottom() - metrics.textPadding.bottom() / 2);
3046 contentsRect.setBottom(contentsRect.bottom() - metrics.textPadding.bottom());
3048 return visualRect(opt->direction, opt->rect, contentsRect);
3051 case SE_ShapedFrameContents:
3052#if QT_CONFIG(combobox)
3053 if (widget && widget->inherits(
"QComboBoxPrivateContainer")) {
3054 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Popup,
3056 if (!resolved.isValid())
3058 const auto &metrics = *resolved.metrics;
3059 QRect contentsRect = opt->rect.marginsRemoved(
3060 metrics.margins + metrics.padding + metrics.textPadding);
3061 return visualRect(opt->direction, opt->rect, contentsRect);
3064#if QT_CONFIG(textedit)
3065 if (qobject_cast<
const QTextEdit *>(widget)) {
3066 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::TextArea,
3068 if (!resolved.isValid())
3070 const auto &metrics = *resolved.metrics;
3071 QRect contentsRect = opt->rect.marginsRemoved(
3072 metrics.margins + metrics.padding + metrics.textPadding);
3073 return visualRect(opt->direction, opt->rect, contentsRect);
3077#if QT_CONFIG(tabbar)
3078 case SE_TabBarTabText:
3079 if (
const auto *tab = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
3080 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::TabButton,
3082 if (!resolved.isValid())
3084 const auto &metrics = *resolved.metrics;
3085 QRect rect = tab->rect.marginsRemoved(
3086 metrics.margins + metrics.padding + metrics.textPadding);
3087 if (!tab->icon.isNull())
3088 rect.setLeft(rect.left() + tab->iconSize.width() + metrics.spacing);
3089 return visualRect(tab->direction, tab->rect, rect);
3092 case SE_TabBarTearIndicatorRight:
3093 case SE_TabBarTearIndicatorLeft:
3094 case SE_TabBarScrollLeftButton:
3095 case SE_TabBarScrollRightButton:
3099#if QT_CONFIG(tabwidget)
3100 case SE_TabWidgetTabContents:
3101 if (qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(opt)) {
3103 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Page, opt->state);
3104 if (!resolved.isValid())
3106 const QRect paneRect = subElementRect(SE_TabWidgetTabPane, opt, widget);
3107 const QRect rect = paneRect.marginsRemoved(resolved.metrics->padding);
3108 return visualRect(opt->direction, opt->rect, rect);
3112#if QT_CONFIG(toolbar)
3113 case SE_ToolBarHandle:
3120 return QCommonStyle::subElementRect(r, opt, widget);
3124void QStyleKitStyle::drawComplexControl(ComplexControl cc,
const QStyleOptionComplex *opt,
3125 QPainter *p,
const QWidget *w)
const
3127 Q_D(
const QStyleKitStyle);
3130#if QT_CONFIG(slider)
3132 if (
const QStyleOptionSlider *slider = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3133 const auto r = d->resolve(w, QQStyleKitReader::ControlType::Slider, slider->state);
3136 const auto &metrics = *r.metrics;
3137 QRect backgroundRect = opt->rect.marginsRemoved(metrics.margins);
3140 d->drawStyledItemRect(r.background(), backgroundRect, p);
3143 if (slider->subControls & SC_SliderGroove) {
3145 const auto grooveRect = proxy()->subControlRect(CC_Slider, opt, SC_SliderGroove, w);
3146 const auto *indicator = r.indicator();
3147 d->drawStyledItemRect(indicator, grooveRect, p);
3150 const auto *foreground = indicator ? indicator->foreground() :
nullptr;
3151 if (foreground && foreground->visible() && foreground->opacity() > 0) {
3152 const bool isHorizontal = slider->orientation == Qt::Horizontal;
3153 const qreal availableW = grooveRect.width()
3154 - foreground->leftMargin() - foreground->rightMargin();
3155 const qreal availableH = grooveRect.height()
3156 - foreground->topMargin() - foreground->bottomMargin();
3158 const qreal range = slider->maximum - slider->minimum;
3159 const qreal ratio = range > 0
3160 ? (slider->sliderPosition - slider->minimum) / range
3163 const auto hAlign = foreground->alignment() & Qt::AlignHorizontal_Mask;
3164 const auto vAlign = foreground->alignment() & Qt::AlignVertical_Mask;
3165 const qreal fgW = resolvedWidth(foreground, availableW);
3166 const qreal fgH = resolvedHeight(foreground, availableH);
3167 const qreal fgX = hAlign & Qt::AlignRight
3168 ? grooveRect.left() + foreground->leftMargin() + availableW - fgW
3169 : hAlign & Qt::AlignHCenter
3170 ? grooveRect.left() + foreground->leftMargin() + (availableW - fgW) / 2
3171 : grooveRect.left() + foreground->leftMargin();
3172 const qreal fgY = vAlign & Qt::AlignBottom
3173 ? grooveRect.top() + foreground->topMargin() + availableH - fgH
3174 : vAlign & Qt::AlignVCenter
3175 ? grooveRect.top() + foreground->topMargin() + (availableH - fgH) / 2
3176 : grooveRect.top() + foreground->topMargin();
3178 const qreal minW = foreground->minimumWidth();
3181 const qreal trackW = foreground->fillWidth()
3182 ? minW + ratio * (fgW - minW)
3184 trackRect = QRectF(fgX, fgY, trackW, fgH);
3186 const qreal trackH = foreground->fillHeight()
3187 ? minW + ratio * (fgH - minW)
3189 const qreal trackY = fgY
3190 + (1.0 - ratio) * (foreground->fillHeight() ? fgH - minW : fgH);
3191 trackRect = QRectF(fgX, trackY, fgW, trackH);
3195 const QRect foregroundBox = visualRect(
3196 opt->direction, grooveRect, QRectF(fgX, fgY, fgW, fgH).toAlignedRect());
3197 QPainterStateGuard stateGuard(p);
3198 if (applyDelegateTransform(p, indicator, grooveRect)
3199 && applyDelegateTransform(p, foreground, foregroundBox)) {
3200 d->drawStyledItemContents(
3202 visualRect(opt->direction, grooveRect, trackRect.toAlignedRect()), p);
3208 if (slider->subControls & SC_SliderHandle) {
3209 QStyleOptionSlider handleOpt(*slider);
3210 handleOpt.rect = subControlRect(CC_Slider, opt, SC_SliderHandle, w);
3211 const auto *handle = r.handle();
3212 if (handle && handle->visible() && handle->opacity() > 0)
3213 d->drawStyledItemRect(handle, handleOpt.rect, p);
3221 if (
const QStyleOptionSlider *dial = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3222 const auto r = d->resolve(w, QQStyleKitReader::ControlType::Dial, dial->state);
3225 const QRectF backgroundRect = QRectF(opt->rect).marginsRemoved(r.metrics->margins);
3226 d->drawStyledItemRect(r.background(), backgroundRect, p);
3228 const auto *handle = r.handle();
3229 if (handle && handle->visible() && handle->opacity() > 0) {
3230 QPainterStateGuard stateGuard(p);
3231 p->translate(backgroundRect.center());
3232 p->rotate(dialAngle(dial));
3233 p->translate(dialHandleOffset(backgroundRect, handle));
3234 d->drawStyledItemRect(handle, QRectF(-handle->width() / 2, -handle->height() / 2,
3235 handle->width(), handle->height()), p);
3241#if QT_CONFIG(combobox)
3243 if (
const QStyleOptionComboBox *combo =
3244 qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
3246 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, combo->state);
3249 QRect frameRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxFrame, w);
3250 d->drawStyledItemRect(r.background(), frameRect, p);
3253 if (combo->subControls & SC_ComboBoxArrow) {
3254 QStyleOptionComboBox indicatorOpt(*combo);
3255 indicatorOpt.rect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
3256 proxy()->drawPrimitive(PE_IndicatorArrowDown, &indicatorOpt, p, w);
3261 if (
auto *cb = qobject_cast<
const QComboBox *>(w); cb && cb->isEditable()) {
3262 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
3263 QPalette stylePalette;
3264 stylePalette.setColor(QPalette::Text, txt->color());
3265 d->setStylePalette(cb->lineEdit(), stylePalette);
3272#if QT_CONFIG(spinbox)
3274 if (
const QStyleOptionSpinBox *spin = qstyleoption_cast<
const QStyleOptionSpinBox *>(opt)) {
3275 const auto r = d->resolve(w, QQStyleKitReader::ControlType::SpinBox, spin->state);
3278 QRect frameRect = opt->rect.marginsRemoved(r.metrics->margins);
3280 d->drawStyledItemRect(r.background(), frameRect, p);
3282 if (spin->subControls & SC_SpinBoxUp) {
3283 QStyleOptionSpinBox upOpt(*spin);
3284 upOpt.rect = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w);
3285 proxy()->drawPrimitive(PE_IndicatorSpinUp, &upOpt, p, w);
3287 if (spin->subControls & SC_SpinBoxDown) {
3288 QStyleOptionSpinBox downOpt(*spin);
3289 downOpt.rect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
3290 proxy()->drawPrimitive(PE_IndicatorSpinDown, &downOpt, p, w);
3294 if (
auto *sb = qobject_cast<
const QSpinBox *>(w)) {
3295 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
3296 QLineEdit *lineEdit = sb->findChild<QLineEdit *>();
3298 QPalette p = lineEdit->palette();
3299 if (p.color(QPalette::Text) != txt->color()) {
3300 p.setColor(QPalette::Text, txt->color());
3301 lineEdit->setPalette(p);
3310#if QT_CONFIG(groupbox)
3312 if (
const QStyleOptionGroupBox *groupBox =
3313 qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
3314 const auto r = d->resolve(w, QQStyleKitReader::ControlType::GroupBox, groupBox->state);
3319 if (groupBox->subControls & SC_GroupBoxFrame) {
3320 QStyleOptionFrame frameOpt;
3321 frameOpt.QStyleOption::operator=(*groupBox);
3322 frameOpt.rect = subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, w);
3323 drawPrimitive(PE_FrameGroupBox, &frameOpt, p, w);
3327 if (groupBox->subControls & SC_GroupBoxLabel && !groupBox->text.isEmpty()) {
3328 const auto *textProps = r.text();
3329 const QFont textFont = r.font();
3330 QRect titleRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w);
3331 d->drawControlText(textProps, textFont,
3332 titleRect.marginsRemoved(r.metrics->textPadding), groupBox->text,
3333 Qt::TextShowMnemonic, p, Qt::AlignLeft | Qt::AlignVCenter);
3341#if QT_CONFIG(scrollbar)
3343 if (
const auto *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3344 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ScrollBar,
3350 if (scrollbar->subControls & SC_ScrollBarGroove) {
3351 QRect backgroundRect = proxy()->subControlRect(
3352 CC_ScrollBar, opt, SC_ScrollBarGroove, w);
3353 d->drawStyledItemRect(r.background(), backgroundRect, p);
3360 if (scrollbar->subControls & SC_ScrollBarSlider) {
3361 QStyleOptionSlider newScrollbar(*scrollbar);
3362 newScrollbar.rect = proxy()->subControlRect(
3363 CC_ScrollBar, opt, SC_ScrollBarSlider, w);
3364 proxy()->drawControl(CE_ScrollBarSlider, &newScrollbar, p, w);
3370#if QT_CONFIG(toolbutton)
3372 if (
const QStyleOptionToolButton *tool =
3373 qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
3374 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolButton, tool->state);
3379 d->drawStyledItemRect(r.background(), opt->rect, p);
3383 & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay))
3384 == QStyleOptionToolButton::MenuButtonPopup
3385 && (tool->subControls & SC_ToolButtonMenu)) {
3386 const QRect menuRect = subControlRect(CC_ToolButton, opt, SC_ToolButtonMenu, w);
3387 d->drawControlIndicator(r.indicator(), menuRect, p);
3391 State bflags = tool->state & ~State_Sunken;
3392 if (bflags & State_AutoRaise) {
3393 if (!(bflags & State_MouseOver) || !(bflags & State_Enabled))
3394 bflags &= ~State_Raised;
3396 if (tool->state & State_Sunken && tool->activeSubControls & SC_ToolButton)
3397 bflags |= State_Sunken;
3398 QStyleOptionToolButton label = *tool;
3399 label.state = bflags;
3400 label.rect = subControlRect(CC_ToolButton, opt, SC_ToolButton, w);
3401 proxy()->drawControl(CE_ToolButtonLabel, &label, p, w);
3409 QCommonStyle::drawComplexControl(cc, opt, p, w);
3413QStyle::SubControl QStyleKitStyle::hitTestComplexControl(ComplexControl cc,
3414 const QStyleOptionComplex *opt,
3415 const QPoint &pt,
const QWidget *w)
const
3417 return QCommonStyle::hitTestComplexControl(cc, opt, pt, w);
3421QRect QStyleKitStyle::subControlRect(ComplexControl cc,
const QStyleOptionComplex *opt,
3422 SubControl sc,
const QWidget *w)
const
3424 using QtPrivate::qSaturateRound;
3425 Q_D(
const QStyleKitStyle);
3428#if QT_CONFIG(slider)
3430 if (
const QStyleOptionSlider *slider = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3431 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Slider,
3433 if (!resolved.isValid())
3435 const auto &metrics = *resolved.metrics;
3436 const bool horizontal = slider->orientation == Qt::Horizontal;
3437 QRect contentsRect = opt->rect
3438 .marginsRemoved(metrics.margins)
3439 .marginsRemoved(metrics.padding);
3441 const auto *indicator = resolved.indicator();
3443 return contentsRect;
3445 case SC_SliderGroove: {
3446 const auto availableW = contentsRect.width()
3447 - indicator->leftMargin() - indicator->rightMargin();
3448 const auto availableH = contentsRect.height()
3449 - indicator->topMargin() - indicator->bottomMargin();
3450 const qreal grooveW = resolvedWidth(indicator, availableW);
3451 const qreal grooveH = resolvedHeight(indicator, availableH);
3453 QRectF grooveRect(0, 0, grooveW, grooveH);
3454 const uint rawHAlign = indicator->alignment() & Qt::AlignHorizontal_Mask;
3455 const uint rawVAlign = indicator->alignment() & Qt::AlignVertical_Mask;
3456 const uint hAlign = rawHAlign
3457 ?
static_cast<Qt::Alignment>(rawHAlign)
3459 const uint vAlign = rawVAlign
3460 ?
static_cast<Qt::Alignment>(rawVAlign)
3463 if (hAlign & Qt::AlignLeft) {
3464 grooveRect.moveLeft(contentsRect.x() + indicator->leftMargin());
3465 }
else if (hAlign & Qt::AlignHCenter) {
3466 const qreal availableWidth = contentsRect.width()
3467 - indicator->leftMargin() - indicator->rightMargin();
3468 grooveRect.moveLeft(contentsRect.x() + indicator->leftMargin()
3469 + (availableWidth - grooveW) / 2.0);
3471 grooveRect.moveLeft(contentsRect.x() + contentsRect.width()
3472 - indicator->rightMargin() - grooveW);
3475 if (vAlign & Qt::AlignTop) {
3476 grooveRect.moveTop(contentsRect.y() + indicator->topMargin());
3477 }
else if (vAlign & Qt::AlignVCenter) {
3478 const qreal availableHeight = contentsRect.height()
3479 - indicator->topMargin() - indicator->bottomMargin();
3480 grooveRect.moveTop(contentsRect.y()
3481 + indicator->topMargin()
3482 + (availableHeight - grooveH) / 2.0);
3484 grooveRect.moveTop(contentsRect.y()
3485 + contentsRect.height()
3486 - indicator->bottomMargin() - grooveH);
3488 return visualRect(opt->direction, opt->rect, grooveRect.toAlignedRect());
3490 case SC_SliderHandle: {
3491 const auto *handle = resolved.handle();
3492 if (!handle || !handle->visible() || handle->opacity() == 0)
3493 return contentsRect;
3495 const qreal handleW = resolvedWidth(
3496 handle, contentsRect.width() - handle->leftMargin() - handle->rightMargin());
3497 const qreal handleH = resolvedHeight(
3498 handle, contentsRect.height() - handle->topMargin() - handle->bottomMargin());
3499 QRectF handleRect(0, 0, handleW, handleH);
3501 const int range = qSaturateRound(contentsRect.width()
3502 - handle->leftMargin() - handle->rightMargin() - handleW);
3503 const int sliderPos = QStyle::sliderPositionFromValue(
3504 slider->minimum, slider->maximum, slider->sliderPosition, range,
false);
3505 handleRect.moveLeft(contentsRect.x() + handle->leftMargin() + sliderPos);
3506 handleRect.moveTop(contentsRect.y()
3507 + handle->topMargin() - handle->bottomMargin()
3508 + (contentsRect.height() - handleH) / 2.0);
3510 const int range = qSaturateRound(contentsRect.height()
3511 - handle->topMargin() - handle->bottomMargin() - handleH);
3512 const int sliderPos = QStyle::sliderPositionFromValue(
3513 slider->minimum, slider->maximum, slider->sliderPosition, range,
true);
3514 handleRect.moveLeft(contentsRect.x()
3515 + handle->leftMargin() - handle->rightMargin()
3516 + (contentsRect.width() - handleW) / 2.0);
3517 handleRect.moveTop(contentsRect.y() + handle->topMargin() + sliderPos);
3519 return visualRect(opt->direction, opt->rect, handleRect.toAlignedRect());
3529 if (
const QStyleOptionSlider *dial = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3530 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Dial, opt->state);
3531 if (!resolved.isValid())
3533 const auto &metrics = *resolved.metrics;
3534 const QRectF backgroundRect(opt->rect.marginsRemoved(metrics.margins));
3535 if (sc == SC_DialGroove)
3536 return visualRect(opt->direction, opt->rect, backgroundRect.toAlignedRect());
3537 if (sc != SC_DialHandle) {
3538 return sc == SC_DialTickmarks
3539 ? QRect() : QRectF(opt->rect.marginsRemoved(metrics.padding)).toAlignedRect();
3542 const auto *handle = resolved.handle();
3545 const QPointF offset = dialHandleOffset(backgroundRect, handle);
3546 const QPointF center = backgroundRect.center()
3547 + QTransform().rotate(dialAngle(dial)).map(offset);
3548 const QRectF handleRect(center.x() - handle->width() / 2,
3549 center.y() - handle->height() / 2,
3550 handle->width(), handle->height());
3551 return visualRect(opt->direction, opt->rect, handleRect.toAlignedRect());
3555#if QT_CONFIG(combobox)
3557 if (
const QStyleOptionComboBox *combo =
3558 qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
3559 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::ComboBox, combo->state);
3562 const auto &metrics = *r.metrics;
3563 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3565 case SC_ComboBoxFrame:
3566 return visualRect(opt->direction, opt->rect, frameRect);
3567 case SC_ComboBoxEditField: {
3568 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3569 QRect indicatorRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
3570 const int spacing = metrics.spacing;
3571 const auto *indicator = r.indicator();
3572 const uint indicatorAlign = indicator
3573 ? resolvedAlignment(indicator->alignment(), Qt::AlignRight, Qt::AlignVCenter)
3574 : uint(Qt::AlignRight | Qt::AlignVCenter);
3575 if (indicatorAlign & Qt::AlignLeft) {
3576 contentsRect.setLeft(indicatorRect.right() + spacing);
3577 }
else if (indicatorAlign & Qt::AlignRight) {
3578 contentsRect.setRight(indicatorRect.left() - spacing);
3580 return visualRect(opt->direction, opt->rect, contentsRect);
3582 case SC_ComboBoxArrow: {
3583 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3584 const auto *indicator = r.indicator();
3585 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
3588 const int w = qSaturateRound(resolvedWidth(
3590 contentsRect.width() - indicator->leftMargin() - indicator->rightMargin()));
3591 const int h = qSaturateRound(resolvedHeight(
3593 contentsRect.height() - indicator->topMargin() - indicator->bottomMargin()));
3594 const uint indicatorAlign = resolvedAlignment(
3595 indicator->alignment(), Qt::AlignRight, Qt::AlignVCenter);
3596 const QMargins indicatorMargins = elementMargins(indicator);
3598 opt->direction, opt->rect,
3599 d->getAlignedRectInContainer(contentsRect, QSize(w, h),
3600 indicatorAlign, QMargins(),
3603 case SC_ComboBoxListBoxPopup: {
3604 QRect popupRect = opt->rect;
3605 popupRect.setTop(opt->rect.bottom());
3606 return visualRect(opt->direction, opt->rect, popupRect);
3614#if QT_CONFIG(spinbox)
3616 if (
const QStyleOptionSpinBox *spinBox =
3617 qstyleoption_cast<
const QStyleOptionSpinBox *>(opt)) {
3618 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::SpinBox, spinBox->state);
3621 const auto &metrics = *r.metrics;
3622 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3623 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3625 case SC_SpinBoxFrame:
3626 return visualRect(opt->direction, opt->rect, frameRect);
3627 case SC_SpinBoxEditField: {
3628 QRect upIndicatorRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w);
3629 QRect downIndicatorRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
3630 const int spacing = metrics.spacing;
3631 const auto *upIndicator = r.indicator() ? r.indicator()->first() :
nullptr;
3632 const auto *downIndicator = r.indicator() ? r.indicator()->second() :
nullptr;
3633 const bool hasUpIndicator = upIndicator
3634 && upIndicator->visible() && upIndicator->opacity() > 0;
3635 const bool hasDownIndicator = downIndicator
3636 && downIndicator->visible() && downIndicator->opacity() > 0;
3637 const uint upAlign = hasUpIndicator
3638 ? resolvedAlignment(upIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
3639 : uint(Qt::AlignLeft | Qt::AlignVCenter);
3640 const uint downAlign = hasDownIndicator
3641 ? resolvedAlignment(downIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
3642 : uint(Qt::AlignLeft | Qt::AlignVCenter);
3643 if (hasUpIndicator && hasDownIndicator) {
3644 if ((upAlign & Qt::AlignLeft) && (downAlign & Qt::AlignRight)) {
3645 contentsRect.setLeft(upIndicatorRect.right() + spacing);
3646 contentsRect.setRight(downIndicatorRect.left() - spacing);
3647 }
else if ((upAlign & Qt::AlignRight) && (downAlign & Qt::AlignLeft)) {
3648 contentsRect.setRight(upIndicatorRect.left() - spacing);
3649 contentsRect.setLeft(downIndicatorRect.right() + spacing);
3651 }
else if (hasUpIndicator) {
3652 if (upAlign & Qt::AlignLeft) {
3653 contentsRect.setLeft(upIndicatorRect.right() + spacing);
3654 }
else if (upAlign & Qt::AlignRight) {
3655 contentsRect.setRight(upIndicatorRect.left() - spacing);
3657 }
else if (hasDownIndicator) {
3658 if (downAlign & Qt::AlignLeft) {
3659 contentsRect.setLeft(downIndicatorRect.right() + spacing);
3660 }
else if (downAlign & Qt::AlignRight) {
3661 contentsRect.setRight(downIndicatorRect.left() - spacing);
3664 return visualRect(opt->direction, opt->rect, contentsRect);
3666 case SC_SpinBoxUp: {
3667 const auto *upIndicator = r.indicator() ? r.indicator()->first() :
nullptr;
3668 if (!upIndicator || !upIndicator->visible() || upIndicator->opacity() == 0)
3669 return contentsRect;
3671 const int w = qSaturateRound(resolvedWidth(
3673 contentsRect.width() - upIndicator->leftMargin() - upIndicator->rightMargin()));
3674 const int h = qSaturateRound(resolvedHeight(
3676 contentsRect.height() - upIndicator->topMargin() - upIndicator->bottomMargin()));
3677 const uint upAlign = resolvedAlignment(
3678 upIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
3679 const QMargins upMargins = elementMargins(upIndicator);
3680 return visualRect(opt->direction, opt->rect,
3681 d->getAlignedRectInContainer(contentsRect, QSize(w, h), upAlign,
3682 QMargins(), upMargins));
3684 case SC_SpinBoxDown: {
3685 const auto *downIndicator = r.indicator() ? r.indicator()->second() :
nullptr;
3686 if (!downIndicator || !downIndicator->visible() || downIndicator->opacity() == 0)
3689 const int w = qSaturateRound(resolvedWidth(
3691 contentsRect.width()
3692 - downIndicator->leftMargin() - downIndicator->rightMargin()));
3693 const int h = qSaturateRound(resolvedHeight(
3695 contentsRect.height()
3696 - downIndicator->topMargin() - downIndicator->bottomMargin()));
3697 const uint downAlign = resolvedAlignment(downIndicator->alignment(), Qt::AlignLeft,
3699 const QMargins downMargins = elementMargins(downIndicator);
3700 return visualRect(opt->direction, opt->rect,
3701 d->getAlignedRectInContainer(contentsRect, QSize(w, h), downAlign,
3702 QMargins(), downMargins));
3710#if QT_CONFIG(groupbox)
3712 if (
const QStyleOptionGroupBox *groupBox =
3713 qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
3714 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::GroupBox,
3718 const auto &metrics = *r.metrics;
3719 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3721 case SC_GroupBoxFrame:
3722 return visualRect(opt->direction, opt->rect, frameRect);
3723 case SC_GroupBoxLabel: {
3724 const int fontHeight = opt->fontMetrics.height();
3725 const int labelHeight = metrics.textPadding.top()
3726 + fontHeight + metrics.textPadding.bottom();
3727 const QRect labelContainer(opt->rect.left(), opt->rect.top(), opt->rect.width(),
3729 return visualRect(opt->direction, opt->rect, labelContainer);
3731 case SC_GroupBoxCheckBox: {
3735 case SC_GroupBoxContents: {
3736 const auto labelHeight = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w)
3738 const auto offset = metrics.padding.top()
3739 + qMax(labelHeight, metrics.margins.top() + metrics.spacing);
3741 opt->rect.left() + metrics.padding.left(), opt->rect.top() + offset,
3742 opt->rect.width() - metrics.padding.left() - metrics.padding.right(),
3743 opt->rect.bottom() - opt->rect.top() - offset - metrics.padding.bottom());
3744 return visualRect(opt->direction, opt->rect, contentsRect);
3752#if QT_CONFIG(scrollbar)
3754 if (
const auto *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3755 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ScrollBar,
3757 if (!resolved.isValid())
3759 const auto &metrics = *resolved.metrics;
3760 const bool horizontal = scrollbar->orientation == Qt::Horizontal;
3761 const QRectF grooveRect = opt->rect.marginsRemoved(metrics.margins);
3765 case SC_ScrollBarAddLine:
3766 case SC_ScrollBarSubLine:
3767 case SC_ScrollBarSubPage:
3768 case SC_ScrollBarAddPage:
3770 case SC_ScrollBarGroove:
3771 return visualRect(opt->direction, opt->rect, grooveRect.toAlignedRect());
3772 case SC_ScrollBarSlider: {
3773 const auto *indicator = resolved.indicator();
3774 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
3776 const QRectF contentsRect = grooveRect.marginsRemoved(metrics.padding);
3778 const qreal availableW = contentsRect.width()
3779 - indicator->leftMargin() - indicator->rightMargin();
3780 const qreal availableH = contentsRect.height()
3781 - indicator->topMargin() - indicator->bottomMargin();
3783 const int totalRange = scrollbar->maximum
3784 - scrollbar->minimum + scrollbar->pageStep;
3785 const qreal ratio = totalRange > 0 ? qreal(scrollbar->pageStep) / totalRange : 1.0;
3789 const qreal sliderW = qMax(
3790 qreal(metrics.indicatorImplicitSize.width()), availableW * ratio);
3791 const qreal sliderH = resolvedHeight(indicator, availableH);
3792 const qreal travelRange = qMax(0.0, availableW - sliderW);
3793 const int sliderPos = QStyle::sliderPositionFromValue(
3794 scrollbar->minimum, scrollbar->maximum, scrollbar->sliderPosition,
3795 int(travelRange), scrollbar->upsideDown);
3796 sliderRect = QRectF(
3797 contentsRect.x() + indicator->leftMargin() + sliderPos,
3798 contentsRect.y() + indicator->topMargin() + (availableH - sliderH) / 2.0,
3801 const qreal sliderH = qMax(
3802 qreal(metrics.indicatorImplicitSize.width()), availableH * ratio);
3803 const qreal sliderW = resolvedWidth(indicator, availableW);
3804 const qreal travelRange = qMax(0.0, availableH - sliderH);
3805 const int sliderPos = QStyle::sliderPositionFromValue(
3806 scrollbar->minimum, scrollbar->maximum, scrollbar->sliderPosition,
3807 int(travelRange), scrollbar->upsideDown);
3808 sliderRect = QRectF(
3809 contentsRect.x() + indicator->leftMargin() + (availableW - sliderW) / 2.0,
3810 contentsRect.y() + indicator->topMargin() + sliderPos, sliderW, sliderH);
3812 return visualRect(opt->direction, opt->rect, sliderRect.toAlignedRect());
3820#if QT_CONFIG(toolbutton)
3822 if (
const auto *tool = qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
3823 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolButton,
3825 if (!resolved.isValid())
3827 const auto &metrics = *resolved.metrics;
3828 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3830 case SC_ToolButton: {
3831 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3832 const bool hasMenuButton = (tool->features
3833 & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::HasMenu))
3835 const auto *indicator = resolved.indicator();
3836 if (hasMenuButton && indicator && indicator->visible()
3837 && indicator->opacity() > 0) {
3838 const QRect menuRect = subControlRect(CC_ToolButton, opt, SC_ToolButtonMenu, w);
3839 const int spacing = metrics.spacing;
3840 const uint indicatorAlign = resolvedAlignment(indicator->alignment(),
3841 Qt::AlignRight, Qt::AlignVCenter);
3842 if (indicatorAlign & Qt::AlignLeft)
3843 contentsRect.setLeft(menuRect.right() + spacing);
3844 else if (indicatorAlign & Qt::AlignRight)
3845 contentsRect.setRight(menuRect.left() - spacing);
3847 return visualRect(opt->direction, opt->rect, contentsRect);
3849 case SC_ToolButtonMenu: {
3850 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3852 & (QStyleOptionToolButton::MenuButtonPopup
3853 | QStyleOptionToolButton::PopupDelay))
3854 != QStyleOptionToolButton::MenuButtonPopup) {
3858 const auto *indicator = resolved.indicator();
3859 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
3862 const int w = qSaturateRound(resolvedWidth(
3864 contentsRect.width() - indicator->leftMargin() - indicator->rightMargin()));
3865 const int h = qSaturateRound(resolvedHeight(
3867 contentsRect.height() - indicator->topMargin() - indicator->bottomMargin()));
3868 const uint indicatorAlign = resolvedAlignment(indicator->alignment(),
3869 Qt::AlignRight, Qt::AlignVCenter);
3870 const QMargins indicatorMargins = elementMargins(indicator);
3871 return visualRect(opt->direction, opt->rect,
3872 d->getAlignedRectInContainer(contentsRect, QSize(w, h), indicatorAlign, QMargins(), indicatorMargins));
3883 return QCommonStyle::subControlRect(cc, opt, sc, w);
3887QSize QStyleKitStyle::sizeFromContents(ContentsType ct,
const QStyleOption *opt,
3888 const QSize &contentsSize,
const QWidget *widget)
const
3890 Q_D(
const QStyleKitStyle);
3893#if QT_CONFIG(pushbutton)
3896#if QT_CONFIG(toolbutton)
3897 case CT_ToolButton: {
3898 auto controlType = QQStyleKitReader::ControlType::ToolButton;
3899 if (
const auto *buttonOpt = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
3900 controlType = (buttonOpt->features & QStyleOptionButton::Flat)
3901 ? QQStyleKitReader::ControlType::FlatButton
3902 : QQStyleKitReader::ControlType::Button;
3904 const auto resolved = d->resolveLayout(controlType, opt->state);
3905 if (!resolved.isValid())
3908 const auto &metrics = *resolved.metrics;
3909 const QSize contentSize = contentsSize
3910 + QSize(metrics.padding.left() + metrics.padding.right(),
3911 metrics.padding.top() + metrics.padding.bottom())
3912 + QSize(metrics.textPadding.left() + metrics.textPadding.right(),
3913 metrics.textPadding.top() + metrics.textPadding.bottom());
3914 const QSize bgSize = metrics.bgImplicitSize
3915 + QSize(metrics.margins.left() + metrics.margins.right(),
3916 metrics.margins.top() + metrics.margins.bottom());
3917 return contentSize.expandedTo(bgSize);
3921 case CT_RadioButton:
3922 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
3923 const auto controlType = ct == CT_CheckBox ? QQStyleKitReader::ControlType::CheckBox
3924 : QQStyleKitReader::ControlType::RadioButton;
3925 const auto resolved = d->resolveLayout(controlType, opt->state);
3926 if (!resolved.isValid())
3928 const auto &metrics = *resolved.metrics;
3929 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, btn->text);
3930 const int bgWidth = metrics.bgImplicitSize.width()
3931 + metrics.margins.left() + metrics.margins.right();
3932 const int bgHeight = metrics.bgImplicitSize.height()
3933 + metrics.margins.top() + metrics.margins.bottom();
3934 const int contentWidth = std::max(textSize.width(), contentsSize.width())
3935 + metrics.padding.left() + metrics.padding.right() + metrics.textPadding.left()
3936 + metrics.textPadding.right();
3937 const int contentHeight = std::max(textSize.height(), contentsSize.height())
3938 + metrics.padding.top() + metrics.padding.bottom() + metrics.textPadding.top()
3939 + metrics.textPadding.bottom();
3940 const int indicatorWidth = metrics.indicatorImplicitSize.width()
3941 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
3942 const int indicatorHeight = metrics.indicatorImplicitSize.height()
3943 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
3944 return QSize(std::max({ contentWidth + indicatorWidth + metrics.spacing, bgWidth }),
3945 std::max({ contentHeight, indicatorHeight, bgHeight }));
3948#if QT_CONFIG(itemviews)
3949 case CT_ItemViewItem:
3950 if (
const auto *item = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
3951 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
3952 if (!resolved.isValid())
3954 const auto &metrics = *resolved.metrics;
3955 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, item->text);
3956 const int bgWidth = metrics.bgImplicitSize.width()
3957 + metrics.margins.left() + metrics.margins.right();
3958 const int bgHeight = metrics.bgImplicitSize.height()
3959 + metrics.margins.top() + metrics.margins.bottom();
3960 const int contentWidth = std::max(textSize.width(), contentsSize.width())
3961 + metrics.padding.left() + metrics.padding.right() + metrics.textPadding.left()
3962 + metrics.textPadding.right();
3963 const int contentHeight = std::max(textSize.height(), contentsSize.height())
3964 + metrics.padding.top() + metrics.padding.bottom() + metrics.textPadding.top()
3965 + metrics.textPadding.bottom();
3966 const int indicatorWidth = metrics.indicatorImplicitSize.width()
3967 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
3968 const int indicatorHeight = metrics.indicatorImplicitSize.height()
3969 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
3970 return QSize(std::max({ contentWidth + indicatorWidth + metrics.spacing, bgWidth }),
3971 std::max({ contentHeight, indicatorHeight, bgHeight }));
3975 case CT_ProgressBar:
3976 if (qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
3977 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar,
3979 if (!resolved.isValid())
3981 const auto &metrics = *resolved.metrics;
3982 const auto indicatorW = metrics.indicatorImplicitSize.width()
3983 + metrics.indicatorMargins.left()
3984 + metrics.indicatorMargins.right();
3985 const auto indicatorH = metrics.indicatorImplicitSize.height()
3986 + metrics.indicatorMargins.top()
3987 + metrics.indicatorMargins.bottom();
3988 const int bgW = metrics.bgImplicitSize.width()
3989 + metrics.margins.left() + metrics.margins.right();
3990 const int bgH = metrics.bgImplicitSize.height()
3991 + metrics.margins.top() + metrics.margins.bottom();
3993 const int contentW = indicatorW + metrics.padding.left() + metrics.padding.right();
3994 const int contentH = indicatorH + metrics.padding.top() + metrics.padding.bottom();
3995 return QSize(std::max(contentW, bgW), std::max(contentH, bgH));
3999 if (qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
4000 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Slider,
4002 if (!resolved.isValid())
4004 const auto &metrics = *resolved.metrics;
4006 const int bgW = std::max(
4007 metrics.padding.left() + metrics.padding.right()
4008 + metrics.indicatorImplicitSize.width()
4009 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right(),
4010 metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right());
4011 const int bgH = std::max(
4012 metrics.padding.top() + metrics.padding.bottom()
4013 + metrics.indicatorImplicitSize.height()
4014 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom(),
4015 metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom());
4016 const int handleW = metrics.handleImplicitSize.width()
4017 + metrics.padding.left()
4018 + metrics.padding.right();
4019 const int handleH = metrics.handleImplicitSize.height()
4020 + metrics.padding.top()
4021 + metrics.padding.bottom();
4022 return QSize(std::max(handleW, bgW), std::max(handleH, bgH));
4025#if QT_CONFIG(lineedit)
4027 if (
const auto *lineEdit = qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
4028 QStyleOption lineEditOpt(*lineEdit);
4029 lineEditOpt.state &= ~QStyle::State_Sunken;
4030# if QT_CONFIG(spinbox)
4031 const bool isInSpinBox = widget && qobject_cast<
const QSpinBox *>(widget->parent());
4033 const bool isInSpinBox =
false;
4035 auto controlType = isInSpinBox ? QQStyleKitReader::ControlType::SpinBox
4036 : QQStyleKitReader::ControlType::TextField;
4037 const auto resolved = d->resolveLayout(controlType, lineEditOpt.state);
4038 if (!resolved.isValid())
4040 const auto &metrics = *resolved.metrics;
4044 bgSize = metrics.bgImplicitSize.grownBy(metrics.margins);
4045 const QSize contentSizeWithPadding = contentsSize
4046 .grownBy(metrics.textPadding)
4047 .grownBy(metrics.padding);
4048 return contentSizeWithPadding.expandedTo(bgSize);
4052#if QT_CONFIG(combobox)
4054 if (
const auto *comboBox = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
4055 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ComboBox,
4057 if (!resolved.isValid())
4059 const auto &metrics = *resolved.metrics;
4060 const QSize textSize = opt->fontMetrics.size(
4061 Qt::TextShowMnemonic, comboBox->currentText);
4062 const int bgW = metrics.bgImplicitSize.width()
4063 + metrics.margins.left() + metrics.margins.right();
4064 const int bgH = metrics.bgImplicitSize.height()
4065 + metrics.margins.top() + metrics.margins.bottom();
4066 const int contentW = textSize.width()
4067 + metrics.padding.left() + metrics.padding.right()
4068 + metrics.textPadding.left() + metrics.textPadding.right();
4069 const int contentH = textSize.height()
4070 + metrics.padding.top() + metrics.padding.bottom()
4071 + metrics.textPadding.top() + metrics.textPadding.bottom();
4072 const int indicatorW = metrics.indicatorImplicitSize.width()
4073 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
4074 const int indicatorH = metrics.indicatorImplicitSize.height()
4075 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
4076 return QSize(std::max({ contentW + indicatorW + metrics.spacing, bgW }),
4077 std::max({ contentH, indicatorH, bgH }));
4081#if QT_CONFIG(spinbox)
4083 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::SpinBox, opt->state);
4084 if (!resolved.isValid())
4086 const auto &metrics = *resolved.metrics;
4087 const int bgW = metrics.bgImplicitSize.width()
4088 + metrics.margins.left() + metrics.margins.right();
4089 const int bgH = metrics.bgImplicitSize.height()
4090 + metrics.margins.top() + metrics.margins.bottom();
4091 const int contentW = contentsSize.width()
4092 + metrics.padding.left() + metrics.padding.right()
4093 + metrics.textPadding.left() + metrics.textPadding.right();
4094 const int contentH = contentsSize.height()
4095 + metrics.padding.top() + metrics.padding.bottom()
4096 + metrics.textPadding.top() + metrics.textPadding.bottom();
4100 const int indicatorW = (metrics.indicatorImplicitSize.width()
4101 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right()) * 2;
4102 const int indicatorH = metrics.indicatorImplicitSize.height()
4103 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
4104 return QSize(std::max({ contentW + indicatorW + metrics.spacing, bgW }),
4105 std::max({ contentH, indicatorH, bgH }));
4108#if QT_CONFIG(tabbar)
4110 if (qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
4111 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::TabButton,
4113 if (!resolved.isValid())
4115 const auto &m = *resolved.metrics;
4116 const auto bgSize = m.bgImplicitSize.grownBy(m.margins);
4117 const auto contentSizeWithPadding = contentsSize.grownBy(m.padding + m.textPadding);
4118 return contentSizeWithPadding.expandedTo(bgSize);
4122#if QT_CONFIG(tabwidget)
4124 if (qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(opt)) {
4126 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Page, opt->state);
4127 if (!resolved.isValid())
4129 const auto &m = *resolved.metrics;
4130 const auto bgSize = m.bgImplicitSize.grownBy(m.margins);
4131 const auto contentSizeWithPadding = contentsSize.grownBy(m.padding);
4132 return contentSizeWithPadding.expandedTo(bgSize);
4136#if QT_CONFIG(groupbox)
4138 if (
const auto *groupBox = qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
4139 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::GroupBox,
4141 if (!resolved.isValid())
4143 const auto &metrics = *resolved.metrics;
4144 const QSize bgSize = metrics.bgImplicitSize
4145 + QSize(metrics.margins.left() + metrics.margins.right(),
4146 metrics.margins.top() + metrics.margins.bottom());
4147 const QSize contentSize = contentsSize.grownBy(metrics.padding);
4148 const QSize textSize = opt->fontMetrics
4149 .size(Qt::TextShowMnemonic, groupBox->text)
4150 .grownBy(metrics.textPadding);
4151 return textSize.expandedTo(contentSize).expandedTo(bgSize);
4155#if QT_CONFIG(scrollbar)
4157 if (qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
4158 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ScrollBar, opt->state);
4159 if (!resolved.isValid())
4161 const auto &metrics = *resolved.metrics;
4163 const int iH = metrics.indicatorImplicitSize.height()
4164 + metrics.padding.top() + metrics.padding.bottom()
4165 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
4166 const int iW = metrics.indicatorImplicitSize.width()
4167 + metrics.padding.left() + metrics.padding.right()
4168 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
4169 const int bgH = metrics.bgImplicitSize.height()
4170 + metrics.margins.top() + metrics.margins.bottom();
4171 const int bgW = metrics.bgImplicitSize.width()
4172 + metrics.margins.left() + metrics.margins.right();
4173 return QSize(std::max(iW, bgW), std::max(iH, bgH));
4179 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
4183 const auto menuType = widget && widget->inherits(
"QComboBoxPrivateContainer")
4184 ? QQStyleKitReader::ControlType::Popup
4185 : QQStyleKitReader::ControlType::Menu;
4186 const auto menuResolved = d->resolveLayout(menuType, opt->state);
4188 if (menuResolved.isValid()) {
4189 const auto &mm = *menuResolved.metrics;
4190 minMenuW = mm.bgImplicitSize.width()
4191 + mm.margins.left() + mm.margins.right() - 2 * mm.padding.left();
4194 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
4195 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuSeparator,
4197 if (!resolved.isValid())
4199 const auto &m = *resolved.metrics;
4200 const int bgWidth = m.bgImplicitSize.width()
4201 + m.margins.left() + m.margins.right();
4202 const int bgHeight = m.bgImplicitSize.height()
4203 + m.margins.top() + m.margins.bottom();
4204 return QSize(std::max(bgWidth, minMenuW), bgHeight);
4207 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuItem, opt->state);
4208 if (!resolved.isValid())
4210 const auto &m = *resolved.metrics;
4211 const auto *indicator = resolved.indicator();
4212 const auto *first = indicator ? indicator->first() :
nullptr;
4213 const auto *second = indicator ? indicator->second() :
nullptr;
4216 using QtPrivate::qSaturateRound;
4217 if (first && menuItem->checkType != QStyleOptionMenuItem::NotCheckable) {
4218 indicatorW += qSaturateRound(
4219 first->leftMargin() + first->width() + first->rightMargin()) + m.spacing;
4220 indicatorH = std::max(
4221 qSaturateRound(first->topMargin() + first->bottomMargin() + first->height()),
4224 if (second && menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {
4225 indicatorW += qSaturateRound(
4226 second->leftMargin() + second->width() + second->rightMargin()) + m.spacing;
4227 indicatorH = std::max(
4228 qSaturateRound(second->topMargin() + second->bottomMargin() + second->height()),
4231 const int bgH = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
4232 const int iconReserved = menuItem->maxIconWidth > 0
4233 ? menuItem->maxIconWidth + m.spacing
4235 const int contentW = contentsSize.width()
4236 + m.padding.left() + m.padding.right()
4237 + m.textPadding.left() + m.textPadding.right()
4238 + indicatorW + iconReserved;
4239 const int contentH = contentsSize.height()
4240 + m.padding.top() + m.padding.bottom()
4241 + m.textPadding.top() + m.textPadding.bottom();
4242 return QSize(std::max(contentW, minMenuW), std::max({ contentH, indicatorH, bgH }));
4246 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Menu, opt->state);
4247 if (!resolved.isValid())
4249 const auto &m = *resolved.metrics;
4250 const int height = std::max(contentsSize.height(), m.bgImplicitSize.height())
4251 + m.margins.top() + m.margins.bottom();
4252 return QSize(contentsSize.width(), height);
4255#if QT_CONFIG(menubar)
4257 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuBar, opt->state);
4258 if (!resolved.isValid())
4260 const auto &m = *resolved.metrics;
4261 const int bgWidth = m.bgImplicitSize.width() + m.margins.left() + m.margins.right();
4262 const int bgHeight = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
4263 const int contentW = contentsSize.width() + m.padding.left() + m.padding.right();
4264 const int contentH = contentsSize.height() + m.padding.top() + m.padding.bottom();
4265 return QSize(std::max(contentW, bgWidth), std::max(contentH, bgHeight));
4267 case CT_MenuBarItem: {
4268 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuBarItem,
4270 if (!resolved.isValid())
4272 const auto &m = *resolved.metrics;
4273 const int bgWidth = m.bgImplicitSize.width() + m.margins.left() + m.margins.right();
4274 const int bgHeight = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
4275 const int contentW = contentsSize.width()
4276 + m.padding.left() + m.padding.right()
4277 + m.textPadding.left() + m.textPadding.right();
4278 const int contentH = contentsSize.height()
4279 + m.padding.top() + m.padding.bottom()
4280 + m.textPadding.top() + m.textPadding.bottom();
4281 return QSize(std::max(contentW, bgWidth), std::max(contentH, bgHeight));
4287 return QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget);
4291int QStyleKitStyle::pixelMetric(PixelMetric m,
const QStyleOption *opt,
const QWidget *widget)
const
4293 Q_D(
const QStyleKitStyle);
4296 case PM_MenuPanelWidth:
4299 case PM_MenuTearoffHeight:
4300 case PM_MenuScrollerHeight:
4302 case PM_MenuHMargin:
4303 case PM_MenuVMargin: {
4304 const auto controlType = widget && widget->inherits(
"QComboBoxPrivateContainer")
4305 ? QQStyleKitReader::ControlType::Popup
4306 : QQStyleKitReader::ControlType::Menu;
4307 const auto resolved = d->resolveLayout(controlType, opt ? opt->state : QStyle::State_None);
4308 if (!resolved.isValid())
4310 return m == PM_MenuHMargin ? resolved.metrics->padding.left()
4311 : resolved.metrics->padding.top();
4314#if QT_CONFIG(menubar)
4315 case PM_MenuBarItemSpacing: {
4316 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuBarItem,
4317 opt ? opt->state : QStyle::State_None);
4318 if (resolved.isValid())
4319 return resolved.metrics->spacing;
4323#if QT_CONFIG(toolbar)
4324 case PM_ToolBarFrameWidth:
4327 case PM_ToolBarItemMargin: {
4328 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolBar,
4329 opt ? opt->state : QStyle::State_None);
4330 if (!resolved.isValid())
4332 return resolved.metrics->padding.left();
4334 case PM_ToolBarItemSpacing: {
4335 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolBar,
4336 opt ? opt->state : QStyle::State_None);
4337 if (resolved.isValid())
4338 return resolved.metrics->spacing;
4341 case PM_ToolBarHandleExtent: {
4344 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolBar,
4345 opt ? opt->state : QStyle::State_None);
4346 if (!resolved.isValid())
4348 const auto &metrics = *resolved.metrics;
4349 const bool horizontal = !opt || (opt->state & State_Horizontal);
4350 const int crossImplicit = horizontal
4351 ? metrics.bgImplicitSize.height()
4352 : metrics.bgImplicitSize.width();
4353 const int crossMargins = horizontal
4354 ? metrics.margins.top() + metrics.margins.bottom()
4355 : metrics.margins.left() + metrics.margins.right();
4356 const int crossPadding = horizontal
4357 ? metrics.padding.top() + metrics.padding.bottom()
4358 : metrics.padding.left() + metrics.padding.right();
4359 return qMax(0, crossImplicit + crossMargins - crossPadding);
4362#if QT_CONFIG(tabbar)
4363 case PM_TabBarTabHSpace:
4364 case PM_TabBarTabVSpace:
4365 case PM_TabBarTabOverlap:
4367 case PM_TabCloseIndicatorWidth:
4368 case PM_TabCloseIndicatorHeight:
4374 return QCommonStyle::pixelMetric(m, opt, widget);
4378int QStyleKitStyle::styleHint(StyleHint sh,
const QStyleOption *opt,
const QWidget *w,
4379 QStyleHintReturn *shret)
const
4383 case SH_SpinBox_SelectOnStep:
4384 case SH_ToolBar_Movable:
4385 case SH_TabBar_PreferNoArrows:
4387 case SH_Menu_MouseTracking:
4388 case SH_MenuBar_MouseTracking:
4389 case SH_Menu_Scrollable:
4394 return QCommonStyle::styleHint(sh, opt, w, shret);
4398QPalette QStyleKitStyle::standardPalette()
const
4400 return QCommonStyle::standardPalette();
4404void QStyleKitStyle::polish(QWidget *widget)
4409 Q_D(QStyleKitStyle);
4414 d->ensureDefaultStyle();
4416 widget->setAttribute(Qt::WA_Hover);
4418#if QT_CONFIG(scrollbar)
4422 if (qobject_cast<QScrollBar *>(widget))
4423 widget->setAttribute(Qt::WA_OpaquePaintEvent,
false);
4427 const bool isInteractiveControl =
false
4428#if QT_CONFIG(pushbutton)
4429 || qobject_cast<
const QPushButton *>(widget)
4431#if QT_CONFIG(checkbox)
4432 || qobject_cast<
const QCheckBox *>(widget)
4434#if QT_CONFIG(radiobutton)
4435 || qobject_cast<
const QRadioButton *>(widget)
4437#if QT_CONFIG(combobox)
4438 || qobject_cast<
const QComboBox *>(widget)
4439 || (widget && widget->inherits(
"QComboBoxPrivateContainer"))
4441#if QT_CONFIG(lineedit)
4442 || qobject_cast<
const QLineEdit *>(widget)
4444#if QT_CONFIG(textedit)
4445 || qobject_cast<
const QTextEdit *>(widget)
4446 || qobject_cast<
const QPlainTextEdit *>(widget)
4449 || qobject_cast<
const QLabel *>(widget)
4451#if QT_CONFIG(progressbar)
4452 || qobject_cast<
const QProgressBar *>(widget)
4454#if QT_CONFIG(slider)
4455 || qobject_cast<
const QSlider *>(widget)
4458 || qobject_cast<
const QDial *>(widget)
4460#if QT_CONFIG(scrollbar)
4461 || qobject_cast<
const QScrollBar *>(widget)
4463#if QT_CONFIG(spinbox)
4464 || qobject_cast<
const QSpinBox *>(widget)
4466#if QT_CONFIG(tabbar)
4467 || qobject_cast<
const QTabBar *>(widget)
4469#if QT_CONFIG(tabwidget)
4470 || qobject_cast<
const QTabWidget *>(widget)
4473 || qobject_cast<
const QMenu *>(widget)
4474 || qobject_cast<
const QMenuBar *>(widget)
4477 if (isInteractiveControl)
4478 d->readerForWidget(widget);
4483 if (QWidget *vp = managedViewport(widget); vp && vp->autoFillBackground()) {
4484 vp->setAutoFillBackground(
false);
4485 d->bgFillDisabledWidgets.insert(widget);
4488 if (qobject_cast<QMenu *>(widget)
4489# if QT_CONFIG(combobox)
4490 || widget->inherits(
"QComboBoxPrivateContainer")
4495 if (!widget->testAttribute(Qt::WA_TranslucentBackground)) {
4496 widget->setAttribute(Qt::WA_TranslucentBackground,
true);
4497 d->bgFillDisabledWidgets.insert(widget);
4502#if QT_CONFIG(lineedit)
4503 if (
auto *lineEdit = qobject_cast<QLineEdit *>(widget)) {
4504 if (!lineEdit->property(
"_q_stylekit_alignment_set").toBool()) {
4505 QQStyleKitReader *r = d->readerForWidget(widget);
4507 const QWidget *target = containerWidget(widget);
4508 QQStyleKitReader::ControlType ct = controlTypeForWidget(target);
4509 r->setControlType(ct);
4510 const auto *textProps = r->global()->text();
4512 const uint align = resolvedAlignment(
4513 textProps->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
4514 lineEdit->setAlignment(Qt::Alignment(align));
4521 d->refreshStyleFont(widget);
4522 d->refreshStylePalette(widget);
4523 d->refreshStyleMinimumSize(widget);
4525 bool needsEventFilter = isSelfPaintingWidget(widget);
4528 needsEventFilter = needsEventFilter || qobject_cast<QMenu *>(widget);
4530 if (needsEventFilter)
4531 widget->installEventFilter(
this);
4533 QCommonStyle::polish(widget);
4537void QStyleKitStyle::polish(QApplication *app)
4539 QCommonStyle::polish(app);
4543void QStyleKitStyle::polish(QPalette &palette)
4545 QCommonStyle::polish(palette);
4549void QStyleKitStyle::unpolish(QWidget *widget)
4551 Q_D(QStyleKitStyle);
4552 d->unsetStylePalette(widget);
4553 d->unsetStyleFont(widget);
4554 d->unsetStyleMinimumSize(widget);
4555 bool hasEventFilter = isSelfPaintingWidget(widget);
4557 hasEventFilter = hasEventFilter || qobject_cast<QMenu *>(widget);
4560 widget->removeEventFilter(
this);
4561 if (d->bgFillDisabledWidgets.remove(widget)) {
4562 if (QWidget *vp = managedViewport(widget))
4563 vp->setAutoFillBackground(
true);
4565 else if (qobject_cast<QMenu *>(widget)
4566# if QT_CONFIG(combobox)
4567 || widget->inherits(
"QComboBoxPrivateContainer")
4570 widget->setAttribute(Qt::WA_TranslucentBackground,
false);
4574 d->cleanupWidgetReader(widget);
4575#if QT_CONFIG(scrollbar)
4576 if (qobject_cast<QScrollBar *>(widget))
4577 widget->setAttribute(Qt::WA_OpaquePaintEvent);
4579 QCommonStyle::unpolish(widget);
4583void QStyleKitStyle::unpolish(QApplication *app)
4585 Q_D(QStyleKitStyle);
4586 d->clearMetricsCache();
4587 QCommonStyle::unpolish(app);
4591bool QStyleKitStyle::eventFilter(QObject *obj, QEvent *event)
4593 Q_D(QStyleKitStyle);
4594 switch (event->type()) {
4595 case QEvent::EnabledChange:
4596 case QEvent::HoverEnter:
4597 case QEvent::HoverLeave:
4598 case QEvent::FocusIn:
4599 case QEvent::FocusOut:
4600 if (
auto *w = qobject_cast<QWidget *>(obj)) {
4601 if (d->customPaletteWidgets.contains(w))
4602 d->refreshStylePalette(w);
4603 if (d->customFontWidgets.contains(w))
4604 d->refreshStyleFont(w);
4609 if (
auto *menu = qobject_cast<QMenu *>(obj))
4610 d->cleanupSubElements(menu);
4616 return QCommonStyle::eventFilter(obj, event);
4620bool QStyleKitStyle::event(QEvent *event)
4622 return QCommonStyle::event(event);
4627#include "moc_qstylekitstyle.cpp"
Combined button and popup list for selecting options.
static QWidget * paintTarget(const QWidget *widget)
static bool applyDelegateTransform(QPainter *painter, const QQStyleKitDelegateProperties *element, const QRectF &box)
static QWidget * managedViewport(QWidget *widget)
static QMargins elementMargins(const QQStyleKitDelegateProperties *element)
static uint resolvedAlignment(uint raw, Qt::Alignment hDefault, Qt::Alignment vDefault)
static qreal resolvedWidth(const QQStyleKitDelegateProperties *element, qreal availableW)
static bool isSelfPaintingWidget(const QWidget *widget)
static qreal resolvedHeight(const QQStyleKitDelegateProperties *element, qreal availableH)
static QUrl urlFromStylePath(const QString &filePath)
static const QWidget * containerWidget(const QWidget *w)