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>
51#include <QtWidgets/qtoolbar.h>
53#if QT_CONFIG(toolbutton)
54#include <QtWidgets/qtoolbutton.h>
56#if QT_CONFIG(groupbox)
57#include <QtWidgets/qgroupbox.h>
60#include <QtWidgets/qmenu.h>
61#include <QtWidgets/qmenubar.h>
64#include <QtWidgets/qlabel.h>
66#include <QtWidgets/private/qwidget_p.h>
67#include <QtCore/private/qobject_p.h>
68#include <QtGui/qpainter.h>
69#include <QtGui/qpainterpath.h>
70#include <QtGui/qpainterstateguard.h>
71#include <QtGui/qstylehints.h>
72#include <QtCore/qloggingcategory.h>
73#include <QtQml/private/qqmlcomponent_p.h>
74#include <QtQml/qqmlengine.h>
75#include <QtQuick/private/qquicktransition_p.h>
76#include <QtLabsStyleKit/private/qqstylekit_p.h>
77#include <QtLabsStyleKit/private/qqstylekitcontrolproperties_p.h>
78#include <QtLabsStyleKit/private/qqstylekitstyle_p.h>
82Q_STATIC_LOGGING_CATEGORY(lcStyleKit,
"qt.labs.stylekit")
85
86
87
88
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
239
240
241
242
243
244
245
246
247
248
251
252
253
254
255
256
257
258
261
262
263
264
265
266
269
270
271
272
273
274
275
276
277
279static QQStyleKitReader::ControlType controlTypeForWidget(
const QWidget *widget)
282 return QQStyleKitReader::Control;
284#if QT_CONFIG(pushbutton)
285 if (qobject_cast<
const QPushButton *>(widget))
286 return QQStyleKitReader::Button;
288#if QT_CONFIG(checkbox)
289 if (qobject_cast<
const QCheckBox *>(widget))
290 return QQStyleKitReader::CheckBox;
292#if QT_CONFIG(radiobutton)
293 if (qobject_cast<
const QRadioButton *>(widget))
294 return QQStyleKitReader::RadioButton;
296#if QT_CONFIG(combobox)
297 if (qobject_cast<
const QComboBox *>(widget))
298 return QQStyleKitReader::ComboBox;
301 if (qobject_cast<
const QSlider *>(widget))
302 return QQStyleKitReader::Slider;
304#if QT_CONFIG(scrollbar)
305 if (qobject_cast<
const QScrollBar *>(widget))
306 return QQStyleKitReader::ScrollBar;
308#if QT_CONFIG(spinbox)
309 if (qobject_cast<
const QSpinBox *>(widget) || qobject_cast<
const QDoubleSpinBox *>(widget))
310 return QQStyleKitReader::SpinBox;
312#if QT_CONFIG(itemviews)
313 if (qobject_cast<
const QAbstractItemView *>(widget))
314 return QQStyleKitReader::ItemDelegate;
316#if QT_CONFIG(progressbar)
317 if (qobject_cast<
const QProgressBar *>(widget))
318 return QQStyleKitReader::ProgressBar;
320#if QT_CONFIG(lineedit)
321 if (qobject_cast<
const QLineEdit *>(widget))
322 return QQStyleKitReader::TextField;
324#if QT_CONFIG(textedit)
325 if (qobject_cast<
const QTextEdit *>(widget) || qobject_cast<
const QPlainTextEdit *>(widget))
326 return QQStyleKitReader::TextArea;
329 if (qobject_cast<
const QTabBar *>(widget))
330 return QQStyleKitReader::TabBar;
332#if QT_CONFIG(toolbar)
333 if (qobject_cast<
const QToolBar *>(widget))
334 return QQStyleKitReader::ToolBar;
336#if QT_CONFIG(toolbutton)
337 if (qobject_cast<
const QToolButton *>(widget))
338 return QQStyleKitReader::ToolButton;
340#if QT_CONFIG(groupbox)
341 if (qobject_cast<
const QGroupBox *>(widget))
342 return QQStyleKitReader::GroupBox;
345 if (qobject_cast<
const QMenuBar *>(widget))
346 return QQStyleKitReader::MenuBar;
347 if (qobject_cast<
const QMenu *>(widget))
348 return QQStyleKitReader::Menu;
350 if (widget->windowType() & Qt::Popup)
351 return QQStyleKitReader::Popup;
352 if (widget->windowType() & Qt::Dialog)
353 return QQStyleKitReader::Dialog;
354 if (widget->windowType() & Qt::Window)
355 return QQStyleKitReader::ApplicationWindow;
357 if (qobject_cast<
const QFrame *>(widget))
358 return QQStyleKitReader::Frame;
361 return QQStyleKitReader::Control;
370 || qobject_cast<
const QLabel *>(widget)
372#if QT_CONFIG(textedit)
373 || qobject_cast<
const QTextEdit *>(widget)
374 || qobject_cast<
const QPlainTextEdit *>(widget)
376#if QT_CONFIG(lineedit)
377 || qobject_cast<
const QLineEdit *>(widget)
384#if QT_CONFIG(textedit)
385 if (
auto *textEdit = qobject_cast<QTextEdit *>(widget))
386 return textEdit->viewport();
387 if (
auto *plainTextEdit = qobject_cast<QPlainTextEdit *>(widget))
388 return plainTextEdit->viewport();
390#if QT_CONFIG(itemviews) && QT_CONFIG(combobox)
391 if (
auto *view = qobject_cast<QAbstractItemView *>(widget)) {
392 if (
auto *p = view->parentWidget(); p && p->inherits(
"QComboBoxPrivateContainer"))
393 return view->viewport();
402 const uint h = raw & Qt::AlignHorizontal_Mask;
403 const uint v = raw & Qt::AlignVertical_Mask;
404 result |= h ? h : uint(hDefault);
405 result |= v ? v : uint(vDefault);
411 return element->fillWidth() ? availableW : qMax(0.0, element->width());
416 return element->fillHeight() ? avilableH : qMax(0.0, element->height());
421 return QMargins(element->leftMargin(), element->topMargin(),
422 element->rightMargin(), element->bottomMargin());
428#if QT_CONFIG(lineedit)
429 if (qobject_cast<
const QLineEdit *>(w)) {
431 QWidget *parent = w->parentWidget();
433#if QT_CONFIG(combobox)
434 || qobject_cast<
const QComboBox *>(parent)
436#if QT_CONFIG(spinbox)
437 || qobject_cast<
const QAbstractSpinBox *>(parent)
445#if QT_CONFIG(scrollarea)
446 if (
const QAbstractScrollArea *sa = qobject_cast<
const QAbstractScrollArea *>(w->parentWidget())) {
447 if (sa->viewport() == w)
448 return w->parentWidget();
456 : QCommonStylePrivate()
462 return filePath.startsWith(QLatin1Char(
':'))
463 ? QUrl(QLatin1String(
"qrc") + filePath)
464 : QUrl::fromLocalFile(filePath);
471 qmlEngine =
new QQmlEngine(q);
474 qWarning(
"QStyleKitStyle: No QML engine available to load style.");
477 const QUrl url = stylePath.isEmpty() ? QUrl() : urlFromStylePath(stylePath);
478 if (stylePath.isEmpty() || !url.isValid()) {
479 qWarning(
"QStyleKitStyle: No valid style path provided: %s", qPrintable(stylePath));
482 QQmlComponent component(qmlEngine, url);
483 if (component.isError()) {
484 qWarning(
"QStyleKitStyle: Failed to load style from %s: %s",
485 qPrintable(stylePath), qPrintable(component.errorString()));
490 QQmlComponentPrivate *componentPrivate = QQmlComponentPrivate::get(&component);
491 const auto compilationUnit = componentPrivate->compilationUnit();
492 const auto propertyCache = compilationUnit ? compilationUnit->rootPropertyCache() :
nullptr;
493 const auto firstMetaObject = propertyCache ? propertyCache->firstCppMetaObject() :
nullptr;
494 if (!firstMetaObject || !firstMetaObject->inherits(&QQStyleKitStyle::staticMetaObject)) {
495 qWarning(
"QStyleKitStyle: Failed to load style from %s: component is not a StyleKit Style.",
496 qPrintable(stylePath));
499 QQStyleKitStyle *styleObject = qobject_cast<QQStyleKitStyle *>(component.create());
501 qWarning(
"QStyleKitStyle: Failed to create style object from %s: component is not a StyleKit style.",
502 qPrintable(stylePath));
505 const bool isReload = style !=
nullptr;
511 QObject::connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, q, [
this]() {
512 if (style && style->themeName() == QLatin1String(
"System")) {
513 style->recreateTheme();
520 QQStyleKitReader::resetReadersForStyle(style);
526
527
528
536 qmlEngine =
new QQmlEngine(q);
538 QQmlComponent component(qmlEngine);
539 component.loadFromModule(
"Qt.labs.StyleKit",
"Style");
540 if (component.isError()) {
541 qWarning(
"QStyleKitStyle: Failed to create default fallback style: %s",
542 qPrintable(component.errorString()));
545 defaultStyle = qobject_cast<QQStyleKitStyle *>(component.create());
547 defaultStyle->setParent(q);
548 qCDebug(lcStyleKit,
"No style set; using a default fallback style. "
549 "Set stylePath to load a StyleKit Style.");
555
556
557
560 return style ? style : defaultStyle;
567 QQStyleKitStyle *effective = effectiveStyle();
569 if (sharedReader && sharedReader->style() != effective)
570 sharedReader->setExplicitStyle(effective);
572 if (subElementReader && subElementReader->style() != effective)
573 subElementReader->setExplicitStyle(effective);
575 clearAllSubElements();
577 for (
auto *wr : std::as_const(widgetReaders)) {
578 if (wr->style() != effective)
579 wr->setExplicitStyle(effective);
582 if (!QWidgetPrivate::allWidgets)
585 for (
auto *widget : std::as_const(*QWidgetPrivate::allWidgets)) {
586 if (customFontWidgets.contains(widget))
587 unsetStyleFont(widget);
588 refreshStyleFont(widget);
589 if (customPaletteWidgets.contains(widget))
590 unsetStylePalette(widget);
591 refreshStylePalette(widget);
594 QEvent styleChange(QEvent::StyleChange);
595 for (
auto *widget : std::as_const(*QWidgetPrivate::allWidgets)) {
596 QApplication::sendEvent(widget, &styleChange);
604 auto it = customFontWidgets.find(widget);
605 if (it == customFontWidgets.end())
608 auto customFont =
std::move(*it);
609 customFontWidgets.erase(it);
610 widget->setFont(
std::move(customFont).reverted(widget->font()));
615 if (!effectiveStyle() || !widget)
618 const auto styleMask = styleFont.resolveMask();
619 auto it = customFontWidgets.find(widget);
621 if (it == customFontWidgets.end()) {
624 it = customFontWidgets.insert(widget, { QWidgetPrivate::get(widget)->localFont(), 0 });
625 QObject::connect(widget, &QObject::destroyed, widget, [
this, widget]() {
626 customFontWidgets.remove(widget);
630 it->resolveMask = styleMask;
632 const QFont &baseline = it->oldWidgetValue;
633 QFont merged = styleFont.resolve(baseline);
634 merged.setResolveMask(baseline.resolveMask() | styleMask);
635 if (widget->font() != merged)
636 widget->setFont(merged);
641 if (!effectiveStyle() || !widget)
644 const QWidget *targetWidget = containerWidget(widget);
645 QQStyleKitReader::ControlType controlType = controlTypeForWidget(targetWidget);
647 auto *shared = ensureSharedReader();
652 opt.initFrom(targetWidget);
653 const QQSK::State currentState = resolvedStateFor(controlType, opt.state, targetWidget);
655 shared->setControlTypeAndState(controlType, currentState);
656 setStyleFont(widget, shared->font());
661 auto it = customPaletteWidgets.find(widget);
662 if (it == customPaletteWidgets.end())
665 auto customPalette =
std::move(*it);
666 customPaletteWidgets.erase(it);
667 widget->setPalette(
std::move(customPalette).reverted(widget->palette()));
672 if (!effectiveStyle() || !widget)
675 const quint64 styleMask = stylePalette.resolveMask();
679 if (!customPaletteWidgets.contains(widget)) {
680 customPaletteWidgets.insert(widget, { widget->palette(), 0 });
681 QObject::connect(widget, &QObject::destroyed, widget, [
this, widget]() {
682 customPaletteWidgets.remove(widget);
686 customPaletteWidgets[widget].resolveMask |= styleMask;
687 QPalette merged = stylePalette.resolve(widget->palette());
688 merged.setResolveMask(widget->palette().resolveMask() | styleMask);
689 widget->setPalette(merged);
696 if (!effectiveStyle() || !widget)
699 const bool isWindow = widget->windowType() & (Qt::Popup | Qt::Window | Qt::Dialog);
700 const bool isPaletteManaged = isSelfPaintingWidget(widget) || isWindow;
701 if (!isPaletteManaged)
704 const QWidget *targetWidget = containerWidget(widget);
705 QQStyleKitReader::ControlType controlType = controlTypeForWidget(targetWidget);
707 auto *shared = ensureSharedReader();
712 opt.initFrom(targetWidget);
713 const QQSK::State currentState = resolvedStateFor(controlType, opt.state, targetWidget);
715 QPalette stylePalette;
718 shared->setControlTypeAndState(controlType, currentState);
719 if (
const auto *bg = shared->global()->background(); bg && bg->isDefined(QQSK::Property::Color))
720 stylePalette.setColor(QPalette::Window, bg->color());
721 shared->setControlTypeAndState(controlType, QQSK::StateFlag::Disabled);
722 if (
const auto *dbg = shared->global()->background(); dbg && dbg->isDefined(QQSK::Property::Color))
723 stylePalette.setColor(QPalette::Disabled, QPalette::Window, dbg->color());
726 shared->setControlTypeAndState(controlType, currentState);
727 if (
const auto *text = shared->global()->text(); text && text->isDefined(QQSK::Property::Color)) {
728 stylePalette.setColor(QPalette::Text, text->color());
729 stylePalette.setColor(QPalette::WindowText, text->color());
731 shared->setControlTypeAndState(controlType, QQSK::StateFlag::Disabled);
732 if (
const auto *dt = shared->global()->text(); dt && dt->isDefined(QQSK::Property::Color)) {
733 stylePalette.setColor(QPalette::Disabled, QPalette::Text, dt->color());
734 stylePalette.setColor(QPalette::Disabled, QPalette::WindowText, dt->color());
738 setStylePalette(widget, stylePalette);
742
743
746 Q_Q(
const QStyleKitStyle);
747 QQStyleKitStyle *effective = effectiveStyle();
748 if (!effective || !widget)
751 if (
auto it = widgetReaders.find(widget); it != widgetReaders.end())
754 auto *widgetReader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
755 widgetReader->setExplicitStyle(effective);
756 widgetReader->setTarget(
const_cast<QWidget *>(widget));
757 widgetReader->setCompleted(
true);
758 widgetReaders.insert(widget, widgetReader);
759 QObjectPrivate::connect(widget, &QObject::destroyed,
this,
760 &QStyleKitStylePrivate::onWidgetDestroyed, Qt::UniqueConnection);
766 if (
auto *reader = widgetReaders.take(widget))
767 reader->deleteLater();
768 cleanupSubElements(widget);
773 cleanupWidgetReader(
static_cast<QWidget *>(w));
777
778
779
780
782 const QStyleOption *opt,
const QWidget *widget)
788#if QT_CONFIG(itemviews)
789 if (
const auto *viewOpt = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
790 const QModelIndex &idx = viewOpt->index;
794 key.id = SubElementKey::ItemViewCell{idx.model(), idx.internalId(), idx.row(), idx.column()};
799 if (
const auto *menuOpt = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
800 if (menuOpt->menuItemType == QStyleOptionMenuItem::Separator)
802 QAction *action =
nullptr;
803 if (
const auto *menu = qobject_cast<
const QMenu *>(widget))
804 action = menu->actionAt(menuOpt->rect.center());
805 else if (
const auto *menuBar = qobject_cast<
const QMenuBar *>(widget))
806 action = menuBar->actionAt(menuOpt->rect.center());
809 key.id = SubElementKey::Action{action};
818
819
820
821
823 const SubElementKey &key, QQStyleKitReader::ControlType type,
824 QQSK::State fromState, QQSK::State toState, QQuickTransition *transition)
const
826 Q_Q(
const QStyleKitStyle);
827 QQStyleKitStyle *effective = effectiveStyle();
833 for (
auto it = subElementAnimationReaders.begin();
834 it != subElementAnimationReaders.end();) {
835 const QQuickTransition *t = it.value()->transition();
836 if (!t || !t->running()) {
837 it.value()->deleteLater();
838 it = subElementAnimationReaders.erase(it);
845 if (subElementAnimationReaders.size() >= kMaxSubElementAnimationReaders) {
846 const auto it = subElementAnimationReaders.begin();
847 if (
const QWidget *widget = it.key().widget)
848 const_cast<QWidget *>(widget)->update();
849 it.value()->deleteLater();
850 subElementAnimationReaders.erase(it);
853 auto *reader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
854 reader->setExplicitStyle(effective);
855 reader->setTarget(
const_cast<QWidget *>(key.widget));
857 reader->setControlTypeAndState(type, fromState);
858 reader->setCompleted(
true);
862 reader->background();
863 auto *indicator = reader->indicator();
864 indicator->first()->foreground();
865 indicator->second()->foreground();
867 reader->setControlTypeAndState(type, toState);
868 if (!transition || !transition->running()) {
869 reader->deleteLater();
872 subElementAnimationReaders.insert(key, reader);
877
878
881 for (
auto it = subElementStates.begin(); it != subElementStates.end();) {
882 if (it.key().widget == widget)
883 it = subElementStates.erase(it);
887 for (
auto it = subElementAnimationReaders.begin();
888 it != subElementAnimationReaders.end();) {
889 if (it.key().widget == widget) {
890 it.value()->deleteLater();
891 it = subElementAnimationReaders.erase(it);
899
900
903 subElementStates.clear();
904 for (QQStyleKitReader *reader : std::as_const(subElementAnimationReaders))
905 reader->deleteLater();
906 subElementAnimationReaders.clear();
910
911
912
914 QQStyleKitReader::ControlType type, QStyle::State state,
const QWidget *widget)
const
917 flags.setFlag(QQSK::StateFlag::Hovered, (state & QStyle::State_MouseOver));
918 flags.setFlag(QQSK::StateFlag::Pressed, state & QStyle::State_Sunken);
919 flags.setFlag(QQSK::StateFlag::Checked, state & QStyle::State_On);
920 flags.setFlag(QQSK::StateFlag::Focused, state & QStyle::State_HasFocus);
921 flags.setFlag(QQSK::StateFlag::Highlighted, state & QStyle::State_Selected);
922 flags.setFlag(QQSK::StateFlag::Vertical, !(state & QStyle::State_Horizontal));
926 const bool disabled = (state & QStyle::State_Enabled) ?
false
927 : (widget ? !widget->isEnabled() :
true);
928 flags.setFlag(QQSK::StateFlag::Disabled, disabled);
932 if (type == QQStyleKitReader::ControlType::ComboBox)
933 flags.setFlag(QQSK::StateFlag::Checked,
false);
936 if (type == QQStyleKitReader::ControlType::Popup)
937 flags.setFlag(QQSK::StateFlag::Hovered,
false);
943
944
945
947 QQStyleKitReader::ControlType type, QQSK::State state)
const
949 if (
auto it = metricsCache.find({type, state}); it != metricsCache.end())
952 auto *reader = ensureSharedReader();
954 reader->setControlTypeAndState(type, state);
955 return *metricsCache.insert({type, state}, metricsForReader(reader));
959
960
961
963 const QWidget *w, QQStyleKitReader::ControlType type, QStyle::State state)
const
965 QQStyleKitResolved out;
968 auto *reader = readerForWidget(w);
972 const QQSK::State resolvedState = resolvedStateFor(type, state, w);
973 reader->setControlTypeAndState(type, resolvedState);
976 out.metrics = &metricsFor(type, resolvedState);
981
982
983
984
985
986
987
988
989
990
991
993 const QWidget *w,
const QStyleOption *opt,
994 QQStyleKitReader::ControlType type, QStyle::State state,
bool track)
const
996 QQStyleKitResolved out;
999 auto *steadyReader = ensureSubElementReader();
1003 const QQSK::State newState = resolvedStateFor(type, state, w);
1004 const SubElementKey key = subElementKeyForOption(opt, w);
1006 QQStyleKitReader *reader =
nullptr;
1007 if (track && key.isValid()) {
1008 QQStyleKitReader *animReader = subElementAnimationReaders.value(key);
1009 const auto it = subElementStates.constFind(key);
1010 const bool seen = it != subElementStates.cend();
1014 const auto baseState = newState & ~(QQSK::State(QQSK::StateFlag::Hovered)
1015 | QQSK::StateFlag::Pressed
1016 | QQSK::StateFlag::Checked
1017 | QQSK::StateFlag::Focused
1018 | QQSK::StateFlag::Highlighted);
1019 const QQSK::State prevState = seen ? *it : baseState;
1020 if (prevState != newState) {
1024 animReader->setControlTypeAndState(type, newState);
1029 const bool shouldAnimate = seen
1030 || newState.testFlag(QQSK::StateFlag::Hovered)
1031 || newState.testFlag(QQSK::StateFlag::Pressed);
1032 if (shouldAnimate) {
1033 steadyReader->setControlTypeAndState(type, newState);
1034 if (QQuickTransition *transition = steadyReader->transition())
1035 animReader = startSubElementTransition(key, type, prevState,
1036 newState, transition);
1040 if (!seen || prevState != newState) {
1041 QObjectPrivate::connect(w, &QObject::destroyed,
this,
1042 &QStyleKitStylePrivate::onWidgetDestroyed, Qt::UniqueConnection);
1043 if (subElementStates.size() >= kMaxSubElementStates)
1044 subElementStates.clear();
1045 subElementStates.insert(key, newState);
1047 reader = animReader;
1051 reader = steadyReader;
1052 reader->setControlTypeAndState(type, newState);
1054 out.reader = reader;
1055 out.metrics = &metricsFor(type, newState);
1061 return reader ? reader->text() :
nullptr;
1066 return reader ? reader->background() :
nullptr;
1071 return reader ? reader->handle() :
nullptr;
1076 return reader ? reader->indicator() :
nullptr;
1081 return reader ? reader->font() : QFont();
1087 return sharedReader;
1089 Q_Q(
const QStyleKitStyle);
1090 QQStyleKitStyle *effective = effectiveStyle();
1093 sharedReader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
1095 sharedReader->setTransitionsEnabled(
false);
1096 sharedReader->setExplicitStyle(effective);
1097 sharedReader->setCompleted(
true);
1098 return sharedReader;
1103 if (subElementReader)
1104 return subElementReader;
1106 Q_Q(
const QStyleKitStyle);
1107 QQStyleKitStyle *effective = effectiveStyle();
1110 subElementReader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
1113 subElementReader->setTransitionsEnabled(
false);
1114 subElementReader->setExplicitStyle(effective);
1115 subElementReader->setCompleted(
true);
1116 return subElementReader;
1120
1121
1122
1123
1125 QQStyleKitReader::ControlType type, QStyle::State state)
const
1127 QQStyleKitLayoutResolved out;
1128 auto *reader = ensureSharedReader();
1132 const QQSK::State resolvedState = resolvedStateFor(type, state);
1133 out.metrics = &metricsFor(type, resolvedState);
1137 reader->setControlTypeAndState(type, resolvedState);
1138 out.staticProps = reader->global();
1139 out.staticFont = reader->font();
1145 return staticProps ? staticProps->text() :
nullptr;
1148const QQStyleKitDelegateProperties *
QStyleKitStylePrivate::QQStyleKitLayoutResolved::background()
const
1150 return staticProps ? staticProps->background() :
nullptr;
1155 return staticProps ? staticProps->handle() :
nullptr;
1160 return staticProps ? staticProps->indicator() :
nullptr;
1165 metricsCache.clear();
1168void QStyleKitStylePrivate::drawControlIndicator(
const QQStyleKitDelegateProperties *indicator,
const QRectF &rect, QPainter *painter)
const
1170 if (!indicator || !indicator->visible() || indicator->opacity() <= 0 || !rect.isValid())
1174 QRectF indicatorRect = rect;
1175 if (indicator->visible() && indicator->opacity() > 0)
1176 drawStyledItemRect(indicator, indicatorRect, painter);
1178 const QQStyleKitDelegateProperties *foreground =
nullptr;
1179 if (
auto *indicatorWithSubTypes = qobject_cast<
const QQStyleKitIndicatorWithSubTypes *>(indicator)) {
1180 foreground = indicatorWithSubTypes->foreground();
1181 }
else if (
auto *indicatorProps = qobject_cast<
const QQStyleKitIndicatorProperties *>(indicator)) {
1182 foreground = indicatorProps->foreground();
1186 if (!foreground || !foreground->visible() || foreground->opacity() <= 0)
1190 QRectF foregroundRect;
1191 const uint foregroundAlign = resolvedAlignment(foreground->alignment(), Qt::AlignHCenter, Qt::AlignVCenter);
1192 const auto foregroundW = resolvedWidth(foreground,
1193 indicatorRect.width() - foreground->leftMargin() - foreground->rightMargin());
1194 const auto foregroundH = resolvedHeight(foreground,
1195 indicatorRect.height() - foreground->topMargin() - foreground->bottomMargin());
1196 foregroundRect.setSize(QSizeF(foregroundW, foregroundH));
1197 if (foregroundAlign & Qt::AlignLeft)
1198 foregroundRect.moveLeft(indicatorRect.left() + foreground->leftMargin());
1199 else if (foregroundAlign & Qt::AlignHCenter)
1200 foregroundRect.moveLeft(indicatorRect.left() + (indicatorRect.width() - foregroundW) / 2.0);
1201 else if (foregroundAlign & Qt::AlignRight)
1202 foregroundRect.moveLeft(indicatorRect.right() - foreground->rightMargin() - foregroundW);
1203 if (foregroundAlign & Qt::AlignTop)
1204 foregroundRect.moveTop(indicatorRect.top() + foreground->topMargin());
1205 else if (foregroundAlign & Qt::AlignVCenter)
1206 foregroundRect.moveTop(indicatorRect.top() + (indicatorRect.height() - foregroundH) / 2.0);
1207 else if (foregroundAlign & Qt::AlignBottom)
1208 foregroundRect.moveTop(indicatorRect.bottom() - foreground->bottomMargin() - foregroundH);
1209 drawStyledItemRect(foreground, foregroundRect, painter);
1213 const QFont &font,
const QRect &rect,
1214 const QString &text, uint textFlags,
1215 QPainter *p, Qt::Alignment defaultAlignment)
const
1217 uint flags = textFlags;
1219 ? resolvedAlignment(textProps->alignment(),
1220 defaultAlignment & Qt::AlignHorizontal_Mask,
1221 defaultAlignment & Qt::AlignVertical_Mask)
1222 : uint(defaultAlignment);
1224 const QFont oldFont = p->font();
1225 p->setFont(font.resolve(oldFont));
1226 p->setBrush(Qt::NoBrush);
1227 p->setPen(textProps ? textProps->color() : QColor());
1228 p->drawText(rect, flags, text,
nullptr);
1231void QStyleKitStylePrivate::drawStyledItemRect(
const QQStyleKitDelegateProperties *props,
const QRectF &rect, QPainter *painter)
const
1233 if (!props || !props->visible() || props->opacity() <= 0 || !rect.isValid())
1236 QPainterStateGuard stateGuard(painter);
1237 painter->setRenderHint(QPainter::Antialiasing,
true);
1239 painter->setClipping(
true);
1242 const auto opacity = props->opacity();
1245 const auto *border = props->border();
1246 auto borderWidth = 0;
1250 borderWidth = border->width();
1251 borderColor = border->color();
1252 inset = borderWidth / 2.0;
1254 if (borderWidth > 0 && borderColor.isValid() && borderColor.alpha() > 0) {
1255 QPen pen(borderColor, borderWidth);
1256 painter->setPen(pen);
1258 painter->setPen(Qt::NoPen);
1263 const qreal minDimension = qMin(rect.width(), rect.height());
1264 const qreal xRadius = qMax(0.0, qMin(props->topLeftRadius() - inset, minDimension / 2.0));
1265 const qreal yRadius = qMax(0.0, qMin(props->bottomLeftRadius() - inset, minDimension / 2.0));
1267 QRectF adjustedRect = rect.adjusted(inset, inset, -inset, -inset);
1270 if (props->rotation() != 0) {
1271 const auto center = rect.center();
1272 painter->translate(center);
1273 painter->rotate(props->rotation());
1274 painter->translate(-center);
1279 QColor color = props->color();
1280 QBrush colorBrush(color);
1281 painter->setBrush(colorBrush);
1282 if (color.isValid()) {
1283 painter->setOpacity(opacity);
1284 painter->drawRoundedRect(adjustedRect, xRadius, yRadius, Qt::AbsoluteSize);
1286 if (QQuickGradient *gradient = props->gradient()) {
1287 QLinearGradient linearGradient(rect.topLeft(), rect.bottomLeft());
1288 QQmlListProperty<QQuickGradientStop> stops = gradient->stops();
1289 const int stopCount = stops.count(&stops);
1290 for (
int i = 0; i < stopCount; i++) {
1291 QQuickGradientStop *stop =
static_cast<QQuickGradientStop*>(stops.at(&stops, i));
1292 linearGradient.setColorAt(stop->position(), stop->color());
1294 QBrush gradientBrush(linearGradient);
1295 painter->setBrush(gradientBrush);
1296 painter->setOpacity(opacity);
1297 painter->drawRoundedRect(adjustedRect, xRadius, yRadius, Qt::AbsoluteSize);
1301 drawStyledItemImage(props->image(), adjustedRect, opacity, painter);
1304void QStyleKitStylePrivate::drawStyledItemImage(
const QQStyleKitImageProperties *image,
const QRectF &rect,
1305 qreal opacity, QPainter *painter)
const
1307 if (!image || image->source().isEmpty() || image->color().alpha() <= 0)
1310 QString imageSource = image->source().toString();
1311 if (imageSource.startsWith(QLatin1String(
"qrc:/")))
1312 imageSource = imageSource.mid(3);
1313 QUrl imageUrl(imageSource);
1314 QString imagePath = imageUrl.isLocalFile() ? imageUrl.toLocalFile() : imageSource;
1315 QPixmap pixmap(imagePath);
1316 if (pixmap.isNull())
1319 if (image->color().isValid()) {
1320 QImage coloredImage = pixmap.toImage();
1321 QPainter imagePainter(&coloredImage);
1322 imagePainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
1323 imagePainter.fillRect(coloredImage.rect(), image->color());
1325 pixmap = QPixmap::fromImage(coloredImage);
1327 painter->setOpacity(opacity);
1328 const QSizeF pixmapSize = pixmap.deviceIndependentSize();
1330 switch (image->fillMode()) {
1331 case QQuickImage::PreserveAspectFit: {
1332 const QSize scaled = pixmapSize.scaled(rect.size(), Qt::KeepAspectRatio).toSize();
1333 const QPointF topLeft(
1334 rect.x() + (rect.width() - scaled.width()) / 2.0,
1335 rect.y() + (rect.height() - scaled.height()) / 2.0
1337 painter->drawPixmap(QRectF(topLeft, scaled), pixmap, QRectF(QPointF(0, 0), pixmapSize));
1340 case QQuickImage::PreserveAspectCrop: {
1341 const QSize scaled = pixmapSize.scaled(rect.size(), Qt::KeepAspectRatioByExpanding).toSize();
1342 const QPointF topLeft(
1343 rect.x() + (rect.width() - scaled.width()) / 2.0,
1344 rect.y() + (rect.height() - scaled.height()) / 2.0
1346 QPainterStateGuard stateGuard(painter);
1347 painter->setClipRect(rect);
1348 painter->drawPixmap(QRectF(topLeft, scaled), pixmap, QRectF(QPointF(0, 0), pixmapSize));
1352 case QQuickImage::Stretch:
1354 painter->drawPixmap(rect, pixmap, QRectF(QPointF(0, 0), pixmapSize));
1360 uint alignment,
const QMargins &padding,
1361 const QMargins &margins)
const
1363 QRect r(QPoint(0, 0), size);
1365 if (alignment & Qt::AlignLeft)
1366 r.moveLeft(container.x() + padding.left() + margins.left());
1367 else if (alignment & Qt::AlignHCenter)
1368 r.moveLeft(container.x() + (container.width() - size.width()) / 2);
1370 r.moveLeft(container.x() + container.width() - padding.right() - margins.right() - size.width());
1372 if (alignment & Qt::AlignTop)
1373 r.moveTop(container.y() + padding.top() + margins.top());
1374 else if (alignment & Qt::AlignVCenter)
1375 r.moveTop(container.y() + (container.height() - size.height()) / 2);
1377 r.moveTop(container.y() + container.height() - padding.bottom() - margins.bottom() - size.height());
1382QStyleKitStylePrivate::ControlMetrics
QStyleKitStylePrivate::metricsForReader(QQStyleKitReader *reader)
const
1385 const QQStyleKitControlProperties *props = reader->global();
1386 ControlMetrics metrics;
1387 metrics.bgImplicitSize = QSize(0, 0);
1388 metrics.textPadding = QMargins(0, 0, 0, 0);
1389 metrics.padding = QMargins(props->leftPadding(), props->topPadding(),
1390 props->rightPadding(), props->bottomPadding());
1391 metrics.spacing = props->spacing();
1392 metrics.margins = QMargins(0, 0, 0, 0);
1393 metrics.indicatorImplicitSize = QSize(0, 0);
1394 metrics.indicatorMargins = QMargins(0, 0, 0, 0);
1395 metrics.foregroundImplicitSize = QSize(0, 0);
1396 metrics.foregroundMargins = QMargins(0, 0, 0, 0);
1397 const auto *background = props->background();
1399 auto scale = background->scale();
1402 metrics.bgImplicitSize = QSize(
static_cast<
int>(background->width()),
static_cast<
int>(background->height())) * scale;
1403 metrics.margins = elementMargins(background);
1405 const auto *textProps = props->text();
1407 metrics.textPadding = QMargins(textProps->leftPadding(), textProps->topPadding(),textProps->rightPadding(), textProps->bottomPadding());
1408 const auto *indicator = props->indicator();
1410 auto scale = indicator->scale();
1413 metrics.indicatorMargins = elementMargins(indicator);
1414 metrics.indicatorImplicitSize = QSize(std::max(.0, indicator->width()),
1415 std::max(.0, indicator->height())) * scale;
1417 const auto *foreground = indicator->foreground();
1419 auto scale = foreground->scale();
1422 metrics.foregroundMargins = elementMargins(foreground);
1423 const auto foregroundW = resolvedWidth(foreground,
1424 std::max(.0, qreal(metrics.indicatorImplicitSize.width() - metrics.foregroundMargins.left() - metrics.foregroundMargins.right())));
1425 const auto foregroundH = resolvedHeight(foreground,
1426 std::max(.0, qreal(metrics.indicatorImplicitSize.height() - metrics.foregroundMargins.top() - metrics.foregroundMargins.bottom())));
1427 metrics.foregroundImplicitSize = QSize(foregroundW, foregroundH) * scale;
1430 const auto *handle = props->handle();
1432 auto scale = handle->scale();
1435 metrics.handleImplicitSize = QSize(std::max(.0, handle->width()),
1436 std::max(.0, handle->height())) * scale;
1437 metrics.handleMargins = elementMargins(handle);
1443
1444
1445
1446
1447
1448QStyleKitStyle::QStyleKitStyle()
1449 : QCommonStyle(*
new QStyleKitStylePrivate())
1454
1455
1456
1457
1458
1459
1460
1461
1462QStyleKitStyle::QStyleKitStyle(
const QString &filePath)
1463 : QCommonStyle(*
new QStyleKitStylePrivate())
1465 Q_D(QStyleKitStyle);
1466 d->stylePath = filePath;
1467 if (!d->loadStyle()) {
1468 qWarning(
"QStyleKitStyle: Failed to load style from %s", qPrintable(filePath));
1473
1474
1475QStyleKitStyle::~QStyleKitStyle()
1480
1481
1482
1483
1484QString QStyleKitStyle::stylePath()
const
1486 Q_D(
const QStyleKitStyle);
1487 return d->stylePath;
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502void QStyleKitStyle::setStylePath(
const QString &filePath)
1504 Q_D(QStyleKitStyle);
1505 if (d->stylePath == filePath)
1507 d->stylePath = filePath;
1510 emit stylePathChanged();
1514
1515
1516
1517
1518
1519QString QStyleKitStyle::themeName()
const
1521 Q_D(
const QStyleKitStyle);
1522 return d->style ? d->style->themeName() : QString();
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535void QStyleKitStyle::setThemeName(
const QString &themeName)
1537 Q_D(QStyleKitStyle);
1539 qWarning(
"QStyleKitStyle: No style loaded, cannot set theme name.");
1542 if (d->style->themeName() == themeName)
1544 d->style->setThemeName(themeName);
1546 emit themeNameChanged();
1550
1551
1552
1553
1554
1555
1556
1557QStringList QStyleKitStyle::themeNames()
const
1559 Q_D(
const QStyleKitStyle);
1560 return d->style ? d->style->themeNames() : QStringList();
1564
1565
1566
1567
1568
1569
1570QStringList QStyleKitStyle::customThemeNames()
const
1572 Q_D(
const QStyleKitStyle);
1573 return d->style ? d->style->customThemeNames() : QStringList();
1577void QStyleKitStyle::drawPrimitive(PrimitiveElement pe,
const QStyleOption *opt, QPainter *p,
1578 const QWidget *w)
const
1580 Q_D(
const QStyleKitStyle);
1584 case PE_PanelMenu: {
1585 const auto controlType = w && w->inherits(
"QComboBoxPrivateContainer")
1586 ? QQStyleKitReader::ControlType::Popup
1587 : QQStyleKitReader::ControlType::Menu;
1588 const auto r = d->resolve(w, controlType, opt->state);
1591 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
1598#if QT_CONFIG(menubar)
1599 case PE_PanelMenuBar: {
1600 const auto r = d->resolve(w, QQStyleKitReader::ControlType::MenuBar, opt->state);
1603 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
1607 case PE_FrameButtonBevel:
1608 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1609 const auto controlType = btn->features & QStyleOptionButton::Flat
1610 ? QQStyleKitReader::ControlType::FlatButton
1611 : QQStyleKitReader::ControlType::Button;
1612 const auto r = d->resolve(w, controlType, btn->state);
1615 d->drawStyledItemRect(r.background(), opt->rect, p);
1620 QQStyleKitReader::ControlType controlType;
1621 const bool isPopup = w && (
false
1622#if QT_CONFIG(combobox)
1623 || w->inherits(
"QComboBoxPrivateContainer")
1627 controlType = QQStyleKitReader::ControlType::Popup;
1628#if QT_CONFIG(lineedit)
1629 else if (qobject_cast<
const QLineEdit *>(w))
1630 controlType = QQStyleKitReader::ControlType::TextField;
1633 controlType = QQStyleKitReader::ControlType::Frame;
1634 const auto r = d->resolve(w, controlType, opt->state);
1637 d->drawStyledItemRect(r.background(), opt->rect, p);
1640#if QT_CONFIG(lineedit)
1641 case PE_PanelLineEdit:
1642 if (
const auto *lineEdit = qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
1645 QStyleOption lineEditOpt(*lineEdit);
1646 lineEditOpt.state &= ~QStyle::State_Sunken;
1647 const auto r = d->resolve(w, QQStyleKitReader::ControlType::TextField, lineEditOpt.state);
1652 if (
auto *le = qobject_cast<
const QLineEdit *>(w)) {
1653 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
1654 QPalette stylePalette;
1655 stylePalette.setColor(QPalette::Text, txt->color());
1656 d->setStylePalette(
const_cast<QLineEdit *>(le), stylePalette);
1658 const_cast<QStyleKitStylePrivate *>(d)->setStyleFont(
const_cast<QLineEdit *>(le), r.font());
1661 const QObject *parent = w ? w->parent() :
nullptr;
1662#if QT_CONFIG(spinbox)
1663 const bool isInSpinBox = qobject_cast<
const QAbstractSpinBox *>(parent);
1665 const bool isInSpinBox =
false;
1667#if QT_CONFIG(combobox)
1668 const bool isInComboBox = qobject_cast<
const QComboBox *>(parent);
1670 const bool isInComboBox =
false;
1673 if (isInSpinBox || isInComboBox)
1676 d->drawStyledItemRect(r.background(), opt->rect, p);
1681#if QT_CONFIG(itemviews)
1682 case PE_PanelItemViewItem: {
1683 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::ItemDelegate, opt->state);
1686 d->drawStyledItemRect(r.background(), opt->rect, p);
1690 case PE_IndicatorCheckBox:
1691 case PE_IndicatorRadioButton: {
1692 const auto controlType = pe == PE_IndicatorCheckBox
1693 ? QQStyleKitReader::ControlType::CheckBox
1694 : QQStyleKitReader::ControlType::RadioButton;
1695 const auto r = d->resolve(w, controlType, opt->state);
1698 d->drawControlIndicator(r.indicator(), opt->rect, p);
1701 case PE_IndicatorArrowDown: {
1702 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, opt->state);
1705 d->drawControlIndicator(r.indicator(), opt->rect, p);
1708 case PE_IndicatorItemViewItemCheck: {
1710 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::ItemDelegate,
1714 d->drawControlIndicator(r.indicator(), opt->rect, p);
1717#if QT_CONFIG(spinbox)
1718 case PE_IndicatorSpinUp:
1719 case PE_IndicatorSpinDown: {
1720 const auto r = d->resolve(w, QQStyleKitReader::ControlType::SpinBox, opt->state);
1723 const auto *indicator = r.indicator();
1724 const auto *upDownIndicator = indicator ? (pe == PE_IndicatorSpinUp ? indicator->first() : indicator->second()) :
nullptr;
1725 d->drawControlIndicator(upDownIndicator, opt->rect, p);
1729#if QT_CONFIG(groupbox)
1730 case PE_FrameGroupBox: {
1731 const auto r = d->resolve(w, QQStyleKitReader::ControlType::GroupBox, opt->state);
1734 d->drawStyledItemRect(r.background(), opt->rect, p);
1738#if QT_CONFIG(toolbutton)
1739 case PE_FrameButtonTool:
1740 case PE_PanelButtonTool: {
1741 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolButton, opt->state);
1744 d->drawStyledItemRect(r.background(), opt->rect, p);
1748#if QT_CONFIG(toolbar)
1749 case PE_IndicatorToolBarHandle:
1751 case PE_IndicatorToolBarSeparator: {
1752 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolSeparator, opt->state);
1755 const auto &metrics = *r.metrics;
1757 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
1758 d->drawStyledItemRect(r.background(), frameRect, p);
1760 const auto *indicator = r.indicator();
1761 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
1763 QRect contentRect = frameRect.marginsRemoved(metrics.padding);
1764 const int iw = resolvedWidth(indicator,
1765 contentRect.width() - metrics.indicatorMargins.left() - metrics.indicatorMargins.right());
1766 const int ih = resolvedHeight(indicator,
1767 contentRect.height() - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom());
1768 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignHCenter, Qt::AlignVCenter);
1769 const QRect indicatorRect = d->getAlignedRectInContainer(
1770 contentRect, QSize(iw, ih), alignment, QMargins(), metrics.indicatorMargins);
1771 d->drawControlIndicator(indicator, visualRect(opt->direction, contentRect, indicatorRect), p);
1778 QCommonStyle::drawPrimitive(pe, opt, p, w);
1782void QStyleKitStyle::drawControl(ControlElement element,
const QStyleOption *opt, QPainter *p,
1783 const QWidget *w)
const
1785 Q_D(
const QStyleKitStyle);
1789 if (
const QStyleOptionButton *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1790 proxy()->drawControl(CE_PushButtonBevel, btn, p, w);
1791 QStyleOptionButton btnContent(*btn);
1792 btnContent.rect = subElementRect(SE_PushButtonContents, btn, w);
1793 proxy()->drawControl(CE_PushButtonLabel, &btnContent, p, w);
1796 case CE_PushButtonBevel:
1797 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1798 QStyleOptionButton btnBg(*btn);
1799 btnBg.rect = subElementRect(SE_PushButtonBevel, btn, w);
1800 proxy()->drawPrimitive(PE_FrameButtonBevel, &btnBg, p, w);
1803 case CE_PushButtonLabel:
1804 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1805 const auto controlType = btn->features & QStyleOptionButton::Flat ? QQStyleKitReader::ControlType::FlatButton : QQStyleKitReader::ControlType::Button;
1806 const auto r = d->resolve(w, controlType, btn->state);
1809 const auto metrics = r.metrics;
1811 QRect textRect = opt->rect;
1812 uint textFlags = Qt::TextShowMnemonic;
1813 if (!styleHint(SH_UnderlineShortcut, opt, w))
1814 textFlags |= Qt::TextHideMnemonic;
1817 const QIcon icon = btn->icon;
1818 if (!icon.isNull()) {
1819 const auto *textProps = r.text();
1820 uint iconTextFlags = textFlags;
1821 iconTextFlags |= textProps
1822 ? resolvedAlignment(textProps->alignment(), Qt::AlignHCenter, Qt::AlignVCenter)
1823 : uint(Qt::AlignHCenter | Qt::AlignVCenter);
1824 QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
1825 if (mode == QIcon::Normal && btn->state & State_HasFocus)
1826 mode = QIcon::Active;
1827 QIcon::State iconState = btn->state & State_On ? QIcon::On : QIcon::Off;
1828 const auto paintDeviceDpr = p->device()->devicePixelRatio();
1829 QPixmap pixmap = icon.pixmap(btn->iconSize, paintDeviceDpr, mode, iconState);
1830 int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
1831 int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
1832 int labelWidth = pixmapWidth;
1833 int iconSpacing = metrics->spacing;
1834 int textWidth = btn->fontMetrics.boundingRect(opt->rect, iconTextFlags, btn->text).width();
1835 if (!btn->text.isEmpty())
1836 labelWidth += (textWidth + iconSpacing + textProps->leftPadding() + textProps->rightPadding());
1839 if (iconTextFlags & Qt::AlignLeft) {
1840 iconRect = QRect(textRect.x(), textRect.y() + (textRect.height() - pixmapHeight) / 2,
1841 pixmapWidth, pixmapHeight);
1842 }
else if (iconTextFlags & Qt::AlignHCenter) {
1843 iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
1844 textRect.y() + (textRect.height() - pixmapHeight) / 2,
1845 pixmapWidth, pixmapHeight);
1847 iconRect = QRect(textRect.x() + textRect.width() - labelWidth,
1848 textRect.y() + (textRect.height() - pixmapHeight) / 2,
1849 pixmapWidth, pixmapHeight);
1851 iconRect = visualRect(btn->direction, textRect, iconRect);
1854 textFlags &= ~Qt::AlignHorizontal_Mask;
1855 textFlags |= Qt::AlignLeft;
1856 if (btn->direction == Qt::RightToLeft)
1857 textRect.setRight(iconRect.left() - iconSpacing);
1859 textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing);
1861 p->drawPixmap(iconRect, pixmap);
1864 if (btn->features & QStyleOptionButton::HasMenu) {
1865 int indicatorSize = pixelMetric(PM_MenuButtonIndicator, btn, w);
1866 if (btn->direction == Qt::LeftToRight)
1867 textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
1869 textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
1871 d->drawControlText(r.text(), r.font(), textRect, btn->text, textFlags, p);
1876 case CE_RadioButton:
1877 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1878 const auto controlType = element == CE_CheckBox ? QQStyleKitReader::ControlType::CheckBox
1879 : QQStyleKitReader::ControlType::RadioButton;
1880 const auto r = d->resolve(w, controlType, btn->state);
1883 QRect backgroundRect = btn->rect.marginsRemoved(r.metrics->margins);
1885 d->drawStyledItemRect(r.background(), backgroundRect, p);
1887 QStyleOptionButton btnContent(*btn);
1888 const auto contentElement = element == CE_CheckBox ? SE_CheckBoxContents : SE_RadioButtonContents;
1889 btnContent.rect = subElementRect(contentElement, btn, w);
1890 const auto labelElement = element == CE_CheckBox ? CE_CheckBoxLabel : CE_RadioButtonLabel;
1891 proxy()->drawControl(labelElement, &btnContent, p, w);
1893 QStyleOptionButton indicator(*btn);
1894 const auto indicatorElement = element == CE_CheckBox ? SE_CheckBoxIndicator : SE_RadioButtonIndicator;
1895 indicator.rect = subElementRect(indicatorElement, btn, w);
1896 const auto primitiveElement = element == CE_CheckBox ? PE_IndicatorCheckBox : PE_IndicatorRadioButton;
1897 proxy()->drawPrimitive(primitiveElement, &indicator, p, w);
1901 case CE_CheckBoxLabel:
1902 case CE_RadioButtonLabel:
1903 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1904 const auto controlType = element == CE_CheckBoxLabel ? QQStyleKitReader::ControlType::CheckBox
1905 : QQStyleKitReader::ControlType::RadioButton;
1906 const auto r = d->resolve(w, controlType, btn->state);
1909 uint textFlags = Qt::TextShowMnemonic;
1910 if (!styleHint(SH_UnderlineShortcut, opt, w))
1911 textFlags |= Qt::TextHideMnemonic;
1912 d->drawControlText(r.text(), r.font(), opt->rect, btn->text, textFlags, p);
1916#if QT_CONFIG(combobox)
1917 case CE_ComboBoxLabel:
1918 if (
const auto *comboBox = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
1919 if (comboBox->editable)
1921 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, comboBox->state);
1924 const QRect textRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, w)
1925 .marginsRemoved(r.metrics->textPadding);
1926 uint textFlags = Qt::TextShowMnemonic;
1927 if (!styleHint(SH_UnderlineShortcut, opt, w))
1928 textFlags |= Qt::TextHideMnemonic;
1929 d->drawControlText(r.text(), r.font(), textRect, comboBox->currentText, textFlags, p);
1934#if QT_CONFIG(progressbar)
1935 case CE_ProgressBar:
1936 if (
const QStyleOptionProgressBar *progressBar = qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
1937 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar, progressBar->state);
1940 QRect backgroundRect = progressBar->rect.marginsRemoved(r.metrics->margins);
1942 d->drawStyledItemRect(r.background(), backgroundRect, p);
1944 QStyleOptionProgressBar contents(*progressBar);
1945 contents.rect = subElementRect(SE_ProgressBarGroove, progressBar, w);
1946 proxy()->drawControl(CE_ProgressBarGroove, &contents, p, w);
1948 contents.rect = subElementRect(SE_ProgressBarContents, progressBar, w);
1949 proxy()->drawControl(CE_ProgressBarContents, &contents, p, w);
1954 case CE_ProgressBarGroove: {
1956 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar, opt->state);
1959 d->drawStyledItemRect(r.indicator(), opt->rect, p);
1962 case CE_ProgressBarContents:
1964 if (
const auto *progressBar = qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
1965 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar, progressBar->state);
1968 const auto progress = progressBar->progress;
1969 const auto ratio = progressBar->maximum > progressBar->minimum ? (progress - progressBar->minimum) /
static_cast<qreal>(progressBar->maximum - progressBar->minimum) : 0;
1970 const auto width =
static_cast<
int>(progressBar->rect.width() * ratio);
1971 const auto x = progressBar->invertedAppearance ? progressBar->rect.right() - width : progressBar->rect.left();
1972 const auto contentsRect = QRect(x, progressBar->rect.y(), width, progressBar->rect.height());
1973 const auto *foreground = r.indicator() ? r.indicator()->foreground() :
nullptr;
1974 if (foreground && foreground->visible() && foreground->opacity() > 0)
1975 d->drawStyledItemRect(foreground, contentsRect, p);
1980#if QT_CONFIG(itemviews)
1981 case CE_ItemViewItem:
1982 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
1983 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::ItemDelegate, opt->state);
1986 QStyleOptionViewItem optBg(*itemViewOption);
1987 optBg.rect = optBg.rect.marginsRemoved(r.metrics->margins);
1988 QRect indicatorRect = subElementRect(SE_ItemViewItemCheckIndicator, itemViewOption, w);
1989 QRect iconRect = subElementRect(SE_ItemViewItemDecoration, itemViewOption, w);
1990 QRect textRect = subElementRect(SE_ItemViewItemText, itemViewOption, w);
1993 const auto *itemTextProps = r.text();
1994 const QFont itemFont = r.font();
1997 proxy()->drawPrimitive(PE_PanelItemViewItem, &optBg, p, w);
2000 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator) {
2001 QStyleOptionViewItem option(*itemViewOption);
2002 option.rect = indicatorRect;
2003 option.state = option.state & ~QStyle::State_HasFocus;
2005 switch (itemViewOption->checkState) {
2007 option.state |= QStyle::State_Off;
2009 case Qt::PartiallyChecked:
2010 option.state |= QStyle::State_NoChange;
2013 option.state |= QStyle::State_On;
2016 proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, p, w);
2020 QIcon::Mode mode = QIcon::Normal;
2021 if (!(itemViewOption->state & QStyle::State_Enabled))
2022 mode = QIcon::Disabled;
2023 else if (itemViewOption->state & QStyle::State_Selected)
2024 mode = QIcon::Selected;
2025 QIcon::State state = itemViewOption->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
2026 itemViewOption->icon.paint(p, iconRect, itemViewOption->decorationAlignment, mode, state);
2029 uint textFlags = Qt::TextShowMnemonic;
2030 if (!styleHint(SH_UnderlineShortcut, opt, w))
2031 textFlags |= Qt::TextHideMnemonic;
2032 d->drawControlText(itemTextProps, itemFont, textRect, itemViewOption->text, textFlags, p,
2033 Qt::AlignLeft | Qt::AlignVCenter);
2039 case CE_ShapedFrame:
2040#if QT_CONFIG(combobox)
2041 if (w && w->inherits(
"QComboBoxPrivateContainer")) {
2042 const auto r = d->resolve(w, QQStyleKitReader::ControlType::Popup, opt->state);
2045 QRect backgroundRect = opt->rect.marginsRemoved(r.metrics->margins);
2046 d->drawStyledItemRect(r.background(), backgroundRect, p);
2050#if QT_CONFIG(textedit)
2051 if (qobject_cast<
const QTextEdit *>(w)) {
2052 const auto r = d->resolve(w, QQStyleKitReader::ControlType::TextArea, opt->state);
2055 QRect backgroundRect = opt->rect.marginsRemoved(r.metrics->margins);
2056 d->drawStyledItemRect(r.background(), backgroundRect, p);
2063#if QT_CONFIG(scrollbar)
2064 case CE_ScrollBarSlider: {
2065 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ScrollBar, opt->state);
2068 d->drawControlIndicator(r.indicator(), opt->rect, p);
2073#if QT_CONFIG(toolbutton)
2074 case CE_ToolButtonLabel:
2075 if (
const auto *tool = qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
2076 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolButton, tool->state);
2079 const auto *metrics = r.metrics;
2080 QRect rect = tool->rect.marginsRemoved(metrics->textPadding);
2082 uint textFlags = Qt::TextShowMnemonic;
2083 if (!styleHint(SH_UnderlineShortcut, opt, w))
2084 textFlags |= Qt::TextHideMnemonic;
2086 const bool hasArrow = tool->features & QStyleOptionToolButton::Arrow;
2087 if ((!hasArrow && tool->icon.isNull() && !tool->text.isEmpty())
2088 || tool->toolButtonStyle == Qt::ToolButtonTextOnly) {
2089 d->drawControlText(r.text(), r.font(), rect, tool->text, textFlags, p);
2095 if (!hasArrow && !tool->icon.isNull()) {
2096 const QIcon::State iconState = tool->state & State_On ? QIcon::On : QIcon::Off;
2098 if (!(tool->state & State_Enabled))
2099 mode = QIcon::Disabled;
2100 else if ((tool->state & State_MouseOver) && (tool->state & State_AutoRaise))
2101 mode = QIcon::Active;
2103 mode = QIcon::Normal;
2104 pm = tool->icon.pixmap(tool->iconSize, p->device()->devicePixelRatio(), mode, iconState);
2105 pmSize = pm.size() / pm.devicePixelRatio();
2108 if (tool->toolButtonStyle == Qt::ToolButtonIconOnly || tool->text.isEmpty()) {
2110 p->drawPixmap(visualRect(tool->direction, rect,
2111 QRect(rect.x() + (rect.width() - pmSize.width()) / 2,
2112 rect.y() + (rect.height() - pmSize.height()) / 2,
2113 pmSize.width(), pmSize.height())), pm);
2118 if (tool->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
2120 const QRect pr(rect.x() + (rect.width() - pmSize.width()) / 2,
2121 rect.y(), pmSize.width(), pmSize.height());
2122 p->drawPixmap(visualRect(tool->direction, rect, pr), pm);
2124 tr.setTop(rect.y() + pmSize.height() + metrics->spacing);
2125 d->drawControlText(r.text(), r.font(), visualRect(tool->direction, rect, tr),
2126 tool->text, textFlags, p, Qt::AlignCenter);
2128 d->drawControlText(r.text(), r.font(), rect, tool->text, textFlags, p, Qt::AlignCenter);
2132 const QRect pr(rect.x(), rect.y() + (rect.height() - pmSize.height()) / 2,
2133 pmSize.width(), pmSize.height());
2134 p->drawPixmap(visualRect(tool->direction, rect, pr), pm);
2136 tr.setLeft(rect.x() + pmSize.width() + metrics->spacing);
2137 d->drawControlText(r.text(), r.font(), visualRect(tool->direction, rect, tr),
2138 tool->text, textFlags, p, Qt::AlignLeft | Qt::AlignVCenter);
2140 d->drawControlText(r.text(), r.font(), rect, tool->text, textFlags, p, Qt::AlignLeft | Qt::AlignVCenter);
2149 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
2151 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
2152 const auto r = d->resolve(w, QQStyleKitReader::ControlType::MenuSeparator, menuItem->state);
2155 const auto metrics = r.metrics;
2156 QRect contentRect = opt->rect.marginsRemoved(metrics->margins).marginsRemoved(metrics->padding);
2157 const auto *indicator = r.indicator();
2158 if (indicator && indicator->visible() && indicator->opacity() > 0) {
2159 const int w = resolvedWidth(indicator,
2160 contentRect.width() - indicator->leftMargin() - indicator->rightMargin());
2161 const int h = resolvedHeight(indicator,
2162 contentRect.height() - indicator->topMargin() - indicator->bottomMargin());
2163 const uint align = resolvedAlignment(indicator->alignment(), Qt::AlignHCenter, Qt::AlignVCenter);
2164 const QRect indicatorRect = d->getAlignedRectInContainer(
2165 contentRect, QSize(w, h), align, QMargins(), elementMargins(indicator));
2166 d->drawControlIndicator(indicator, visualRect(opt->direction, contentRect, indicatorRect), p);
2171 QStyle::State adjustedState = menuItem->state;
2172 if (adjustedState & State_Selected)
2173 adjustedState |= State_MouseOver;
2175 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::MenuItem, adjustedState);
2180 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
2183 const QRect contentRect = opt->rect.marginsRemoved(r.metrics->padding);
2184 const auto *indicator = r.indicator();
2185 const auto *first = indicator ? indicator->first() :
nullptr;
2186 const auto *second = indicator ? indicator->second() :
nullptr;
2187 int leftOffset = 0, rightOffset = 0;
2188 const int spacing = r.metrics->spacing;
2189 QRect firstDrawRect, secondDrawRect;
2190 auto placeSubIndicator = [&](
const QQStyleKitIndicatorProperties *sub, QRect &drawRect) {
2193 const QSize sz(
static_cast<
int>(sub->width()),
static_cast<
int>(sub->height()));
2194 const QMargins subMargins(
static_cast<
int>(sub->leftMargin()),
static_cast<
int>(sub->topMargin()),
2195 static_cast<
int>(sub->rightMargin()),
static_cast<
int>(sub->bottomMargin()));
2196 const int slotW = subMargins.left() + sz.width() + subMargins.right();
2197 if (sub->alignment() & Qt::AlignRight) {
2198 const QRect slot(contentRect.right() - rightOffset - slotW, contentRect.top(),
2199 slotW, contentRect.height());
2200 drawRect = d->getAlignedRectInContainer(slot, sz, Qt::AlignRight | Qt::AlignVCenter, {}, subMargins);
2201 rightOffset += slotW + spacing;
2203 const QRect slot(contentRect.left() + leftOffset, contentRect.top(),
2204 slotW, contentRect.height());
2205 drawRect = d->getAlignedRectInContainer(slot, sz, Qt::AlignLeft | Qt::AlignVCenter, {}, subMargins);
2206 leftOffset += slotW + spacing;
2209 placeSubIndicator(first, firstDrawRect);
2210 placeSubIndicator(second, secondDrawRect);
2212 if (first && menuItem->checkType != QStyleOptionMenuItem::NotCheckable && menuItem->checked)
2213 d->drawControlIndicator(first, visualRect(menuItem->direction, contentRect, firstDrawRect), p);
2215 if (second && menuItem->menuItemType == QStyleOptionMenuItem::SubMenu)
2216 d->drawControlIndicator(second, visualRect(menuItem->direction, contentRect, secondDrawRect), p);
2219 QRect textRect = contentRect.adjusted(leftOffset, 0, -rightOffset, 0)
2220 .marginsRemoved(r.metrics->textPadding);
2221 if (!menuItem->icon.isNull()) {
2222 const int iconW = menuItem->maxIconWidth;
2223 const QIcon::Mode mode = (menuItem->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled;
2224 const QPixmap pm = menuItem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, opt, w),
2225 p->device()->devicePixelRatio(), mode);
2226 const int pmW = pm.width() / pm.devicePixelRatio();
2227 const int pmH = pm.height() / pm.devicePixelRatio();
2228 p->drawPixmap(visualRect(menuItem->direction, textRect,
2229 QRect(textRect.left(), textRect.top() + (textRect.height() - pmH) / 2, pmW, pmH)), pm);
2230 textRect.setLeft(textRect.left() + iconW + r.metrics->spacing);
2233 const int tabIdx = menuItem->text.indexOf(QLatin1Char(
'\t'));
2234 const QString label = tabIdx >= 0 ? menuItem->text.left(tabIdx) : menuItem->text;
2235 const QString shortcut = tabIdx >= 0 ? menuItem->text.mid(tabIdx + 1) : QString();
2236 uint textFlags = Qt::TextShowMnemonic;
2237 if (!styleHint(SH_UnderlineShortcut, opt, w))
2238 textFlags |= Qt::TextHideMnemonic;
2239 QRect labelRect = textRect;
2240 if (!shortcut.isEmpty() && menuItem->reservedShortcutWidth > 0) {
2241 const QRect shortcutRect(textRect.right() - menuItem->reservedShortcutWidth + 1,
2242 textRect.top(), menuItem->reservedShortcutWidth,
2244 labelRect.setRight(shortcutRect.left() - r.metrics->spacing - 1);
2245 const int shortcutFlags =
2246 int(QStyle::visualAlignment(menuItem->direction,
2247 Qt::AlignRight | Qt::AlignVCenter))
2250 p->setFont(r.font().resolve(p->font()));
2251 p->setBrush(Qt::NoBrush);
2252 if (
const auto *shortcutText = r.text())
2253 p->setPen(shortcutText->color());
2254 p->drawText(visualRect(menuItem->direction, textRect, shortcutRect),
2255 shortcutFlags, shortcut);
2258 d->drawControlText(r.text(), r.font(),
2259 visualRect(menuItem->direction, textRect, labelRect),
2260 label, textFlags, p, Qt::AlignLeft | Qt::AlignVCenter);
2266 case CE_MenuScroller:
2267 case CE_MenuTearoff:
2269 case CE_MenuEmptyArea:
2272#if QT_CONFIG(menubar)
2273 case CE_MenuBarEmptyArea:
2275 case CE_MenuBarItem:
2276 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
2277 QStyle::State adjustedState = menuItem->state;
2278 if (adjustedState & State_Selected)
2279 adjustedState |= State_MouseOver;
2280 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::MenuBarItem, adjustedState);
2283 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
2284 const QRect textRect = opt->rect.marginsRemoved(
2285 r.metrics->margins + r.metrics->padding + r.metrics->textPadding);
2286 uint textFlags = Qt::TextShowMnemonic;
2287 if (!styleHint(SH_UnderlineShortcut, opt, w))
2288 textFlags |= Qt::TextHideMnemonic;
2289 d->drawControlText(r.text(), r.font(), textRect, menuItem->text, textFlags, p);
2294#if QT_CONFIG(toolbar)
2296 if (
const auto *toolBar = qstyleoption_cast<
const QStyleOptionToolBar *>(opt)) {
2297 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolBar, toolBar->state);
2300 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
2308 QCommonStyle::drawControl(element, opt, p, w);
2312QRect QStyleKitStyle::subElementRect(SubElement r,
const QStyleOption *opt,
const QWidget *widget)
const
2314 Q_D(
const QStyleKitStyle);
2317 case SE_PushButtonLayoutItem:
2318 case SE_PushButtonBevel:
2319 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2320 const auto controlType = btn->features & QStyleOptionButton::Flat
2321 ? QQStyleKitReader::ControlType::FlatButton
2322 : QQStyleKitReader::ControlType::Button;
2323 const auto resolved = d->resolveLayout(controlType, opt->state);
2324 if (!resolved.isValid())
2326 const auto &metrics = *resolved.metrics;
2327 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2328 return visualRect(opt->direction, opt->rect, rect);
2331 case SE_PushButtonContents:
2332 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2333 const auto controlType = btn->features & QStyleOptionButton::Flat
2334 ? QQStyleKitReader::ControlType::FlatButton
2335 : QQStyleKitReader::ControlType::Button;
2336 const auto resolved = d->resolveLayout(controlType, opt->state);
2337 if (!resolved.isValid())
2339 const auto &metrics = *resolved.metrics;
2340 QRect rect = opt->rect.marginsRemoved(metrics.margins + metrics.padding + metrics.textPadding);
2341 return visualRect(opt->direction, opt->rect, rect);
2344 case SE_CheckBoxContents:
2345 case SE_RadioButtonContents: {
2346 const auto controlType = r == SE_CheckBoxContents ? QQStyleKitReader::ControlType::CheckBox
2347 : QQStyleKitReader::ControlType::RadioButton;
2348 const auto resolved = d->resolveLayout(controlType, opt->state);
2349 if (!resolved.isValid())
2351 const auto &metrics = *resolved.metrics;
2352 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
2353 const auto subElement = r == SE_CheckBoxContents ? SE_CheckBoxIndicator : SE_RadioButtonIndicator;
2354 QRect indicatorRect = visualRect(opt->direction, opt->rect, subElementRect(subElement, opt, widget));
2355 const int spacing = metrics.spacing;
2356 const auto *indicator = resolved.indicator();
2357 const uint alignment = indicator
2358 ? resolvedAlignment(indicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
2359 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2360 if (alignment & Qt::AlignLeft) {
2361 contentsRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
2362 }
else if (alignment & Qt::AlignHCenter) {
2363 contentsRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
2364 contentsRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
2366 contentsRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
2368 return visualRect(opt->direction, opt->rect, contentsRect);
2370 case SE_CheckBoxIndicator:
2371 case SE_RadioButtonIndicator: {
2372 const auto controlType = r == SE_CheckBoxIndicator
2373 ? QQStyleKitReader::ControlType::CheckBox
2374 : QQStyleKitReader::ControlType::RadioButton;
2375 const auto resolved = d->resolveLayout(controlType, opt->state);
2376 if (!resolved.isValid())
2378 const auto &metrics = *resolved.metrics;
2379 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2380 const auto *indicator = resolved.indicator();
2381 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2384 const int w = resolvedWidth(indicator,
2385 rect.width() - metrics.padding.left() - metrics.padding.right()
2386 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right());
2387 const int h = resolvedHeight(indicator,
2388 rect.height() - metrics.padding.top() - metrics.padding.bottom()
2389 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom());
2390 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
2391 const QRect indicatorRect = d->getAlignedRectInContainer(
2392 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
2393 return visualRect(opt->direction, rect, indicatorRect);
2395#if QT_CONFIG(itemviews)
2396 case SE_ItemViewItemCheckIndicator: {
2397 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ItemDelegate, opt->state);
2398 if (!resolved.isValid())
2400 const auto &metrics = *resolved.metrics;
2401 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2402 const auto *indicator = resolved.indicator();
2403 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2406 const int w = resolvedWidth(indicator,
2407 rect.width() - metrics.padding.left() - metrics.padding.right()
2408 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right());
2409 const int h = resolvedHeight(indicator,
2410 rect.height() - metrics.padding.top() - metrics.padding.bottom()
2411 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom());
2412 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
2413 const QRect indicatorRect = d->getAlignedRectInContainer(
2414 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
2415 return visualRect(opt->direction, rect, indicatorRect);
2417 case SE_ItemViewItemText:
2418 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
2419 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ItemDelegate, opt->state);
2420 if (!resolved.isValid())
2422 const auto &metrics = *resolved.metrics;
2423 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
2424 QRect indicatorRect;
2425 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator)
2426 indicatorRect = subElementRect(SE_ItemViewItemCheckIndicator, opt, widget);
2427 const int spacing = metrics.spacing;
2428 QRect textRect = contentsRect;
2429 const auto *textProps = resolved.text();
2432 textAlign = resolvedAlignment(textProps->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
2434 textAlign = Qt::AlignLeft | Qt::AlignVCenter;
2435 if (indicatorRect.isValid()) {
2436 if (textAlign & Qt::AlignLeft) {
2437 textRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
2438 }
else if (textAlign & Qt::AlignHCenter) {
2439 textRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
2440 textRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
2442 textRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
2445 if (textAlign & Qt::AlignLeft) {
2446 textRect.setLeft(textRect.left() + metrics.textPadding.left());
2447 }
else if (textAlign & Qt::AlignHCenter) {
2448 textRect.setLeft(textRect.left() + metrics.textPadding.left() / 2);
2449 textRect.setRight(textRect.right() - metrics.textPadding.right() / 2);
2451 textRect.setRight(textRect.right() - metrics.textPadding.right());
2454 if (textAlign & Qt::AlignTop) {
2455 textRect.setTop(textRect.top() + metrics.textPadding.top());
2456 }
else if (textAlign & Qt::AlignVCenter) {
2457 textRect.setTop(textRect.top() + metrics.textPadding.top() / 2);
2458 textRect.setBottom(textRect.bottom() - metrics.textPadding.bottom() / 2);
2460 textRect.setBottom(textRect.bottom() - metrics.textPadding.bottom());
2462 return visualRect(opt->direction, opt->rect, textRect);
2466 case SE_PushButtonFocusRect:
2467 case SE_CheckBoxClickRect:
2468 case SE_RadioButtonClickRect:
2470#if QT_CONFIG(progressbar)
2471 case SE_ProgressBarGroove: {
2472 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar, opt->state);
2473 if (!resolved.isValid())
2475 const auto &metrics = *resolved.metrics;
2476 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2477 const auto *indicator = resolved.indicator();
2478 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2481 const int w = resolvedWidth(indicator,
2482 rect.width() - metrics.padding.left() - metrics.padding.right()
2483 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right());
2484 const int h = resolvedHeight(indicator,
2485 rect.height() - metrics.padding.top() - metrics.padding.bottom()
2486 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom());
2487 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
2488 const QRect indicatorRect = d->getAlignedRectInContainer(
2489 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
2490 return visualRect(opt->direction, rect, indicatorRect);
2492 case SE_ProgressBarContents: {
2493 if (qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
2494 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar, opt->state);
2495 if (!resolved.isValid())
2497 const auto *foreground = resolved.indicator() ? resolved.indicator()->foreground() :
nullptr;
2498 if (!foreground || !foreground->visible() || foreground->opacity() == 0)
2501 QRect indicatorRect = subElementRect(SE_ProgressBarGroove, opt, widget);
2502 const auto foregroundW = resolvedWidth(foreground,
2503 indicatorRect.width() - foreground->leftMargin() - foreground->rightMargin());
2504 const auto foregroundH = resolvedHeight(foreground,
2505 indicatorRect.height() - foreground->topMargin() - foreground->bottomMargin());
2506 const uint foregroundAlign = resolvedAlignment(foreground->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
2507 const QMargins foregroundMargins = elementMargins(foreground);
2508 const QRect foregroundRect = d->getAlignedRectInContainer(
2509 indicatorRect, QSize(foregroundW, foregroundH), foregroundAlign, QMargins(0, 0, 0, 0), foregroundMargins);
2510 return visualRect(opt->direction, opt->rect, foregroundRect);
2515 case SE_LineEditContents:
2516 if (qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
2517#if QT_CONFIG(spinbox)
2518 const bool isInSpinBox = widget && qobject_cast<
const QSpinBox *>(widget->parentWidget());
2520 const bool isInSpinBox =
false;
2522 const auto controlType = isInSpinBox ? QQStyleKitReader::ControlType::SpinBox : QQStyleKitReader::ControlType::TextField;
2523 const auto resolved = d->resolveLayout(controlType, opt->state);
2524 if (!resolved.isValid())
2526 const auto &metrics = *resolved.metrics;
2527 QRect contentsRect = opt->rect.marginsRemoved(metrics.padding);
2528 const auto *textProps = resolved.text();
2529 const uint textAlign = resolvedAlignment(
2530 textProps ? textProps->alignment() : 0u, Qt::AlignLeft, Qt::AlignVCenter);
2531 if (textAlign & Qt::AlignLeft)
2532 contentsRect.setLeft(contentsRect.left() + metrics.textPadding.left());
2533 else if (textAlign & Qt::AlignHCenter) {
2534 contentsRect.setLeft(contentsRect.left() + metrics.textPadding.left() / 2);
2535 contentsRect.setRight(contentsRect.right() - metrics.textPadding.right() / 2);
2537 contentsRect.setRight(contentsRect.right() - metrics.textPadding.right());
2539 if (textAlign & Qt::AlignTop)
2540 contentsRect.setTop(contentsRect.top() + metrics.textPadding.top());
2541 else if (textAlign & Qt::AlignVCenter) {
2542 contentsRect.setTop(contentsRect.top() + metrics.textPadding.top() / 2);
2543 contentsRect.setBottom(contentsRect.bottom() - metrics.textPadding.bottom() / 2);
2545 contentsRect.setBottom(contentsRect.bottom() - metrics.textPadding.bottom());
2547 return visualRect(opt->direction, opt->rect, contentsRect);
2550 case SE_ShapedFrameContents:
2551#if QT_CONFIG(combobox)
2552 if (widget && widget->inherits(
"QComboBoxPrivateContainer")) {
2553 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Popup, opt->state);
2554 if (!resolved.isValid())
2556 const auto &metrics = *resolved.metrics;
2557 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding + metrics.textPadding);
2558 return visualRect(opt->direction, opt->rect, contentsRect);
2561#if QT_CONFIG(textedit)
2562 if (qobject_cast<
const QTextEdit *>(widget)) {
2563 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::TextArea, opt->state);
2564 if (!resolved.isValid())
2566 const auto &metrics = *resolved.metrics;
2567 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding + metrics.textPadding);
2568 return visualRect(opt->direction, opt->rect, contentsRect);
2572#if QT_CONFIG(toolbar)
2573 case SE_ToolBarHandle:
2581 return QCommonStyle::subElementRect(r, opt, widget);
2585void QStyleKitStyle::drawComplexControl(ComplexControl cc,
const QStyleOptionComplex *opt, QPainter *p,
2586 const QWidget *w)
const
2588 Q_D(
const QStyleKitStyle);
2591#if QT_CONFIG(slider)
2593 if (
const QStyleOptionSlider *slider = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
2594 const auto r = d->resolve(w, QQStyleKitReader::ControlType::Slider, slider->state);
2597 const auto &metrics = *r.metrics;
2598 QRect backgroundRect = opt->rect.marginsRemoved(metrics.margins);
2601 d->drawStyledItemRect(r.background(), backgroundRect, p);
2604 if (slider->subControls & SC_SliderGroove) {
2606 const auto grooveRect = proxy()->subControlRect(CC_Slider, opt, SC_SliderGroove, w);
2607 const auto *indicator = r.indicator();
2608 d->drawStyledItemRect(indicator, grooveRect, p);
2611 const auto *foreground = indicator ? indicator->foreground() :
nullptr;
2612 if (foreground && foreground->visible() && foreground->opacity() > 0) {
2613 const bool isHorizontal = slider->orientation == Qt::Horizontal;
2614 const qreal availableW = grooveRect.width() - foreground->leftMargin() - foreground->rightMargin();
2615 const qreal availableH = grooveRect.height() - foreground->topMargin() - foreground->bottomMargin();
2617 const qreal range = slider->maximum - slider->minimum;
2618 const qreal ratio = range > 0 ? (slider->sliderPosition - slider->minimum) / range : 0;
2620 const auto hAlign = foreground->alignment() & Qt::AlignHorizontal_Mask;
2621 const auto vAlign = foreground->alignment() & Qt::AlignVertical_Mask;
2622 const qreal fgW = resolvedWidth(foreground, availableW);
2623 const qreal fgH = resolvedHeight(foreground, availableH);
2624 const qreal fgX = hAlign & Qt::AlignRight
2625 ? grooveRect.left() + foreground->leftMargin() + availableW - fgW
2626 : hAlign & Qt::AlignHCenter
2627 ? grooveRect.left() + foreground->leftMargin() + (availableW - fgW) / 2
2628 : grooveRect.left() + foreground->leftMargin();
2629 const qreal fgY = vAlign & Qt::AlignBottom
2630 ? grooveRect.top() + foreground->topMargin() + availableH - fgH
2631 : vAlign & Qt::AlignVCenter
2632 ? grooveRect.top() + foreground->topMargin() + (availableH - fgH) / 2
2633 : grooveRect.top() + foreground->topMargin();
2635 const qreal minW = foreground->minimumWidth();
2638 const qreal trackW = foreground->fillWidth()
2639 ? minW + ratio * (fgW - minW)
2641 trackRect = QRectF(fgX, fgY, trackW, fgH);
2643 const qreal trackH = foreground->fillHeight()
2644 ? minW + ratio * (fgH - minW)
2646 const qreal trackY = fgY + (1.0 - ratio) * (foreground->fillHeight() ? fgH - minW : fgH);
2647 trackRect = QRectF(fgX, trackY, fgW, trackH);
2649 d->drawStyledItemRect(foreground, visualRect(opt->direction, grooveRect, trackRect.toAlignedRect()), p);
2654 if (slider->subControls & SC_SliderHandle) {
2655 QStyleOptionSlider handleOpt(*slider);
2656 handleOpt.rect = subControlRect(CC_Slider, opt, SC_SliderHandle, w);
2657 const auto *handle = r.handle();
2658 if (handle && handle->visible() && handle->opacity() > 0)
2659 d->drawStyledItemRect(handle, handleOpt.rect, p);
2665#if QT_CONFIG(combobox)
2667 if (
const QStyleOptionComboBox *combo = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
2669 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, combo->state);
2672 QRect frameRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxFrame, w);
2673 d->drawStyledItemRect(r.background(), frameRect, p);
2676 if (combo->subControls & SC_ComboBoxArrow) {
2677 QStyleOptionComboBox indicatorOpt(*combo);
2678 indicatorOpt.rect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
2679 proxy()->drawPrimitive(PE_IndicatorArrowDown, &indicatorOpt, p, w);
2684 if (
auto *cb = qobject_cast<
const QComboBox *>(w); cb && cb->isEditable()) {
2685 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
2686 QPalette stylePalette;
2687 stylePalette.setColor(QPalette::Text, txt->color());
2688 d->setStylePalette(cb->lineEdit(), stylePalette);
2695#if QT_CONFIG(spinbox)
2697 if (
const QStyleOptionSpinBox *spin = qstyleoption_cast<
const QStyleOptionSpinBox *>(opt)) {
2698 const auto r = d->resolve(w, QQStyleKitReader::ControlType::SpinBox, spin->state);
2701 QRect frameRect = opt->rect.marginsRemoved(r.metrics->margins);
2703 d->drawStyledItemRect(r.background(), frameRect, p);
2705 if (spin->subControls & SC_SpinBoxUp) {
2706 QStyleOptionSpinBox upOpt(*spin);
2707 upOpt.rect = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w);
2708 proxy()->drawPrimitive(PE_IndicatorSpinUp, &upOpt, p, w);
2710 if (spin->subControls & SC_SpinBoxDown) {
2711 QStyleOptionSpinBox downOpt(*spin);
2712 downOpt.rect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
2713 proxy()->drawPrimitive(PE_IndicatorSpinDown, &downOpt, p, w);
2717 if (
auto *sb = qobject_cast<
const QSpinBox *>(w)) {
2718 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
2719 QLineEdit *lineEdit = sb->findChild<QLineEdit *>();
2721 QPalette p = lineEdit->palette();
2722 if (p.color(QPalette::Text) != txt->color()) {
2723 p.setColor(QPalette::Text, txt->color());
2724 lineEdit->setPalette(p);
2733#if QT_CONFIG(groupbox)
2735 if (
const QStyleOptionGroupBox *groupBox = qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
2736 const auto r = d->resolve(w, QQStyleKitReader::ControlType::GroupBox, groupBox->state);
2741 if (groupBox->subControls & SC_GroupBoxFrame) {
2742 QStyleOptionFrame frameOpt;
2743 frameOpt.QStyleOption::operator=(*groupBox);
2744 frameOpt.rect = subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, w);
2745 drawPrimitive(PE_FrameGroupBox, &frameOpt, p, w);
2749 if (groupBox->subControls & SC_GroupBoxLabel && !groupBox->text.isEmpty()) {
2750 const auto *textProps = r.text();
2751 const QFont textFont = r.font();
2752 QRect titleRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w);
2753 d->drawControlText(textProps, textFont, titleRect.marginsRemoved(r.metrics->textPadding),
2754 groupBox->text, Qt::TextShowMnemonic, p, Qt::AlignLeft | Qt::AlignVCenter);
2762#if QT_CONFIG(scrollbar)
2764 if (
const auto *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
2765 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ScrollBar, scrollbar->state);
2770 if (scrollbar->subControls & SC_ScrollBarGroove) {
2771 QRect backgroundRect = proxy()->subControlRect(CC_ScrollBar, opt, SC_ScrollBarGroove, w);
2772 d->drawStyledItemRect(r.background(), backgroundRect, p);
2779 if (scrollbar->subControls & SC_ScrollBarSlider) {
2780 QStyleOptionSlider newScrollbar(*scrollbar);
2781 newScrollbar.rect = proxy()->subControlRect(CC_ScrollBar, opt, SC_ScrollBarSlider, w);
2782 proxy()->drawControl(CE_ScrollBarSlider, &newScrollbar, p, w);
2788#if QT_CONFIG(toolbutton)
2790 if (
const QStyleOptionToolButton *tool = qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
2791 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolButton, tool->state);
2796 d->drawStyledItemRect(r.background(), opt->rect, p);
2799 if ((tool->features & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay))
2800 == QStyleOptionToolButton::MenuButtonPopup
2801 && (tool->subControls & SC_ToolButtonMenu)) {
2802 const QRect menuRect = subControlRect(CC_ToolButton, opt, SC_ToolButtonMenu, w);
2803 d->drawControlIndicator(r.indicator(), menuRect, p);
2807 State bflags = tool->state & ~State_Sunken;
2808 if (bflags & State_AutoRaise) {
2809 if (!(bflags & State_MouseOver) || !(bflags & State_Enabled))
2810 bflags &= ~State_Raised;
2812 if (tool->state & State_Sunken && tool->activeSubControls & SC_ToolButton)
2813 bflags |= State_Sunken;
2814 QStyleOptionToolButton label = *tool;
2815 label.state = bflags;
2816 label.rect = subControlRect(CC_ToolButton, opt, SC_ToolButton, w);
2817 proxy()->drawControl(CE_ToolButtonLabel, &label, p, w);
2825 QCommonStyle::drawComplexControl(cc, opt, p, w);
2829QStyle::SubControl QStyleKitStyle::hitTestComplexControl(ComplexControl cc,
const QStyleOptionComplex *opt,
2830 const QPoint &pt,
const QWidget *w)
const
2832 return QCommonStyle::hitTestComplexControl(cc, opt, pt, w);
2836QRect QStyleKitStyle::subControlRect(ComplexControl cc,
const QStyleOptionComplex *opt, SubControl sc,
2837 const QWidget *w)
const
2839 Q_D(
const QStyleKitStyle);
2842#if QT_CONFIG(slider)
2844 if (
const QStyleOptionSlider *slider = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
2845 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Slider, opt->state);
2846 if (!resolved.isValid())
2848 const auto &metrics = *resolved.metrics;
2849 const bool horizontal = slider->orientation == Qt::Horizontal;
2850 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins).marginsRemoved(metrics.padding);
2852 const auto *indicator = resolved.indicator();
2854 return contentsRect;
2856 case SC_SliderGroove: {
2857 const auto availableW = contentsRect.width() - indicator->leftMargin() - indicator->rightMargin();
2858 const auto availableH = contentsRect.height() - indicator->topMargin() - indicator->bottomMargin();
2859 const qreal grooveW = resolvedWidth(indicator, availableW);
2860 const qreal grooveH = resolvedHeight(indicator, availableH);
2862 QRectF grooveRect(0, 0, grooveW, grooveH);
2863 const uint rawHAlign = indicator->alignment() & Qt::AlignHorizontal_Mask;
2864 const uint rawVAlign = indicator->alignment() & Qt::AlignVertical_Mask;
2865 const uint hAlign = rawHAlign ?
static_cast<Qt::Alignment>(rawHAlign) : Qt::AlignLeft;
2866 const uint vAlign = rawVAlign ?
static_cast<Qt::Alignment>(rawVAlign) : Qt::AlignVCenter;
2868 if (hAlign & Qt::AlignLeft) {
2869 grooveRect.moveLeft(contentsRect.x() + indicator->leftMargin());
2870 }
else if (hAlign & Qt::AlignHCenter) {
2871 const int availableWidth = contentsRect.width()
2872 - indicator->leftMargin()
2873 - indicator->rightMargin();
2874 grooveRect.moveLeft(contentsRect.x() + indicator->leftMargin()
2875 + (availableWidth - grooveW) / 2.0);
2877 grooveRect.moveLeft(contentsRect.x() + contentsRect.width()
2878 - indicator->rightMargin() - grooveW);
2881 if (vAlign & Qt::AlignTop) {
2882 grooveRect.moveTop(contentsRect.y() + indicator->topMargin());
2883 }
else if (vAlign & Qt::AlignVCenter) {
2884 const int availableHeight = contentsRect.height()
2885 - indicator->topMargin()
2886 - indicator->bottomMargin();
2887 grooveRect.moveTop(contentsRect.y() + indicator->topMargin()
2888 + (availableHeight - grooveH) / 2.0);
2890 grooveRect.moveTop(contentsRect.y() + contentsRect.height()
2891 - indicator->bottomMargin() - grooveH);
2893 return visualRect(opt->direction, opt->rect, grooveRect.toAlignedRect());
2895 case SC_SliderHandle: {
2896 const auto *handle = resolved.handle();
2897 if (!handle || !handle->visible() || handle->opacity() == 0)
2898 return contentsRect;
2901 const auto handleW = resolvedWidth(handle,
2902 contentsRect.width() - handle->leftMargin() - handle->rightMargin());
2903 const auto handleH = resolvedHeight(handle,
2904 contentsRect.height() - handle->topMargin() - handle->bottomMargin());
2906 const int range = contentsRect.width()
2907 - handle->leftMargin() - handle->rightMargin() - handleW;
2908 const int sliderPos = QStyle::sliderPositionFromValue(
2909 slider->minimum, slider->maximum, slider->sliderPosition, range,
false);
2911 contentsRect.x() + handle->leftMargin() + sliderPos,
2912 contentsRect.y() + handle->topMargin() - handle->bottomMargin()
2913 + (contentsRect.height() - handleH) / 2,
2916 const int range = contentsRect.height()
2917 - handle->topMargin() - handle->bottomMargin() - handleH;
2918 const int sliderPos = QStyle::sliderPositionFromValue(
2919 slider->minimum, slider->maximum, slider->sliderPosition, range,
true);
2921 contentsRect.x() + handle->leftMargin() - handle->rightMargin()
2922 + (contentsRect.width() - handleW) / 2,
2923 contentsRect.y() + handle->topMargin() + sliderPos,
2926 return visualRect(opt->direction, opt->rect, handleRect);
2934#if QT_CONFIG(combobox)
2936 if (
const QStyleOptionComboBox *combo = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
2937 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::ComboBox, combo->state);
2940 const auto &metrics = *r.metrics;
2941 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
2943 case SC_ComboBoxFrame:
2944 return visualRect(opt->direction, opt->rect, frameRect);
2945 case SC_ComboBoxEditField: {
2946 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
2947 QRect indicatorRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
2948 const int spacing = metrics.spacing;
2949 const auto *indicator = r.indicator();
2950 const uint indicatorAlign = indicator
2951 ? resolvedAlignment(indicator->alignment(), Qt::AlignRight, Qt::AlignVCenter)
2952 : uint(Qt::AlignRight | Qt::AlignVCenter);
2953 if (indicatorAlign & Qt::AlignLeft) {
2954 contentsRect.setLeft(indicatorRect.right() + spacing);
2955 }
else if (indicatorAlign & Qt::AlignRight) {
2956 contentsRect.setRight(indicatorRect.left() - spacing);
2958 return visualRect(opt->direction, opt->rect, contentsRect);
2960 case SC_ComboBoxArrow: {
2961 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
2962 const auto *indicator = r.indicator();
2963 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2966 const int w = resolvedWidth(indicator,
2967 contentsRect.width() - indicator->leftMargin() - indicator->rightMargin());
2968 const int h = resolvedHeight(indicator,
2969 contentsRect.height() - indicator->topMargin() - indicator->bottomMargin());
2970 const uint indicatorAlign = resolvedAlignment(indicator->alignment(), Qt::AlignRight, Qt::AlignVCenter);
2971 const QMargins indicatorMargins = elementMargins(indicator);
2972 return visualRect(opt->direction, opt->rect,
2973 d->getAlignedRectInContainer(contentsRect, QSize(w, h), indicatorAlign, QMargins(), indicatorMargins));
2975 case SC_ComboBoxListBoxPopup: {
2976 QRect popupRect = opt->rect;
2977 popupRect.setTop(opt->rect.bottom());
2978 return visualRect(opt->direction, opt->rect, popupRect);
2986#if QT_CONFIG(spinbox)
2988 if (
const QStyleOptionSpinBox *spinBox = qstyleoption_cast<
const QStyleOptionSpinBox *>(opt)) {
2989 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::SpinBox, spinBox->state);
2992 const auto &metrics = *r.metrics;
2993 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
2994 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
2996 case SC_SpinBoxFrame:
2997 return visualRect(opt->direction, opt->rect, frameRect);
2998 case SC_SpinBoxEditField: {
2999 QRect upIndicatorRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w);
3000 QRect downIndicatorRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
3001 const int spacing = metrics.spacing;
3002 const auto *upIndicator = r.indicator() ? r.indicator()->first() :
nullptr;
3003 const auto *downIndicator = r.indicator() ? r.indicator()->second() :
nullptr;
3004 const bool hasUpIndicator = upIndicator && upIndicator->visible() && upIndicator->opacity() > 0;
3005 const bool hasDownIndicator = downIndicator && downIndicator->visible() && downIndicator->opacity() > 0;
3006 const uint upAlign = hasUpIndicator
3007 ? resolvedAlignment(upIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
3008 : uint(Qt::AlignLeft | Qt::AlignVCenter);
3009 const uint downAlign = hasDownIndicator
3010 ? resolvedAlignment(downIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
3011 : uint(Qt::AlignLeft | Qt::AlignVCenter);
3012 if (hasUpIndicator && hasDownIndicator) {
3013 if ((upAlign & Qt::AlignLeft) && (downAlign & Qt::AlignRight)) {
3014 contentsRect.setLeft(upIndicatorRect.right() + spacing);
3015 contentsRect.setRight(downIndicatorRect.left() - spacing);
3016 }
else if ((upAlign & Qt::AlignRight) && (downAlign & Qt::AlignLeft)) {
3017 contentsRect.setRight(upIndicatorRect.left() - spacing);
3018 contentsRect.setLeft(downIndicatorRect.right() + spacing);
3020 }
else if (hasUpIndicator) {
3021 if (upAlign & Qt::AlignLeft) {
3022 contentsRect.setLeft(upIndicatorRect.right() + spacing);
3023 }
else if (upAlign & Qt::AlignRight) {
3024 contentsRect.setRight(upIndicatorRect.left() - spacing);
3026 }
else if (hasDownIndicator) {
3027 if (downAlign & Qt::AlignLeft) {
3028 contentsRect.setLeft(downIndicatorRect.right() + spacing);
3029 }
else if (downAlign & Qt::AlignRight) {
3030 contentsRect.setRight(downIndicatorRect.left() - spacing);
3033 return visualRect(opt->direction, opt->rect, contentsRect);
3035 case SC_SpinBoxUp: {
3036 const auto *upIndicator = r.indicator() ? r.indicator()->first() :
nullptr;
3037 if (!upIndicator || !upIndicator->visible() || upIndicator->opacity() == 0)
3038 return contentsRect;
3040 const int w = resolvedWidth(upIndicator,
3041 contentsRect.width() - upIndicator->leftMargin() - upIndicator->rightMargin());
3042 const int h = resolvedHeight(upIndicator,
3043 contentsRect.height() - upIndicator->topMargin() - upIndicator->bottomMargin());
3044 const uint upAlign = resolvedAlignment(upIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
3045 const QMargins upMargins = elementMargins(upIndicator);
3046 return visualRect(opt->direction, opt->rect,
3047 d->getAlignedRectInContainer(contentsRect, QSize(w, h), upAlign, QMargins(), upMargins));
3049 case SC_SpinBoxDown: {
3050 const auto *downIndicator = r.indicator() ? r.indicator()->second() :
nullptr;
3051 if (!downIndicator || !downIndicator->visible() || downIndicator->opacity() == 0)
3054 const int w = resolvedWidth(downIndicator,
3055 contentsRect.width() - downIndicator->leftMargin() - downIndicator->rightMargin());
3056 const int h = resolvedHeight(downIndicator,
3057 contentsRect.height() - downIndicator->topMargin() - downIndicator->bottomMargin());
3058 const uint downAlign = resolvedAlignment(downIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
3059 const QMargins downMargins = elementMargins(downIndicator);
3060 return visualRect(opt->direction, opt->rect,
3061 d->getAlignedRectInContainer(contentsRect, QSize(w, h), downAlign, QMargins(), downMargins));
3069#if QT_CONFIG(groupbox)
3071 if (
const QStyleOptionGroupBox *groupBox = qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
3072 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::GroupBox, groupBox->state);
3075 const auto &metrics = *r.metrics;
3076 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3078 case SC_GroupBoxFrame:
3079 return visualRect(opt->direction, opt->rect, frameRect);
3080 case SC_GroupBoxLabel: {
3081 const int fontHeight = opt->fontMetrics.height();
3082 const int labelHeight = metrics.textPadding.top() + fontHeight
3083 + metrics.textPadding.bottom();
3084 const QRect labelContainer(opt->rect.left(), opt->rect.top(),
3087 return visualRect(opt->direction, opt->rect, labelContainer);
3089 case SC_GroupBoxCheckBox: {
3093 case SC_GroupBoxContents: {
3094 const auto labelHeight = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w).height();
3095 const auto offset = metrics.padding.top() + qMax(labelHeight, metrics.margins.top() + metrics.spacing);
3096 QRect contentsRect(opt->rect.left() + metrics.padding.left(),
3097 opt->rect.top() + offset,
3098 opt->rect.width() - metrics.padding.left() - metrics.padding.right(),
3099 opt->rect.bottom() - opt->rect.top() - offset - metrics.padding.bottom());
3100 return visualRect(opt->direction, opt->rect, contentsRect);
3108#if QT_CONFIG(scrollbar)
3110 if (
const auto *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3111 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ScrollBar, opt->state);
3112 if (!resolved.isValid())
3114 const auto &metrics = *resolved.metrics;
3115 const bool horizontal = scrollbar->orientation == Qt::Horizontal;
3116 const QRectF grooveRect = opt->rect.marginsRemoved(metrics.margins);
3120 case SC_ScrollBarAddLine:
3121 case SC_ScrollBarSubLine:
3122 case SC_ScrollBarSubPage:
3123 case SC_ScrollBarAddPage:
3125 case SC_ScrollBarGroove:
3126 return visualRect(opt->direction, opt->rect, grooveRect.toAlignedRect());
3127 case SC_ScrollBarSlider: {
3128 const auto *indicator = resolved.indicator();
3129 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
3131 const QRectF contentsRect = grooveRect.marginsRemoved(metrics.padding);
3133 const qreal availableW = contentsRect.width() - indicator->leftMargin() - indicator->rightMargin();
3134 const qreal availableH = contentsRect.height() - indicator->topMargin() - indicator->bottomMargin();
3136 const int totalRange = scrollbar->maximum - scrollbar->minimum + scrollbar->pageStep;
3137 const qreal ratio = totalRange > 0 ? qreal(scrollbar->pageStep) / totalRange : 1.0;
3141 const qreal sliderW = qMax(qreal(metrics.indicatorImplicitSize.width()), availableW * ratio);
3142 const qreal sliderH = resolvedHeight(indicator, availableH);
3143 const qreal travelRange = qMax(0.0, availableW - sliderW);
3144 const int sliderPos = QStyle::sliderPositionFromValue(
3145 scrollbar->minimum, scrollbar->maximum,
3146 scrollbar->sliderPosition,
int(travelRange), scrollbar->upsideDown);
3147 sliderRect = QRectF(
3148 contentsRect.x() + indicator->leftMargin() + sliderPos,
3149 contentsRect.y() + indicator->topMargin() + (availableH - sliderH) / 2.0,
3152 const qreal sliderH = qMax(qreal(metrics.indicatorImplicitSize.width()), availableH * ratio);
3153 const qreal sliderW = resolvedWidth(indicator, availableW);
3154 const qreal travelRange = qMax(0.0, availableH - sliderH);
3155 const int sliderPos = QStyle::sliderPositionFromValue(
3156 scrollbar->minimum, scrollbar->maximum,
3157 scrollbar->sliderPosition,
int(travelRange), scrollbar->upsideDown);
3158 sliderRect = QRectF(
3159 contentsRect.x() + indicator->leftMargin() + (availableW - sliderW) / 2.0,
3160 contentsRect.y() + indicator->topMargin() + sliderPos,
3163 return visualRect(opt->direction, opt->rect, sliderRect.toAlignedRect());
3171#if QT_CONFIG(toolbutton)
3173 if (
const auto *tool = qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
3174 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolButton, opt->state);
3175 if (!resolved.isValid())
3177 const auto &metrics = *resolved.metrics;
3178 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3180 case SC_ToolButton: {
3181 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3182 const bool hasMenuButton = (tool->features
3183 & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::HasMenu))
3185 const auto *indicator = resolved.indicator();
3186 if (hasMenuButton && indicator && indicator->visible() && indicator->opacity() > 0) {
3187 const QRect menuRect = subControlRect(CC_ToolButton, opt, SC_ToolButtonMenu, w);
3188 const int spacing = metrics.spacing;
3189 const uint indicatorAlign = resolvedAlignment(indicator->alignment(),
3190 Qt::AlignRight, Qt::AlignVCenter);
3191 if (indicatorAlign & Qt::AlignLeft)
3192 contentsRect.setLeft(menuRect.right() + spacing);
3193 else if (indicatorAlign & Qt::AlignRight)
3194 contentsRect.setRight(menuRect.left() - spacing);
3196 return visualRect(opt->direction, opt->rect, contentsRect);
3198 case SC_ToolButtonMenu: {
3199 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3201 & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay))
3202 != QStyleOptionToolButton::MenuButtonPopup)
3205 const auto *indicator = resolved.indicator();
3206 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
3209 const int w = resolvedWidth(indicator,
3210 contentsRect.width() - indicator->leftMargin() - indicator->rightMargin());
3211 const int h = resolvedHeight(indicator,
3212 contentsRect.height() - indicator->topMargin() - indicator->bottomMargin());
3213 const uint indicatorAlign = resolvedAlignment(indicator->alignment(), Qt::AlignRight, Qt::AlignVCenter);
3214 const QMargins indicatorMargins = elementMargins(indicator);
3215 return visualRect(opt->direction, opt->rect,
3216 d->getAlignedRectInContainer(contentsRect, QSize(w, h), indicatorAlign, QMargins(), indicatorMargins));
3227 return QCommonStyle::subControlRect(cc, opt, sc, w);
3231QSize QStyleKitStyle::sizeFromContents(ContentsType ct,
const QStyleOption *opt,
3232 const QSize &contentsSize,
const QWidget *widget)
const
3234 Q_D(
const QStyleKitStyle);
3237#if QT_CONFIG(pushbutton)
3240#if QT_CONFIG(toolbutton)
3241 case CT_ToolButton: {
3242 auto controlType = QQStyleKitReader::ControlType::ToolButton;
3243 if (
const auto *buttonOpt = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
3244 controlType = (buttonOpt->features & QStyleOptionButton::Flat)
3245 ? QQStyleKitReader::ControlType::FlatButton
3246 : QQStyleKitReader::ControlType::Button;
3248 const auto resolved = d->resolveLayout(controlType, opt->state);
3249 if (!resolved.isValid())
3252 const auto &metrics = *resolved.metrics;
3253 const QSize contentSize = contentsSize
3254 + QSize(metrics.padding.left() + metrics.padding.right(),
3255 metrics.padding.top() + metrics.padding.bottom())
3256 + QSize(metrics.textPadding.left() + metrics.textPadding.right(),
3257 metrics.textPadding.top() + metrics.textPadding.bottom());
3258 const QSize bgSize = metrics.bgImplicitSize
3259 + QSize(metrics.margins.left() + metrics.margins.right(),
3260 metrics.margins.top() + metrics.margins.bottom());
3261 return contentSize.expandedTo(bgSize);
3265 case CT_RadioButton:
3266 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
3267 const auto controlType = ct == CT_CheckBox ? QQStyleKitReader::ControlType::CheckBox
3268 : QQStyleKitReader::ControlType::RadioButton;
3269 const auto resolved = d->resolveLayout(controlType, opt->state);
3270 if (!resolved.isValid())
3272 const auto &metrics = *resolved.metrics;
3273 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, btn->text);
3274 const int bgWidth = metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right();
3275 const int bgHeight = metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom();
3276 const int contentWidth = std::max(textSize.width(), contentsSize.width()) + metrics.padding.left() + metrics.padding.right()
3277 + metrics.textPadding.left() + metrics.textPadding.right();
3278 const int contentHeight = std::max(textSize.height(), contentsSize.height()) + metrics.padding.top() + metrics.padding.bottom()
3279 + metrics.textPadding.top() + metrics.textPadding.bottom();
3280 const int indicatorWidth = metrics.indicatorImplicitSize.width() + metrics.indicatorMargins.left()
3281 + metrics.indicatorMargins.right();
3282 const int indicatorHeight = metrics.indicatorImplicitSize.height() + metrics.indicatorMargins.top()
3283 + metrics.indicatorMargins.bottom();
3284 return QSize(std::max({contentWidth + indicatorWidth + metrics.spacing, bgWidth}),
3285 std::max({contentHeight, indicatorHeight, bgHeight}));
3288#if QT_CONFIG(itemviews)
3289 case CT_ItemViewItem:
3290 if (
const auto *item = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
3291 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ItemDelegate, opt->state);
3292 if (!resolved.isValid())
3294 const auto &metrics = *resolved.metrics;
3295 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, item->text);
3296 const int bgWidth = metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right();
3297 const int bgHeight = metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom();
3298 const int contentWidth = std::max(textSize.width(), contentsSize.width()) + metrics.padding.left() + metrics.padding.right()
3299 + metrics.textPadding.left() + metrics.textPadding.right();
3300 const int contentHeight = std::max(textSize.height(), contentsSize.height()) + metrics.padding.top() + metrics.padding.bottom()
3301 + metrics.textPadding.top() + metrics.textPadding.bottom();
3302 const int indicatorWidth = metrics.indicatorImplicitSize.width() + metrics.indicatorMargins.left()
3303 + metrics.indicatorMargins.right();
3304 const int indicatorHeight = metrics.indicatorImplicitSize.height() + metrics.indicatorMargins.top()
3305 + metrics.indicatorMargins.bottom();
3306 return QSize(std::max({contentWidth + indicatorWidth + metrics.spacing, bgWidth}),
3307 std::max({contentHeight, indicatorHeight, bgHeight}));
3311 case CT_ProgressBar:
3312 if (qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
3313 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar, opt->state);
3314 if (!resolved.isValid())
3316 const auto &metrics = *resolved.metrics;
3317 const auto indicatorW = std::max(metrics.indicatorImplicitSize.width()
3318 + metrics.indicatorMargins.left()
3319 + metrics.indicatorMargins.right(),
3320 metrics.foregroundImplicitSize.width()
3321 + metrics.foregroundMargins.left()
3322 + metrics.foregroundMargins.right());
3323 const auto indicatorH = std::max(metrics.indicatorImplicitSize.height()
3324 + metrics.indicatorMargins.top()
3325 + metrics.indicatorMargins.bottom(),
3326 metrics.foregroundImplicitSize.height()
3327 + metrics.foregroundMargins.top()
3328 + metrics.foregroundMargins.bottom());
3329 const int bgW = metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right();
3330 const int bgH = metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom();
3332 const int contentW = indicatorW + metrics.padding.left() + metrics.padding.right();
3333 const int contentH = indicatorH + metrics.padding.top() + metrics.padding.bottom();
3334 return QSize(std::max(contentW, bgW), std::max(contentH, bgH));
3338 if (qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3339 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Slider, opt->state);
3340 if (!resolved.isValid())
3342 const auto &metrics = *resolved.metrics;
3344 const int bgW = std::max(
3345 metrics.padding.left() + metrics.padding.right()
3346 + metrics.indicatorImplicitSize.width()
3347 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right(),
3348 metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right());
3349 const int bgH = std::max(
3350 metrics.padding.top() + metrics.padding.bottom()
3351 + metrics.indicatorImplicitSize.height()
3352 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom(),
3353 metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom());
3354 const int handleW = metrics.handleImplicitSize.width() + metrics.padding.left() + metrics.padding.right();
3355 const int handleH = metrics.handleImplicitSize.height() + metrics.padding.top() + metrics.padding.bottom();
3356 return QSize(std::max(handleW, bgW), std::max(handleH, bgH));
3359#if QT_CONFIG(lineedit)
3361 if (
const auto *lineEdit = qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
3362 QStyleOption lineEditOpt(*lineEdit);
3363 lineEditOpt.state &= ~QStyle::State_Sunken;
3364#if QT_CONFIG(spinbox)
3365 const bool isInSpinBox = widget && qobject_cast<
const QSpinBox *>(widget->parent());
3367 const bool isInSpinBox =
false;
3369 auto controlType = isInSpinBox ? QQStyleKitReader::ControlType::SpinBox : QQStyleKitReader::ControlType::TextField;
3370 const auto resolved = d->resolveLayout(controlType, lineEditOpt.state);
3371 if (!resolved.isValid())
3373 const auto &metrics = *resolved.metrics;
3377 bgSize = metrics.bgImplicitSize.grownBy(metrics.margins);
3378 const QSize contentSizeWithPadding = contentsSize.grownBy(metrics.textPadding).grownBy(metrics.padding);
3379 return contentSizeWithPadding.expandedTo(bgSize);
3383#if QT_CONFIG(combobox)
3385 if (
const auto *comboBox = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
3386 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ComboBox, opt->state);
3387 if (!resolved.isValid())
3389 const auto &metrics = *resolved.metrics;
3390 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, comboBox->currentText);
3391 const int bgW = metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right();
3392 const int bgH = metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom();
3393 const int contentW = textSize.width() + metrics.padding.left() + metrics.padding.right()
3394 + metrics.textPadding.left() + metrics.textPadding.right();
3395 const int contentH = textSize.height() + metrics.padding.top() + metrics.padding.bottom()
3396 + metrics.textPadding.top() + metrics.textPadding.bottom();
3397 const int indicatorW = metrics.indicatorImplicitSize.width() + metrics.indicatorMargins.left()
3398 + metrics.indicatorMargins.right();
3399 const int indicatorH = metrics.indicatorImplicitSize.height() + metrics.indicatorMargins.top()
3400 + metrics.indicatorMargins.bottom();
3401 return QSize(std::max({contentW + indicatorW + metrics.spacing, bgW}),
3402 std::max({contentH, indicatorH, bgH}));
3406#if QT_CONFIG(spinbox)
3408 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::SpinBox, opt->state);
3409 if (!resolved.isValid())
3411 const auto &metrics = *resolved.metrics;
3412 const int bgW = metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right();
3413 const int bgH = metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom();
3414 const int contentW = contentsSize.width() + metrics.padding.left() + metrics.padding.right()
3415 + metrics.textPadding.left() + metrics.textPadding.right();
3416 const int contentH = contentsSize.height() + metrics.padding.top() + metrics.padding.bottom()
3417 + metrics.textPadding.top() + metrics.textPadding.bottom();
3420 const int indicatorW = (metrics.indicatorImplicitSize.width() + metrics.indicatorMargins.left()
3421 + metrics.indicatorMargins.right()) * 2;
3422 const int indicatorH = metrics.indicatorImplicitSize.height() + metrics.indicatorMargins.top()
3423 + metrics.indicatorMargins.bottom();
3424 return QSize(std::max({contentW + indicatorW + metrics.spacing, bgW}),
3425 std::max({contentH, indicatorH, bgH}));
3428#if QT_CONFIG(groupbox)
3430 if (
const auto *groupBox = qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
3431 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::GroupBox, opt->state);
3432 if (!resolved.isValid())
3434 const auto &metrics = *resolved.metrics;
3435 const QSize bgSize = metrics.bgImplicitSize + QSize(metrics.margins.left() + metrics.margins.right(),
3436 metrics.margins.top() + metrics.margins.bottom());
3437 const QSize contentSize = contentsSize.grownBy(metrics.padding);
3438 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, groupBox->text).grownBy(metrics.textPadding);
3439 return textSize.expandedTo(contentSize).expandedTo(bgSize);
3443#if QT_CONFIG(scrollbar)
3445 if (qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3446 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ScrollBar, opt->state);
3447 if (!resolved.isValid())
3449 const auto &metrics = *resolved.metrics;
3451 const int iH = metrics.indicatorImplicitSize.height()
3452 + metrics.padding.top() + metrics.padding.bottom()
3453 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
3454 const int iW = metrics.indicatorImplicitSize.width()
3455 + metrics.padding.left() + metrics.padding.right()
3456 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
3457 const int bgH = metrics.bgImplicitSize.height()
3458 + metrics.margins.top() + metrics.margins.bottom();
3459 const int bgW = metrics.bgImplicitSize.width()
3460 + metrics.margins.left() + metrics.margins.right();
3461 return QSize(std::max(iW, bgW), std::max(iH, bgH));
3467 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
3471 const auto menuType = widget && widget->inherits(
"QComboBoxPrivateContainer")
3472 ? QQStyleKitReader::ControlType::Popup
3473 : QQStyleKitReader::ControlType::Menu;
3474 const auto menuResolved = d->resolveLayout(menuType, opt->state);
3476 if (menuResolved.isValid()) {
3477 const auto &mm = *menuResolved.metrics;
3478 minMenuW = mm.bgImplicitSize.width() + mm.margins.left() + mm.margins.right()
3479 - 2 * mm.padding.left();
3482 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
3483 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuSeparator, opt->state);
3484 if (!resolved.isValid())
3486 const auto &m = *resolved.metrics;
3487 const int bgWidth = m.bgImplicitSize.width() + m.margins.left() + m.margins.right();
3488 const int bgHeight = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
3489 return QSize(std::max(bgWidth, minMenuW), bgHeight);
3492 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuItem, opt->state);
3493 if (!resolved.isValid())
3495 const auto &m = *resolved.metrics;
3496 const auto *indicator = resolved.indicator();
3497 const auto *first = indicator ? indicator->first() :
nullptr;
3498 const auto *second = indicator ? indicator->second() :
nullptr;
3499 int indicatorWidth = 0;
3500 int indicatorHeight = 0;
3501 if (first && menuItem->checkType != QStyleOptionMenuItem::NotCheckable) {
3502 indicatorWidth += first->leftMargin() + first->width() + first->rightMargin() + m.spacing;
3503 indicatorHeight = std::max(indicatorHeight, (
int)(first->topMargin() + first->height() + first->bottomMargin()));
3505 if (second && menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {
3506 indicatorWidth += second->leftMargin() + second->width() + second->rightMargin() + m.spacing;
3507 indicatorHeight = std::max(indicatorHeight, (
int)(second->topMargin() + second->height() + second->bottomMargin()));
3509 const int bgHeight = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
3510 const int iconReserved = menuItem->maxIconWidth > 0 ? menuItem->maxIconWidth + m.spacing : 0;
3511 const int contentWidth = contentsSize.width() + m.padding.left() + m.padding.right()
3512 + m.textPadding.left() + m.textPadding.right()
3513 + indicatorWidth + iconReserved;
3514 const int contentHeight = contentsSize.height() + m.padding.top() + m.padding.bottom()
3515 + m.textPadding.top() + m.textPadding.bottom();
3516 return QSize(std::max(contentWidth, minMenuW),
3517 std::max({contentHeight, indicatorHeight, bgHeight}));
3521 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Menu, opt->state);
3522 if (!resolved.isValid())
3524 const auto &m = *resolved.metrics;
3525 const int height = std::max(contentsSize.height(), m.bgImplicitSize.height())
3526 + m.margins.top() + m.margins.bottom();
3527 return QSize(contentsSize.width(), height);
3530#if QT_CONFIG(menubar)
3532 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuBar, opt->state);
3533 if (!resolved.isValid())
3535 const auto &m = *resolved.metrics;
3536 const int bgWidth = m.bgImplicitSize.width() + m.margins.left() + m.margins.right();
3537 const int bgHeight = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
3538 const int contentW = contentsSize.width() + m.padding.left() + m.padding.right();
3539 const int contentH = contentsSize.height() + m.padding.top() + m.padding.bottom();
3540 return QSize(std::max(contentW, bgWidth), std::max(contentH, bgHeight));
3542 case CT_MenuBarItem: {
3543 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuBarItem, opt->state);
3544 if (!resolved.isValid())
3546 const auto &m = *resolved.metrics;
3547 const int bgWidth = m.bgImplicitSize.width() + m.margins.left() + m.margins.right();
3548 const int bgHeight = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
3549 const int contentW = contentsSize.width() + m.padding.left() + m.padding.right()
3550 + m.textPadding.left() + m.textPadding.right();
3551 const int contentH = contentsSize.height() + m.padding.top() + m.padding.bottom()
3552 + m.textPadding.top() + m.textPadding.bottom();
3553 return QSize(std::max(contentW, bgWidth), std::max(contentH, bgHeight));
3559 return QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget);
3563int QStyleKitStyle::pixelMetric(PixelMetric m,
const QStyleOption *opt,
const QWidget *widget)
const
3565 Q_D(
const QStyleKitStyle);
3568 case PM_MenuPanelWidth:
3571 case PM_MenuTearoffHeight:
3572 case PM_MenuScrollerHeight:
3574 case PM_MenuHMargin:
3575 case PM_MenuVMargin: {
3576 const auto controlType = widget && widget->inherits(
"QComboBoxPrivateContainer")
3577 ? QQStyleKitReader::ControlType::Popup
3578 : QQStyleKitReader::ControlType::Menu;
3579 const auto resolved = d->resolveLayout(controlType, opt ? opt->state : QStyle::State_None);
3580 if (!resolved.isValid())
3582 return m == PM_MenuHMargin ? resolved.metrics->padding.left()
3583 : resolved.metrics->padding.top();
3586#if QT_CONFIG(menubar)
3587 case PM_MenuBarItemSpacing: {
3588 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuBarItem,
3589 opt ? opt->state : QStyle::State_None);
3590 if (resolved.isValid())
3591 return resolved.metrics->spacing;
3595#if QT_CONFIG(toolbar)
3596 case PM_ToolBarFrameWidth:
3599 case PM_ToolBarItemMargin: {
3600 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolBar,
3601 opt ? opt->state : QStyle::State_None);
3602 if (!resolved.isValid())
3604 return resolved.metrics->padding.left();
3606 case PM_ToolBarItemSpacing: {
3607 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolBar,
3608 opt ? opt->state : QStyle::State_None);
3609 if (resolved.isValid())
3610 return resolved.metrics->spacing;
3613 case PM_ToolBarHandleExtent: {
3616 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolBar,
3617 opt ? opt->state : QStyle::State_None);
3618 if (!resolved.isValid())
3620 const auto &metrics = *resolved.metrics;
3621 const bool horizontal = !opt || (opt->state & State_Horizontal);
3622 const int crossImplicit = horizontal ? metrics.bgImplicitSize.height() : metrics.bgImplicitSize.width();
3623 const int crossMargins = horizontal ? metrics.margins.top() + metrics.margins.bottom()
3624 : metrics.margins.left() + metrics.margins.right();
3625 const int crossPadding = horizontal ? metrics.padding.top() + metrics.padding.bottom()
3626 : metrics.padding.left() + metrics.padding.right();
3627 return qMax(0, crossImplicit + crossMargins - crossPadding);
3633 return QCommonStyle::pixelMetric(m, opt, widget);
3637int QStyleKitStyle::styleHint(StyleHint sh,
const QStyleOption *opt,
const QWidget *w,
3638 QStyleHintReturn *shret)
const
3642 case SH_SpinBox_SelectOnStep:
3643 case SH_ToolBar_Movable:
3645 case SH_Menu_MouseTracking:
3646 case SH_MenuBar_MouseTracking:
3647 case SH_Menu_Scrollable:
3652 return QCommonStyle::styleHint(sh, opt, w, shret);
3656QPalette QStyleKitStyle::standardPalette()
const
3658 return QCommonStyle::standardPalette();
3662void QStyleKitStyle::polish(QWidget *widget)
3667 Q_D(QStyleKitStyle);
3672 d->ensureDefaultStyle();
3674 widget->setAttribute(Qt::WA_Hover);
3676#if QT_CONFIG(scrollbar)
3680 if (qobject_cast<QScrollBar *>(widget))
3681 widget->setAttribute(Qt::WA_OpaquePaintEvent,
false);
3685 const bool isInteractiveControl =
false
3686#if QT_CONFIG(pushbutton)
3687 || qobject_cast<
const QPushButton *>(widget)
3689#if QT_CONFIG(checkbox)
3690 || qobject_cast<
const QCheckBox *>(widget)
3692#if QT_CONFIG(radiobutton)
3693 || qobject_cast<
const QRadioButton *>(widget)
3695#if QT_CONFIG(combobox)
3696 || qobject_cast<
const QComboBox *>(widget)
3697 || (widget && widget->inherits(
"QComboBoxPrivateContainer"))
3699#if QT_CONFIG(lineedit)
3700 || qobject_cast<
const QLineEdit *>(widget)
3702#if QT_CONFIG(textedit)
3703 || qobject_cast<
const QTextEdit *>(widget)
3704 || qobject_cast<
const QPlainTextEdit *>(widget)
3707 || qobject_cast<
const QLabel *>(widget)
3709#if QT_CONFIG(progressbar)
3710 || qobject_cast<
const QProgressBar *>(widget)
3712#if QT_CONFIG(slider)
3713 || qobject_cast<
const QSlider *>(widget)
3715#if QT_CONFIG(scrollbar)
3716 || qobject_cast<
const QScrollBar *>(widget)
3718#if QT_CONFIG(spinbox)
3719 || qobject_cast<
const QSpinBox *>(widget)
3721#if QT_CONFIG(tabbar)
3722 || qobject_cast<
const QTabBar *>(widget)
3725 || qobject_cast<
const QMenu *>(widget)
3726 || qobject_cast<
const QMenuBar *>(widget)
3729 if (isInteractiveControl)
3730 d->readerForWidget(widget);
3735 if (QWidget *vp = managedViewport(widget); vp && vp->autoFillBackground()) {
3736 vp->setAutoFillBackground(
false);
3737 d->bgFillDisabledWidgets.insert(widget);
3740 if (qobject_cast<QMenu *>(widget)
3741# if QT_CONFIG(combobox)
3742 || widget->inherits(
"QComboBoxPrivateContainer")
3747 if (!widget->testAttribute(Qt::WA_TranslucentBackground)) {
3748 widget->setAttribute(Qt::WA_TranslucentBackground,
true);
3749 d->bgFillDisabledWidgets.insert(widget);
3754#if QT_CONFIG(lineedit)
3755 if (
auto *lineEdit = qobject_cast<QLineEdit *>(widget)) {
3756 if (!lineEdit->property(
"_q_stylekit_alignment_set").toBool()) {
3757 QQStyleKitReader *r = d->readerForWidget(widget);
3759 const QWidget *target = containerWidget(widget);
3760 QQStyleKitReader::ControlType ct = controlTypeForWidget(target);
3761 r->setControlType(ct);
3762 const auto *textProps = r->global()->text();
3764 const uint align = resolvedAlignment(
3765 textProps->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
3766 lineEdit->setAlignment(Qt::Alignment(align));
3773 d->refreshStyleFont(widget);
3774 d->refreshStylePalette(widget);
3776 bool needsEventFilter = isSelfPaintingWidget(widget);
3779 needsEventFilter = needsEventFilter || qobject_cast<QMenu *>(widget);
3781 if (needsEventFilter)
3782 widget->installEventFilter(
this);
3784 QCommonStyle::polish(widget);
3788void QStyleKitStyle::polish(QApplication *app)
3790 QCommonStyle::polish(app);
3794void QStyleKitStyle::polish(QPalette &palette)
3796 QCommonStyle::polish(palette);
3800void QStyleKitStyle::unpolish(QWidget *widget)
3802 Q_D(QStyleKitStyle);
3803 d->unsetStylePalette(widget);
3804 d->unsetStyleFont(widget);
3805 bool hasEventFilter = isSelfPaintingWidget(widget);
3807 hasEventFilter = hasEventFilter || qobject_cast<QMenu *>(widget);
3810 widget->removeEventFilter(
this);
3811 if (d->bgFillDisabledWidgets.remove(widget)) {
3812 if (QWidget *vp = managedViewport(widget))
3813 vp->setAutoFillBackground(
true);
3815 else if (qobject_cast<QMenu *>(widget)
3816# if QT_CONFIG(combobox)
3817 || widget->inherits(
"QComboBoxPrivateContainer")
3820 widget->setAttribute(Qt::WA_TranslucentBackground,
false);
3824 d->cleanupWidgetReader(widget);
3825#if QT_CONFIG(scrollbar)
3826 if (qobject_cast<QScrollBar *>(widget))
3827 widget->setAttribute(Qt::WA_OpaquePaintEvent);
3829 QCommonStyle::unpolish(widget);
3833void QStyleKitStyle::unpolish(QApplication *app)
3835 Q_D(QStyleKitStyle);
3836 d->clearMetricsCache();
3837 QCommonStyle::unpolish(app);
3841bool QStyleKitStyle::eventFilter(QObject *obj, QEvent *event)
3843 Q_D(QStyleKitStyle);
3844 switch (event->type()) {
3845 case QEvent::EnabledChange:
3846 case QEvent::HoverEnter:
3847 case QEvent::HoverLeave:
3848 case QEvent::FocusIn:
3849 case QEvent::FocusOut:
3850 if (
auto *w = qobject_cast<QWidget *>(obj)) {
3851 if (d->customPaletteWidgets.contains(w))
3852 d->refreshStylePalette(w);
3853 if (d->customFontWidgets.contains(w))
3854 d->refreshStyleFont(w);
3859 if (
auto *menu = qobject_cast<QMenu *>(obj))
3860 d->cleanupSubElements(menu);
3866 return QCommonStyle::eventFilter(obj, event);
3870bool QStyleKitStyle::event(QEvent *event)
3872 return QCommonStyle::event(event);
3877#include "moc_qstylekitstyle.cpp"
Combined button and popup list for selecting options.
static QWidget * managedViewport(QWidget *widget)
static qreal resolvedHeight(const QQStyleKitDelegateProperties *element, qreal avilableH)
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 QUrl urlFromStylePath(const QString &filePath)
static const QWidget * containerWidget(const QWidget *w)