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>
34#if QT_CONFIG(scrollbar)
35# include <QtWidgets/qscrollbar.h>
38# include <QtWidgets/qspinbox.h>
40#if QT_CONFIG(progressbar)
41# include <QtWidgets/qprogressbar.h>
43#if QT_CONFIG(textedit)
44# include <QtWidgets/qtextedit.h>
45# include <QtWidgets/qplaintextedit.h>
48# include <QtWidgets/qtabbar.h>
50#if QT_CONFIG(tabwidget)
51# include <QtWidgets/qtabwidget.h>
54# include <QtWidgets/qtoolbar.h>
56#if QT_CONFIG(toolbutton)
57# include <QtWidgets/qtoolbutton.h>
59#if QT_CONFIG(groupbox)
60# include <QtWidgets/qgroupbox.h>
63# include <QtWidgets/qmenu.h>
64# include <QtWidgets/qmenubar.h>
67# include <QtWidgets/qlabel.h>
69#include <QtWidgets/private/qwidget_p.h>
70#include <QtCore/private/qobject_p.h>
71#include <QtGui/qpainter.h>
72#include <QtGui/qpainterpath.h>
73#include <QtGui/qpainterstateguard.h>
74#include <QtGui/qstylehints.h>
75#include <QtCore/qloggingcategory.h>
76#include <QtCore/qnumeric.h>
77#include <QtQml/private/qqmlcomponent_p.h>
78#include <QtQml/qqmlengine.h>
79#include <QtQuick/private/qquicktransition_p.h>
80#include <QtLabsStyleKit/private/qqstylekit_p.h>
81#include <QtLabsStyleKit/private/qqstylekitcontrolproperties_p.h>
82#include <QtLabsStyleKit/private/qqstylekitstyle_p.h>
86Q_STATIC_LOGGING_CATEGORY(lcStyleKit,
"qt.labs.stylekit")
89
90
91
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
290
291
292
293
294
295
296
297
298
299
302
303
304
305
306
307
308
309
312
313
314
315
316
317
320
321
322
323
324
325
326
327
328
330static QQStyleKitReader::ControlType controlTypeForWidget(
const QWidget *widget)
333 return QQStyleKitReader::Control;
335#if QT_CONFIG(pushbutton)
336 if (qobject_cast<
const QPushButton *>(widget))
337 return QQStyleKitReader::Button;
339#if QT_CONFIG(checkbox)
340 if (qobject_cast<
const QCheckBox *>(widget))
341 return QQStyleKitReader::CheckBox;
343#if QT_CONFIG(radiobutton)
344 if (qobject_cast<
const QRadioButton *>(widget))
345 return QQStyleKitReader::RadioButton;
347#if QT_CONFIG(combobox)
348 if (qobject_cast<
const QComboBox *>(widget))
349 return QQStyleKitReader::ComboBox;
352 if (qobject_cast<
const QSlider *>(widget))
353 return QQStyleKitReader::Slider;
355#if QT_CONFIG(scrollbar)
356 if (qobject_cast<
const QScrollBar *>(widget))
357 return QQStyleKitReader::ScrollBar;
359#if QT_CONFIG(spinbox)
360 if (qobject_cast<
const QSpinBox *>(widget) || qobject_cast<
const QDoubleSpinBox *>(widget))
361 return QQStyleKitReader::SpinBox;
363#if QT_CONFIG(itemviews)
364 if (qobject_cast<
const QAbstractItemView *>(widget))
365 return QQStyleKitReader::ItemDelegate;
367#if QT_CONFIG(progressbar)
368 if (qobject_cast<
const QProgressBar *>(widget))
369 return QQStyleKitReader::ProgressBar;
371#if QT_CONFIG(lineedit)
372 if (qobject_cast<
const QLineEdit *>(widget))
373 return QQStyleKitReader::TextField;
375#if QT_CONFIG(textedit)
376 if (qobject_cast<
const QTextEdit *>(widget) || qobject_cast<
const QPlainTextEdit *>(widget))
377 return QQStyleKitReader::TextArea;
380 if (qobject_cast<
const QTabBar *>(widget))
381 return QQStyleKitReader::TabBar;
383#if QT_CONFIG(tabwidget)
384 if (qobject_cast<
const QTabWidget *>(widget))
385 return QQStyleKitReader::Page;
387#if QT_CONFIG(toolbar)
388 if (qobject_cast<
const QToolBar *>(widget))
389 return QQStyleKitReader::ToolBar;
391#if QT_CONFIG(toolbutton)
392 if (qobject_cast<
const QToolButton *>(widget))
393 return QQStyleKitReader::ToolButton;
395#if QT_CONFIG(groupbox)
396 if (qobject_cast<
const QGroupBox *>(widget))
397 return QQStyleKitReader::GroupBox;
400 if (qobject_cast<
const QMenuBar *>(widget))
401 return QQStyleKitReader::MenuBar;
402 if (qobject_cast<
const QMenu *>(widget))
403 return QQStyleKitReader::Menu;
405 if (widget->windowType() & Qt::Popup)
406 return QQStyleKitReader::Popup;
407 if (widget->windowType() & Qt::Dialog)
408 return QQStyleKitReader::Dialog;
409 if (widget->windowType() & Qt::Window)
410 return QQStyleKitReader::ApplicationWindow;
412 if (qobject_cast<
const QFrame *>(widget))
413 return QQStyleKitReader::Frame;
416 return QQStyleKitReader::Control;
419#if QT_CONFIG(itemviews)
420static QQStyleKitReader::ControlType itemViewControlType(
const QStyleOption *opt)
422 const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt);
423 return itemViewOption && (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator)
424 ? QQStyleKitReader::ControlType::CheckDelegate
425 : QQStyleKitReader::ControlType::ItemDelegate;
434#if QT_CONFIG(scrollarea)
435 if (
const auto *area = qobject_cast<
const QAbstractScrollArea *>(widget))
436 return area->viewport();
438 return const_cast<QWidget *>(widget);
447 || qobject_cast<
const QLabel *>(widget)
449#if QT_CONFIG(textedit)
450 || qobject_cast<
const QTextEdit *>(widget)
451 || qobject_cast<
const QPlainTextEdit *>(widget)
453#if QT_CONFIG(lineedit)
454 || qobject_cast<
const QLineEdit *>(widget)
461#if QT_CONFIG(textedit)
462 if (
auto *textEdit = qobject_cast<QTextEdit *>(widget))
463 return textEdit->viewport();
464 if (
auto *plainTextEdit = qobject_cast<QPlainTextEdit *>(widget))
465 return plainTextEdit->viewport();
467#if QT_CONFIG(itemviews) && QT_CONFIG(combobox)
468 if (
auto *view = qobject_cast<QAbstractItemView *>(widget)) {
469 if (
auto *p = view->parentWidget(); p && p->inherits(
"QComboBoxPrivateContainer"))
470 return view->viewport();
479 const uint h = raw & Qt::AlignHorizontal_Mask;
480 const uint v = raw & Qt::AlignVertical_Mask;
481 result |= h ? h : uint(hDefault);
482 result |= v ? v : uint(vDefault);
488 return qMax(0.0, element->fillWidth() ? availableW : element->width());
493 return qMax(0.0, element->fillHeight() ? availableH : element->height());
498 using QtPrivate::qSaturateRound;
499 return QMargins(qSaturateRound(element->leftMargin()),
500 qSaturateRound(element->topMargin()),
501 qSaturateRound(element->rightMargin()),
502 qSaturateRound(element->bottomMargin()));
506
507
508
510 const QQStyleKitDelegateProperties *element,
516 const qreal scale = element->scale();
517 if (qFuzzyIsNull(scale))
520 const qreal rotation = element->rotation();
521 if (qFuzzyIsNull(rotation) && qFuzzyCompare(scale, 1.0))
524 const QPointF center = box.center();
525 painter->translate(center);
526 if (!qFuzzyIsNull(rotation))
527 painter->rotate(rotation);
528 if (!qFuzzyCompare(scale, 1.0))
529 painter->scale(scale, scale);
530 painter->translate(-center);
537#if QT_CONFIG(lineedit)
538 if (qobject_cast<
const QLineEdit *>(w)) {
540 QWidget *parent = w->parentWidget();
542# if QT_CONFIG(combobox)
543 || qobject_cast<
const QComboBox *>(parent)
545# if QT_CONFIG(spinbox)
546 || qobject_cast<
const QAbstractSpinBox *>(parent)
554#if QT_CONFIG(scrollarea)
555 if (
const QAbstractScrollArea *sa =
556 qobject_cast<
const QAbstractScrollArea *>(w->parentWidget())) {
557 if (sa->viewport() == w)
558 return w->parentWidget();
566 : QCommonStylePrivate()
572 return filePath.startsWith(QLatin1Char(
':')) ? QUrl(QLatin1String(
"qrc") + filePath)
573 : QUrl::fromLocalFile(filePath);
580 qmlEngine =
new QQmlEngine(q);
583 qWarning(
"QStyleKitStyle: No QML engine available to load style.");
586 const QUrl url = stylePath.isEmpty() ? QUrl() : urlFromStylePath(stylePath);
587 if (stylePath.isEmpty() || !url.isValid()) {
588 qWarning(
"QStyleKitStyle: No valid style path provided: %s", qPrintable(stylePath));
591 QQmlComponent component(qmlEngine, url);
592 if (component.isError()) {
593 qWarning(
"QStyleKitStyle: Failed to load style from %s: %s", qPrintable(stylePath),
594 qPrintable(component.errorString()));
599 QQmlComponentPrivate *componentPrivate = QQmlComponentPrivate::get(&component);
600 const auto compilationUnit = componentPrivate->compilationUnit();
601 const auto propertyCache = compilationUnit ? compilationUnit->rootPropertyCache() :
nullptr;
602 const auto firstMetaObject = propertyCache ? propertyCache->firstCppMetaObject() :
nullptr;
603 if (!firstMetaObject || !firstMetaObject->inherits(&QQStyleKitStyle::staticMetaObject)) {
604 qWarning(
"QStyleKitStyle: Failed to load style from %s: component is not a StyleKit Style.",
605 qPrintable(stylePath));
608 QQStyleKitStyle *styleObject = qobject_cast<QQStyleKitStyle *>(component.create());
610 qWarning(
"QStyleKitStyle: Failed to create style object from %s: "
611 "component is not a StyleKit style.",
612 qPrintable(stylePath));
615 const bool isReload = style !=
nullptr;
621 QObject::connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, q,
623 if (style && style->themeName() == QLatin1String(
"System")) {
624 style->recreateTheme();
631 QQStyleKitReader::resetReadersForStyle(style);
637
638
639
647 qmlEngine =
new QQmlEngine(q);
649 QQmlComponent component(qmlEngine);
650 component.loadFromModule(
"Qt.labs.StyleKit",
"Style");
651 if (component.isError()) {
652 qWarning(
"QStyleKitStyle: Failed to create default fallback style: %s",
653 qPrintable(component.errorString()));
656 defaultStyle = qobject_cast<QQStyleKitStyle *>(component.create());
658 defaultStyle->setParent(q);
660 "No style set; using a default fallback style. "
661 "Set stylePath to load a StyleKit Style.");
667
668
669
672 return style ? style : defaultStyle;
679 QQStyleKitStyle *effective = effectiveStyle();
681 if (sharedReader && sharedReader->style() != effective)
682 sharedReader->setExplicitStyle(effective);
684 if (subElementReader && subElementReader->style() != effective)
685 subElementReader->setExplicitStyle(effective);
687 clearAllSubElements();
689 for (
auto *wr : std::as_const(widgetReaders)) {
690 if (wr->style() != effective)
691 wr->setExplicitStyle(effective);
694 if (!QWidgetPrivate::allWidgets)
697 for (
auto *widget : std::as_const(*QWidgetPrivate::allWidgets)) {
698 if (customFontWidgets.contains(widget))
699 unsetStyleFont(widget);
700 refreshStyleFont(widget);
701 if (customPaletteWidgets.contains(widget))
702 unsetStylePalette(widget);
703 refreshStylePalette(widget);
706 QEvent styleChange(QEvent::StyleChange);
707 for (
auto *widget : std::as_const(*QWidgetPrivate::allWidgets)) {
708 QApplication::sendEvent(widget, &styleChange);
716 auto it = customFontWidgets.find(widget);
717 if (it == customFontWidgets.end())
720 auto customFont =
std::move(*it);
721 customFontWidgets.erase(it);
722 widget->setFont(
std::move(customFont).reverted(widget->font()));
727 if (!effectiveStyle() || !widget)
730 const auto styleMask = styleFont.resolveMask();
731 auto it = customFontWidgets.find(widget);
733 if (it == customFontWidgets.end()) {
736 it = customFontWidgets.insert(widget, { QWidgetPrivate::get(widget)->localFont(), 0 });
737 QObject::connect(widget, &QObject::destroyed, widget,
738 [
this, widget]() { customFontWidgets.remove(widget); });
741 it->resolveMask = styleMask;
743 const QFont &baseline = it->oldWidgetValue;
744 QFont merged = styleFont.resolve(baseline);
745 merged.setResolveMask(baseline.resolveMask() | styleMask);
746 if (widget->font() != merged)
747 widget->setFont(merged);
752 if (!effectiveStyle() || !widget)
755 const QWidget *targetWidget = containerWidget(widget);
756 QQStyleKitReader::ControlType controlType = controlTypeForWidget(targetWidget);
758 auto *shared = ensureSharedReader();
763 opt.initFrom(targetWidget);
764 const QQSK::State currentState = resolvedStateFor(controlType, opt.state, targetWidget);
766 shared->setControlTypeAndState(controlType, currentState);
767 setStyleFont(widget, shared->font());
772 auto it = customPaletteWidgets.find(widget);
773 if (it == customPaletteWidgets.end())
776 auto customPalette =
std::move(*it);
777 customPaletteWidgets.erase(it);
778 widget->setPalette(
std::move(customPalette).reverted(widget->palette()));
783 if (!effectiveStyle() || !widget)
786 const quint64 styleMask = stylePalette.resolveMask();
790 if (!customPaletteWidgets.contains(widget)) {
791 customPaletteWidgets.insert(widget, { widget->palette(), 0 });
792 QObject::connect(widget, &QObject::destroyed, widget,
793 [
this, widget]() { customPaletteWidgets.remove(widget); });
796 customPaletteWidgets[widget].resolveMask |= styleMask;
797 QPalette merged = stylePalette.resolve(widget->palette());
798 merged.setResolveMask(widget->palette().resolveMask() | styleMask);
799 widget->setPalette(merged);
806 if (!effectiveStyle() || !widget)
809 const bool isWindow = widget->windowType() & (Qt::Popup | Qt::Window | Qt::Dialog);
810 const bool isPaletteManaged = isSelfPaintingWidget(widget) || isWindow;
811 if (!isPaletteManaged)
814 const QWidget *targetWidget = containerWidget(widget);
815 QQStyleKitReader::ControlType controlType = controlTypeForWidget(targetWidget);
817 auto *shared = ensureSharedReader();
822 opt.initFrom(targetWidget);
823 const QQSK::State currentState = resolvedStateFor(controlType, opt.state, targetWidget);
825 QPalette stylePalette;
828 shared->setControlTypeAndState(controlType, currentState);
829 if (
const auto *bg = shared->global()->background();
830 bg && bg->isDefined(QQSK::Property::Color)) {
831 stylePalette.setColor(QPalette::Window, bg->color());
833 shared->setControlTypeAndState(controlType, QQSK::StateFlag::Disabled);
834 if (
const auto *dbg = shared->global()->background();
835 dbg && dbg->isDefined(QQSK::Property::Color)) {
836 stylePalette.setColor(QPalette::Disabled, QPalette::Window, dbg->color());
841 shared->setControlTypeAndState(controlType, currentState);
842 if (
const auto *text = shared->global()->text();
843 text && text->isDefined(QQSK::Property::Color)) {
844 stylePalette.setColor(QPalette::Text, text->color());
845 stylePalette.setColor(QPalette::WindowText, text->color());
847 shared->setControlTypeAndState(controlType, QQSK::StateFlag::Disabled);
848 if (
const auto *dt = shared->global()->text();
849 dt && dt->isDefined(QQSK::Property::Color)) {
850 stylePalette.setColor(QPalette::Disabled, QPalette::Text, dt->color());
851 stylePalette.setColor(QPalette::Disabled, QPalette::WindowText, dt->color());
855 setStylePalette(widget, stylePalette);
859
860
863 Q_Q(
const QStyleKitStyle);
864 QQStyleKitStyle *effective = effectiveStyle();
865 if (!effective || !widget)
868 if (
auto it = widgetReaders.find(widget); it != widgetReaders.end())
871 auto *widgetReader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
872 widgetReader->setExplicitStyle(effective);
873 widgetReader->setTarget(paintTarget(widget));
874 widgetReader->setControlType(controlTypeForWidget(widget));
875 widgetReader->setCompleted(
true);
876 widgetReaders.insert(widget, widgetReader);
877 QObjectPrivate::connect(widget, &QObject::destroyed,
this,
878 &QStyleKitStylePrivate::onWidgetDestroyed, Qt::UniqueConnection);
884 if (
auto *reader = widgetReaders.take(widget))
885 reader->deleteLater();
886 cleanupSubElements(widget);
891 cleanupWidgetReader(
static_cast<QWidget *>(w));
895
896
897
898
906#if QT_CONFIG(itemviews)
907 if (
const auto *viewOpt = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
908 const QModelIndex &idx = viewOpt->index;
912 key.id = SubElementKey::ItemViewCell{ idx.model(), idx.internalId(), idx.row(),
918 if (
const auto *menuOpt = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
919 if (menuOpt->menuItemType == QStyleOptionMenuItem::Separator)
921 QAction *action =
nullptr;
922 if (
const auto *menu = qobject_cast<
const QMenu *>(widget))
923 action = menu->actionAt(menuOpt->rect.center());
924 else if (
const auto *menuBar = qobject_cast<
const QMenuBar *>(widget))
925 action = menuBar->actionAt(menuOpt->rect.center());
928 key.id = SubElementKey::Action{ action };
934 if (
const auto *tabOpt = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
935 if (tabOpt->tabIndex < 0)
938 key.id = SubElementKey::Tab{ tabOpt->tabIndex };
946
947
948
949
951 const SubElementKey &key, QQStyleKitReader::ControlType type, QQSK::State fromState,
952 QQSK::State toState, QQuickTransition *transition)
const
954 Q_Q(
const QStyleKitStyle);
955 QQStyleKitStyle *effective = effectiveStyle();
961 for (
auto it = subElementAnimationReaders.begin(); it != subElementAnimationReaders.end();) {
962 const QQuickTransition *t = it.value()->transition();
963 if (!t || !t->running()) {
964 it.value()->deleteLater();
965 it = subElementAnimationReaders.erase(it);
972 if (subElementAnimationReaders.size() >= kMaxSubElementAnimationReaders) {
973 const auto it = subElementAnimationReaders.begin();
974 if (
const QWidget *widget = it.key().widget)
975 paintTarget(widget)->update();
976 it.value()->deleteLater();
977 subElementAnimationReaders.erase(it);
980 auto *reader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
981 reader->setExplicitStyle(effective);
982 reader->setTarget(paintTarget(key.widget));
984 reader->setControlTypeAndState(type, fromState);
985 reader->setCompleted(
true);
989 reader->background();
990 auto *indicator = reader->indicator();
991 indicator->first()->foreground();
992 indicator->second()->foreground();
994 reader->setControlTypeAndState(type, toState);
995 if (!transition || !transition->running()) {
996 reader->deleteLater();
999 subElementAnimationReaders.insert(key, reader);
1004
1005
1008 for (
auto it = subElementStates.begin(); it != subElementStates.end();) {
1009 if (it.key().widget == widget)
1010 it = subElementStates.erase(it);
1014 for (
auto it = subElementAnimationReaders.begin(); it != subElementAnimationReaders.end();) {
1015 if (it.key().widget == widget) {
1016 it.value()->deleteLater();
1017 it = subElementAnimationReaders.erase(it);
1025
1026
1029 subElementStates.clear();
1030 for (QQStyleKitReader *reader : std::as_const(subElementAnimationReaders))
1031 reader->deleteLater();
1032 subElementAnimationReaders.clear();
1036
1037
1038
1040 QStyle::State state,
1041 const QWidget *widget)
const
1044 flags.setFlag(QQSK::StateFlag::Hovered, (state & QStyle::State_MouseOver));
1045 flags.setFlag(QQSK::StateFlag::Pressed, state & QStyle::State_Sunken);
1046 flags.setFlag(QQSK::StateFlag::Checked, state & QStyle::State_On);
1047 flags.setFlag(QQSK::StateFlag::Focused, state & QStyle::State_HasFocus);
1048 flags.setFlag(QQSK::StateFlag::Highlighted, state & QStyle::State_Selected);
1050 bool hasOrientation =
false;
1052 case QQStyleKitReader::ProgressBar:
1053 case QQStyleKitReader::ScrollBar:
1054 case QQStyleKitReader::ScrollIndicator:
1055 case QQStyleKitReader::Slider:
1056 case QQStyleKitReader::ToolBar:
1057 case QQStyleKitReader::ToolSeparator:
1058 hasOrientation =
true;
1064 flags.setFlag(QQSK::StateFlag::Vertical, !(state & QStyle::State_Horizontal));
1068 const bool enabled = (state & QStyle::State_Enabled) || (widget && widget->isEnabled());
1069 flags.setFlag(QQSK::StateFlag::Disabled, !enabled);
1073 if (type == QQStyleKitReader::ControlType::ComboBox)
1074 flags.setFlag(QQSK::StateFlag::Checked,
false);
1077 if (type == QQStyleKitReader::ControlType::Popup)
1078 flags.setFlag(QQSK::StateFlag::Hovered,
false);
1081 if (type == QQStyleKitReader::ControlType::TabButton) {
1082 flags.setFlag(QQSK::StateFlag::Checked, state & QStyle::State_Selected);
1083 flags.setFlag(QQSK::StateFlag::Highlighted,
false);
1090
1091
1092
1093const QStyleKitStylePrivate::ControlMetrics &
1096 if (
auto it = metricsCache.find({ type, state }); it != metricsCache.end())
1099 auto *reader = ensureSharedReader();
1101 reader->setControlTypeAndState(type, state);
1102 return *metricsCache.insert({ type, state }, metricsForReader(reader));
1106
1107
1108
1111 QStyle::State state)
const
1113 QQStyleKitResolved out;
1116 auto *reader = readerForWidget(w);
1120 const QQSK::State resolvedState = resolvedStateFor(type, state, w);
1121 reader->setControlTypeAndState(type, resolvedState);
1123 out.reader = reader;
1124 out.metrics = &metricsFor(type, resolvedState);
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1142 QQStyleKitReader::ControlType type, QStyle::State state,
1145 QQStyleKitResolved out;
1148 auto *steadyReader = ensureSubElementReader();
1152 const QQSK::State newState = resolvedStateFor(type, state, w);
1153 const SubElementKey key = subElementKeyForOption(opt, w);
1155 QQStyleKitReader *reader =
nullptr;
1156 if (track && key.isValid()) {
1157 QQStyleKitReader *animReader = subElementAnimationReaders.value(key);
1158 const auto it = subElementStates.constFind(key);
1159 const bool seen = it != subElementStates.cend();
1163 constexpr QQSK::State InteractiveStates = QQSK::State(QQSK::StateFlag::Hovered)
1164 | QQSK::StateFlag::Pressed | QQSK::StateFlag::Checked
1165 | QQSK::StateFlag::Focused | QQSK::StateFlag::Highlighted;
1166 const auto baseState = newState & ~InteractiveStates;
1167 const QQSK::State prevState = seen ? *it : baseState;
1168 if (prevState != newState) {
1173 animReader->setControlTypeAndState(type, newState);
1178 const bool shouldAnimate = seen || newState.testFlag(QQSK::StateFlag::Hovered)
1179 || newState.testFlag(QQSK::StateFlag::Pressed);
1180 if (shouldAnimate) {
1181 steadyReader->setControlTypeAndState(type, newState);
1182 if (QQuickTransition *transition = steadyReader->transition())
1183 animReader = startSubElementTransition(key, type, prevState,
1184 newState, transition);
1188 if (!seen || prevState != newState) {
1189 QObjectPrivate::connect(w, &QObject::destroyed,
this,
1190 &QStyleKitStylePrivate::onWidgetDestroyed,
1191 Qt::UniqueConnection);
1192 if (subElementStates.size() >= kMaxSubElementStates)
1193 subElementStates.clear();
1194 subElementStates.insert(key, newState);
1196 reader = animReader;
1200 reader = steadyReader;
1201 reader->setControlTypeAndState(type, newState);
1203 out.reader = reader;
1204 out.metrics = &metricsFor(type, newState);
1210 return reader ? reader->text() :
nullptr;
1215 return reader ? reader->background() :
nullptr;
1220 return reader ? reader->handle() :
nullptr;
1225 return reader ? reader->indicator() :
nullptr;
1230 return reader ? reader->font() : QFont();
1236 return sharedReader;
1238 Q_Q(
const QStyleKitStyle);
1239 QQStyleKitStyle *effective = effectiveStyle();
1242 sharedReader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
1244 sharedReader->setTransitionsEnabled(
false);
1245 sharedReader->setExplicitStyle(effective);
1246 sharedReader->setCompleted(
true);
1247 return sharedReader;
1252 if (subElementReader)
1253 return subElementReader;
1255 Q_Q(
const QStyleKitStyle);
1256 QQStyleKitStyle *effective = effectiveStyle();
1259 subElementReader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
1262 subElementReader->setTransitionsEnabled(
false);
1263 subElementReader->setExplicitStyle(effective);
1264 subElementReader->setCompleted(
true);
1265 return subElementReader;
1269
1270
1271
1272
1276 QQStyleKitLayoutResolved out;
1277 auto *reader = ensureSharedReader();
1281 const QQSK::State resolvedState = resolvedStateFor(type, state);
1282 out.metrics = &metricsFor(type, resolvedState);
1286 reader->setControlTypeAndState(type, resolvedState);
1287 out.staticProps = reader->global();
1288 out.staticFont = reader->font();
1294 return staticProps ? staticProps->text() :
nullptr;
1297const QQStyleKitDelegateProperties *
1300 return staticProps ? staticProps->background() :
nullptr;
1305 return staticProps ? staticProps->handle() :
nullptr;
1311 return staticProps ? staticProps->indicator() :
nullptr;
1316 metricsCache.clear();
1320 const QRectF &rect, QPainter *painter)
const
1322 if (!indicator || !indicator->visible() || indicator->opacity() <= 0 || !rect.isValid())
1328 QPainterStateGuard stateGuard(painter);
1329 if (!applyDelegateTransform(painter, indicator, rect))
1333 QRectF indicatorRect = rect;
1334 drawStyledItemContents(indicator, indicatorRect, painter);
1336 const QQStyleKitDelegateProperties *foreground =
nullptr;
1337 if (
auto *indicatorWithSubTypes =
1338 qobject_cast<
const QQStyleKitIndicatorWithSubTypes *>(indicator)) {
1339 foreground = indicatorWithSubTypes->foreground();
1340 }
else if (
auto *indicatorProps =
1341 qobject_cast<
const QQStyleKitIndicatorProperties *>(indicator)) {
1342 foreground = indicatorProps->foreground();
1346 if (!foreground || !foreground->visible() || foreground->opacity() <= 0)
1350 QRectF foregroundRect;
1351 const uint foregroundAlign = resolvedAlignment(foreground->alignment(), Qt::AlignHCenter,
1353 const auto foregroundW = resolvedWidth(
1354 foreground, indicatorRect.width() - foreground->leftMargin() - foreground->rightMargin());
1355 const auto foregroundH = resolvedHeight(
1356 foreground, indicatorRect.height() - foreground->topMargin() - foreground->bottomMargin());
1357 foregroundRect.setSize(QSizeF(foregroundW, foregroundH));
1358 if (foregroundAlign & Qt::AlignLeft)
1359 foregroundRect.moveLeft(indicatorRect.left() + foreground->leftMargin());
1360 else if (foregroundAlign & Qt::AlignHCenter)
1361 foregroundRect.moveLeft(indicatorRect.left() + (indicatorRect.width() - foregroundW) / 2.0);
1362 else if (foregroundAlign & Qt::AlignRight)
1363 foregroundRect.moveLeft(indicatorRect.right() - foreground->rightMargin() - foregroundW);
1364 if (foregroundAlign & Qt::AlignTop)
1365 foregroundRect.moveTop(indicatorRect.top() + foreground->topMargin());
1366 else if (foregroundAlign & Qt::AlignVCenter)
1367 foregroundRect.moveTop(indicatorRect.top() + (indicatorRect.height() - foregroundH) / 2.0);
1368 else if (foregroundAlign & Qt::AlignBottom)
1369 foregroundRect.moveTop(indicatorRect.bottom() - foreground->bottomMargin() - foregroundH);
1370 drawStyledItemRect(foreground, foregroundRect, painter);
1374 const QFont &font,
const QRect &rect,
1375 const QString &text, uint textFlags, QPainter *p,
1376 Qt::Alignment defaultAlignment)
const
1378 uint flags = textFlags;
1380 ? resolvedAlignment(textProps->alignment(), defaultAlignment & Qt::AlignHorizontal_Mask,
1381 defaultAlignment & Qt::AlignVertical_Mask)
1382 : uint(defaultAlignment);
1384 const QFont oldFont = p->font();
1385 p->setFont(font.resolve(oldFont));
1386 p->setBrush(Qt::NoBrush);
1387 p->setPen(textProps ? textProps->color() : QColor());
1388 p->drawText(rect, flags, text,
nullptr);
1392 const QRectF &rect, QPainter *painter)
const
1394 if (!props || !props->visible() || props->opacity() <= 0 || !rect.isValid())
1397 QPainterStateGuard stateGuard(painter);
1398 if (!applyDelegateTransform(painter, props, rect))
1400 drawStyledItemContents(props, rect, painter);
1404 const QRectF &rect, QPainter *painter)
const
1406 if (!props || !props->visible() || props->opacity() <= 0 || !rect.isValid())
1409 QPainterStateGuard stateGuard(painter);
1410 painter->setRenderHint(QPainter::Antialiasing,
true);
1412 painter->setClipping(
true);
1415 const auto opacity = props->opacity();
1418 const auto *border = props->border();
1419 auto borderWidth = 0;
1423 borderWidth = border->width();
1424 borderColor = border->color();
1425 inset = borderWidth / 2.0;
1427 if (borderWidth > 0 && borderColor.isValid() && borderColor.alpha() > 0) {
1428 QPen pen(borderColor, borderWidth);
1429 painter->setPen(pen);
1431 painter->setPen(Qt::NoPen);
1436 const qreal minDimension = qMin(rect.width(), rect.height());
1437 const qreal xRadius = qMax(0.0, qMin(props->topLeftRadius() - inset, minDimension / 2.0));
1438 const qreal yRadius = qMax(0.0, qMin(props->bottomLeftRadius() - inset, minDimension / 2.0));
1440 QRectF adjustedRect = rect.adjusted(inset, inset, -inset, -inset);
1444 QColor color = props->color();
1445 QBrush colorBrush(color);
1446 painter->setBrush(colorBrush);
1447 if (color.isValid()) {
1448 painter->setOpacity(opacity);
1449 painter->drawRoundedRect(adjustedRect, xRadius, yRadius, Qt::AbsoluteSize);
1451 if (QQuickGradient *gradient = props->gradient()) {
1452 QLinearGradient linearGradient(rect.topLeft(), rect.bottomLeft());
1453 QQmlListProperty<QQuickGradientStop> stops = gradient->stops();
1454 const int stopCount = stops.count(&stops);
1455 for (
int i = 0; i < stopCount; i++) {
1456 QQuickGradientStop *stop =
static_cast<QQuickGradientStop *>(stops.at(&stops, i));
1457 linearGradient.setColorAt(stop->position(), stop->color());
1459 QBrush gradientBrush(linearGradient);
1460 painter->setBrush(gradientBrush);
1461 painter->setOpacity(opacity);
1462 painter->drawRoundedRect(adjustedRect, xRadius, yRadius, Qt::AbsoluteSize);
1466 drawStyledItemImage(props->image(), adjustedRect, opacity, painter);
1470 const QRectF &rect, qreal opacity,
1471 QPainter *painter)
const
1473 if (!image || image->source().isEmpty() || image->color().alpha() <= 0)
1476 QString imageSource = image->source().toString();
1477 if (imageSource.startsWith(QLatin1String(
"qrc:/")))
1478 imageSource = imageSource.mid(3);
1479 QUrl imageUrl(imageSource);
1480 QString imagePath = imageUrl.isLocalFile() ? imageUrl.toLocalFile() : imageSource;
1481 QPixmap pixmap(imagePath);
1482 if (pixmap.isNull())
1485 if (image->color().isValid()) {
1486 QImage coloredImage = pixmap.toImage();
1487 QPainter imagePainter(&coloredImage);
1488 imagePainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
1489 imagePainter.fillRect(coloredImage.rect(), image->color());
1491 pixmap = QPixmap::fromImage(coloredImage);
1493 painter->setOpacity(opacity);
1494 const QSizeF pixmapSize = pixmap.deviceIndependentSize();
1496 switch (image->fillMode()) {
1497 case QQuickImage::PreserveAspectFit: {
1498 const QSize scaled = pixmapSize.scaled(rect.size(), Qt::KeepAspectRatio).toSize();
1499 const QPointF topLeft(rect.x() + (rect.width() - scaled.width()) / 2.0,
1500 rect.y() + (rect.height() - scaled.height()) / 2.0);
1501 painter->drawPixmap(QRectF(topLeft, scaled), pixmap, QRectF(QPointF(0, 0), pixmapSize));
1504 case QQuickImage::PreserveAspectCrop: {
1505 const QSize scaled = pixmapSize
1506 .scaled(rect.size(), Qt::KeepAspectRatioByExpanding)
1508 const QPointF topLeft(rect.x() + (rect.width() - scaled.width()) / 2.0,
1509 rect.y() + (rect.height() - scaled.height()) / 2.0);
1510 QPainterStateGuard stateGuard(painter);
1511 painter->setClipRect(rect);
1512 painter->drawPixmap(QRectF(topLeft, scaled), pixmap, QRectF(QPointF(0, 0), pixmapSize));
1516 case QQuickImage::Stretch:
1518 painter->drawPixmap(rect, pixmap, QRectF(QPointF(0, 0), pixmapSize));
1524 uint alignment,
const QMargins &padding,
1525 const QMargins &margins)
const
1527 QRect r(QPoint(0, 0), size);
1529 if (alignment & Qt::AlignLeft)
1530 r.moveLeft(container.x() + padding.left() + margins.left());
1531 else if (alignment & Qt::AlignHCenter)
1532 r.moveLeft(container.x() + (container.width() - size.width()) / 2);
1534 r.moveLeft(container.right() + 1 - padding.right() - margins.right() - size.width());
1536 if (alignment & Qt::AlignTop)
1537 r.moveTop(container.y() + padding.top() + margins.top());
1538 else if (alignment & Qt::AlignVCenter)
1539 r.moveTop(container.y() + (container.height() - size.height()) / 2);
1541 r.moveTop(container.bottom() + 1 - padding.bottom() - margins.bottom() - size.height());
1546QStyleKitStylePrivate::ControlMetrics
1550 using QtPrivate::qSaturateRound;
1551 const QQStyleKitControlProperties *props = reader->global();
1552 ControlMetrics metrics;
1553 metrics.bgImplicitSize = QSize(0, 0);
1554 metrics.textPadding = QMargins(0, 0, 0, 0);
1555 metrics.padding = QMargins(qSaturateRound(props->leftPadding()),
1556 qSaturateRound(props->topPadding()),
1557 qSaturateRound(props->rightPadding()),
1558 qSaturateRound(props->bottomPadding()));
1559 metrics.spacing = qSaturateRound(props->spacing());
1560 metrics.margins = QMargins(0, 0, 0, 0);
1561 metrics.indicatorImplicitSize = QSize(0, 0);
1562 metrics.indicatorMargins = QMargins(0, 0, 0, 0);
1563 metrics.foregroundImplicitSize = QSize(0, 0);
1564 metrics.foregroundMargins = QMargins(0, 0, 0, 0);
1565 const auto *background = props->background();
1568 const auto elementSize = [](qreal w, qreal h) {
1569 constexpr qreal zero(.0);
1570 return QSizeF(std::max(zero, w), std::max(zero, h)).toSize();
1574 metrics.bgImplicitSize = elementSize(background->width(), background->height());
1575 metrics.margins = elementMargins(background);
1577 const auto *textProps = props->text();
1579 metrics.textPadding = QMargins(qSaturateRound(textProps->leftPadding()),
1580 qSaturateRound(textProps->topPadding()),
1581 qSaturateRound(textProps->rightPadding()),
1582 qSaturateRound(textProps->bottomPadding()));
1584 const auto *indicator = props->indicator();
1586 metrics.indicatorMargins = elementMargins(indicator);
1587 metrics.indicatorImplicitSize = elementSize(indicator->width(), indicator->height());
1589 const auto *foreground = indicator->foreground();
1591 metrics.foregroundMargins = elementMargins(foreground);
1592 const auto foregroundW = resolvedWidth(
1594 std::max(.0, qreal(metrics.indicatorImplicitSize.width()
1595 - metrics.foregroundMargins.left()
1596 - metrics.foregroundMargins.right())));
1597 const auto foregroundH = resolvedHeight(
1599 std::max(.0, qreal(metrics.indicatorImplicitSize.height()
1600 - metrics.foregroundMargins.top()
1601 - metrics.foregroundMargins.bottom())));
1602 metrics.foregroundImplicitSize = elementSize(foregroundW, foregroundH);
1605 const auto *handle = props->handle();
1607 metrics.handleImplicitSize = elementSize(handle->width(), handle->height());
1608 metrics.handleMargins = elementMargins(handle);
1614
1615
1616
1617
1618
1619QStyleKitStyle::QStyleKitStyle()
1620 : QCommonStyle(*
new QStyleKitStylePrivate())
1625
1626
1627
1628
1629
1630
1631
1632
1633QStyleKitStyle::QStyleKitStyle(
const QString &filePath)
1634 : QCommonStyle(*
new QStyleKitStylePrivate())
1636 Q_D(QStyleKitStyle);
1637 d->stylePath = filePath;
1638 if (!d->loadStyle()) {
1639 qWarning(
"QStyleKitStyle: Failed to load style from %s", qPrintable(filePath));
1644
1645
1646QStyleKitStyle::~QStyleKitStyle()
1651
1652
1653
1654
1655QString QStyleKitStyle::stylePath()
const
1657 Q_D(
const QStyleKitStyle);
1658 return d->stylePath;
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673void QStyleKitStyle::setStylePath(
const QString &filePath)
1675 Q_D(QStyleKitStyle);
1676 if (d->stylePath == filePath)
1679 const QString oldThemeName = themeName();
1680 const QStringList oldThemeNames = availableThemeNames();
1681 const QStringList oldCustomThemeNames = customThemeNames();
1683 d->stylePath = filePath;
1684 if (d->loadStyle()) {
1686 if (
const QStringList names = availableThemeNames(); names != oldThemeNames)
1687 emit availableThemeNamesChanged(names);
1688 if (
const QStringList names = customThemeNames(); names != oldCustomThemeNames)
1689 emit customThemeNamesChanged(names);
1691 emit stylePathChanged(d->stylePath);
1695
1696
1697
1698
1699
1700QString QStyleKitStyle::themeName()
const
1702 Q_D(
const QStyleKitStyle);
1703 return d->style ? d->style->themeName() : QString();
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716void QStyleKitStyle::setThemeName(
const QString &themeName)
1718 Q_D(QStyleKitStyle);
1720 qWarning(
"QStyleKitStyle: No style loaded, cannot set theme name.");
1723 if (d->style->themeName() == themeName)
1725 d->style->setThemeName(themeName);
1727 emit themeNameChanged(d->style->themeName());
1731
1732
1733
1734
1735
1736
1737
1738QStringList QStyleKitStyle::availableThemeNames()
const
1740 Q_D(
const QStyleKitStyle);
1741 return d->style ? d->style->availableThemeNames() : QStringList();
1745
1746
1747
1748
1749
1750
1751QStringList QStyleKitStyle::customThemeNames()
const
1753 Q_D(
const QStyleKitStyle);
1754 return d->style ? d->style->customThemeNames() : QStringList();
1758void QStyleKitStyle::drawPrimitive(PrimitiveElement pe,
const QStyleOption *opt, QPainter *p,
1759 const QWidget *w)
const
1761 Q_D(
const QStyleKitStyle);
1765 case PE_PanelMenu: {
1766 const auto controlType = w && w->inherits(
"QComboBoxPrivateContainer")
1767 ? QQStyleKitReader::ControlType::Popup
1768 : QQStyleKitReader::ControlType::Menu;
1769 const auto r = d->resolve(w, controlType, opt->state);
1772 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
1779#if QT_CONFIG(menubar)
1780 case PE_PanelMenuBar: {
1781 const auto r = d->resolve(w, QQStyleKitReader::ControlType::MenuBar, opt->state);
1784 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
1788 case PE_FrameButtonBevel:
1789 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1790 const auto controlType = btn->features & QStyleOptionButton::Flat
1791 ? QQStyleKitReader::ControlType::FlatButton
1792 : QQStyleKitReader::ControlType::Button;
1793 const auto r = d->resolve(w, controlType, btn->state);
1796 d->drawStyledItemRect(r.background(), opt->rect, p);
1801 QQStyleKitReader::ControlType controlType;
1802 const bool isPopup = w
1804#if QT_CONFIG(combobox)
1805 || w->inherits(
"QComboBoxPrivateContainer")
1809 controlType = QQStyleKitReader::ControlType::Popup;
1810#if QT_CONFIG(lineedit)
1811 else if (qobject_cast<
const QLineEdit *>(w))
1812 controlType = QQStyleKitReader::ControlType::TextField;
1815 controlType = QQStyleKitReader::ControlType::Frame;
1816 const auto r = d->resolve(w, controlType, opt->state);
1819 d->drawStyledItemRect(r.background(), opt->rect, p);
1822#if QT_CONFIG(lineedit)
1823 case PE_PanelLineEdit:
1824 if (
const auto *lineEdit = qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
1827 QStyleOption lineEditOpt(*lineEdit);
1828 lineEditOpt.state &= ~QStyle::State_Sunken;
1829 const auto r = d->resolve(w, QQStyleKitReader::ControlType::TextField,
1835 if (
auto *le = qobject_cast<
const QLineEdit *>(w)) {
1836 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
1837 QPalette stylePalette;
1838 stylePalette.setColor(QPalette::Text, txt->color());
1839 d->setStylePalette(
const_cast<QLineEdit *>(le), stylePalette);
1841 const_cast<QStyleKitStylePrivate *>(d)->setStyleFont(
const_cast<QLineEdit *>(le),
1845 const QObject *parent = w ? w->parent() :
nullptr;
1846# if QT_CONFIG(spinbox)
1847 const bool isInSpinBox = qobject_cast<
const QAbstractSpinBox *>(parent);
1849 const bool isInSpinBox =
false;
1851# if QT_CONFIG(combobox)
1852 const bool isInComboBox = qobject_cast<
const QComboBox *>(parent);
1854 const bool isInComboBox =
false;
1857 if (isInSpinBox || isInComboBox)
1860 d->drawStyledItemRect(r.background(), opt->rect, p);
1865#if QT_CONFIG(itemviews)
1866 case PE_PanelItemViewItem: {
1867 const auto r = d->resolveSubElement(w, opt, itemViewControlType(opt), opt->state);
1870 d->drawStyledItemRect(r.background(), opt->rect, p);
1874 case PE_IndicatorCheckBox:
1875 case PE_IndicatorRadioButton: {
1876 const auto controlType = pe == PE_IndicatorCheckBox
1877 ? QQStyleKitReader::ControlType::CheckBox
1878 : QQStyleKitReader::ControlType::RadioButton;
1879 const auto r = d->resolve(w, controlType, opt->state);
1882 d->drawControlIndicator(r.indicator(), opt->rect, p);
1885 case PE_IndicatorArrowDown: {
1886 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, opt->state);
1889 d->drawControlIndicator(r.indicator(), opt->rect, p);
1892 case PE_IndicatorItemViewItemCheck: {
1894 const auto r = d->resolveSubElement(w, opt, itemViewControlType(opt), opt->state,
false);
1897 d->drawControlIndicator(r.indicator(), opt->rect, p);
1900#if QT_CONFIG(spinbox)
1901 case PE_IndicatorSpinUp:
1902 case PE_IndicatorSpinDown: {
1903 const auto r = d->resolve(w, QQStyleKitReader::ControlType::SpinBox, opt->state);
1906 const auto *indicator = r.indicator();
1907 const auto *upDownIndicator = indicator
1908 ? (pe == PE_IndicatorSpinUp ? indicator->first() : indicator->second())
1910 d->drawControlIndicator(upDownIndicator, opt->rect, p);
1914#if QT_CONFIG(groupbox)
1915 case PE_FrameGroupBox: {
1916 const auto r = d->resolve(w, QQStyleKitReader::ControlType::GroupBox, opt->state);
1919 d->drawStyledItemRect(r.background(), opt->rect, p);
1923#if QT_CONFIG(tabwidget)
1924 case PE_FrameTabWidget: {
1925 const auto r = d->resolve(w, QQStyleKitReader::ControlType::Page, opt->state);
1928 d->drawStyledItemRect(r.background(), opt->rect, p);
1932#if QT_CONFIG(tabbar)
1934 case PE_IndicatorTabClose:
1935 case PE_IndicatorTabTearRight:
1936 case PE_IndicatorTabTearLeft:
1939#if QT_CONFIG(toolbutton)
1940 case PE_FrameButtonTool:
1941 case PE_PanelButtonTool: {
1942 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolButton, opt->state);
1945 d->drawStyledItemRect(r.background(), opt->rect, p);
1949#if QT_CONFIG(toolbar)
1950 case PE_IndicatorToolBarHandle:
1952 case PE_IndicatorToolBarSeparator: {
1953 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolSeparator, opt->state);
1956 const auto &metrics = *r.metrics;
1958 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
1959 d->drawStyledItemRect(r.background(), frameRect, p);
1961 const auto *indicator = r.indicator();
1962 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
1964 QRect contentRect = frameRect.marginsRemoved(metrics.padding);
1965 const int iw = QtPrivate::qSaturateRound(
1966 resolvedWidth(indicator,
1968 - metrics.indicatorMargins.left()
1969 - metrics.indicatorMargins.right()));
1970 const int ih = QtPrivate::qSaturateRound(
1971 resolvedHeight(indicator,
1972 contentRect.height()
1973 - metrics.indicatorMargins.top()
1974 - metrics.indicatorMargins.bottom()));
1975 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignHCenter,
1977 const QRect indicatorRect = d->getAlignedRectInContainer(
1978 contentRect, QSize(iw, ih), alignment, QMargins(), metrics.indicatorMargins);
1979 d->drawControlIndicator(indicator, visualRect(opt->direction, contentRect, indicatorRect),
1987 QCommonStyle::drawPrimitive(pe, opt, p, w);
1991void QStyleKitStyle::drawControl(ControlElement element,
const QStyleOption *opt, QPainter *p,
1992 const QWidget *w)
const
1994 Q_D(
const QStyleKitStyle);
1998 if (
const QStyleOptionButton *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1999 proxy()->drawControl(CE_PushButtonBevel, btn, p, w);
2000 QStyleOptionButton btnContent(*btn);
2001 btnContent.rect = subElementRect(SE_PushButtonContents, btn, w);
2002 proxy()->drawControl(CE_PushButtonLabel, &btnContent, p, w);
2005 case CE_PushButtonBevel:
2006 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2007 QStyleOptionButton btnBg(*btn);
2008 btnBg.rect = subElementRect(SE_PushButtonBevel, btn, w);
2009 proxy()->drawPrimitive(PE_FrameButtonBevel, &btnBg, p, w);
2012 case CE_PushButtonLabel:
2013 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2014 const auto controlType = btn->features & QStyleOptionButton::Flat
2015 ? QQStyleKitReader::ControlType::FlatButton
2016 : QQStyleKitReader::ControlType::Button;
2017 const auto r = d->resolve(w, controlType, btn->state);
2020 const auto metrics = r.metrics;
2022 QRect textRect = opt->rect;
2023 uint textFlags = Qt::TextShowMnemonic;
2024 if (!styleHint(SH_UnderlineShortcut, opt, w))
2025 textFlags |= Qt::TextHideMnemonic;
2028 const QIcon icon = btn->icon;
2029 if (!icon.isNull()) {
2030 const auto *textProps = r.text();
2031 uint iconTextFlags = textFlags;
2032 iconTextFlags |= textProps
2033 ? resolvedAlignment(textProps->alignment(), Qt::AlignHCenter, Qt::AlignVCenter)
2034 : uint(Qt::AlignHCenter | Qt::AlignVCenter);
2035 QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
2036 if (mode == QIcon::Normal && btn->state & State_HasFocus)
2037 mode = QIcon::Active;
2038 QIcon::State iconState = btn->state & State_On ? QIcon::On : QIcon::Off;
2039 const auto paintDeviceDpr = p->device()->devicePixelRatio();
2040 QPixmap pixmap = icon.pixmap(btn->iconSize, paintDeviceDpr, mode, iconState);
2041 int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
2042 int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
2043 int labelWidth = pixmapWidth;
2044 int iconSpacing = metrics->spacing;
2045 int textWidth = btn->fontMetrics
2046 .boundingRect(opt->rect, iconTextFlags, btn->text)
2048 if (!btn->text.isEmpty()) {
2049 labelWidth += (textWidth
2050 + iconSpacing + textProps->leftPadding() + textProps->rightPadding());
2054 if (iconTextFlags & Qt::AlignLeft) {
2055 iconRect = QRect(textRect.x(),
2056 textRect.y() + (textRect.height() - pixmapHeight) / 2,
2057 pixmapWidth, pixmapHeight);
2058 }
else if (iconTextFlags & Qt::AlignHCenter) {
2059 iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
2060 textRect.y() + (textRect.height() - pixmapHeight) / 2,
2061 pixmapWidth, pixmapHeight);
2063 iconRect = QRect(textRect.x() + textRect.width() - labelWidth,
2064 textRect.y() + (textRect.height() - pixmapHeight) / 2,
2065 pixmapWidth, pixmapHeight);
2067 iconRect = visualRect(btn->direction, textRect, iconRect);
2070 textFlags &= ~Qt::AlignHorizontal_Mask;
2071 textFlags |= Qt::AlignLeft;
2072 if (btn->direction == Qt::RightToLeft)
2073 textRect.setRight(iconRect.left() - iconSpacing);
2075 textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing);
2077 p->drawPixmap(iconRect, pixmap);
2080 if (btn->features & QStyleOptionButton::HasMenu) {
2081 int indicatorSize = pixelMetric(PM_MenuButtonIndicator, btn, w);
2082 if (btn->direction == Qt::LeftToRight)
2083 textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
2085 textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
2087 d->drawControlText(r.text(), r.font(), textRect, btn->text, textFlags, p);
2092 case CE_RadioButton:
2093 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2094 const auto controlType = element == CE_CheckBox
2095 ? QQStyleKitReader::ControlType::CheckBox
2096 : QQStyleKitReader::ControlType::RadioButton;
2097 const auto r = d->resolve(w, controlType, btn->state);
2100 QRect backgroundRect = btn->rect.marginsRemoved(r.metrics->margins);
2102 d->drawStyledItemRect(r.background(), backgroundRect, p);
2104 QStyleOptionButton btnContent(*btn);
2105 const auto contentElement = element == CE_CheckBox
2106 ? SE_CheckBoxContents
2107 : SE_RadioButtonContents;
2108 btnContent.rect = subElementRect(contentElement, btn, w);
2109 const auto labelElement = element == CE_CheckBox
2111 : CE_RadioButtonLabel;
2112 proxy()->drawControl(labelElement, &btnContent, p, w);
2114 QStyleOptionButton indicator(*btn);
2115 const auto indicatorElement = element == CE_CheckBox
2116 ? SE_CheckBoxIndicator
2117 : SE_RadioButtonIndicator;
2118 indicator.rect = subElementRect(indicatorElement, btn, w);
2119 const auto primitiveElement = element == CE_CheckBox
2120 ? PE_IndicatorCheckBox
2121 : PE_IndicatorRadioButton;
2122 proxy()->drawPrimitive(primitiveElement, &indicator, p, w);
2126 case CE_CheckBoxLabel:
2127 case CE_RadioButtonLabel:
2128 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2129 const auto controlType = element == CE_CheckBoxLabel
2130 ? QQStyleKitReader::ControlType::CheckBox
2131 : QQStyleKitReader::ControlType::RadioButton;
2132 const auto r = d->resolve(w, controlType, btn->state);
2135 uint textFlags = Qt::TextShowMnemonic;
2136 if (!styleHint(SH_UnderlineShortcut, opt, w))
2137 textFlags |= Qt::TextHideMnemonic;
2138 d->drawControlText(r.text(), r.font(), opt->rect, btn->text, textFlags, p);
2142#if QT_CONFIG(combobox)
2143 case CE_ComboBoxLabel:
2144 if (
const auto *comboBox = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
2145 if (comboBox->editable)
2147 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, comboBox->state);
2150 const QRect textRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, w)
2151 .marginsRemoved(r.metrics->textPadding);
2152 uint textFlags = Qt::TextShowMnemonic;
2153 if (!styleHint(SH_UnderlineShortcut, opt, w))
2154 textFlags |= Qt::TextHideMnemonic;
2155 d->drawControlText(r.text(), r.font(), textRect, comboBox->currentText, textFlags, p);
2160#if QT_CONFIG(progressbar)
2161 case CE_ProgressBar:
2162 if (
const QStyleOptionProgressBar *progressBar =
2163 qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
2164 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar,
2165 progressBar->state);
2168 QRect backgroundRect = progressBar->rect.marginsRemoved(r.metrics->margins);
2170 d->drawStyledItemRect(r.background(), backgroundRect, p);
2172 QStyleOptionProgressBar contents(*progressBar);
2173 contents.rect = subElementRect(SE_ProgressBarGroove, progressBar, w);
2174 const QRect grooveRect = contents.rect;
2175 proxy()->drawControl(CE_ProgressBarGroove, &contents, p, w);
2177 contents.rect = subElementRect(SE_ProgressBarContents, progressBar, w);
2180 QPainterStateGuard stateGuard(p);
2181 if (applyDelegateTransform(p, r.indicator(), grooveRect))
2182 proxy()->drawControl(CE_ProgressBarContents, &contents, p, w);
2187 case CE_ProgressBarGroove: {
2189 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar, opt->state);
2192 d->drawStyledItemRect(r.indicator(), opt->rect, p);
2195 case CE_ProgressBarContents:
2197 if (
const auto *progressBar = qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
2198 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar,
2199 progressBar->state);
2202 const auto progress = progressBar->progress;
2203 const auto ratio = progressBar->maximum > progressBar->minimum
2204 ? (progress - progressBar->minimum)
2205 /
static_cast<qreal>(progressBar->maximum - progressBar->minimum)
2207 const auto width =
static_cast<
int>(progressBar->rect.width() * ratio);
2208 const auto x = progressBar->invertedAppearance
2209 ? progressBar->rect.right() - width
2210 : progressBar->rect.left();
2211 const auto contentsRect = QRect(x, progressBar->rect.y(),
2212 width, progressBar->rect.height());
2213 const auto *foreground = r.indicator() ? r.indicator()->foreground() :
nullptr;
2214 if (foreground && foreground->visible() && foreground->opacity() > 0) {
2215 QPainterStateGuard stateGuard(p);
2216 if (applyDelegateTransform(p, foreground, progressBar->rect))
2217 d->drawStyledItemContents(foreground, contentsRect, p);
2223#if QT_CONFIG(itemviews)
2224 case CE_ItemViewItem:
2225 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
2226 const auto r = d->resolveSubElement(w, opt, itemViewControlType(opt), opt->state);
2229 QStyleOptionViewItem optBg(*itemViewOption);
2230 optBg.rect = optBg.rect.marginsRemoved(r.metrics->margins);
2231 QRect indicatorRect = subElementRect(SE_ItemViewItemCheckIndicator, itemViewOption, w);
2232 QRect iconRect = subElementRect(SE_ItemViewItemDecoration, itemViewOption, w);
2233 QRect textRect = subElementRect(SE_ItemViewItemText, itemViewOption, w);
2236 const auto *itemTextProps = r.text();
2237 const QFont itemFont = r.font();
2240 proxy()->drawPrimitive(PE_PanelItemViewItem, &optBg, p, w);
2243 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator) {
2244 QStyleOptionViewItem option(*itemViewOption);
2245 option.rect = indicatorRect;
2246 option.state = option.state & ~QStyle::State_HasFocus;
2248 switch (itemViewOption->checkState) {
2250 option.state |= QStyle::State_Off;
2252 case Qt::PartiallyChecked:
2253 option.state |= QStyle::State_NoChange;
2256 option.state |= QStyle::State_On;
2259 proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, p, w);
2263 QIcon::Mode mode = QIcon::Normal;
2264 if (!(itemViewOption->state & QStyle::State_Enabled))
2265 mode = QIcon::Disabled;
2266 else if (itemViewOption->state & QStyle::State_Selected)
2267 mode = QIcon::Selected;
2268 QIcon::State state = itemViewOption->state & QStyle::State_Open
2271 itemViewOption->icon.paint(p, iconRect, itemViewOption->decorationAlignment, mode,
2275 uint textFlags = Qt::TextShowMnemonic;
2276 if (!styleHint(SH_UnderlineShortcut, opt, w))
2277 textFlags |= Qt::TextHideMnemonic;
2278 d->drawControlText(itemTextProps, itemFont, textRect, itemViewOption->text, textFlags,
2279 p, Qt::AlignLeft | Qt::AlignVCenter);
2285 case CE_ShapedFrame: {
2286# if QT_CONFIG(scrollarea)
2287 if (qobject_cast<
const QAbstractScrollArea *>(w))
2291 auto controlType = QQStyleKitReader::ControlType::Frame;
2292# if QT_CONFIG(combobox)
2293 if (w && w->inherits(
"QComboBoxPrivateContainer"))
2294 controlType = QQStyleKitReader::ControlType::Popup;
2296# if QT_CONFIG(textedit)
2297 else if (w && qobject_cast<
const QTextEdit *>(w))
2298 controlType = QQStyleKitReader::ControlType::TextArea;
2300# if QT_CONFIG(label)
2301 else if (w && qobject_cast<
const QLabel *>(w))
2302 controlType = QQStyleKitReader::ControlType::Label;
2305 if (qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
2306 const auto r = d->resolve(w, controlType, opt->state);
2309 QRect backgroundRect = opt->rect.marginsRemoved(r.metrics->margins);
2310 d->drawStyledItemRect(r.background(), backgroundRect, p);
2316#if QT_CONFIG(scrollbar)
2317 case CE_ScrollBarSlider: {
2318 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ScrollBar, opt->state);
2321 d->drawControlIndicator(r.indicator(), opt->rect, p);
2325#if QT_CONFIG(toolbutton)
2326 case CE_ToolButtonLabel:
2327 if (
const auto *tool = qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
2328 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolButton, tool->state);
2331 const auto *metrics = r.metrics;
2332 QRect rect = tool->rect.marginsRemoved(metrics->textPadding);
2334 uint textFlags = Qt::TextShowMnemonic;
2335 if (!styleHint(SH_UnderlineShortcut, opt, w))
2336 textFlags |= Qt::TextHideMnemonic;
2338 const bool hasArrow = tool->features & QStyleOptionToolButton::Arrow;
2339 if ((!hasArrow && tool->icon.isNull() && !tool->text.isEmpty())
2340 || tool->toolButtonStyle == Qt::ToolButtonTextOnly) {
2341 d->drawControlText(r.text(), r.font(), rect, tool->text, textFlags, p);
2347 if (!hasArrow && !tool->icon.isNull()) {
2348 const QIcon::State iconState = tool->state & State_On ? QIcon::On : QIcon::Off;
2350 if (!(tool->state & State_Enabled))
2351 mode = QIcon::Disabled;
2352 else if ((tool->state & State_MouseOver) && (tool->state & State_AutoRaise))
2353 mode = QIcon::Active;
2355 mode = QIcon::Normal;
2356 pm = tool->icon.pixmap(tool->iconSize, p->device()->devicePixelRatio(), mode,
2358 pmSize = pm.size() / pm.devicePixelRatio();
2361 if (tool->toolButtonStyle == Qt::ToolButtonIconOnly || tool->text.isEmpty()) {
2363 p->drawPixmap(visualRect(tool->direction, rect,
2364 QRect(rect.x() + (rect.width() - pmSize.width()) / 2,
2365 rect.y() + (rect.height() - pmSize.height()) / 2,
2366 pmSize.width(), pmSize.height())),
2372 if (tool->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
2374 const QRect pr(rect.x() + (rect.width() - pmSize.width()) / 2, rect.y(),
2375 pmSize.width(), pmSize.height());
2376 p->drawPixmap(visualRect(tool->direction, rect, pr), pm);
2378 tr.setTop(rect.y() + pmSize.height() + metrics->spacing);
2379 d->drawControlText(r.text(), r.font(), visualRect(tool->direction, rect, tr),
2380 tool->text, textFlags, p, Qt::AlignCenter);
2382 d->drawControlText(r.text(), r.font(), rect, tool->text, textFlags, p,
2387 const QRect pr(rect.x(), rect.y() + (rect.height() - pmSize.height()) / 2,
2388 pmSize.width(), pmSize.height());
2389 p->drawPixmap(visualRect(tool->direction, rect, pr), pm);
2391 tr.setLeft(rect.x() + pmSize.width() + metrics->spacing);
2392 d->drawControlText(r.text(), r.font(), visualRect(tool->direction, rect, tr),
2393 tool->text, textFlags, p, Qt::AlignLeft | Qt::AlignVCenter);
2395 d->drawControlText(r.text(), r.font(), rect, tool->text, textFlags, p,
2396 Qt::AlignLeft | Qt::AlignVCenter);
2405 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
2406 using QtPrivate::qSaturateRound;
2408 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
2409 const auto r = d->resolve(w, QQStyleKitReader::ControlType::MenuSeparator,
2413 const auto metrics = r.metrics;
2414 QRect contentRect = opt->rect
2415 .marginsRemoved(metrics->margins)
2416 .marginsRemoved(metrics->padding);
2417 const auto *indicator = r.indicator();
2418 if (indicator && indicator->visible() && indicator->opacity() > 0) {
2419 const int w = qSaturateRound(resolvedWidth(
2421 contentRect.width() - indicator->leftMargin() - indicator->rightMargin()));
2422 const int h = qSaturateRound(resolvedHeight(
2424 contentRect.height() - indicator->topMargin() - indicator->bottomMargin()));
2425 const uint align = resolvedAlignment(indicator->alignment(), Qt::AlignHCenter,
2427 const QRect indicatorRect = d->getAlignedRectInContainer(
2428 contentRect, QSize(w, h), align, QMargins(), elementMargins(indicator));
2429 d->drawControlIndicator(
2430 indicator, visualRect(opt->direction, contentRect, indicatorRect), p);
2435 QStyle::State adjustedState = menuItem->state;
2436 if (adjustedState & State_Selected)
2437 adjustedState |= State_MouseOver;
2439 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::MenuItem,
2445 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
2448 const QRect contentRect = opt->rect.marginsRemoved(r.metrics->padding);
2449 const auto *indicator = r.indicator();
2450 const auto *first = indicator ? indicator->first() :
nullptr;
2451 const auto *second = indicator ? indicator->second() :
nullptr;
2452 int leftOffset = 0, rightOffset = 0;
2453 const int spacing = r.metrics->spacing;
2454 QRect firstDrawRect, secondDrawRect;
2455 auto placeSubIndicator = [&](
const QQStyleKitIndicatorProperties *sub,
2459 const QSize sz(qSaturateRound(sub->width()), qSaturateRound(sub->height()));
2460 const QMargins subMargins = elementMargins(sub);
2461 const int slotW = qSaturateRound(sub->leftMargin() + sub->width() + sub->rightMargin());
2462 if (sub->alignment() & Qt::AlignRight) {
2463 const QRect slot(contentRect.right() - rightOffset - slotW, contentRect.top(),
2464 slotW, contentRect.height());
2465 drawRect = d->getAlignedRectInContainer(
2466 slot, sz, Qt::AlignRight | Qt::AlignVCenter, { }, subMargins);
2467 rightOffset += slotW + spacing;
2469 const QRect slot(contentRect.left() + leftOffset, contentRect.top(), slotW,
2470 contentRect.height());
2471 drawRect = d->getAlignedRectInContainer(
2472 slot, sz, Qt::AlignLeft | Qt::AlignVCenter, { }, subMargins);
2473 leftOffset += slotW + spacing;
2476 placeSubIndicator(first, firstDrawRect);
2477 placeSubIndicator(second, secondDrawRect);
2479 if (first && menuItem->checkType != QStyleOptionMenuItem::NotCheckable
2480 && menuItem->checked) {
2481 d->drawControlIndicator(
2482 first, visualRect(menuItem->direction, contentRect, firstDrawRect), p);
2485 if (second && menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {
2486 d->drawControlIndicator(
2487 second, visualRect(menuItem->direction, contentRect, secondDrawRect), p);
2491 QRect textRect = contentRect
2492 .adjusted(leftOffset, 0, -rightOffset, 0)
2493 .marginsRemoved(r.metrics->textPadding);
2494 if (!menuItem->icon.isNull()) {
2495 const int iconW = menuItem->maxIconWidth;
2496 const QIcon::Mode mode = (menuItem->state & State_Enabled)
2499 const int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt, w);
2500 const QPixmap pm = menuItem->icon.pixmap(
2501 QSize(iconExtent, iconExtent), p->device()->devicePixelRatio(), mode);
2502 const QSize pmSize = pm.size() / pm.devicePixelRatio();
2503 const int pmW = pmSize.width();
2504 const int pmH = pmSize.height();
2506 visualRect(menuItem->direction, textRect,
2507 QRect(textRect.left(),
2508 textRect.top() + (textRect.height() - pmH) / 2, pmW, pmH)),
2510 textRect.setLeft(textRect.left() + iconW + r.metrics->spacing);
2513 const int tabIdx = menuItem->text.indexOf(QLatin1Char(
'\t'));
2514 const QString label = tabIdx >= 0 ? menuItem->text.left(tabIdx) : menuItem->text;
2515 const QString shortcut = tabIdx >= 0 ? menuItem->text.mid(tabIdx + 1) : QString();
2516 uint textFlags = Qt::TextShowMnemonic;
2517 if (!styleHint(SH_UnderlineShortcut, opt, w))
2518 textFlags |= Qt::TextHideMnemonic;
2519 QRect labelRect = textRect;
2520 if (!shortcut.isEmpty() && menuItem->reservedShortcutWidth > 0) {
2521 const QRect shortcutRect(textRect.right() - menuItem->reservedShortcutWidth + 1,
2522 textRect.top(), menuItem->reservedShortcutWidth,
2524 labelRect.setRight(shortcutRect.left() - r.metrics->spacing - 1);
2525 const int shortcutFlags =
2526 int(QStyle::visualAlignment(menuItem->direction,
2527 Qt::AlignRight | Qt::AlignVCenter))
2530 p->setFont(r.font().resolve(p->font()));
2531 p->setBrush(Qt::NoBrush);
2532 if (
const auto *shortcutText = r.text())
2533 p->setPen(shortcutText->color());
2534 p->drawText(visualRect(menuItem->direction, textRect, shortcutRect), shortcutFlags,
2538 d->drawControlText(r.text(), r.font(),
2539 visualRect(menuItem->direction, textRect, labelRect), label,
2540 textFlags, p, Qt::AlignLeft | Qt::AlignVCenter);
2546 case CE_MenuScroller:
2547 case CE_MenuTearoff:
2549 case CE_MenuEmptyArea:
2552#if QT_CONFIG(menubar)
2553 case CE_MenuBarEmptyArea:
2555 case CE_MenuBarItem:
2556 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
2557 QStyle::State adjustedState = menuItem->state;
2558 if (adjustedState & State_Selected)
2559 adjustedState |= State_MouseOver;
2560 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::MenuBarItem,
2564 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
2565 const QRect textRect = opt->rect.marginsRemoved(
2566 r.metrics->margins + r.metrics->padding + r.metrics->textPadding);
2567 uint textFlags = Qt::TextShowMnemonic;
2568 if (!styleHint(SH_UnderlineShortcut, opt, w))
2569 textFlags |= Qt::TextHideMnemonic;
2570 d->drawControlText(r.text(), r.font(), textRect, menuItem->text, textFlags, p);
2575#if QT_CONFIG(tabbar)
2577 if (
const auto *tab = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
2578 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::TabButton,
2582 const auto &m = *r.metrics;
2584 const QRect backgroundRect = opt->rect.marginsRemoved(m.margins);
2585 d->drawStyledItemRect(r.background(), backgroundRect, p);
2587 const QRect contentRect = backgroundRect.marginsRemoved(m.padding);
2588 uint textFlags = Qt::TextShowMnemonic;
2589 if (!styleHint(SH_UnderlineShortcut, opt, w))
2590 textFlags |= Qt::TextHideMnemonic;
2592 if (!tab->icon.isNull()) {
2593 const QIcon::Mode mode = (tab->state & State_Enabled)
2596 const QIcon::State iconState = (tab->state & State_Selected)
2599 const QPixmap pm = tab->icon.pixmap(tab->iconSize, p->device()->devicePixelRatio(),
2601 const QSize pmSize = pm.size() / pm.devicePixelRatio();
2602 const QRect pr(contentRect.x(),
2603 contentRect.y() + (contentRect.height() - pmSize.height()) / 2,
2604 pmSize.width(), pmSize.height());
2605 p->drawPixmap(visualRect(tab->direction, contentRect, pr), pm);
2606 QRect tr = contentRect;
2607 tr.setLeft(contentRect.x() + pmSize.width() + m.spacing);
2608 d->drawControlText(r.text(), r.font(), visualRect(tab->direction, contentRect, tr),
2609 tab->text, textFlags, p, Qt::AlignCenter);
2611 d->drawControlText(r.text(), r.font(), contentRect, tab->text, textFlags, p,
2618#if QT_CONFIG(toolbar)
2620 if (
const auto *toolBar = qstyleoption_cast<
const QStyleOptionToolBar *>(opt)) {
2621 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolBar, toolBar->state);
2624 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
2632 QCommonStyle::drawControl(element, opt, p, w);
2636QRect QStyleKitStyle::subElementRect(SubElement r,
const QStyleOption *opt,
2637 const QWidget *widget)
const
2639 using QtPrivate::qSaturateRound;
2640 Q_D(
const QStyleKitStyle);
2643 case SE_PushButtonLayoutItem:
2644 case SE_PushButtonBevel:
2645 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2646 const auto controlType = btn->features & QStyleOptionButton::Flat
2647 ? QQStyleKitReader::ControlType::FlatButton
2648 : QQStyleKitReader::ControlType::Button;
2649 const auto resolved = d->resolveLayout(controlType, opt->state);
2650 if (!resolved.isValid())
2652 const auto &metrics = *resolved.metrics;
2653 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2654 return visualRect(opt->direction, opt->rect, rect);
2657 case SE_PushButtonContents:
2658 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2659 const auto controlType = btn->features & QStyleOptionButton::Flat
2660 ? QQStyleKitReader::ControlType::FlatButton
2661 : QQStyleKitReader::ControlType::Button;
2662 const auto resolved = d->resolveLayout(controlType, opt->state);
2663 if (!resolved.isValid())
2665 const auto &metrics = *resolved.metrics;
2666 QRect rect = opt->rect.marginsRemoved(
2667 metrics.margins + metrics.padding + metrics.textPadding);
2668 return visualRect(opt->direction, opt->rect, rect);
2671 case SE_CheckBoxContents:
2672 case SE_RadioButtonContents: {
2673 const auto controlType = r == SE_CheckBoxContents
2674 ? QQStyleKitReader::ControlType::CheckBox
2675 : QQStyleKitReader::ControlType::RadioButton;
2676 const auto resolved = d->resolveLayout(controlType, opt->state);
2677 if (!resolved.isValid())
2679 const auto &metrics = *resolved.metrics;
2680 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
2681 const auto subElement = r == SE_CheckBoxContents
2682 ? SE_CheckBoxIndicator
2683 : SE_RadioButtonIndicator;
2684 QRect indicatorRect = visualRect(opt->direction, opt->rect,
2685 subElementRect(subElement, opt, widget));
2686 const int spacing = metrics.spacing;
2687 const auto *indicator = resolved.indicator();
2688 const uint alignment = indicator
2689 ? resolvedAlignment(indicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
2690 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2691 if (alignment & Qt::AlignLeft) {
2692 contentsRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
2693 }
else if (alignment & Qt::AlignHCenter) {
2694 contentsRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
2695 contentsRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
2697 contentsRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
2699 return visualRect(opt->direction, opt->rect, contentsRect);
2701 case SE_CheckBoxIndicator:
2702 case SE_RadioButtonIndicator: {
2703 const auto controlType = r == SE_CheckBoxIndicator
2704 ? QQStyleKitReader::ControlType::CheckBox
2705 : QQStyleKitReader::ControlType::RadioButton;
2706 const auto resolved = d->resolveLayout(controlType, opt->state);
2707 if (!resolved.isValid())
2709 const auto &metrics = *resolved.metrics;
2710 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2711 const auto *indicator = resolved.indicator();
2712 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2715 const int w = qSaturateRound(resolvedWidth(
2717 rect.width() - metrics.padding.left() - metrics.padding.right()
2718 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right()));
2719 const int h = qSaturateRound(resolvedHeight(
2722 - metrics.padding.top() - metrics.padding.bottom()
2723 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom()));
2724 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft,
2726 const QRect indicatorRect = d->getAlignedRectInContainer(
2727 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
2728 return visualRect(opt->direction, rect, indicatorRect);
2730#if QT_CONFIG(itemviews)
2731 case SE_ItemViewItemCheckIndicator: {
2732 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
2733 if (!resolved.isValid())
2735 const auto &metrics = *resolved.metrics;
2736 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2737 const auto *indicator = resolved.indicator();
2738 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2741 const int w = qSaturateRound(resolvedWidth(
2744 - metrics.padding.left() - metrics.padding.right()
2745 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right()));
2746 const int h = qSaturateRound(resolvedHeight(
2748 rect.height() - metrics.padding.top() - metrics.padding.bottom()
2749 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom()));
2750 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft,
2752 const QRect indicatorRect = d->getAlignedRectInContainer(
2753 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
2754 return visualRect(opt->direction, rect, indicatorRect);
2756 case SE_ItemViewItemDecoration:
2757 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
2758 if (!(itemViewOption->features & QStyleOptionViewItem::HasDecoration))
2760 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
2761 if (!resolved.isValid())
2763 const auto &metrics = *resolved.metrics;
2764 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
2765 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator) {
2766 const QRect indicatorRect = subElementRect(
2767 SE_ItemViewItemCheckIndicator, opt, widget);
2768 const auto *checkIndicator = resolved.indicator();
2769 const uint checkAlign = checkIndicator
2770 ? resolvedAlignment(checkIndicator->alignment(), Qt::AlignLeft,
2772 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2773 if (checkAlign & Qt::AlignLeft) {
2774 contentsRect.setLeft(indicatorRect.right()
2775 + metrics.indicatorMargins.right() + metrics.spacing);
2776 }
else if (checkAlign & Qt::AlignRight) {
2777 contentsRect.setRight(indicatorRect.left()
2778 - metrics.indicatorMargins.left() - metrics.spacing);
2782 const QSize decorationSize = itemViewOption->decorationSize
2783 .boundedTo(contentsRect.size());
2784 QRect decorationRect;
2785 switch (itemViewOption->decorationPosition) {
2786 case QStyleOptionViewItem::Top:
2787 decorationRect = QRect(contentsRect.left(), contentsRect.top(),
2788 contentsRect.width(), decorationSize.height());
2790 case QStyleOptionViewItem::Bottom:
2791 decorationRect = QRect(contentsRect.left(),
2792 contentsRect.bottom() - decorationSize.height() + 1,
2793 contentsRect.width(), decorationSize.height());
2795 case QStyleOptionViewItem::Right:
2796 decorationRect = QRect(contentsRect.right() - decorationSize.width() + 1,
2797 contentsRect.top(), decorationSize.width(),
2798 contentsRect.height());
2800 case QStyleOptionViewItem::Left:
2802 decorationRect = QRect(contentsRect.left(), contentsRect.top(),
2803 decorationSize.width(), contentsRect.height());
2806 const uint decorationAlign = resolvedAlignment(itemViewOption->decorationAlignment,
2807 Qt::AlignLeft, Qt::AlignVCenter);
2808 decorationRect = d->getAlignedRectInContainer(
2809 decorationRect, decorationSize, decorationAlign, QMargins(0, 0, 0, 0),
2810 QMargins(0, 0, 0, 0));
2811 return visualRect(opt->direction, opt->rect, decorationRect);
2814 case SE_ItemViewItemText:
2815 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
2816 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
2817 if (!resolved.isValid())
2819 const auto &metrics = *resolved.metrics;
2820 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
2821 const int spacing = metrics.spacing;
2823 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator) {
2824 const QRect indicatorRect = subElementRect(
2825 SE_ItemViewItemCheckIndicator, opt, widget);
2826 const auto *checkIndicator = resolved.indicator();
2827 const uint checkAlign = checkIndicator
2828 ? resolvedAlignment(checkIndicator->alignment(), Qt::AlignLeft,
2830 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2831 if (checkAlign & Qt::AlignLeft) {
2832 contentsRect.setLeft(
2833 indicatorRect.right() + metrics.indicatorMargins.right() + spacing);
2834 }
else if (checkAlign & Qt::AlignRight) {
2835 contentsRect.setRight(
2836 indicatorRect.left() - metrics.indicatorMargins.left() - spacing);
2840 QRect textRect = contentsRect;
2841 if (itemViewOption->features & QStyleOptionViewItem::HasDecoration) {
2842 const QRect decorationRect = subElementRect(
2843 SE_ItemViewItemDecoration, opt, widget);
2844 switch (itemViewOption->decorationPosition) {
2845 case QStyleOptionViewItem::Top:
2846 textRect.setTop(decorationRect.bottom() + spacing);
2848 case QStyleOptionViewItem::Bottom:
2849 textRect.setBottom(decorationRect.top() - spacing);
2851 case QStyleOptionViewItem::Right:
2852 textRect.setRight(decorationRect.left() - spacing);
2854 case QStyleOptionViewItem::Left:
2856 textRect.setLeft(decorationRect.right() + spacing);
2861 const auto *textProps = resolved.text();
2862 const uint textAlign = textProps
2863 ? resolvedAlignment(textProps->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
2864 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2865 if (textAlign & Qt::AlignLeft) {
2866 textRect.setLeft(textRect.left() + metrics.textPadding.left());
2867 }
else if (textAlign & Qt::AlignHCenter) {
2868 textRect.setLeft(textRect.left() + metrics.textPadding.left() / 2);
2869 textRect.setRight(textRect.right() - metrics.textPadding.right() / 2);
2871 textRect.setRight(textRect.right() - metrics.textPadding.right());
2873 if (textAlign & Qt::AlignTop) {
2874 textRect.setTop(textRect.top() + metrics.textPadding.top());
2875 }
else if (textAlign & Qt::AlignVCenter) {
2876 textRect.setTop(textRect.top() + metrics.textPadding.top() / 2);
2877 textRect.setBottom(textRect.bottom() - metrics.textPadding.bottom() / 2);
2879 textRect.setBottom(textRect.bottom() - metrics.textPadding.bottom());
2881 return visualRect(opt->direction, opt->rect, textRect);
2885 case SE_PushButtonFocusRect:
2886 case SE_CheckBoxClickRect:
2887 case SE_RadioButtonClickRect:
2889#if QT_CONFIG(progressbar)
2890 case SE_ProgressBarGroove: {
2891 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar,
2893 if (!resolved.isValid())
2895 const auto &metrics = *resolved.metrics;
2896 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2897 const auto *indicator = resolved.indicator();
2898 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2901 const int w = qSaturateRound(resolvedWidth(
2903 rect.width() - metrics.padding.left() - metrics.padding.right()
2904 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right()));
2905 const int h = qSaturateRound(resolvedHeight(
2907 rect.height() - metrics.padding.top() - metrics.padding.bottom()
2908 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom()));
2909 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft,
2911 const QRect indicatorRect = d->getAlignedRectInContainer(
2912 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
2913 return visualRect(opt->direction, rect, indicatorRect);
2915 case SE_ProgressBarContents: {
2916 if (qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
2917 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar,
2919 if (!resolved.isValid())
2921 const auto *foreground = resolved.indicator()
2922 ? resolved.indicator()->foreground()
2924 if (!foreground || !foreground->visible() || foreground->opacity() == 0)
2927 QRect indicatorRect = subElementRect(SE_ProgressBarGroove, opt, widget);
2928 const int foregroundW = qSaturateRound(resolvedWidth(
2930 indicatorRect.width() - foreground->leftMargin() - foreground->rightMargin()));
2931 const int foregroundH = qSaturateRound(resolvedHeight(
2933 indicatorRect.height() - foreground->topMargin() - foreground->bottomMargin()));
2934 const uint foregroundAlign = resolvedAlignment(foreground->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
2935 const QMargins foregroundMargins = elementMargins(foreground);
2936 const QRect foregroundRect = d->getAlignedRectInContainer(
2937 indicatorRect, QSize(foregroundW, foregroundH), foregroundAlign,
2938 QMargins(0, 0, 0, 0), foregroundMargins);
2939 return visualRect(opt->direction, opt->rect, foregroundRect);
2944 case SE_LineEditContents:
2945 if (qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
2946#if QT_CONFIG(spinbox)
2947 const bool isInSpinBox = widget && qobject_cast<
const QSpinBox *>(widget->parentWidget());
2949 const bool isInSpinBox =
false;
2951 const auto controlType = isInSpinBox ? QQStyleKitReader::ControlType::SpinBox
2952 : QQStyleKitReader::ControlType::TextField;
2953 const auto resolved = d->resolveLayout(controlType, opt->state);
2954 if (!resolved.isValid())
2956 const auto &metrics = *resolved.metrics;
2957 QRect contentsRect = opt->rect.marginsRemoved(metrics.padding);
2958 const auto *textProps = resolved.text();
2959 const uint textAlign = resolvedAlignment(textProps ? textProps->alignment() : 0u,
2960 Qt::AlignLeft, Qt::AlignVCenter);
2961 if (textAlign & Qt::AlignLeft)
2962 contentsRect.setLeft(contentsRect.left() + metrics.textPadding.left());
2963 else if (textAlign & Qt::AlignHCenter) {
2964 contentsRect.setLeft(contentsRect.left() + metrics.textPadding.left() / 2);
2965 contentsRect.setRight(contentsRect.right() - metrics.textPadding.right() / 2);
2967 contentsRect.setRight(contentsRect.right() - metrics.textPadding.right());
2969 if (textAlign & Qt::AlignTop)
2970 contentsRect.setTop(contentsRect.top() + metrics.textPadding.top());
2971 else if (textAlign & Qt::AlignVCenter) {
2972 contentsRect.setTop(contentsRect.top() + metrics.textPadding.top() / 2);
2973 contentsRect.setBottom(contentsRect.bottom() - metrics.textPadding.bottom() / 2);
2975 contentsRect.setBottom(contentsRect.bottom() - metrics.textPadding.bottom());
2977 return visualRect(opt->direction, opt->rect, contentsRect);
2980 case SE_ShapedFrameContents:
2981#if QT_CONFIG(combobox)
2982 if (widget && widget->inherits(
"QComboBoxPrivateContainer")) {
2983 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Popup,
2985 if (!resolved.isValid())
2987 const auto &metrics = *resolved.metrics;
2988 QRect contentsRect = opt->rect.marginsRemoved(
2989 metrics.margins + metrics.padding + metrics.textPadding);
2990 return visualRect(opt->direction, opt->rect, contentsRect);
2993#if QT_CONFIG(textedit)
2994 if (qobject_cast<
const QTextEdit *>(widget)) {
2995 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::TextArea,
2997 if (!resolved.isValid())
2999 const auto &metrics = *resolved.metrics;
3000 QRect contentsRect = opt->rect.marginsRemoved(
3001 metrics.margins + metrics.padding + metrics.textPadding);
3002 return visualRect(opt->direction, opt->rect, contentsRect);
3006#if QT_CONFIG(tabbar)
3007 case SE_TabBarTabText:
3008 if (
const auto *tab = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
3009 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::TabButton,
3011 if (!resolved.isValid())
3013 const auto &metrics = *resolved.metrics;
3014 QRect rect = tab->rect.marginsRemoved(
3015 metrics.margins + metrics.padding + metrics.textPadding);
3016 if (!tab->icon.isNull())
3017 rect.setLeft(rect.left() + tab->iconSize.width() + metrics.spacing);
3018 return visualRect(tab->direction, tab->rect, rect);
3021 case SE_TabBarTearIndicatorRight:
3022 case SE_TabBarTearIndicatorLeft:
3023 case SE_TabBarScrollLeftButton:
3024 case SE_TabBarScrollRightButton:
3028#if QT_CONFIG(tabwidget)
3029 case SE_TabWidgetTabContents:
3030 if (qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(opt)) {
3032 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Page, opt->state);
3033 if (!resolved.isValid())
3035 const QRect paneRect = subElementRect(SE_TabWidgetTabPane, opt, widget);
3036 const QRect rect = paneRect.marginsRemoved(resolved.metrics->padding);
3037 return visualRect(opt->direction, opt->rect, rect);
3041#if QT_CONFIG(toolbar)
3042 case SE_ToolBarHandle:
3049 return QCommonStyle::subElementRect(r, opt, widget);
3053void QStyleKitStyle::drawComplexControl(ComplexControl cc,
const QStyleOptionComplex *opt,
3054 QPainter *p,
const QWidget *w)
const
3056 Q_D(
const QStyleKitStyle);
3059#if QT_CONFIG(slider)
3061 if (
const QStyleOptionSlider *slider = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3062 const auto r = d->resolve(w, QQStyleKitReader::ControlType::Slider, slider->state);
3065 const auto &metrics = *r.metrics;
3066 QRect backgroundRect = opt->rect.marginsRemoved(metrics.margins);
3069 d->drawStyledItemRect(r.background(), backgroundRect, p);
3072 if (slider->subControls & SC_SliderGroove) {
3074 const auto grooveRect = proxy()->subControlRect(CC_Slider, opt, SC_SliderGroove, w);
3075 const auto *indicator = r.indicator();
3076 d->drawStyledItemRect(indicator, grooveRect, p);
3079 const auto *foreground = indicator ? indicator->foreground() :
nullptr;
3080 if (foreground && foreground->visible() && foreground->opacity() > 0) {
3081 const bool isHorizontal = slider->orientation == Qt::Horizontal;
3082 const qreal availableW = grooveRect.width()
3083 - foreground->leftMargin() - foreground->rightMargin();
3084 const qreal availableH = grooveRect.height()
3085 - foreground->topMargin() - foreground->bottomMargin();
3087 const qreal range = slider->maximum - slider->minimum;
3088 const qreal ratio = range > 0
3089 ? (slider->sliderPosition - slider->minimum) / range
3092 const auto hAlign = foreground->alignment() & Qt::AlignHorizontal_Mask;
3093 const auto vAlign = foreground->alignment() & Qt::AlignVertical_Mask;
3094 const qreal fgW = resolvedWidth(foreground, availableW);
3095 const qreal fgH = resolvedHeight(foreground, availableH);
3096 const qreal fgX = hAlign & Qt::AlignRight
3097 ? grooveRect.left() + foreground->leftMargin() + availableW - fgW
3098 : hAlign & Qt::AlignHCenter
3099 ? grooveRect.left() + foreground->leftMargin() + (availableW - fgW) / 2
3100 : grooveRect.left() + foreground->leftMargin();
3101 const qreal fgY = vAlign & Qt::AlignBottom
3102 ? grooveRect.top() + foreground->topMargin() + availableH - fgH
3103 : vAlign & Qt::AlignVCenter
3104 ? grooveRect.top() + foreground->topMargin() + (availableH - fgH) / 2
3105 : grooveRect.top() + foreground->topMargin();
3107 const qreal minW = foreground->minimumWidth();
3110 const qreal trackW = foreground->fillWidth()
3111 ? minW + ratio * (fgW - minW)
3113 trackRect = QRectF(fgX, fgY, trackW, fgH);
3115 const qreal trackH = foreground->fillHeight()
3116 ? minW + ratio * (fgH - minW)
3118 const qreal trackY = fgY
3119 + (1.0 - ratio) * (foreground->fillHeight() ? fgH - minW : fgH);
3120 trackRect = QRectF(fgX, trackY, fgW, trackH);
3124 const QRect foregroundBox = visualRect(
3125 opt->direction, grooveRect, QRectF(fgX, fgY, fgW, fgH).toAlignedRect());
3126 QPainterStateGuard stateGuard(p);
3127 if (applyDelegateTransform(p, indicator, grooveRect)
3128 && applyDelegateTransform(p, foreground, foregroundBox)) {
3129 d->drawStyledItemContents(
3131 visualRect(opt->direction, grooveRect, trackRect.toAlignedRect()), p);
3137 if (slider->subControls & SC_SliderHandle) {
3138 QStyleOptionSlider handleOpt(*slider);
3139 handleOpt.rect = subControlRect(CC_Slider, opt, SC_SliderHandle, w);
3140 const auto *handle = r.handle();
3141 if (handle && handle->visible() && handle->opacity() > 0)
3142 d->drawStyledItemRect(handle, handleOpt.rect, p);
3148#if QT_CONFIG(combobox)
3150 if (
const QStyleOptionComboBox *combo =
3151 qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
3153 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, combo->state);
3156 QRect frameRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxFrame, w);
3157 d->drawStyledItemRect(r.background(), frameRect, p);
3160 if (combo->subControls & SC_ComboBoxArrow) {
3161 QStyleOptionComboBox indicatorOpt(*combo);
3162 indicatorOpt.rect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
3163 proxy()->drawPrimitive(PE_IndicatorArrowDown, &indicatorOpt, p, w);
3168 if (
auto *cb = qobject_cast<
const QComboBox *>(w); cb && cb->isEditable()) {
3169 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
3170 QPalette stylePalette;
3171 stylePalette.setColor(QPalette::Text, txt->color());
3172 d->setStylePalette(cb->lineEdit(), stylePalette);
3179#if QT_CONFIG(spinbox)
3181 if (
const QStyleOptionSpinBox *spin = qstyleoption_cast<
const QStyleOptionSpinBox *>(opt)) {
3182 const auto r = d->resolve(w, QQStyleKitReader::ControlType::SpinBox, spin->state);
3185 QRect frameRect = opt->rect.marginsRemoved(r.metrics->margins);
3187 d->drawStyledItemRect(r.background(), frameRect, p);
3189 if (spin->subControls & SC_SpinBoxUp) {
3190 QStyleOptionSpinBox upOpt(*spin);
3191 upOpt.rect = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w);
3192 proxy()->drawPrimitive(PE_IndicatorSpinUp, &upOpt, p, w);
3194 if (spin->subControls & SC_SpinBoxDown) {
3195 QStyleOptionSpinBox downOpt(*spin);
3196 downOpt.rect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
3197 proxy()->drawPrimitive(PE_IndicatorSpinDown, &downOpt, p, w);
3201 if (
auto *sb = qobject_cast<
const QSpinBox *>(w)) {
3202 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
3203 QLineEdit *lineEdit = sb->findChild<QLineEdit *>();
3205 QPalette p = lineEdit->palette();
3206 if (p.color(QPalette::Text) != txt->color()) {
3207 p.setColor(QPalette::Text, txt->color());
3208 lineEdit->setPalette(p);
3217#if QT_CONFIG(groupbox)
3219 if (
const QStyleOptionGroupBox *groupBox =
3220 qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
3221 const auto r = d->resolve(w, QQStyleKitReader::ControlType::GroupBox, groupBox->state);
3226 if (groupBox->subControls & SC_GroupBoxFrame) {
3227 QStyleOptionFrame frameOpt;
3228 frameOpt.QStyleOption::operator=(*groupBox);
3229 frameOpt.rect = subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, w);
3230 drawPrimitive(PE_FrameGroupBox, &frameOpt, p, w);
3234 if (groupBox->subControls & SC_GroupBoxLabel && !groupBox->text.isEmpty()) {
3235 const auto *textProps = r.text();
3236 const QFont textFont = r.font();
3237 QRect titleRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w);
3238 d->drawControlText(textProps, textFont,
3239 titleRect.marginsRemoved(r.metrics->textPadding), groupBox->text,
3240 Qt::TextShowMnemonic, p, Qt::AlignLeft | Qt::AlignVCenter);
3248#if QT_CONFIG(scrollbar)
3250 if (
const auto *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3251 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ScrollBar,
3257 if (scrollbar->subControls & SC_ScrollBarGroove) {
3258 QRect backgroundRect = proxy()->subControlRect(
3259 CC_ScrollBar, opt, SC_ScrollBarGroove, w);
3260 d->drawStyledItemRect(r.background(), backgroundRect, p);
3267 if (scrollbar->subControls & SC_ScrollBarSlider) {
3268 QStyleOptionSlider newScrollbar(*scrollbar);
3269 newScrollbar.rect = proxy()->subControlRect(
3270 CC_ScrollBar, opt, SC_ScrollBarSlider, w);
3271 proxy()->drawControl(CE_ScrollBarSlider, &newScrollbar, p, w);
3277#if QT_CONFIG(toolbutton)
3279 if (
const QStyleOptionToolButton *tool =
3280 qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
3281 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolButton, tool->state);
3286 d->drawStyledItemRect(r.background(), opt->rect, p);
3290 & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay))
3291 == QStyleOptionToolButton::MenuButtonPopup
3292 && (tool->subControls & SC_ToolButtonMenu)) {
3293 const QRect menuRect = subControlRect(CC_ToolButton, opt, SC_ToolButtonMenu, w);
3294 d->drawControlIndicator(r.indicator(), menuRect, p);
3298 State bflags = tool->state & ~State_Sunken;
3299 if (bflags & State_AutoRaise) {
3300 if (!(bflags & State_MouseOver) || !(bflags & State_Enabled))
3301 bflags &= ~State_Raised;
3303 if (tool->state & State_Sunken && tool->activeSubControls & SC_ToolButton)
3304 bflags |= State_Sunken;
3305 QStyleOptionToolButton label = *tool;
3306 label.state = bflags;
3307 label.rect = subControlRect(CC_ToolButton, opt, SC_ToolButton, w);
3308 proxy()->drawControl(CE_ToolButtonLabel, &label, p, w);
3316 QCommonStyle::drawComplexControl(cc, opt, p, w);
3320QStyle::SubControl QStyleKitStyle::hitTestComplexControl(ComplexControl cc,
3321 const QStyleOptionComplex *opt,
3322 const QPoint &pt,
const QWidget *w)
const
3324 return QCommonStyle::hitTestComplexControl(cc, opt, pt, w);
3328QRect QStyleKitStyle::subControlRect(ComplexControl cc,
const QStyleOptionComplex *opt,
3329 SubControl sc,
const QWidget *w)
const
3331 using QtPrivate::qSaturateRound;
3332 Q_D(
const QStyleKitStyle);
3335#if QT_CONFIG(slider)
3337 if (
const QStyleOptionSlider *slider = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3338 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Slider,
3340 if (!resolved.isValid())
3342 const auto &metrics = *resolved.metrics;
3343 const bool horizontal = slider->orientation == Qt::Horizontal;
3344 QRect contentsRect = opt->rect
3345 .marginsRemoved(metrics.margins)
3346 .marginsRemoved(metrics.padding);
3348 const auto *indicator = resolved.indicator();
3350 return contentsRect;
3352 case SC_SliderGroove: {
3353 const auto availableW = contentsRect.width()
3354 - indicator->leftMargin() - indicator->rightMargin();
3355 const auto availableH = contentsRect.height()
3356 - indicator->topMargin() - indicator->bottomMargin();
3357 const qreal grooveW = resolvedWidth(indicator, availableW);
3358 const qreal grooveH = resolvedHeight(indicator, availableH);
3360 QRectF grooveRect(0, 0, grooveW, grooveH);
3361 const uint rawHAlign = indicator->alignment() & Qt::AlignHorizontal_Mask;
3362 const uint rawVAlign = indicator->alignment() & Qt::AlignVertical_Mask;
3363 const uint hAlign = rawHAlign
3364 ?
static_cast<Qt::Alignment>(rawHAlign)
3366 const uint vAlign = rawVAlign
3367 ?
static_cast<Qt::Alignment>(rawVAlign)
3370 if (hAlign & Qt::AlignLeft) {
3371 grooveRect.moveLeft(contentsRect.x() + indicator->leftMargin());
3372 }
else if (hAlign & Qt::AlignHCenter) {
3373 const qreal availableWidth = contentsRect.width()
3374 - indicator->leftMargin() - indicator->rightMargin();
3375 grooveRect.moveLeft(contentsRect.x() + indicator->leftMargin()
3376 + (availableWidth - grooveW) / 2.0);
3378 grooveRect.moveLeft(contentsRect.x() + contentsRect.width()
3379 - indicator->rightMargin() - grooveW);
3382 if (vAlign & Qt::AlignTop) {
3383 grooveRect.moveTop(contentsRect.y() + indicator->topMargin());
3384 }
else if (vAlign & Qt::AlignVCenter) {
3385 const qreal availableHeight = contentsRect.height()
3386 - indicator->topMargin() - indicator->bottomMargin();
3387 grooveRect.moveTop(contentsRect.y()
3388 + indicator->topMargin()
3389 + (availableHeight - grooveH) / 2.0);
3391 grooveRect.moveTop(contentsRect.y()
3392 + contentsRect.height()
3393 - indicator->bottomMargin() - grooveH);
3395 return visualRect(opt->direction, opt->rect, grooveRect.toAlignedRect());
3397 case SC_SliderHandle: {
3398 const auto *handle = resolved.handle();
3399 if (!handle || !handle->visible() || handle->opacity() == 0)
3400 return contentsRect;
3402 const qreal handleW = resolvedWidth(
3403 handle, contentsRect.width() - handle->leftMargin() - handle->rightMargin());
3404 const qreal handleH = resolvedHeight(
3405 handle, contentsRect.height() - handle->topMargin() - handle->bottomMargin());
3406 QRectF handleRect(0, 0, handleW, handleH);
3408 const int range = qSaturateRound(contentsRect.width()
3409 - handle->leftMargin() - handle->rightMargin() - handleW);
3410 const int sliderPos = QStyle::sliderPositionFromValue(
3411 slider->minimum, slider->maximum, slider->sliderPosition, range,
false);
3412 handleRect.moveLeft(contentsRect.x() + handle->leftMargin() + sliderPos);
3413 handleRect.moveTop(contentsRect.y()
3414 + handle->topMargin() - handle->bottomMargin()
3415 + (contentsRect.height() - handleH) / 2.0);
3417 const int range = qSaturateRound(contentsRect.height()
3418 - handle->topMargin() - handle->bottomMargin() - handleH);
3419 const int sliderPos = QStyle::sliderPositionFromValue(
3420 slider->minimum, slider->maximum, slider->sliderPosition, range,
true);
3421 handleRect.moveLeft(contentsRect.x()
3422 + handle->leftMargin() - handle->rightMargin()
3423 + (contentsRect.width() - handleW) / 2.0);
3424 handleRect.moveTop(contentsRect.y() + handle->topMargin() + sliderPos);
3426 return visualRect(opt->direction, opt->rect, handleRect.toAlignedRect());
3434#if QT_CONFIG(combobox)
3436 if (
const QStyleOptionComboBox *combo =
3437 qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
3438 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::ComboBox, combo->state);
3441 const auto &metrics = *r.metrics;
3442 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3444 case SC_ComboBoxFrame:
3445 return visualRect(opt->direction, opt->rect, frameRect);
3446 case SC_ComboBoxEditField: {
3447 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3448 QRect indicatorRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
3449 const int spacing = metrics.spacing;
3450 const auto *indicator = r.indicator();
3451 const uint indicatorAlign = indicator
3452 ? resolvedAlignment(indicator->alignment(), Qt::AlignRight, Qt::AlignVCenter)
3453 : uint(Qt::AlignRight | Qt::AlignVCenter);
3454 if (indicatorAlign & Qt::AlignLeft) {
3455 contentsRect.setLeft(indicatorRect.right() + spacing);
3456 }
else if (indicatorAlign & Qt::AlignRight) {
3457 contentsRect.setRight(indicatorRect.left() - spacing);
3459 return visualRect(opt->direction, opt->rect, contentsRect);
3461 case SC_ComboBoxArrow: {
3462 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3463 const auto *indicator = r.indicator();
3464 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
3467 const int w = qSaturateRound(resolvedWidth(
3469 contentsRect.width() - indicator->leftMargin() - indicator->rightMargin()));
3470 const int h = qSaturateRound(resolvedHeight(
3472 contentsRect.height() - indicator->topMargin() - indicator->bottomMargin()));
3473 const uint indicatorAlign = resolvedAlignment(
3474 indicator->alignment(), Qt::AlignRight, Qt::AlignVCenter);
3475 const QMargins indicatorMargins = elementMargins(indicator);
3477 opt->direction, opt->rect,
3478 d->getAlignedRectInContainer(contentsRect, QSize(w, h),
3479 indicatorAlign, QMargins(),
3482 case SC_ComboBoxListBoxPopup: {
3483 QRect popupRect = opt->rect;
3484 popupRect.setTop(opt->rect.bottom());
3485 return visualRect(opt->direction, opt->rect, popupRect);
3493#if QT_CONFIG(spinbox)
3495 if (
const QStyleOptionSpinBox *spinBox =
3496 qstyleoption_cast<
const QStyleOptionSpinBox *>(opt)) {
3497 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::SpinBox, spinBox->state);
3500 const auto &metrics = *r.metrics;
3501 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3502 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3504 case SC_SpinBoxFrame:
3505 return visualRect(opt->direction, opt->rect, frameRect);
3506 case SC_SpinBoxEditField: {
3507 QRect upIndicatorRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w);
3508 QRect downIndicatorRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
3509 const int spacing = metrics.spacing;
3510 const auto *upIndicator = r.indicator() ? r.indicator()->first() :
nullptr;
3511 const auto *downIndicator = r.indicator() ? r.indicator()->second() :
nullptr;
3512 const bool hasUpIndicator = upIndicator
3513 && upIndicator->visible() && upIndicator->opacity() > 0;
3514 const bool hasDownIndicator = downIndicator
3515 && downIndicator->visible() && downIndicator->opacity() > 0;
3516 const uint upAlign = hasUpIndicator
3517 ? resolvedAlignment(upIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
3518 : uint(Qt::AlignLeft | Qt::AlignVCenter);
3519 const uint downAlign = hasDownIndicator
3520 ? resolvedAlignment(downIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
3521 : uint(Qt::AlignLeft | Qt::AlignVCenter);
3522 if (hasUpIndicator && hasDownIndicator) {
3523 if ((upAlign & Qt::AlignLeft) && (downAlign & Qt::AlignRight)) {
3524 contentsRect.setLeft(upIndicatorRect.right() + spacing);
3525 contentsRect.setRight(downIndicatorRect.left() - spacing);
3526 }
else if ((upAlign & Qt::AlignRight) && (downAlign & Qt::AlignLeft)) {
3527 contentsRect.setRight(upIndicatorRect.left() - spacing);
3528 contentsRect.setLeft(downIndicatorRect.right() + spacing);
3530 }
else if (hasUpIndicator) {
3531 if (upAlign & Qt::AlignLeft) {
3532 contentsRect.setLeft(upIndicatorRect.right() + spacing);
3533 }
else if (upAlign & Qt::AlignRight) {
3534 contentsRect.setRight(upIndicatorRect.left() - spacing);
3536 }
else if (hasDownIndicator) {
3537 if (downAlign & Qt::AlignLeft) {
3538 contentsRect.setLeft(downIndicatorRect.right() + spacing);
3539 }
else if (downAlign & Qt::AlignRight) {
3540 contentsRect.setRight(downIndicatorRect.left() - spacing);
3543 return visualRect(opt->direction, opt->rect, contentsRect);
3545 case SC_SpinBoxUp: {
3546 const auto *upIndicator = r.indicator() ? r.indicator()->first() :
nullptr;
3547 if (!upIndicator || !upIndicator->visible() || upIndicator->opacity() == 0)
3548 return contentsRect;
3550 const int w = qSaturateRound(resolvedWidth(
3552 contentsRect.width() - upIndicator->leftMargin() - upIndicator->rightMargin()));
3553 const int h = qSaturateRound(resolvedHeight(
3555 contentsRect.height() - upIndicator->topMargin() - upIndicator->bottomMargin()));
3556 const uint upAlign = resolvedAlignment(
3557 upIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
3558 const QMargins upMargins = elementMargins(upIndicator);
3559 return visualRect(opt->direction, opt->rect,
3560 d->getAlignedRectInContainer(contentsRect, QSize(w, h), upAlign,
3561 QMargins(), upMargins));
3563 case SC_SpinBoxDown: {
3564 const auto *downIndicator = r.indicator() ? r.indicator()->second() :
nullptr;
3565 if (!downIndicator || !downIndicator->visible() || downIndicator->opacity() == 0)
3568 const int w = qSaturateRound(resolvedWidth(
3570 contentsRect.width()
3571 - downIndicator->leftMargin() - downIndicator->rightMargin()));
3572 const int h = qSaturateRound(resolvedHeight(
3574 contentsRect.height()
3575 - downIndicator->topMargin() - downIndicator->bottomMargin()));
3576 const uint downAlign = resolvedAlignment(downIndicator->alignment(), Qt::AlignLeft,
3578 const QMargins downMargins = elementMargins(downIndicator);
3579 return visualRect(opt->direction, opt->rect,
3580 d->getAlignedRectInContainer(contentsRect, QSize(w, h), downAlign,
3581 QMargins(), downMargins));
3589#if QT_CONFIG(groupbox)
3591 if (
const QStyleOptionGroupBox *groupBox =
3592 qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
3593 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::GroupBox,
3597 const auto &metrics = *r.metrics;
3598 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3600 case SC_GroupBoxFrame:
3601 return visualRect(opt->direction, opt->rect, frameRect);
3602 case SC_GroupBoxLabel: {
3603 const int fontHeight = opt->fontMetrics.height();
3604 const int labelHeight = metrics.textPadding.top()
3605 + fontHeight + metrics.textPadding.bottom();
3606 const QRect labelContainer(opt->rect.left(), opt->rect.top(), opt->rect.width(),
3608 return visualRect(opt->direction, opt->rect, labelContainer);
3610 case SC_GroupBoxCheckBox: {
3614 case SC_GroupBoxContents: {
3615 const auto labelHeight = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w)
3617 const auto offset = metrics.padding.top()
3618 + qMax(labelHeight, metrics.margins.top() + metrics.spacing);
3620 opt->rect.left() + metrics.padding.left(), opt->rect.top() + offset,
3621 opt->rect.width() - metrics.padding.left() - metrics.padding.right(),
3622 opt->rect.bottom() - opt->rect.top() - offset - metrics.padding.bottom());
3623 return visualRect(opt->direction, opt->rect, contentsRect);
3631#if QT_CONFIG(scrollbar)
3633 if (
const auto *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3634 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ScrollBar,
3636 if (!resolved.isValid())
3638 const auto &metrics = *resolved.metrics;
3639 const bool horizontal = scrollbar->orientation == Qt::Horizontal;
3640 const QRectF grooveRect = opt->rect.marginsRemoved(metrics.margins);
3644 case SC_ScrollBarAddLine:
3645 case SC_ScrollBarSubLine:
3646 case SC_ScrollBarSubPage:
3647 case SC_ScrollBarAddPage:
3649 case SC_ScrollBarGroove:
3650 return visualRect(opt->direction, opt->rect, grooveRect.toAlignedRect());
3651 case SC_ScrollBarSlider: {
3652 const auto *indicator = resolved.indicator();
3653 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
3655 const QRectF contentsRect = grooveRect.marginsRemoved(metrics.padding);
3657 const qreal availableW = contentsRect.width()
3658 - indicator->leftMargin() - indicator->rightMargin();
3659 const qreal availableH = contentsRect.height()
3660 - indicator->topMargin() - indicator->bottomMargin();
3662 const int totalRange = scrollbar->maximum
3663 - scrollbar->minimum + scrollbar->pageStep;
3664 const qreal ratio = totalRange > 0 ? qreal(scrollbar->pageStep) / totalRange : 1.0;
3668 const qreal sliderW = qMax(
3669 qreal(metrics.indicatorImplicitSize.width()), availableW * ratio);
3670 const qreal sliderH = resolvedHeight(indicator, availableH);
3671 const qreal travelRange = qMax(0.0, availableW - sliderW);
3672 const int sliderPos = QStyle::sliderPositionFromValue(
3673 scrollbar->minimum, scrollbar->maximum, scrollbar->sliderPosition,
3674 int(travelRange), scrollbar->upsideDown);
3675 sliderRect = QRectF(
3676 contentsRect.x() + indicator->leftMargin() + sliderPos,
3677 contentsRect.y() + indicator->topMargin() + (availableH - sliderH) / 2.0,
3680 const qreal sliderH = qMax(
3681 qreal(metrics.indicatorImplicitSize.width()), availableH * ratio);
3682 const qreal sliderW = resolvedWidth(indicator, availableW);
3683 const qreal travelRange = qMax(0.0, availableH - sliderH);
3684 const int sliderPos = QStyle::sliderPositionFromValue(
3685 scrollbar->minimum, scrollbar->maximum, scrollbar->sliderPosition,
3686 int(travelRange), scrollbar->upsideDown);
3687 sliderRect = QRectF(
3688 contentsRect.x() + indicator->leftMargin() + (availableW - sliderW) / 2.0,
3689 contentsRect.y() + indicator->topMargin() + sliderPos, sliderW, sliderH);
3691 return visualRect(opt->direction, opt->rect, sliderRect.toAlignedRect());
3699#if QT_CONFIG(toolbutton)
3701 if (
const auto *tool = qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
3702 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolButton,
3704 if (!resolved.isValid())
3706 const auto &metrics = *resolved.metrics;
3707 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3709 case SC_ToolButton: {
3710 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3711 const bool hasMenuButton = (tool->features
3712 & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::HasMenu))
3714 const auto *indicator = resolved.indicator();
3715 if (hasMenuButton && indicator && indicator->visible()
3716 && indicator->opacity() > 0) {
3717 const QRect menuRect = subControlRect(CC_ToolButton, opt, SC_ToolButtonMenu, w);
3718 const int spacing = metrics.spacing;
3719 const uint indicatorAlign = resolvedAlignment(indicator->alignment(),
3720 Qt::AlignRight, Qt::AlignVCenter);
3721 if (indicatorAlign & Qt::AlignLeft)
3722 contentsRect.setLeft(menuRect.right() + spacing);
3723 else if (indicatorAlign & Qt::AlignRight)
3724 contentsRect.setRight(menuRect.left() - spacing);
3726 return visualRect(opt->direction, opt->rect, contentsRect);
3728 case SC_ToolButtonMenu: {
3729 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3731 & (QStyleOptionToolButton::MenuButtonPopup
3732 | QStyleOptionToolButton::PopupDelay))
3733 != QStyleOptionToolButton::MenuButtonPopup) {
3737 const auto *indicator = resolved.indicator();
3738 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
3741 const int w = qSaturateRound(resolvedWidth(
3743 contentsRect.width() - indicator->leftMargin() - indicator->rightMargin()));
3744 const int h = qSaturateRound(resolvedHeight(
3746 contentsRect.height() - indicator->topMargin() - indicator->bottomMargin()));
3747 const uint indicatorAlign = resolvedAlignment(indicator->alignment(),
3748 Qt::AlignRight, Qt::AlignVCenter);
3749 const QMargins indicatorMargins = elementMargins(indicator);
3750 return visualRect(opt->direction, opt->rect,
3751 d->getAlignedRectInContainer(contentsRect, QSize(w, h), indicatorAlign, QMargins(), indicatorMargins));
3762 return QCommonStyle::subControlRect(cc, opt, sc, w);
3766QSize QStyleKitStyle::sizeFromContents(ContentsType ct,
const QStyleOption *opt,
3767 const QSize &contentsSize,
const QWidget *widget)
const
3769 Q_D(
const QStyleKitStyle);
3772#if QT_CONFIG(pushbutton)
3775#if QT_CONFIG(toolbutton)
3776 case CT_ToolButton: {
3777 auto controlType = QQStyleKitReader::ControlType::ToolButton;
3778 if (
const auto *buttonOpt = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
3779 controlType = (buttonOpt->features & QStyleOptionButton::Flat)
3780 ? QQStyleKitReader::ControlType::FlatButton
3781 : QQStyleKitReader::ControlType::Button;
3783 const auto resolved = d->resolveLayout(controlType, opt->state);
3784 if (!resolved.isValid())
3787 const auto &metrics = *resolved.metrics;
3788 const QSize contentSize = contentsSize
3789 + QSize(metrics.padding.left() + metrics.padding.right(),
3790 metrics.padding.top() + metrics.padding.bottom())
3791 + QSize(metrics.textPadding.left() + metrics.textPadding.right(),
3792 metrics.textPadding.top() + metrics.textPadding.bottom());
3793 const QSize bgSize = metrics.bgImplicitSize
3794 + QSize(metrics.margins.left() + metrics.margins.right(),
3795 metrics.margins.top() + metrics.margins.bottom());
3796 return contentSize.expandedTo(bgSize);
3800 case CT_RadioButton:
3801 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
3802 const auto controlType = ct == CT_CheckBox ? QQStyleKitReader::ControlType::CheckBox
3803 : QQStyleKitReader::ControlType::RadioButton;
3804 const auto resolved = d->resolveLayout(controlType, opt->state);
3805 if (!resolved.isValid())
3807 const auto &metrics = *resolved.metrics;
3808 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, btn->text);
3809 const int bgWidth = metrics.bgImplicitSize.width()
3810 + metrics.margins.left() + metrics.margins.right();
3811 const int bgHeight = metrics.bgImplicitSize.height()
3812 + metrics.margins.top() + metrics.margins.bottom();
3813 const int contentWidth = std::max(textSize.width(), contentsSize.width())
3814 + metrics.padding.left() + metrics.padding.right() + metrics.textPadding.left()
3815 + metrics.textPadding.right();
3816 const int contentHeight = std::max(textSize.height(), contentsSize.height())
3817 + metrics.padding.top() + metrics.padding.bottom() + metrics.textPadding.top()
3818 + metrics.textPadding.bottom();
3819 const int indicatorWidth = metrics.indicatorImplicitSize.width()
3820 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
3821 const int indicatorHeight = metrics.indicatorImplicitSize.height()
3822 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
3823 return QSize(std::max({ contentWidth + indicatorWidth + metrics.spacing, bgWidth }),
3824 std::max({ contentHeight, indicatorHeight, bgHeight }));
3827#if QT_CONFIG(itemviews)
3828 case CT_ItemViewItem:
3829 if (
const auto *item = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
3830 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
3831 if (!resolved.isValid())
3833 const auto &metrics = *resolved.metrics;
3834 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, item->text);
3835 const int bgWidth = metrics.bgImplicitSize.width()
3836 + metrics.margins.left() + metrics.margins.right();
3837 const int bgHeight = metrics.bgImplicitSize.height()
3838 + metrics.margins.top() + metrics.margins.bottom();
3839 const int contentWidth = std::max(textSize.width(), contentsSize.width())
3840 + metrics.padding.left() + metrics.padding.right() + metrics.textPadding.left()
3841 + metrics.textPadding.right();
3842 const int contentHeight = std::max(textSize.height(), contentsSize.height())
3843 + metrics.padding.top() + metrics.padding.bottom() + metrics.textPadding.top()
3844 + metrics.textPadding.bottom();
3845 const int indicatorWidth = metrics.indicatorImplicitSize.width()
3846 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
3847 const int indicatorHeight = metrics.indicatorImplicitSize.height()
3848 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
3849 return QSize(std::max({ contentWidth + indicatorWidth + metrics.spacing, bgWidth }),
3850 std::max({ contentHeight, indicatorHeight, bgHeight }));
3854 case CT_ProgressBar:
3855 if (qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
3856 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar,
3858 if (!resolved.isValid())
3860 const auto &metrics = *resolved.metrics;
3861 const auto indicatorW = std::max(
3862 metrics.indicatorImplicitSize.width()
3863 + metrics.indicatorMargins.left()
3864 + metrics.indicatorMargins.right(),
3865 metrics.foregroundImplicitSize.width()
3866 + metrics.foregroundMargins.left()
3867 + metrics.foregroundMargins.right());
3868 const auto indicatorH = std::max(
3869 metrics.indicatorImplicitSize.height()
3870 + metrics.indicatorMargins.top()
3871 + metrics.indicatorMargins.bottom(),
3872 metrics.foregroundImplicitSize.height()
3873 + metrics.foregroundMargins.top()
3874 + metrics.foregroundMargins.bottom());
3875 const int bgW = metrics.bgImplicitSize.width()
3876 + metrics.margins.left() + metrics.margins.right();
3877 const int bgH = metrics.bgImplicitSize.height()
3878 + metrics.margins.top() + metrics.margins.bottom();
3880 const int contentW = indicatorW + metrics.padding.left() + metrics.padding.right();
3881 const int contentH = indicatorH + metrics.padding.top() + metrics.padding.bottom();
3882 return QSize(std::max(contentW, bgW), std::max(contentH, bgH));
3886 if (qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3887 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Slider,
3889 if (!resolved.isValid())
3891 const auto &metrics = *resolved.metrics;
3893 const int bgW = std::max(
3894 metrics.padding.left() + metrics.padding.right()
3895 + metrics.indicatorImplicitSize.width()
3896 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right(),
3897 metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right());
3898 const int bgH = std::max(
3899 metrics.padding.top() + metrics.padding.bottom()
3900 + metrics.indicatorImplicitSize.height()
3901 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom(),
3902 metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom());
3903 const int handleW = metrics.handleImplicitSize.width()
3904 + metrics.padding.left()
3905 + metrics.padding.right();
3906 const int handleH = metrics.handleImplicitSize.height()
3907 + metrics.padding.top()
3908 + metrics.padding.bottom();
3909 return QSize(std::max(handleW, bgW), std::max(handleH, bgH));
3912#if QT_CONFIG(lineedit)
3914 if (
const auto *lineEdit = qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
3915 QStyleOption lineEditOpt(*lineEdit);
3916 lineEditOpt.state &= ~QStyle::State_Sunken;
3917# if QT_CONFIG(spinbox)
3918 const bool isInSpinBox = widget && qobject_cast<
const QSpinBox *>(widget->parent());
3920 const bool isInSpinBox =
false;
3922 auto controlType = isInSpinBox ? QQStyleKitReader::ControlType::SpinBox
3923 : QQStyleKitReader::ControlType::TextField;
3924 const auto resolved = d->resolveLayout(controlType, lineEditOpt.state);
3925 if (!resolved.isValid())
3927 const auto &metrics = *resolved.metrics;
3931 bgSize = metrics.bgImplicitSize.grownBy(metrics.margins);
3932 const QSize contentSizeWithPadding = contentsSize
3933 .grownBy(metrics.textPadding)
3934 .grownBy(metrics.padding);
3935 return contentSizeWithPadding.expandedTo(bgSize);
3939#if QT_CONFIG(combobox)
3941 if (
const auto *comboBox = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
3942 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ComboBox,
3944 if (!resolved.isValid())
3946 const auto &metrics = *resolved.metrics;
3947 const QSize textSize = opt->fontMetrics.size(
3948 Qt::TextShowMnemonic, comboBox->currentText);
3949 const int bgW = metrics.bgImplicitSize.width()
3950 + metrics.margins.left() + metrics.margins.right();
3951 const int bgH = metrics.bgImplicitSize.height()
3952 + metrics.margins.top() + metrics.margins.bottom();
3953 const int contentW = textSize.width()
3954 + metrics.padding.left() + metrics.padding.right()
3955 + metrics.textPadding.left() + metrics.textPadding.right();
3956 const int contentH = textSize.height()
3957 + metrics.padding.top() + metrics.padding.bottom()
3958 + metrics.textPadding.top() + metrics.textPadding.bottom();
3959 const int indicatorW = metrics.indicatorImplicitSize.width()
3960 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
3961 const int indicatorH = metrics.indicatorImplicitSize.height()
3962 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
3963 return QSize(std::max({ contentW + indicatorW + metrics.spacing, bgW }),
3964 std::max({ contentH, indicatorH, bgH }));
3968#if QT_CONFIG(spinbox)
3970 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::SpinBox, opt->state);
3971 if (!resolved.isValid())
3973 const auto &metrics = *resolved.metrics;
3974 const int bgW = metrics.bgImplicitSize.width()
3975 + metrics.margins.left() + metrics.margins.right();
3976 const int bgH = metrics.bgImplicitSize.height()
3977 + metrics.margins.top() + metrics.margins.bottom();
3978 const int contentW = contentsSize.width()
3979 + metrics.padding.left() + metrics.padding.right()
3980 + metrics.textPadding.left() + metrics.textPadding.right();
3981 const int contentH = contentsSize.height()
3982 + metrics.padding.top() + metrics.padding.bottom()
3983 + metrics.textPadding.top() + metrics.textPadding.bottom();
3987 const int indicatorW = (metrics.indicatorImplicitSize.width()
3988 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right()) * 2;
3989 const int indicatorH = metrics.indicatorImplicitSize.height()
3990 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
3991 return QSize(std::max({ contentW + indicatorW + metrics.spacing, bgW }),
3992 std::max({ contentH, indicatorH, bgH }));
3995#if QT_CONFIG(tabbar)
3997 if (qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
3998 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::TabButton,
4000 if (!resolved.isValid())
4002 const auto &m = *resolved.metrics;
4003 const auto bgSize = m.bgImplicitSize.grownBy(m.margins);
4004 const auto contentSizeWithPadding = contentsSize.grownBy(m.padding + m.textPadding);
4005 return contentSizeWithPadding.expandedTo(bgSize);
4009#if QT_CONFIG(tabwidget)
4011 if (qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(opt)) {
4013 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Page, opt->state);
4014 if (!resolved.isValid())
4016 const auto &m = *resolved.metrics;
4017 const auto bgSize = m.bgImplicitSize.grownBy(m.margins);
4018 const auto contentSizeWithPadding = contentsSize.grownBy(m.padding);
4019 return contentSizeWithPadding.expandedTo(bgSize);
4023#if QT_CONFIG(groupbox)
4025 if (
const auto *groupBox = qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
4026 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::GroupBox,
4028 if (!resolved.isValid())
4030 const auto &metrics = *resolved.metrics;
4031 const QSize bgSize = metrics.bgImplicitSize
4032 + QSize(metrics.margins.left() + metrics.margins.right(),
4033 metrics.margins.top() + metrics.margins.bottom());
4034 const QSize contentSize = contentsSize.grownBy(metrics.padding);
4035 const QSize textSize = opt->fontMetrics
4036 .size(Qt::TextShowMnemonic, groupBox->text)
4037 .grownBy(metrics.textPadding);
4038 return textSize.expandedTo(contentSize).expandedTo(bgSize);
4042#if QT_CONFIG(scrollbar)
4044 if (qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
4045 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ScrollBar, opt->state);
4046 if (!resolved.isValid())
4048 const auto &metrics = *resolved.metrics;
4050 const int iH = metrics.indicatorImplicitSize.height()
4051 + metrics.padding.top() + metrics.padding.bottom()
4052 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
4053 const int iW = metrics.indicatorImplicitSize.width()
4054 + metrics.padding.left() + metrics.padding.right()
4055 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
4056 const int bgH = metrics.bgImplicitSize.height()
4057 + metrics.margins.top() + metrics.margins.bottom();
4058 const int bgW = metrics.bgImplicitSize.width()
4059 + metrics.margins.left() + metrics.margins.right();
4060 return QSize(std::max(iW, bgW), std::max(iH, bgH));
4066 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
4070 const auto menuType = widget && widget->inherits(
"QComboBoxPrivateContainer")
4071 ? QQStyleKitReader::ControlType::Popup
4072 : QQStyleKitReader::ControlType::Menu;
4073 const auto menuResolved = d->resolveLayout(menuType, opt->state);
4075 if (menuResolved.isValid()) {
4076 const auto &mm = *menuResolved.metrics;
4077 minMenuW = mm.bgImplicitSize.width()
4078 + mm.margins.left() + mm.margins.right() - 2 * mm.padding.left();
4081 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
4082 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuSeparator,
4084 if (!resolved.isValid())
4086 const auto &m = *resolved.metrics;
4087 const int bgWidth = m.bgImplicitSize.width()
4088 + m.margins.left() + m.margins.right();
4089 const int bgHeight = m.bgImplicitSize.height()
4090 + m.margins.top() + m.margins.bottom();
4091 return QSize(std::max(bgWidth, minMenuW), bgHeight);
4094 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuItem, opt->state);
4095 if (!resolved.isValid())
4097 const auto &m = *resolved.metrics;
4098 const auto *indicator = resolved.indicator();
4099 const auto *first = indicator ? indicator->first() :
nullptr;
4100 const auto *second = indicator ? indicator->second() :
nullptr;
4103 using QtPrivate::qSaturateRound;
4104 if (first && menuItem->checkType != QStyleOptionMenuItem::NotCheckable) {
4105 indicatorW += qSaturateRound(
4106 first->leftMargin() + first->width() + first->rightMargin()) + m.spacing;
4107 indicatorH = std::max(
4108 qSaturateRound(first->topMargin() + first->bottomMargin() + first->height()),
4111 if (second && menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {
4112 indicatorW += qSaturateRound(
4113 second->leftMargin() + second->width() + second->rightMargin()) + m.spacing;
4114 indicatorH = std::max(
4115 qSaturateRound(second->topMargin() + second->bottomMargin() + second->height()),
4118 const int bgH = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
4119 const int iconReserved = menuItem->maxIconWidth > 0
4120 ? menuItem->maxIconWidth + m.spacing
4122 const int contentW = contentsSize.width()
4123 + m.padding.left() + m.padding.right()
4124 + m.textPadding.left() + m.textPadding.right()
4125 + indicatorW + iconReserved;
4126 const int contentH = contentsSize.height()
4127 + m.padding.top() + m.padding.bottom()
4128 + m.textPadding.top() + m.textPadding.bottom();
4129 return QSize(std::max(contentW, minMenuW), std::max({ contentH, indicatorH, bgH }));
4133 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Menu, opt->state);
4134 if (!resolved.isValid())
4136 const auto &m = *resolved.metrics;
4137 const int height = std::max(contentsSize.height(), m.bgImplicitSize.height())
4138 + m.margins.top() + m.margins.bottom();
4139 return QSize(contentsSize.width(), height);
4142#if QT_CONFIG(menubar)
4144 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuBar, opt->state);
4145 if (!resolved.isValid())
4147 const auto &m = *resolved.metrics;
4148 const int bgWidth = m.bgImplicitSize.width() + m.margins.left() + m.margins.right();
4149 const int bgHeight = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
4150 const int contentW = contentsSize.width() + m.padding.left() + m.padding.right();
4151 const int contentH = contentsSize.height() + m.padding.top() + m.padding.bottom();
4152 return QSize(std::max(contentW, bgWidth), std::max(contentH, bgHeight));
4154 case CT_MenuBarItem: {
4155 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuBarItem,
4157 if (!resolved.isValid())
4159 const auto &m = *resolved.metrics;
4160 const int bgWidth = m.bgImplicitSize.width() + m.margins.left() + m.margins.right();
4161 const int bgHeight = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
4162 const int contentW = contentsSize.width()
4163 + m.padding.left() + m.padding.right()
4164 + m.textPadding.left() + m.textPadding.right();
4165 const int contentH = contentsSize.height()
4166 + m.padding.top() + m.padding.bottom()
4167 + m.textPadding.top() + m.textPadding.bottom();
4168 return QSize(std::max(contentW, bgWidth), std::max(contentH, bgHeight));
4174 return QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget);
4178int QStyleKitStyle::pixelMetric(PixelMetric m,
const QStyleOption *opt,
const QWidget *widget)
const
4180 Q_D(
const QStyleKitStyle);
4183 case PM_MenuPanelWidth:
4186 case PM_MenuTearoffHeight:
4187 case PM_MenuScrollerHeight:
4189 case PM_MenuHMargin:
4190 case PM_MenuVMargin: {
4191 const auto controlType = widget && widget->inherits(
"QComboBoxPrivateContainer")
4192 ? QQStyleKitReader::ControlType::Popup
4193 : QQStyleKitReader::ControlType::Menu;
4194 const auto resolved = d->resolveLayout(controlType, opt ? opt->state : QStyle::State_None);
4195 if (!resolved.isValid())
4197 return m == PM_MenuHMargin ? resolved.metrics->padding.left()
4198 : resolved.metrics->padding.top();
4201#if QT_CONFIG(menubar)
4202 case PM_MenuBarItemSpacing: {
4203 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuBarItem,
4204 opt ? opt->state : QStyle::State_None);
4205 if (resolved.isValid())
4206 return resolved.metrics->spacing;
4210#if QT_CONFIG(toolbar)
4211 case PM_ToolBarFrameWidth:
4214 case PM_ToolBarItemMargin: {
4215 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolBar,
4216 opt ? opt->state : QStyle::State_None);
4217 if (!resolved.isValid())
4219 return resolved.metrics->padding.left();
4221 case PM_ToolBarItemSpacing: {
4222 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolBar,
4223 opt ? opt->state : QStyle::State_None);
4224 if (resolved.isValid())
4225 return resolved.metrics->spacing;
4228 case PM_ToolBarHandleExtent: {
4231 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolBar,
4232 opt ? opt->state : QStyle::State_None);
4233 if (!resolved.isValid())
4235 const auto &metrics = *resolved.metrics;
4236 const bool horizontal = !opt || (opt->state & State_Horizontal);
4237 const int crossImplicit = horizontal
4238 ? metrics.bgImplicitSize.height()
4239 : metrics.bgImplicitSize.width();
4240 const int crossMargins = horizontal
4241 ? metrics.margins.top() + metrics.margins.bottom()
4242 : metrics.margins.left() + metrics.margins.right();
4243 const int crossPadding = horizontal
4244 ? metrics.padding.top() + metrics.padding.bottom()
4245 : metrics.padding.left() + metrics.padding.right();
4246 return qMax(0, crossImplicit + crossMargins - crossPadding);
4249#if QT_CONFIG(tabbar)
4250 case PM_TabBarTabHSpace:
4251 case PM_TabBarTabVSpace:
4252 case PM_TabBarTabOverlap:
4254 case PM_TabCloseIndicatorWidth:
4255 case PM_TabCloseIndicatorHeight:
4261 return QCommonStyle::pixelMetric(m, opt, widget);
4265int QStyleKitStyle::styleHint(StyleHint sh,
const QStyleOption *opt,
const QWidget *w,
4266 QStyleHintReturn *shret)
const
4270 case SH_SpinBox_SelectOnStep:
4271 case SH_ToolBar_Movable:
4272 case SH_TabBar_PreferNoArrows:
4274 case SH_Menu_MouseTracking:
4275 case SH_MenuBar_MouseTracking:
4276 case SH_Menu_Scrollable:
4281 return QCommonStyle::styleHint(sh, opt, w, shret);
4285QPalette QStyleKitStyle::standardPalette()
const
4287 return QCommonStyle::standardPalette();
4291void QStyleKitStyle::polish(QWidget *widget)
4296 Q_D(QStyleKitStyle);
4301 d->ensureDefaultStyle();
4303 widget->setAttribute(Qt::WA_Hover);
4305#if QT_CONFIG(scrollbar)
4309 if (qobject_cast<QScrollBar *>(widget))
4310 widget->setAttribute(Qt::WA_OpaquePaintEvent,
false);
4314 const bool isInteractiveControl =
false
4315#if QT_CONFIG(pushbutton)
4316 || qobject_cast<
const QPushButton *>(widget)
4318#if QT_CONFIG(checkbox)
4319 || qobject_cast<
const QCheckBox *>(widget)
4321#if QT_CONFIG(radiobutton)
4322 || qobject_cast<
const QRadioButton *>(widget)
4324#if QT_CONFIG(combobox)
4325 || qobject_cast<
const QComboBox *>(widget)
4326 || (widget && widget->inherits(
"QComboBoxPrivateContainer"))
4328#if QT_CONFIG(lineedit)
4329 || qobject_cast<
const QLineEdit *>(widget)
4331#if QT_CONFIG(textedit)
4332 || qobject_cast<
const QTextEdit *>(widget)
4333 || qobject_cast<
const QPlainTextEdit *>(widget)
4336 || qobject_cast<
const QLabel *>(widget)
4338#if QT_CONFIG(progressbar)
4339 || qobject_cast<
const QProgressBar *>(widget)
4341#if QT_CONFIG(slider)
4342 || qobject_cast<
const QSlider *>(widget)
4344#if QT_CONFIG(scrollbar)
4345 || qobject_cast<
const QScrollBar *>(widget)
4347#if QT_CONFIG(spinbox)
4348 || qobject_cast<
const QSpinBox *>(widget)
4350#if QT_CONFIG(tabbar)
4351 || qobject_cast<
const QTabBar *>(widget)
4353#if QT_CONFIG(tabwidget)
4354 || qobject_cast<
const QTabWidget *>(widget)
4357 || qobject_cast<
const QMenu *>(widget)
4358 || qobject_cast<
const QMenuBar *>(widget)
4361 if (isInteractiveControl)
4362 d->readerForWidget(widget);
4367 if (QWidget *vp = managedViewport(widget); vp && vp->autoFillBackground()) {
4368 vp->setAutoFillBackground(
false);
4369 d->bgFillDisabledWidgets.insert(widget);
4372 if (qobject_cast<QMenu *>(widget)
4373# if QT_CONFIG(combobox)
4374 || widget->inherits(
"QComboBoxPrivateContainer")
4379 if (!widget->testAttribute(Qt::WA_TranslucentBackground)) {
4380 widget->setAttribute(Qt::WA_TranslucentBackground,
true);
4381 d->bgFillDisabledWidgets.insert(widget);
4386#if QT_CONFIG(lineedit)
4387 if (
auto *lineEdit = qobject_cast<QLineEdit *>(widget)) {
4388 if (!lineEdit->property(
"_q_stylekit_alignment_set").toBool()) {
4389 QQStyleKitReader *r = d->readerForWidget(widget);
4391 const QWidget *target = containerWidget(widget);
4392 QQStyleKitReader::ControlType ct = controlTypeForWidget(target);
4393 r->setControlType(ct);
4394 const auto *textProps = r->global()->text();
4396 const uint align = resolvedAlignment(
4397 textProps->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
4398 lineEdit->setAlignment(Qt::Alignment(align));
4405 d->refreshStyleFont(widget);
4406 d->refreshStylePalette(widget);
4408 bool needsEventFilter = isSelfPaintingWidget(widget);
4411 needsEventFilter = needsEventFilter || qobject_cast<QMenu *>(widget);
4413 if (needsEventFilter)
4414 widget->installEventFilter(
this);
4416 QCommonStyle::polish(widget);
4420void QStyleKitStyle::polish(QApplication *app)
4422 QCommonStyle::polish(app);
4426void QStyleKitStyle::polish(QPalette &palette)
4428 QCommonStyle::polish(palette);
4432void QStyleKitStyle::unpolish(QWidget *widget)
4434 Q_D(QStyleKitStyle);
4435 d->unsetStylePalette(widget);
4436 d->unsetStyleFont(widget);
4437 bool hasEventFilter = isSelfPaintingWidget(widget);
4439 hasEventFilter = hasEventFilter || qobject_cast<QMenu *>(widget);
4442 widget->removeEventFilter(
this);
4443 if (d->bgFillDisabledWidgets.remove(widget)) {
4444 if (QWidget *vp = managedViewport(widget))
4445 vp->setAutoFillBackground(
true);
4447 else if (qobject_cast<QMenu *>(widget)
4448# if QT_CONFIG(combobox)
4449 || widget->inherits(
"QComboBoxPrivateContainer")
4452 widget->setAttribute(Qt::WA_TranslucentBackground,
false);
4456 d->cleanupWidgetReader(widget);
4457#if QT_CONFIG(scrollbar)
4458 if (qobject_cast<QScrollBar *>(widget))
4459 widget->setAttribute(Qt::WA_OpaquePaintEvent);
4461 QCommonStyle::unpolish(widget);
4465void QStyleKitStyle::unpolish(QApplication *app)
4467 Q_D(QStyleKitStyle);
4468 d->clearMetricsCache();
4469 QCommonStyle::unpolish(app);
4473bool QStyleKitStyle::eventFilter(QObject *obj, QEvent *event)
4475 Q_D(QStyleKitStyle);
4476 switch (event->type()) {
4477 case QEvent::EnabledChange:
4478 case QEvent::HoverEnter:
4479 case QEvent::HoverLeave:
4480 case QEvent::FocusIn:
4481 case QEvent::FocusOut:
4482 if (
auto *w = qobject_cast<QWidget *>(obj)) {
4483 if (d->customPaletteWidgets.contains(w))
4484 d->refreshStylePalette(w);
4485 if (d->customFontWidgets.contains(w))
4486 d->refreshStyleFont(w);
4491 if (
auto *menu = qobject_cast<QMenu *>(obj))
4492 d->cleanupSubElements(menu);
4498 return QCommonStyle::eventFilter(obj, event);
4502bool QStyleKitStyle::event(QEvent *event)
4504 return QCommonStyle::event(event);
4509#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)