7#include <QtWidgets/qstyleoption.h>
8#include <QtWidgets/qstyle.h>
9#include <QtWidgets/qapplication.h>
10#if QT_CONFIG(scrollarea)
11# include <QtWidgets/qabstractscrollarea.h>
13#if QT_CONFIG(itemviews)
14# include <QtWidgets/qabstractitemview.h>
16#if QT_CONFIG(lineedit)
17# include <QtWidgets/qlineedit.h>
19#if QT_CONFIG(pushbutton)
20# include <QtWidgets/qpushbutton.h>
22#if QT_CONFIG(checkbox)
23# include <QtWidgets/qcheckbox.h>
25#if QT_CONFIG(radiobutton)
26# include <QtWidgets/qradiobutton.h>
28#if QT_CONFIG(combobox)
29# include <QtWidgets/qcombobox.h>
32# include <QtWidgets/qslider.h>
34#if QT_CONFIG(scrollbar)
35# include <QtWidgets/qscrollbar.h>
38# include <QtWidgets/qspinbox.h>
40#if QT_CONFIG(progressbar)
41# include <QtWidgets/qprogressbar.h>
43#if QT_CONFIG(textedit)
44# include <QtWidgets/qtextedit.h>
45# include <QtWidgets/qplaintextedit.h>
48# include <QtWidgets/qtabbar.h>
50#if QT_CONFIG(tabwidget)
51# include <QtWidgets/qtabwidget.h>
54# include <QtWidgets/qtoolbar.h>
56#if QT_CONFIG(toolbutton)
57# include <QtWidgets/qtoolbutton.h>
59#if QT_CONFIG(groupbox)
60# include <QtWidgets/qgroupbox.h>
63# include <QtWidgets/qmenu.h>
64# include <QtWidgets/qmenubar.h>
67# include <QtWidgets/qlabel.h>
69#include <QtWidgets/private/qwidget_p.h>
70#include <QtCore/private/qobject_p.h>
71#include <QtGui/qpainter.h>
72#include <QtGui/qpainterpath.h>
73#include <QtGui/qpainterstateguard.h>
74#include <QtGui/qstylehints.h>
75#include <QtCore/qloggingcategory.h>
76#include <QtCore/qnumeric.h>
77#include <QtQml/private/qqmlcomponent_p.h>
78#include <QtQml/qqmlengine.h>
79#include <QtQuick/private/qquicktransition_p.h>
80#include <QtLabsStyleKit/private/qqstylekit_p.h>
81#include <QtLabsStyleKit/private/qqstylekitcontrolproperties_p.h>
82#include <QtLabsStyleKit/private/qqstylekitstyle_p.h>
86Q_STATIC_LOGGING_CATEGORY(lcStyleKit,
"qt.labs.stylekit")
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
291
292
293
294
295
296
297
298
299
300
301
304
305
306
307
308
309
310
311
312
313
314
317
318
319
320
321
322
323
324
327
328
329
330
331
332
333
334
335
337static QQStyleKitReader::ControlType controlTypeForWidget(
const QWidget *widget)
340 return QQStyleKitReader::Control;
342#if QT_CONFIG(pushbutton)
343 if (qobject_cast<
const QPushButton *>(widget))
344 return QQStyleKitReader::Button;
346#if QT_CONFIG(checkbox)
347 if (qobject_cast<
const QCheckBox *>(widget))
348 return QQStyleKitReader::CheckBox;
350#if QT_CONFIG(radiobutton)
351 if (qobject_cast<
const QRadioButton *>(widget))
352 return QQStyleKitReader::RadioButton;
354#if QT_CONFIG(combobox)
355 if (qobject_cast<
const QComboBox *>(widget))
356 return QQStyleKitReader::ComboBox;
359 if (qobject_cast<
const QSlider *>(widget))
360 return QQStyleKitReader::Slider;
362#if QT_CONFIG(scrollbar)
363 if (qobject_cast<
const QScrollBar *>(widget))
364 return QQStyleKitReader::ScrollBar;
366#if QT_CONFIG(spinbox)
367 if (qobject_cast<
const QSpinBox *>(widget) || qobject_cast<
const QDoubleSpinBox *>(widget))
368 return QQStyleKitReader::SpinBox;
370#if QT_CONFIG(itemviews)
371 if (qobject_cast<
const QAbstractItemView *>(widget))
372 return QQStyleKitReader::ItemDelegate;
374#if QT_CONFIG(progressbar)
375 if (qobject_cast<
const QProgressBar *>(widget))
376 return QQStyleKitReader::ProgressBar;
378#if QT_CONFIG(lineedit)
379 if (qobject_cast<
const QLineEdit *>(widget))
380 return QQStyleKitReader::TextField;
382#if QT_CONFIG(textedit)
383 if (qobject_cast<
const QTextEdit *>(widget) || qobject_cast<
const QPlainTextEdit *>(widget))
384 return QQStyleKitReader::TextArea;
387 if (qobject_cast<
const QTabBar *>(widget))
388 return QQStyleKitReader::TabBar;
390#if QT_CONFIG(tabwidget)
391 if (qobject_cast<
const QTabWidget *>(widget))
392 return QQStyleKitReader::Page;
394#if QT_CONFIG(toolbar)
395 if (qobject_cast<
const QToolBar *>(widget))
396 return QQStyleKitReader::ToolBar;
398#if QT_CONFIG(toolbutton)
399 if (qobject_cast<
const QToolButton *>(widget))
400 return QQStyleKitReader::ToolButton;
402#if QT_CONFIG(groupbox)
403 if (qobject_cast<
const QGroupBox *>(widget))
404 return QQStyleKitReader::GroupBox;
407 if (qobject_cast<
const QMenuBar *>(widget))
408 return QQStyleKitReader::MenuBar;
409 if (qobject_cast<
const QMenu *>(widget))
410 return QQStyleKitReader::Menu;
412 if (widget->windowType() == Qt::Popup)
413 return QQStyleKitReader::Popup;
414 if (widget->windowType() == Qt::Dialog)
415 return QQStyleKitReader::Dialog;
416 if (widget->windowType() == Qt::Window)
417 return QQStyleKitReader::ApplicationWindow;
419 if (qobject_cast<
const QFrame *>(widget))
420 return QQStyleKitReader::Frame;
423 return QQStyleKitReader::Control;
426#if QT_CONFIG(itemviews)
427static QQStyleKitReader::ControlType itemViewControlType(
const QStyleOption *opt)
429 const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt);
430 return itemViewOption && (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator)
431 ? QQStyleKitReader::ControlType::CheckDelegate
432 : QQStyleKitReader::ControlType::ItemDelegate;
441#if QT_CONFIG(scrollarea)
442 if (
const auto *area = qobject_cast<
const QAbstractScrollArea *>(widget))
443 return area->viewport();
445 return const_cast<QWidget *>(widget);
454 || qobject_cast<
const QLabel *>(widget)
456#if QT_CONFIG(textedit)
457 || qobject_cast<
const QTextEdit *>(widget)
458 || qobject_cast<
const QPlainTextEdit *>(widget)
460#if QT_CONFIG(lineedit)
461 || qobject_cast<
const QLineEdit *>(widget)
468#if QT_CONFIG(textedit)
469 if (
auto *textEdit = qobject_cast<QTextEdit *>(widget))
470 return textEdit->viewport();
471 if (
auto *plainTextEdit = qobject_cast<QPlainTextEdit *>(widget))
472 return plainTextEdit->viewport();
474#if QT_CONFIG(itemviews) && QT_CONFIG(combobox)
475 if (
auto *view = qobject_cast<QAbstractItemView *>(widget)) {
476 if (
auto *p = view->parentWidget(); p && p->inherits(
"QComboBoxPrivateContainer"))
477 return view->viewport();
486 const uint h = raw & Qt::AlignHorizontal_Mask;
487 const uint v = raw & Qt::AlignVertical_Mask;
488 result |= h ? h : uint(hDefault);
489 result |= v ? v : uint(vDefault);
495 return qMax(0.0, element->fillWidth() ? availableW : element->width());
500 return qMax(0.0, element->fillHeight() ? availableH : element->height());
505 using QtPrivate::qSaturateRound;
506 return QMargins(qSaturateRound(element->leftMargin()),
507 qSaturateRound(element->topMargin()),
508 qSaturateRound(element->rightMargin()),
509 qSaturateRound(element->bottomMargin()));
513
514
515
517 const QQStyleKitDelegateProperties *element,
523 const qreal scale = element->scale();
524 if (qFuzzyIsNull(scale))
527 const qreal rotation = element->rotation();
528 if (qFuzzyIsNull(rotation) && qFuzzyCompare(scale, 1.0))
531 const QPointF center = box.center();
532 painter->translate(center);
533 if (!qFuzzyIsNull(rotation))
534 painter->rotate(rotation);
535 if (!qFuzzyCompare(scale, 1.0))
536 painter->scale(scale, scale);
537 painter->translate(-center);
544#if QT_CONFIG(lineedit)
545 if (qobject_cast<
const QLineEdit *>(w)) {
547 QWidget *parent = w->parentWidget();
549# if QT_CONFIG(combobox)
550 || qobject_cast<
const QComboBox *>(parent)
552# if QT_CONFIG(spinbox)
553 || qobject_cast<
const QAbstractSpinBox *>(parent)
561#if QT_CONFIG(scrollarea)
562 if (
const QAbstractScrollArea *sa =
563 qobject_cast<
const QAbstractScrollArea *>(w->parentWidget())) {
564 if (sa->viewport() == w)
565 return w->parentWidget();
573 : QCommonStylePrivate()
579 if (filePath.startsWith(QLatin1Char(
':')))
580 return QUrl(QLatin1String(
"qrc") + filePath);
581 if (filePath.startsWith(QLatin1String(
"qrc:")) || filePath.startsWith(QLatin1String(
"file:")))
582 return QUrl(filePath);
583 return QUrl::fromLocalFile(filePath);
590 qmlEngine =
new QQmlEngine(q);
593 qWarning(
"QStyleKitStyle: No QML engine available to load style.");
596 const QUrl url = stylePath.isEmpty() ? QUrl() : urlFromStylePath(stylePath);
597 if (stylePath.isEmpty() || !url.isValid()) {
598 qWarning(
"QStyleKitStyle: No valid style path provided: %s", qPrintable(stylePath));
601 QQmlComponent component(qmlEngine, url);
602 if (component.isError()) {
603 qWarning(
"QStyleKitStyle: Failed to load style from %s: %s", qPrintable(stylePath),
604 qPrintable(component.errorString()));
609 QQmlComponentPrivate *componentPrivate = QQmlComponentPrivate::get(&component);
610 const auto compilationUnit = componentPrivate->compilationUnit();
611 const auto propertyCache = compilationUnit ? compilationUnit->rootPropertyCache() :
nullptr;
612 const auto firstMetaObject = propertyCache ? propertyCache->firstCppMetaObject() :
nullptr;
613 if (!firstMetaObject || !firstMetaObject->inherits(&QQStyleKitStyle::staticMetaObject)) {
614 qWarning(
"QStyleKitStyle: Failed to load style from %s: component is not a StyleKit Style.",
615 qPrintable(stylePath));
618 QQStyleKitStyle *styleObject = qobject_cast<QQStyleKitStyle *>(component.create());
620 qWarning(
"QStyleKitStyle: Failed to create style object from %s: "
621 "component is not a StyleKit style.",
622 qPrintable(stylePath));
625 const bool isReload = style !=
nullptr;
631 QObject::connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, q,
633 if (style && style->themeName() == QLatin1String(
"System")) {
634 style->recreateTheme();
641 QQStyleKitReader::resetReadersForStyle(style);
647
648
649
657 qmlEngine =
new QQmlEngine(q);
659 QQmlComponent component(qmlEngine);
660 component.loadFromModule(
"Qt.labs.StyleKit",
"Style");
661 if (component.isError()) {
662 qWarning(
"QStyleKitStyle: Failed to create default fallback style: %s",
663 qPrintable(component.errorString()));
666 defaultStyle = qobject_cast<QQStyleKitStyle *>(component.create());
668 defaultStyle->setParent(q);
670 "No style set; using a default fallback style. "
671 "Set stylePath to load a StyleKit Style.");
677
678
679
682 return style ? style : defaultStyle;
689 QQStyleKitStyle *effective = effectiveStyle();
691 if (sharedReader && sharedReader->style() != effective)
692 sharedReader->setExplicitStyle(effective);
694 if (subElementReader && subElementReader->style() != effective)
695 subElementReader->setExplicitStyle(effective);
697 clearAllSubElements();
699 for (
auto *wr : std::as_const(widgetReaders)) {
700 if (wr->style() != effective)
701 wr->setExplicitStyle(effective);
704 if (!QWidgetPrivate::allWidgets)
707 for (
auto *widget : std::as_const(*QWidgetPrivate::allWidgets)) {
708 if (customFontWidgets.contains(widget))
709 unsetStyleFont(widget);
710 refreshStyleFont(widget);
711 if (customPaletteWidgets.contains(widget))
712 unsetStylePalette(widget);
713 refreshStylePalette(widget);
716 QEvent styleChange(QEvent::StyleChange);
717 for (
auto *widget : std::as_const(*QWidgetPrivate::allWidgets)) {
718 QApplication::sendEvent(widget, &styleChange);
726 auto it = customFontWidgets.find(widget);
727 if (it == customFontWidgets.end())
730 auto customFont =
std::move(*it);
731 customFontWidgets.erase(it);
732 widget->setFont(
std::move(customFont).reverted(QWidgetPrivate::get(widget)->localFont()));
737 if (!effectiveStyle() || !widget)
740 const auto styleMask = styleFont.resolveMask();
741 auto it = customFontWidgets.find(widget);
743 if (it == customFontWidgets.end()) {
746 it = customFontWidgets.insert(widget, { QWidgetPrivate::get(widget)->localFont(), 0 });
747 QObject::connect(widget, &QObject::destroyed, widget,
748 [
this, widget]() { customFontWidgets.remove(widget); });
751 it->resolveMask = styleMask;
753 const QFont &baseline = it->oldWidgetValue;
754 QFont merged = styleFont.resolve(baseline);
755 merged.setResolveMask(baseline.resolveMask() | styleMask);
756 widget->setFont(merged);
761 if (!effectiveStyle() || !widget)
764 const QWidget *targetWidget = containerWidget(widget);
765 QQStyleKitReader::ControlType controlType = controlTypeForWidget(targetWidget);
767 auto *shared = ensureSharedReader();
772 opt.initFrom(targetWidget);
773 const QQSK::State currentState = resolvedStateFor(controlType, opt.state, targetWidget);
775 shared->setControlTypeAndState(controlType, currentState,
false);
776 setStyleFont(widget, shared->font());
781 auto it = customPaletteWidgets.find(widget);
782 if (it == customPaletteWidgets.end())
785 auto customPalette =
std::move(*it);
786 customPaletteWidgets.erase(it);
787 widget->setPalette(
std::move(customPalette).reverted(widget->palette()));
792 if (!effectiveStyle() || !widget)
795 const quint64 styleMask = stylePalette.resolveMask();
799 if (!customPaletteWidgets.contains(widget)) {
800 customPaletteWidgets.insert(widget, { widget->palette(), 0 });
801 QObject::connect(widget, &QObject::destroyed, widget,
802 [
this, widget]() { customPaletteWidgets.remove(widget); });
805 customPaletteWidgets[widget].resolveMask |= styleMask;
806 QPalette merged = stylePalette.resolve(widget->palette());
807 merged.setResolveMask(widget->palette().resolveMask() | styleMask);
808 widget->setPalette(merged);
815 if (!effectiveStyle() || !widget)
818 const bool isWindow = widget->windowType() & (Qt::Popup | Qt::Window | Qt::Dialog);
819 const bool isPaletteManaged = isSelfPaintingWidget(widget) || isWindow;
820 if (!isPaletteManaged)
823 const QWidget *targetWidget = containerWidget(widget);
824 QQStyleKitReader::ControlType controlType = controlTypeForWidget(targetWidget);
826 auto *shared = ensureSharedReader();
831 opt.initFrom(targetWidget);
832 const QQSK::State currentState = resolvedStateFor(controlType, opt.state, targetWidget);
834 QPalette stylePalette;
837 shared->setControlTypeAndState(controlType, currentState,
false);
838 if (
const auto *bg = shared->global()->background();
839 bg && bg->isDefined(QQSK::Property::Color)) {
840 stylePalette.setColor(QPalette::Window, bg->color());
842 shared->setControlTypeAndState(controlType, QQSK::StateFlag::Disabled,
false);
843 if (
const auto *dbg = shared->global()->background();
844 dbg && dbg->isDefined(QQSK::Property::Color)) {
845 stylePalette.setColor(QPalette::Disabled, QPalette::Window, dbg->color());
850 shared->setControlTypeAndState(controlType, currentState,
false);
851 if (
const auto *text = shared->global()->text();
852 text && text->isDefined(QQSK::Property::Color)) {
853 stylePalette.setColor(QPalette::Text, text->color());
854 stylePalette.setColor(QPalette::WindowText, text->color());
856 shared->setControlTypeAndState(controlType, QQSK::StateFlag::Disabled,
false);
857 if (
const auto *dt = shared->global()->text();
858 dt && dt->isDefined(QQSK::Property::Color)) {
859 stylePalette.setColor(QPalette::Disabled, QPalette::Text, dt->color());
860 stylePalette.setColor(QPalette::Disabled, QPalette::WindowText, dt->color());
864 setStylePalette(widget, stylePalette);
868
869
872 Q_Q(
const QStyleKitStyle);
873 QQStyleKitStyle *effective = effectiveStyle();
874 if (!effective || !widget)
877 if (
auto it = widgetReaders.find(widget); it != widgetReaders.end())
880 auto *widgetReader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
881 widgetReader->setExplicitStyle(effective);
882 widgetReader->setTarget(paintTarget(widget));
883 widgetReader->setControlType(controlTypeForWidget(widget));
884 widgetReader->setCompleted(
true);
885 widgetReaders.insert(widget, widgetReader);
886 QObjectPrivate::connect(widget, &QObject::destroyed,
this,
887 &QStyleKitStylePrivate::onWidgetDestroyed, Qt::UniqueConnection);
893 if (
auto *reader = widgetReaders.take(widget))
894 reader->deleteLater();
895 cleanupSubElements(widget);
900 cleanupWidgetReader(
static_cast<QWidget *>(w));
904
905
906
907
915#if QT_CONFIG(itemviews)
916 if (
const auto *viewOpt = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
917 const QModelIndex &idx = viewOpt->index;
921 key.id = SubElementKey::ItemViewCell{ idx.model(), idx.internalId(), idx.row(),
927 if (
const auto *menuOpt = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
928 if (menuOpt->menuItemType == QStyleOptionMenuItem::Separator)
930 QAction *action =
nullptr;
931 if (
const auto *menu = qobject_cast<
const QMenu *>(widget))
932 action = menu->actionAt(menuOpt->rect.center());
933 else if (
const auto *menuBar = qobject_cast<
const QMenuBar *>(widget))
934 action = menuBar->actionAt(menuOpt->rect.center());
937 key.id = SubElementKey::Action{ action };
943 if (
const auto *tabOpt = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
944 if (tabOpt->tabIndex < 0)
947 key.id = SubElementKey::Tab{ tabOpt->tabIndex };
955
956
957
958
960 const SubElementKey &key, QQStyleKitReader::ControlType type, QQSK::State fromState,
961 QQSK::State toState, QQuickTransition *transition)
const
963 Q_Q(
const QStyleKitStyle);
964 QQStyleKitStyle *effective = effectiveStyle();
970 for (
auto it = subElementAnimationReaders.begin(); it != subElementAnimationReaders.end();) {
971 const QQuickTransition *t = it.value()->transition();
972 if (!t || !t->running()) {
973 it.value()->deleteLater();
974 it = subElementAnimationReaders.erase(it);
981 if (subElementAnimationReaders.size() >= kMaxSubElementAnimationReaders) {
982 const auto it = subElementAnimationReaders.begin();
983 if (
const QWidget *widget = it.key().widget)
984 paintTarget(widget)->update();
985 it.value()->deleteLater();
986 subElementAnimationReaders.erase(it);
989 auto *reader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
990 reader->setExplicitStyle(effective);
991 reader->setTarget(paintTarget(key.widget));
993 reader->setControlTypeAndState(type, fromState);
994 reader->setCompleted(
true);
998 reader->background();
999 auto *indicator = reader->indicator();
1000 indicator->first()->foreground();
1001 indicator->second()->foreground();
1003 reader->setControlTypeAndState(type, toState);
1004 if (!transition || !transition->running()) {
1005 reader->deleteLater();
1008 subElementAnimationReaders.insert(key, reader);
1013
1014
1017 for (
auto it = subElementStates.begin(); it != subElementStates.end();) {
1018 if (it.key().widget == widget)
1019 it = subElementStates.erase(it);
1023 for (
auto it = subElementAnimationReaders.begin(); it != subElementAnimationReaders.end();) {
1024 if (it.key().widget == widget) {
1025 it.value()->deleteLater();
1026 it = subElementAnimationReaders.erase(it);
1034
1035
1038 subElementStates.clear();
1039 for (QQStyleKitReader *reader : std::as_const(subElementAnimationReaders))
1040 reader->deleteLater();
1041 subElementAnimationReaders.clear();
1045
1046
1047
1049 QStyle::State state,
1050 const QWidget *widget)
const
1053 flags.setFlag(QQSK::StateFlag::Hovered, (state & QStyle::State_MouseOver));
1054 flags.setFlag(QQSK::StateFlag::Pressed, state & QStyle::State_Sunken);
1055 flags.setFlag(QQSK::StateFlag::Checked, state & QStyle::State_On);
1056 flags.setFlag(QQSK::StateFlag::Focused, state & QStyle::State_HasFocus);
1057 flags.setFlag(QQSK::StateFlag::Highlighted, state & QStyle::State_Selected);
1059 bool hasOrientation =
false;
1061 case QQStyleKitReader::ProgressBar:
1062 case QQStyleKitReader::ScrollBar:
1063 case QQStyleKitReader::ScrollIndicator:
1064 case QQStyleKitReader::Slider:
1065 case QQStyleKitReader::ToolBar:
1066 case QQStyleKitReader::ToolSeparator:
1067 hasOrientation =
true;
1073 flags.setFlag(QQSK::StateFlag::Vertical, !(state & QStyle::State_Horizontal));
1077 const bool enabled = (state & QStyle::State_Enabled) || (widget && widget->isEnabled());
1078 flags.setFlag(QQSK::StateFlag::Disabled, !enabled);
1082 if (type == QQStyleKitReader::ControlType::ComboBox)
1083 flags.setFlag(QQSK::StateFlag::Checked,
false);
1086 if (type == QQStyleKitReader::ControlType::Popup)
1087 flags.setFlag(QQSK::StateFlag::Hovered,
false);
1090 if (type == QQStyleKitReader::ControlType::TabButton) {
1091 flags.setFlag(QQSK::StateFlag::Checked, state & QStyle::State_Selected);
1092 flags.setFlag(QQSK::StateFlag::Highlighted,
false);
1099
1100
1101
1102const QStyleKitStylePrivate::ControlMetrics &
1105 if (
auto it = metricsCache.find({ type, state }); it != metricsCache.end())
1108 auto *reader = ensureSharedReader();
1110 reader->setControlTypeAndState(type, state,
false);
1111 return *metricsCache.insert({ type, state }, metricsForReader(reader));
1115
1116
1117
1120 QStyle::State state)
const
1122 QQStyleKitResolved out;
1125 auto *reader = readerForWidget(w);
1129 const QQSK::State resolvedState = resolvedStateFor(type, state, w);
1130 reader->setControlTypeAndState(type, resolvedState);
1132 out.reader = reader;
1133 out.metrics = &metricsFor(type, resolvedState);
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1151 QQStyleKitReader::ControlType type, QStyle::State state,
1154 QQStyleKitResolved out;
1157 auto *steadyReader = ensureSubElementReader();
1161 const QQSK::State newState = resolvedStateFor(type, state, w);
1162 const SubElementKey key = subElementKeyForOption(opt, w);
1164 QQStyleKitReader *reader =
nullptr;
1165 if (track && key.isValid()) {
1166 QQStyleKitReader *animReader = subElementAnimationReaders.value(key);
1167 const auto it = subElementStates.constFind(key);
1168 const bool seen = it != subElementStates.cend();
1172 constexpr QQSK::State InteractiveStates = QQSK::State(QQSK::StateFlag::Hovered)
1173 | QQSK::StateFlag::Pressed | QQSK::StateFlag::Checked
1174 | QQSK::StateFlag::Focused | QQSK::StateFlag::Highlighted;
1175 const auto baseState = newState & ~InteractiveStates;
1176 const QQSK::State prevState = seen ? *it : baseState;
1177 if (prevState != newState) {
1182 animReader->setControlTypeAndState(type, newState);
1187 const bool shouldAnimate = seen || newState.testFlag(QQSK::StateFlag::Hovered)
1188 || newState.testFlag(QQSK::StateFlag::Pressed);
1189 if (shouldAnimate) {
1190 steadyReader->setControlTypeAndState(type, newState);
1191 if (QQuickTransition *transition = steadyReader->transition())
1192 animReader = startSubElementTransition(key, type, prevState,
1193 newState, transition);
1197 if (!seen || prevState != newState) {
1198 QObjectPrivate::connect(w, &QObject::destroyed,
this,
1199 &QStyleKitStylePrivate::onWidgetDestroyed,
1200 Qt::UniqueConnection);
1201 if (subElementStates.size() >= kMaxSubElementStates)
1202 subElementStates.clear();
1203 subElementStates.insert(key, newState);
1205 reader = animReader;
1209 reader = steadyReader;
1210 reader->setControlTypeAndState(type, newState);
1212 out.reader = reader;
1213 out.metrics = &metricsFor(type, newState);
1219 return reader ? reader->text() :
nullptr;
1224 return reader ? reader->background() :
nullptr;
1229 return reader ? reader->handle() :
nullptr;
1234 return reader ? reader->indicator() :
nullptr;
1239 return reader ? reader->font() : QFont();
1245 return sharedReader;
1247 Q_Q(
const QStyleKitStyle);
1248 QQStyleKitStyle *effective = effectiveStyle();
1251 sharedReader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
1253 sharedReader->setTransitionsEnabled(
false);
1254 sharedReader->setExplicitStyle(effective);
1255 sharedReader->setCompleted(
true);
1256 return sharedReader;
1261 if (subElementReader)
1262 return subElementReader;
1264 Q_Q(
const QStyleKitStyle);
1265 QQStyleKitStyle *effective = effectiveStyle();
1268 subElementReader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
1271 subElementReader->setTransitionsEnabled(
false);
1272 subElementReader->setExplicitStyle(effective);
1273 subElementReader->setCompleted(
true);
1274 return subElementReader;
1278
1279
1280
1281
1285 QQStyleKitLayoutResolved out;
1286 auto *reader = ensureSharedReader();
1290 const QQSK::State resolvedState = resolvedStateFor(type, state);
1291 out.metrics = &metricsFor(type, resolvedState);
1295 reader->setControlTypeAndState(type, resolvedState,
false);
1296 out.staticProps = reader->global();
1297 out.staticFont = reader->font();
1303 return staticProps ? staticProps->text() :
nullptr;
1306const QQStyleKitDelegateProperties *
1309 return staticProps ? staticProps->background() :
nullptr;
1314 return staticProps ? staticProps->handle() :
nullptr;
1320 return staticProps ? staticProps->indicator() :
nullptr;
1325 metricsCache.clear();
1329 const QRectF &rect, QPainter *painter)
const
1331 if (!indicator || !indicator->visible() || indicator->opacity() <= 0 || !rect.isValid())
1337 QPainterStateGuard stateGuard(painter);
1338 if (!applyDelegateTransform(painter, indicator, rect))
1342 QRectF indicatorRect = rect;
1343 drawStyledItemContents(indicator, indicatorRect, painter);
1345 const QQStyleKitDelegateProperties *foreground =
nullptr;
1346 if (
auto *indicatorWithSubTypes =
1347 qobject_cast<
const QQStyleKitIndicatorWithSubTypes *>(indicator)) {
1348 foreground = indicatorWithSubTypes->foreground();
1349 }
else if (
auto *indicatorProps =
1350 qobject_cast<
const QQStyleKitIndicatorProperties *>(indicator)) {
1351 foreground = indicatorProps->foreground();
1355 if (!foreground || !foreground->visible() || foreground->opacity() <= 0)
1359 QRectF foregroundRect;
1360 const uint foregroundAlign = resolvedAlignment(foreground->alignment(), Qt::AlignHCenter,
1362 const auto foregroundW = resolvedWidth(
1363 foreground, indicatorRect.width() - foreground->leftMargin() - foreground->rightMargin());
1364 const auto foregroundH = resolvedHeight(
1365 foreground, indicatorRect.height() - foreground->topMargin() - foreground->bottomMargin());
1366 foregroundRect.setSize(QSizeF(foregroundW, foregroundH));
1367 if (foregroundAlign & Qt::AlignLeft)
1368 foregroundRect.moveLeft(indicatorRect.left() + foreground->leftMargin());
1369 else if (foregroundAlign & Qt::AlignHCenter)
1370 foregroundRect.moveLeft(indicatorRect.left() + (indicatorRect.width() - foregroundW) / 2.0);
1371 else if (foregroundAlign & Qt::AlignRight)
1372 foregroundRect.moveLeft(indicatorRect.right() - foreground->rightMargin() - foregroundW);
1373 if (foregroundAlign & Qt::AlignTop)
1374 foregroundRect.moveTop(indicatorRect.top() + foreground->topMargin());
1375 else if (foregroundAlign & Qt::AlignVCenter)
1376 foregroundRect.moveTop(indicatorRect.top() + (indicatorRect.height() - foregroundH) / 2.0);
1377 else if (foregroundAlign & Qt::AlignBottom)
1378 foregroundRect.moveTop(indicatorRect.bottom() - foreground->bottomMargin() - foregroundH);
1379 drawStyledItemRect(foreground, foregroundRect, painter);
1383 const QFont &font,
const QRect &rect,
1384 const QString &text, uint textFlags, QPainter *p,
1385 Qt::Alignment defaultAlignment)
const
1387 uint flags = textFlags;
1389 ? resolvedAlignment(textProps->alignment(), defaultAlignment & Qt::AlignHorizontal_Mask,
1390 defaultAlignment & Qt::AlignVertical_Mask)
1391 : uint(defaultAlignment);
1393 const QFont oldFont = p->font();
1394 p->setFont(font.resolve(oldFont));
1395 p->setBrush(Qt::NoBrush);
1396 p->setPen(textProps ? textProps->color() : QColor());
1397 p->drawText(rect, flags, text,
nullptr);
1401 const QRectF &rect, QPainter *painter)
const
1403 if (!props || !props->visible() || props->opacity() <= 0 || !rect.isValid())
1406 QPainterStateGuard stateGuard(painter);
1407 if (!applyDelegateTransform(painter, props, rect))
1409 drawStyledItemContents(props, rect, painter);
1413 const QRectF &rect, QPainter *painter)
const
1415 if (!props || !props->visible() || props->opacity() <= 0 || !rect.isValid())
1418 QPainterStateGuard stateGuard(painter);
1419 painter->setRenderHint(QPainter::Antialiasing,
true);
1421 painter->setClipping(
true);
1424 const auto opacity = props->opacity();
1427 const auto *border = props->border();
1428 auto borderWidth = 0;
1432 borderWidth = border->width();
1433 borderColor = border->color();
1434 inset = borderWidth / 2.0;
1436 if (borderWidth > 0 && borderColor.isValid() && borderColor.alpha() > 0) {
1437 QPen pen(borderColor, borderWidth);
1438 painter->setPen(pen);
1440 painter->setPen(Qt::NoPen);
1445 const qreal minDimension = qMin(rect.width(), rect.height());
1446 const qreal xRadius = qMax(0.0, qMin(props->topLeftRadius() - inset, minDimension / 2.0));
1447 const qreal yRadius = qMax(0.0, qMin(props->bottomLeftRadius() - inset, minDimension / 2.0));
1449 QRectF adjustedRect = rect.adjusted(inset, inset, -inset, -inset);
1453 QColor color = props->color();
1454 QBrush colorBrush(color);
1455 painter->setBrush(colorBrush);
1456 if (color.isValid()) {
1457 painter->setOpacity(opacity);
1458 painter->drawRoundedRect(adjustedRect, xRadius, yRadius, Qt::AbsoluteSize);
1460 if (QQuickGradient *gradient = props->gradient()) {
1461 QLinearGradient linearGradient(rect.topLeft(), rect.bottomLeft());
1462 QQmlListProperty<QQuickGradientStop> stops = gradient->stops();
1463 const int stopCount = stops.count(&stops);
1464 for (
int i = 0; i < stopCount; i++) {
1465 QQuickGradientStop *stop =
static_cast<QQuickGradientStop *>(stops.at(&stops, i));
1466 linearGradient.setColorAt(stop->position(), stop->color());
1468 QBrush gradientBrush(linearGradient);
1469 painter->setBrush(gradientBrush);
1470 painter->setOpacity(opacity);
1471 painter->drawRoundedRect(adjustedRect, xRadius, yRadius, Qt::AbsoluteSize);
1475 drawStyledItemImage(props->image(), adjustedRect, opacity, painter);
1479 const QRectF &rect, qreal opacity,
1480 QPainter *painter)
const
1482 if (!image || image->source().isEmpty() || image->color().alpha() <= 0)
1485 QString imageSource = image->source().toString();
1486 if (imageSource.startsWith(QLatin1String(
"qrc:/")))
1487 imageSource = imageSource.mid(3);
1488 QUrl imageUrl(imageSource);
1489 QString imagePath = imageUrl.isLocalFile() ? imageUrl.toLocalFile() : imageSource;
1490 QPixmap pixmap(imagePath);
1491 if (pixmap.isNull())
1494 if (image->color().isValid()) {
1495 QImage coloredImage = pixmap.toImage();
1496 QPainter imagePainter(&coloredImage);
1497 imagePainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
1498 imagePainter.fillRect(coloredImage.rect(), image->color());
1500 pixmap = QPixmap::fromImage(coloredImage);
1502 painter->setOpacity(opacity);
1503 const QSizeF pixmapSize = pixmap.deviceIndependentSize();
1505 switch (image->fillMode()) {
1506 case QQuickImage::PreserveAspectFit: {
1507 const QSize scaled = pixmapSize.scaled(rect.size(), Qt::KeepAspectRatio).toSize();
1508 const QPointF topLeft(rect.x() + (rect.width() - scaled.width()) / 2.0,
1509 rect.y() + (rect.height() - scaled.height()) / 2.0);
1510 painter->drawPixmap(QRectF(topLeft, scaled), pixmap, QRectF(QPointF(0, 0), pixmapSize));
1513 case QQuickImage::PreserveAspectCrop: {
1514 const QSize scaled = pixmapSize
1515 .scaled(rect.size(), Qt::KeepAspectRatioByExpanding)
1517 const QPointF topLeft(rect.x() + (rect.width() - scaled.width()) / 2.0,
1518 rect.y() + (rect.height() - scaled.height()) / 2.0);
1519 QPainterStateGuard stateGuard(painter);
1520 painter->setClipRect(rect);
1521 painter->drawPixmap(QRectF(topLeft, scaled), pixmap, QRectF(QPointF(0, 0), pixmapSize));
1525 case QQuickImage::Stretch:
1527 painter->drawPixmap(rect, pixmap, QRectF(QPointF(0, 0), pixmapSize));
1533 uint alignment,
const QMargins &padding,
1534 const QMargins &margins)
const
1536 QRect r(QPoint(0, 0), size);
1538 if (alignment & Qt::AlignLeft)
1539 r.moveLeft(container.x() + padding.left() + margins.left());
1540 else if (alignment & Qt::AlignHCenter)
1541 r.moveLeft(container.x() + (container.width() - size.width()) / 2);
1543 r.moveLeft(container.right() + 1 - padding.right() - margins.right() - size.width());
1545 if (alignment & Qt::AlignTop)
1546 r.moveTop(container.y() + padding.top() + margins.top());
1547 else if (alignment & Qt::AlignVCenter)
1548 r.moveTop(container.y() + (container.height() - size.height()) / 2);
1550 r.moveTop(container.bottom() + 1 - padding.bottom() - margins.bottom() - size.height());
1555QStyleKitStylePrivate::ControlMetrics
1559 using QtPrivate::qSaturateRound;
1560 const QQStyleKitControlProperties *props = reader->global();
1561 ControlMetrics metrics;
1562 metrics.bgImplicitSize = QSize(0, 0);
1563 metrics.textPadding = QMargins(0, 0, 0, 0);
1564 metrics.padding = QMargins(qSaturateRound(props->leftPadding()),
1565 qSaturateRound(props->topPadding()),
1566 qSaturateRound(props->rightPadding()),
1567 qSaturateRound(props->bottomPadding()));
1568 metrics.spacing = qSaturateRound(props->spacing());
1569 metrics.margins = QMargins(0, 0, 0, 0);
1570 metrics.indicatorImplicitSize = QSize(0, 0);
1571 metrics.indicatorMargins = QMargins(0, 0, 0, 0);
1572 const auto *background = props->background();
1575 const auto elementSize = [](qreal w, qreal h) {
1576 constexpr qreal zero(.0);
1577 return QSizeF(std::max(zero, w), std::max(zero, h)).toSize();
1581 metrics.bgImplicitSize = elementSize(background->width(), background->height());
1582 metrics.margins = elementMargins(background);
1584 const auto *textProps = props->text();
1586 metrics.textPadding = QMargins(qSaturateRound(textProps->leftPadding()),
1587 qSaturateRound(textProps->topPadding()),
1588 qSaturateRound(textProps->rightPadding()),
1589 qSaturateRound(textProps->bottomPadding()));
1591 const auto *indicator = props->indicator();
1593 metrics.indicatorMargins = elementMargins(indicator);
1594 metrics.indicatorImplicitSize = elementSize(indicator->width(), indicator->height());
1596 const auto *handle = props->handle();
1598 metrics.handleImplicitSize = elementSize(handle->width(), handle->height());
1599 metrics.handleMargins = elementMargins(handle);
1605
1606
1607
1608
1609
1610QStyleKitStyle::QStyleKitStyle()
1611 : QCommonStyle(*
new QStyleKitStylePrivate())
1616
1617
1618
1619
1620
1621
1622
1623QStyleKitStyle::QStyleKitStyle(
const QString &filePath)
1624 : QCommonStyle(*
new QStyleKitStylePrivate())
1626 Q_D(QStyleKitStyle);
1627 d->stylePath = filePath;
1628 if (!d->loadStyle()) {
1629 d->stylePath.clear();
1630 qWarning(
"QStyleKitStyle: Failed to load style from %s", qPrintable(filePath));
1635
1636
1637QStyleKitStyle::~QStyleKitStyle()
1642
1643
1644
1645
1646QString QStyleKitStyle::stylePath()
const
1648 Q_D(
const QStyleKitStyle);
1649 return d->stylePath;
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664void QStyleKitStyle::setStylePath(
const QString &filePath)
1666 Q_D(QStyleKitStyle);
1667 if (d->stylePath == filePath)
1670 const QString oldThemeName = themeName();
1671 const QStringList oldThemeNames = availableThemeNames();
1672 const QStringList oldCustomThemeNames = customThemeNames();
1674 const QString previousPath = d->stylePath;
1675 d->stylePath = filePath;
1676 if (!d->loadStyle()) {
1677 d->stylePath = previousPath;
1681 if (
const QStringList names = availableThemeNames(); names != oldThemeNames)
1682 emit availableThemeNamesChanged(names);
1683 if (
const QStringList names = customThemeNames(); names != oldCustomThemeNames)
1684 emit customThemeNamesChanged(names);
1685 emit stylePathChanged(d->stylePath);
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698QString QStyleKitStyle::themeName()
const
1700 Q_D(
const QStyleKitStyle);
1701 return d->style ? d->style->themeName() : QString();
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718void QStyleKitStyle::setThemeName(
const QString &themeName)
1720 Q_D(QStyleKitStyle);
1722 qWarning(
"QStyleKitStyle: No style loaded, cannot set theme name.");
1725 if (d->style->themeName() == themeName)
1727 d->style->setThemeName(themeName);
1729 emit themeNameChanged(d->style->themeName());
1733
1734
1735
1736
1737
1738
1739
1740
1741QStringList QStyleKitStyle::availableThemeNames()
const
1743 Q_D(
const QStyleKitStyle);
1744 return d->style ? d->style->availableThemeNames() : QStringList();
1748
1749
1750
1751
1752
1753
1754QStringList QStyleKitStyle::customThemeNames()
const
1756 Q_D(
const QStyleKitStyle);
1757 return d->style ? d->style->customThemeNames() : QStringList();
1761void QStyleKitStyle::drawPrimitive(PrimitiveElement pe,
const QStyleOption *opt, QPainter *p,
1762 const QWidget *w)
const
1764 Q_D(
const QStyleKitStyle);
1768 case PE_PanelMenu: {
1769 const auto controlType = w && w->inherits(
"QComboBoxPrivateContainer")
1770 ? QQStyleKitReader::ControlType::Popup
1771 : QQStyleKitReader::ControlType::Menu;
1772 const auto r = d->resolve(w, controlType, opt->state);
1775 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
1782#if QT_CONFIG(menubar)
1783 case PE_PanelMenuBar: {
1784 const auto r = d->resolve(w, QQStyleKitReader::ControlType::MenuBar, opt->state);
1787 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
1791 case PE_FrameButtonBevel:
1792 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1793 const auto controlType = btn->features & QStyleOptionButton::Flat
1794 ? QQStyleKitReader::ControlType::FlatButton
1795 : QQStyleKitReader::ControlType::Button;
1796 const auto r = d->resolve(w, controlType, btn->state);
1799 d->drawStyledItemRect(r.background(), opt->rect, p);
1804 QQStyleKitReader::ControlType controlType;
1805 const bool isPopup = w
1807#if QT_CONFIG(combobox)
1808 || w->inherits(
"QComboBoxPrivateContainer")
1812 controlType = QQStyleKitReader::ControlType::Popup;
1813#if QT_CONFIG(lineedit)
1814 else if (qobject_cast<
const QLineEdit *>(w))
1815 controlType = QQStyleKitReader::ControlType::TextField;
1818 controlType = QQStyleKitReader::ControlType::Frame;
1819 const auto r = d->resolve(w, controlType, opt->state);
1822 d->drawStyledItemRect(r.background(), opt->rect, p);
1825#if QT_CONFIG(lineedit)
1826 case PE_PanelLineEdit:
1827 if (
const auto *lineEdit = qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
1830 QStyleOption lineEditOpt(*lineEdit);
1831 lineEditOpt.state &= ~QStyle::State_Sunken;
1832 const auto r = d->resolve(w, QQStyleKitReader::ControlType::TextField,
1838 if (
auto *le = qobject_cast<
const QLineEdit *>(w)) {
1839 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
1840 QPalette stylePalette;
1841 stylePalette.setColor(QPalette::Text, txt->color());
1842 d->setStylePalette(
const_cast<QLineEdit *>(le), stylePalette);
1844 const_cast<QStyleKitStylePrivate *>(d)->setStyleFont(
const_cast<QLineEdit *>(le),
1848 const QObject *parent = w ? w->parent() :
nullptr;
1849# if QT_CONFIG(spinbox)
1850 const bool isInSpinBox = qobject_cast<
const QAbstractSpinBox *>(parent);
1852 const bool isInSpinBox =
false;
1854# if QT_CONFIG(combobox)
1855 const bool isInComboBox = qobject_cast<
const QComboBox *>(parent);
1857 const bool isInComboBox =
false;
1860 if (isInSpinBox || isInComboBox)
1863 d->drawStyledItemRect(r.background(), opt->rect, p);
1868#if QT_CONFIG(itemviews)
1869 case PE_PanelItemViewItem: {
1870 const auto r = d->resolveSubElement(w, opt, itemViewControlType(opt), opt->state);
1873 d->drawStyledItemRect(r.background(), opt->rect, p);
1877 case PE_IndicatorCheckBox:
1878 case PE_IndicatorRadioButton: {
1879 const auto controlType = pe == PE_IndicatorCheckBox
1880 ? QQStyleKitReader::ControlType::CheckBox
1881 : QQStyleKitReader::ControlType::RadioButton;
1882 const auto r = d->resolve(w, controlType, opt->state);
1885 d->drawControlIndicator(r.indicator(), opt->rect, p);
1888 case PE_IndicatorArrowDown: {
1889 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, opt->state);
1892 d->drawControlIndicator(r.indicator(), opt->rect, p);
1895 case PE_IndicatorItemViewItemCheck: {
1897 const auto r = d->resolveSubElement(w, opt, itemViewControlType(opt), opt->state,
false);
1900 d->drawControlIndicator(r.indicator(), opt->rect, p);
1903#if QT_CONFIG(spinbox)
1904 case PE_IndicatorSpinUp:
1905 case PE_IndicatorSpinDown: {
1906 const auto r = d->resolve(w, QQStyleKitReader::ControlType::SpinBox, opt->state);
1909 const auto *indicator = r.indicator();
1910 const auto *upDownIndicator = indicator
1911 ? (pe == PE_IndicatorSpinUp ? indicator->first() : indicator->second())
1913 d->drawControlIndicator(upDownIndicator, opt->rect, p);
1917#if QT_CONFIG(groupbox)
1918 case PE_FrameGroupBox: {
1919 const auto r = d->resolve(w, QQStyleKitReader::ControlType::GroupBox, opt->state);
1922 d->drawStyledItemRect(r.background(), opt->rect, p);
1926#if QT_CONFIG(tabwidget)
1927 case PE_FrameTabWidget: {
1928 const auto r = d->resolve(w, QQStyleKitReader::ControlType::Page, opt->state);
1931 d->drawStyledItemRect(r.background(), opt->rect, p);
1935#if QT_CONFIG(tabbar)
1937 case PE_IndicatorTabClose:
1938 case PE_IndicatorTabTearRight:
1939 case PE_IndicatorTabTearLeft:
1942#if QT_CONFIG(toolbutton)
1943 case PE_FrameButtonTool:
1944 case PE_PanelButtonTool: {
1945 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolButton, opt->state);
1948 d->drawStyledItemRect(r.background(), opt->rect, p);
1952#if QT_CONFIG(toolbar)
1953 case PE_IndicatorToolBarHandle:
1955 case PE_IndicatorToolBarSeparator: {
1956 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolSeparator, opt->state);
1959 const auto &metrics = *r.metrics;
1961 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
1962 d->drawStyledItemRect(r.background(), frameRect, p);
1964 const auto *indicator = r.indicator();
1965 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
1967 QRect contentRect = frameRect.marginsRemoved(metrics.padding);
1968 const int iw = QtPrivate::qSaturateRound(
1969 resolvedWidth(indicator,
1971 - metrics.indicatorMargins.left()
1972 - metrics.indicatorMargins.right()));
1973 const int ih = QtPrivate::qSaturateRound(
1974 resolvedHeight(indicator,
1975 contentRect.height()
1976 - metrics.indicatorMargins.top()
1977 - metrics.indicatorMargins.bottom()));
1978 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignHCenter,
1980 const QRect indicatorRect = d->getAlignedRectInContainer(
1981 contentRect, QSize(iw, ih), alignment, QMargins(), metrics.indicatorMargins);
1982 d->drawControlIndicator(indicator, visualRect(opt->direction, contentRect, indicatorRect),
1990 QCommonStyle::drawPrimitive(pe, opt, p, w);
1994void QStyleKitStyle::drawControl(ControlElement element,
const QStyleOption *opt, QPainter *p,
1995 const QWidget *w)
const
1997 Q_D(
const QStyleKitStyle);
2001 if (
const QStyleOptionButton *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2002 proxy()->drawControl(CE_PushButtonBevel, btn, p, w);
2003 QStyleOptionButton btnContent(*btn);
2004 btnContent.rect = subElementRect(SE_PushButtonContents, btn, w);
2005 proxy()->drawControl(CE_PushButtonLabel, &btnContent, p, w);
2008 case CE_PushButtonBevel:
2009 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2010 QStyleOptionButton btnBg(*btn);
2011 btnBg.rect = subElementRect(SE_PushButtonBevel, btn, w);
2012 proxy()->drawPrimitive(PE_FrameButtonBevel, &btnBg, p, w);
2015 case CE_PushButtonLabel:
2016 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2017 const auto controlType = btn->features & QStyleOptionButton::Flat
2018 ? QQStyleKitReader::ControlType::FlatButton
2019 : QQStyleKitReader::ControlType::Button;
2020 const auto r = d->resolve(w, controlType, btn->state);
2023 const auto metrics = r.metrics;
2025 QRect textRect = opt->rect;
2026 uint textFlags = Qt::TextShowMnemonic;
2027 if (!styleHint(SH_UnderlineShortcut, opt, w))
2028 textFlags |= Qt::TextHideMnemonic;
2031 const QIcon icon = btn->icon;
2032 if (!icon.isNull()) {
2033 const auto *textProps = r.text();
2034 uint iconTextFlags = textFlags;
2035 iconTextFlags |= textProps
2036 ? resolvedAlignment(textProps->alignment(), Qt::AlignHCenter, Qt::AlignVCenter)
2037 : uint(Qt::AlignHCenter | Qt::AlignVCenter);
2038 QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
2039 if (mode == QIcon::Normal && btn->state & State_HasFocus)
2040 mode = QIcon::Active;
2041 QIcon::State iconState = btn->state & State_On ? QIcon::On : QIcon::Off;
2042 const auto paintDeviceDpr = p->device()->devicePixelRatio();
2043 QPixmap pixmap = icon.pixmap(btn->iconSize, paintDeviceDpr, mode, iconState);
2044 int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
2045 int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
2046 int labelWidth = pixmapWidth;
2047 int iconSpacing = metrics->spacing;
2048 int textWidth = btn->fontMetrics
2049 .boundingRect(opt->rect, iconTextFlags, btn->text)
2051 if (!btn->text.isEmpty()) {
2052 labelWidth += (textWidth
2053 + iconSpacing + textProps->leftPadding() + textProps->rightPadding());
2057 if (iconTextFlags & Qt::AlignLeft) {
2058 iconRect = QRect(textRect.x(),
2059 textRect.y() + (textRect.height() - pixmapHeight) / 2,
2060 pixmapWidth, pixmapHeight);
2061 }
else if (iconTextFlags & Qt::AlignHCenter) {
2062 iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
2063 textRect.y() + (textRect.height() - pixmapHeight) / 2,
2064 pixmapWidth, pixmapHeight);
2066 iconRect = QRect(textRect.x() + textRect.width() - labelWidth,
2067 textRect.y() + (textRect.height() - pixmapHeight) / 2,
2068 pixmapWidth, pixmapHeight);
2070 iconRect = visualRect(btn->direction, textRect, iconRect);
2073 textFlags &= ~Qt::AlignHorizontal_Mask;
2074 textFlags |= Qt::AlignLeft;
2075 if (btn->direction == Qt::RightToLeft)
2076 textRect.setRight(iconRect.left() - iconSpacing);
2078 textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing);
2080 p->drawPixmap(iconRect, pixmap);
2083 if (btn->features & QStyleOptionButton::HasMenu) {
2084 int indicatorSize = pixelMetric(PM_MenuButtonIndicator, btn, w);
2085 if (btn->direction == Qt::LeftToRight)
2086 textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
2088 textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
2090 d->drawControlText(r.text(), r.font(), textRect, btn->text, textFlags, p);
2095 case CE_RadioButton:
2096 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2097 const auto controlType = element == CE_CheckBox
2098 ? QQStyleKitReader::ControlType::CheckBox
2099 : QQStyleKitReader::ControlType::RadioButton;
2100 const auto r = d->resolve(w, controlType, btn->state);
2103 QRect backgroundRect = btn->rect.marginsRemoved(r.metrics->margins);
2105 d->drawStyledItemRect(r.background(), backgroundRect, p);
2107 QStyleOptionButton btnContent(*btn);
2108 const auto contentElement = element == CE_CheckBox
2109 ? SE_CheckBoxContents
2110 : SE_RadioButtonContents;
2111 btnContent.rect = subElementRect(contentElement, btn, w);
2112 const auto labelElement = element == CE_CheckBox
2114 : CE_RadioButtonLabel;
2115 proxy()->drawControl(labelElement, &btnContent, p, w);
2117 QStyleOptionButton indicator(*btn);
2118 const auto indicatorElement = element == CE_CheckBox
2119 ? SE_CheckBoxIndicator
2120 : SE_RadioButtonIndicator;
2121 indicator.rect = subElementRect(indicatorElement, btn, w);
2122 const auto primitiveElement = element == CE_CheckBox
2123 ? PE_IndicatorCheckBox
2124 : PE_IndicatorRadioButton;
2125 proxy()->drawPrimitive(primitiveElement, &indicator, p, w);
2129 case CE_CheckBoxLabel:
2130 case CE_RadioButtonLabel:
2131 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2132 const auto controlType = element == CE_CheckBoxLabel
2133 ? QQStyleKitReader::ControlType::CheckBox
2134 : QQStyleKitReader::ControlType::RadioButton;
2135 const auto r = d->resolve(w, controlType, btn->state);
2138 uint textFlags = Qt::TextShowMnemonic;
2139 if (!styleHint(SH_UnderlineShortcut, opt, w))
2140 textFlags |= Qt::TextHideMnemonic;
2141 d->drawControlText(r.text(), r.font(), opt->rect, btn->text, textFlags, p);
2145#if QT_CONFIG(combobox)
2146 case CE_ComboBoxLabel:
2147 if (
const auto *comboBox = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
2148 if (comboBox->editable)
2150 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, comboBox->state);
2153 const QRect textRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, w)
2154 .marginsRemoved(r.metrics->textPadding);
2155 uint textFlags = Qt::TextShowMnemonic;
2156 if (!styleHint(SH_UnderlineShortcut, opt, w))
2157 textFlags |= Qt::TextHideMnemonic;
2158 d->drawControlText(r.text(), r.font(), textRect, comboBox->currentText, textFlags, p);
2163#if QT_CONFIG(progressbar)
2164 case CE_ProgressBar:
2165 if (
const QStyleOptionProgressBar *progressBar =
2166 qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
2167 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar,
2168 progressBar->state);
2171 QRect backgroundRect = progressBar->rect.marginsRemoved(r.metrics->margins);
2173 d->drawStyledItemRect(r.background(), backgroundRect, p);
2175 QStyleOptionProgressBar contents(*progressBar);
2176 contents.rect = subElementRect(SE_ProgressBarGroove, progressBar, w);
2177 const QRect grooveRect = contents.rect;
2178 proxy()->drawControl(CE_ProgressBarGroove, &contents, p, w);
2180 contents.rect = subElementRect(SE_ProgressBarContents, progressBar, w);
2183 QPainterStateGuard stateGuard(p);
2184 if (applyDelegateTransform(p, r.indicator(), grooveRect))
2185 proxy()->drawControl(CE_ProgressBarContents, &contents, p, w);
2190 case CE_ProgressBarGroove: {
2192 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar, opt->state);
2195 d->drawStyledItemRect(r.indicator(), opt->rect, p);
2198 case CE_ProgressBarContents:
2200 if (
const auto *progressBar = qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
2201 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar,
2202 progressBar->state);
2205 const auto progress = progressBar->progress;
2206 const auto ratio = progressBar->maximum > progressBar->minimum
2207 ? (progress - progressBar->minimum)
2208 /
static_cast<qreal>(progressBar->maximum - progressBar->minimum)
2210 const auto width =
static_cast<
int>(progressBar->rect.width() * ratio);
2211 const auto x = progressBar->invertedAppearance
2212 ? progressBar->rect.right() - width
2213 : progressBar->rect.left();
2214 const auto contentsRect = QRect(x, progressBar->rect.y(),
2215 width, progressBar->rect.height());
2216 const auto *foreground = r.indicator() ? r.indicator()->foreground() :
nullptr;
2217 if (foreground && foreground->visible() && foreground->opacity() > 0) {
2218 QPainterStateGuard stateGuard(p);
2219 if (applyDelegateTransform(p, foreground, progressBar->rect))
2220 d->drawStyledItemContents(foreground, contentsRect, p);
2226#if QT_CONFIG(itemviews)
2227 case CE_ItemViewItem:
2228 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
2229 const auto r = d->resolveSubElement(w, opt, itemViewControlType(opt), opt->state);
2232 QStyleOptionViewItem optBg(*itemViewOption);
2233 optBg.rect = optBg.rect.marginsRemoved(r.metrics->margins);
2234 QRect indicatorRect = subElementRect(SE_ItemViewItemCheckIndicator, itemViewOption, w);
2235 QRect iconRect = subElementRect(SE_ItemViewItemDecoration, itemViewOption, w);
2236 QRect textRect = subElementRect(SE_ItemViewItemText, itemViewOption, w);
2239 const auto *itemTextProps = r.text();
2240 const QFont itemFont = r.font();
2243 proxy()->drawPrimitive(PE_PanelItemViewItem, &optBg, p, w);
2246 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator) {
2247 QStyleOptionViewItem option(*itemViewOption);
2248 option.rect = indicatorRect;
2249 option.state = option.state & ~QStyle::State_HasFocus;
2251 switch (itemViewOption->checkState) {
2253 option.state |= QStyle::State_Off;
2255 case Qt::PartiallyChecked:
2256 option.state |= QStyle::State_NoChange;
2259 option.state |= QStyle::State_On;
2262 proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, p, w);
2266 QIcon::Mode mode = QIcon::Normal;
2267 if (!(itemViewOption->state & QStyle::State_Enabled))
2268 mode = QIcon::Disabled;
2269 else if (itemViewOption->state & QStyle::State_Selected)
2270 mode = QIcon::Selected;
2271 QIcon::State state = itemViewOption->state & QStyle::State_Open
2274 itemViewOption->icon.paint(p, iconRect, itemViewOption->decorationAlignment, mode,
2278 uint textFlags = Qt::TextShowMnemonic;
2279 if (!styleHint(SH_UnderlineShortcut, opt, w))
2280 textFlags |= Qt::TextHideMnemonic;
2281 d->drawControlText(itemTextProps, itemFont, textRect, itemViewOption->text, textFlags,
2282 p, Qt::AlignLeft | Qt::AlignVCenter);
2288 case CE_ShapedFrame: {
2289# if QT_CONFIG(scrollarea)
2290 if (qobject_cast<
const QAbstractScrollArea *>(w))
2294 auto controlType = QQStyleKitReader::ControlType::Frame;
2295# if QT_CONFIG(combobox)
2296 if (w && w->inherits(
"QComboBoxPrivateContainer"))
2297 controlType = QQStyleKitReader::ControlType::Popup;
2299# if QT_CONFIG(textedit)
2300 else if (w && qobject_cast<
const QTextEdit *>(w))
2301 controlType = QQStyleKitReader::ControlType::TextArea;
2303# if QT_CONFIG(label)
2304 else if (w && qobject_cast<
const QLabel *>(w))
2305 controlType = QQStyleKitReader::ControlType::Label;
2308 if (qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
2309 const auto r = d->resolve(w, controlType, opt->state);
2312 QRect backgroundRect = opt->rect.marginsRemoved(r.metrics->margins);
2313 d->drawStyledItemRect(r.background(), backgroundRect, p);
2319#if QT_CONFIG(scrollbar)
2320 case CE_ScrollBarSlider: {
2321 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ScrollBar, opt->state);
2324 d->drawControlIndicator(r.indicator(), opt->rect, p);
2328#if QT_CONFIG(toolbutton)
2329 case CE_ToolButtonLabel:
2330 if (
const auto *tool = qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
2331 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolButton, tool->state);
2334 const auto *metrics = r.metrics;
2335 QRect rect = tool->rect.marginsRemoved(metrics->textPadding);
2337 uint textFlags = Qt::TextShowMnemonic;
2338 if (!styleHint(SH_UnderlineShortcut, opt, w))
2339 textFlags |= Qt::TextHideMnemonic;
2341 const bool hasArrow = tool->features & QStyleOptionToolButton::Arrow;
2342 if ((!hasArrow && tool->icon.isNull() && !tool->text.isEmpty())
2343 || tool->toolButtonStyle == Qt::ToolButtonTextOnly) {
2344 d->drawControlText(r.text(), r.font(), rect, tool->text, textFlags, p);
2350 if (!hasArrow && !tool->icon.isNull()) {
2351 const QIcon::State iconState = tool->state & State_On ? QIcon::On : QIcon::Off;
2353 if (!(tool->state & State_Enabled))
2354 mode = QIcon::Disabled;
2355 else if ((tool->state & State_MouseOver) && (tool->state & State_AutoRaise))
2356 mode = QIcon::Active;
2358 mode = QIcon::Normal;
2359 pm = tool->icon.pixmap(tool->iconSize, p->device()->devicePixelRatio(), mode,
2361 pmSize = pm.size() / pm.devicePixelRatio();
2364 if (tool->toolButtonStyle == Qt::ToolButtonIconOnly || tool->text.isEmpty()) {
2366 p->drawPixmap(visualRect(tool->direction, rect,
2367 QRect(rect.x() + (rect.width() - pmSize.width()) / 2,
2368 rect.y() + (rect.height() - pmSize.height()) / 2,
2369 pmSize.width(), pmSize.height())),
2375 if (tool->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
2377 const QRect pr(rect.x() + (rect.width() - pmSize.width()) / 2, rect.y(),
2378 pmSize.width(), pmSize.height());
2379 p->drawPixmap(visualRect(tool->direction, rect, pr), pm);
2381 tr.setTop(rect.y() + pmSize.height() + metrics->spacing);
2382 d->drawControlText(r.text(), r.font(), visualRect(tool->direction, rect, tr),
2383 tool->text, textFlags, p, Qt::AlignCenter);
2385 d->drawControlText(r.text(), r.font(), rect, tool->text, textFlags, p,
2390 const QRect pr(rect.x(), rect.y() + (rect.height() - pmSize.height()) / 2,
2391 pmSize.width(), pmSize.height());
2392 p->drawPixmap(visualRect(tool->direction, rect, pr), pm);
2394 tr.setLeft(rect.x() + pmSize.width() + metrics->spacing);
2395 d->drawControlText(r.text(), r.font(), visualRect(tool->direction, rect, tr),
2396 tool->text, textFlags, p, Qt::AlignLeft | Qt::AlignVCenter);
2398 d->drawControlText(r.text(), r.font(), rect, tool->text, textFlags, p,
2399 Qt::AlignLeft | Qt::AlignVCenter);
2408 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
2409 using QtPrivate::qSaturateRound;
2411 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
2412 const auto r = d->resolve(w, QQStyleKitReader::ControlType::MenuSeparator,
2416 const auto metrics = r.metrics;
2417 QRect contentRect = opt->rect
2418 .marginsRemoved(metrics->margins)
2419 .marginsRemoved(metrics->padding);
2420 const auto *indicator = r.indicator();
2421 if (indicator && indicator->visible() && indicator->opacity() > 0) {
2422 const int w = qSaturateRound(resolvedWidth(
2424 contentRect.width() - indicator->leftMargin() - indicator->rightMargin()));
2425 const int h = qSaturateRound(resolvedHeight(
2427 contentRect.height() - indicator->topMargin() - indicator->bottomMargin()));
2428 const uint align = resolvedAlignment(indicator->alignment(), Qt::AlignHCenter,
2430 const QRect indicatorRect = d->getAlignedRectInContainer(
2431 contentRect, QSize(w, h), align, QMargins(), elementMargins(indicator));
2432 d->drawControlIndicator(
2433 indicator, visualRect(opt->direction, contentRect, indicatorRect), p);
2438 QStyle::State adjustedState = menuItem->state;
2439 if (adjustedState & State_Selected)
2440 adjustedState |= State_MouseOver;
2442 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::MenuItem,
2448 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
2451 const QRect contentRect = opt->rect.marginsRemoved(r.metrics->padding);
2452 const auto *indicator = r.indicator();
2453 const auto *first = indicator ? indicator->first() :
nullptr;
2454 const auto *second = indicator ? indicator->second() :
nullptr;
2455 int leftOffset = 0, rightOffset = 0;
2456 const int spacing = r.metrics->spacing;
2457 QRect firstDrawRect, secondDrawRect;
2458 auto placeSubIndicator = [&](
const QQStyleKitIndicatorProperties *sub,
2462 const QSize sz(qSaturateRound(sub->width()), qSaturateRound(sub->height()));
2463 const QMargins subMargins = elementMargins(sub);
2464 const int slotW = qSaturateRound(sub->leftMargin() + sub->width() + sub->rightMargin());
2465 if (sub->alignment() & Qt::AlignRight) {
2466 const QRect slot(contentRect.right() - rightOffset - slotW, contentRect.top(),
2467 slotW, contentRect.height());
2468 drawRect = d->getAlignedRectInContainer(
2469 slot, sz, Qt::AlignRight | Qt::AlignVCenter, { }, subMargins);
2470 rightOffset += slotW + spacing;
2472 const QRect slot(contentRect.left() + leftOffset, contentRect.top(), slotW,
2473 contentRect.height());
2474 drawRect = d->getAlignedRectInContainer(
2475 slot, sz, Qt::AlignLeft | Qt::AlignVCenter, { }, subMargins);
2476 leftOffset += slotW + spacing;
2479 placeSubIndicator(first, firstDrawRect);
2480 placeSubIndicator(second, secondDrawRect);
2482 if (first && menuItem->checkType != QStyleOptionMenuItem::NotCheckable
2483 && menuItem->checked) {
2484 d->drawControlIndicator(
2485 first, visualRect(menuItem->direction, contentRect, firstDrawRect), p);
2488 if (second && menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {
2489 d->drawControlIndicator(
2490 second, visualRect(menuItem->direction, contentRect, secondDrawRect), p);
2494 QRect textRect = contentRect
2495 .adjusted(leftOffset, 0, -rightOffset, 0)
2496 .marginsRemoved(r.metrics->textPadding);
2497 if (!menuItem->icon.isNull()) {
2498 const int iconW = menuItem->maxIconWidth;
2499 const QIcon::Mode mode = (menuItem->state & State_Enabled)
2502 const int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt, w);
2503 const QPixmap pm = menuItem->icon.pixmap(
2504 QSize(iconExtent, iconExtent), p->device()->devicePixelRatio(), mode);
2505 const QSize pmSize = pm.size() / pm.devicePixelRatio();
2506 const int pmW = pmSize.width();
2507 const int pmH = pmSize.height();
2509 visualRect(menuItem->direction, textRect,
2510 QRect(textRect.left(),
2511 textRect.top() + (textRect.height() - pmH) / 2, pmW, pmH)),
2513 textRect.setLeft(textRect.left() + iconW + r.metrics->spacing);
2516 const int tabIdx = menuItem->text.indexOf(QLatin1Char(
'\t'));
2517 const QString label = tabIdx >= 0 ? menuItem->text.left(tabIdx) : menuItem->text;
2518 const QString shortcut = tabIdx >= 0 ? menuItem->text.mid(tabIdx + 1) : QString();
2519 uint textFlags = Qt::TextShowMnemonic;
2520 if (!styleHint(SH_UnderlineShortcut, opt, w))
2521 textFlags |= Qt::TextHideMnemonic;
2522 QRect labelRect = textRect;
2523 if (!shortcut.isEmpty() && menuItem->reservedShortcutWidth > 0) {
2524 const QRect shortcutRect(textRect.right() - menuItem->reservedShortcutWidth + 1,
2525 textRect.top(), menuItem->reservedShortcutWidth,
2527 labelRect.setRight(shortcutRect.left() - r.metrics->spacing - 1);
2528 const int shortcutFlags =
2529 int(QStyle::visualAlignment(menuItem->direction,
2530 Qt::AlignRight | Qt::AlignVCenter))
2533 p->setFont(r.font().resolve(p->font()));
2534 p->setBrush(Qt::NoBrush);
2535 if (
const auto *shortcutText = r.text())
2536 p->setPen(shortcutText->color());
2537 p->drawText(visualRect(menuItem->direction, textRect, shortcutRect), shortcutFlags,
2541 d->drawControlText(r.text(), r.font(),
2542 visualRect(menuItem->direction, textRect, labelRect), label,
2543 textFlags, p, Qt::AlignLeft | Qt::AlignVCenter);
2549 case CE_MenuScroller:
2550 case CE_MenuTearoff:
2552 case CE_MenuEmptyArea:
2555#if QT_CONFIG(menubar)
2556 case CE_MenuBarEmptyArea:
2558 case CE_MenuBarItem:
2559 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
2560 QStyle::State adjustedState = menuItem->state;
2561 if (adjustedState & State_Selected)
2562 adjustedState |= State_MouseOver;
2563 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::MenuBarItem,
2567 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
2568 const QRect textRect = opt->rect.marginsRemoved(
2569 r.metrics->margins + r.metrics->padding + r.metrics->textPadding);
2570 uint textFlags = Qt::TextShowMnemonic;
2571 if (!styleHint(SH_UnderlineShortcut, opt, w))
2572 textFlags |= Qt::TextHideMnemonic;
2573 d->drawControlText(r.text(), r.font(), textRect, menuItem->text, textFlags, p);
2578#if QT_CONFIG(tabbar)
2580 if (
const auto *tab = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
2581 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::TabButton,
2585 const auto &m = *r.metrics;
2587 const QRect backgroundRect = opt->rect.marginsRemoved(m.margins);
2588 d->drawStyledItemRect(r.background(), backgroundRect, p);
2590 const QRect contentRect = backgroundRect.marginsRemoved(m.padding);
2591 uint textFlags = Qt::TextShowMnemonic;
2592 if (!styleHint(SH_UnderlineShortcut, opt, w))
2593 textFlags |= Qt::TextHideMnemonic;
2595 if (!tab->icon.isNull()) {
2596 const QIcon::Mode mode = (tab->state & State_Enabled)
2599 const QIcon::State iconState = (tab->state & State_Selected)
2602 const QPixmap pm = tab->icon.pixmap(tab->iconSize, p->device()->devicePixelRatio(),
2604 const QSize pmSize = pm.size() / pm.devicePixelRatio();
2605 const QRect pr(contentRect.x(),
2606 contentRect.y() + (contentRect.height() - pmSize.height()) / 2,
2607 pmSize.width(), pmSize.height());
2608 p->drawPixmap(visualRect(tab->direction, contentRect, pr), pm);
2609 QRect tr = contentRect;
2610 tr.setLeft(contentRect.x() + pmSize.width() + m.spacing);
2611 d->drawControlText(r.text(), r.font(), visualRect(tab->direction, contentRect, tr),
2612 tab->text, textFlags, p, Qt::AlignCenter);
2614 d->drawControlText(r.text(), r.font(), contentRect, tab->text, textFlags, p,
2621#if QT_CONFIG(toolbar)
2623 if (
const auto *toolBar = qstyleoption_cast<
const QStyleOptionToolBar *>(opt)) {
2624 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolBar, toolBar->state);
2627 d->drawStyledItemRect(r.background(), opt->rect.marginsRemoved(r.metrics->margins), p);
2635 QCommonStyle::drawControl(element, opt, p, w);
2639QRect QStyleKitStyle::subElementRect(SubElement r,
const QStyleOption *opt,
2640 const QWidget *widget)
const
2642 using QtPrivate::qSaturateRound;
2643 Q_D(
const QStyleKitStyle);
2646 case SE_PushButtonBevel:
2647 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2648 const auto controlType = btn->features & QStyleOptionButton::Flat
2649 ? QQStyleKitReader::ControlType::FlatButton
2650 : QQStyleKitReader::ControlType::Button;
2651 const auto resolved = d->resolveLayout(controlType, opt->state);
2652 if (!resolved.isValid())
2654 const auto &metrics = *resolved.metrics;
2655 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2656 return visualRect(opt->direction, opt->rect, rect);
2659 case SE_PushButtonContents:
2660 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2661 const auto controlType = btn->features & QStyleOptionButton::Flat
2662 ? QQStyleKitReader::ControlType::FlatButton
2663 : QQStyleKitReader::ControlType::Button;
2664 const auto resolved = d->resolveLayout(controlType, opt->state);
2665 if (!resolved.isValid())
2667 const auto &metrics = *resolved.metrics;
2668 QRect rect = opt->rect.marginsRemoved(
2669 metrics.margins + metrics.padding + metrics.textPadding);
2670 return visualRect(opt->direction, opt->rect, rect);
2673 case SE_CheckBoxContents:
2674 case SE_RadioButtonContents: {
2675 const auto controlType = r == SE_CheckBoxContents
2676 ? QQStyleKitReader::ControlType::CheckBox
2677 : QQStyleKitReader::ControlType::RadioButton;
2678 const auto resolved = d->resolveLayout(controlType, opt->state);
2679 if (!resolved.isValid())
2681 const auto &metrics = *resolved.metrics;
2682 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
2683 const auto subElement = r == SE_CheckBoxContents
2684 ? SE_CheckBoxIndicator
2685 : SE_RadioButtonIndicator;
2686 QRect indicatorRect = visualRect(opt->direction, opt->rect,
2687 subElementRect(subElement, opt, widget));
2688 const int spacing = metrics.spacing;
2689 const auto *indicator = resolved.indicator();
2690 const uint alignment = indicator
2691 ? resolvedAlignment(indicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
2692 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2693 if (alignment & Qt::AlignLeft) {
2694 contentsRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
2695 }
else if (alignment & Qt::AlignHCenter) {
2696 contentsRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
2697 contentsRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
2699 contentsRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
2701 return visualRect(opt->direction, opt->rect, contentsRect);
2703 case SE_CheckBoxIndicator:
2704 case SE_RadioButtonIndicator: {
2705 const auto controlType = r == SE_CheckBoxIndicator
2706 ? QQStyleKitReader::ControlType::CheckBox
2707 : QQStyleKitReader::ControlType::RadioButton;
2708 const auto resolved = d->resolveLayout(controlType, opt->state);
2709 if (!resolved.isValid())
2711 const auto &metrics = *resolved.metrics;
2712 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2713 const auto *indicator = resolved.indicator();
2714 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2717 const int w = qSaturateRound(resolvedWidth(
2719 rect.width() - metrics.padding.left() - metrics.padding.right()
2720 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right()));
2721 const int h = qSaturateRound(resolvedHeight(
2724 - metrics.padding.top() - metrics.padding.bottom()
2725 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom()));
2726 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft,
2728 const QRect indicatorRect = d->getAlignedRectInContainer(
2729 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
2730 return visualRect(opt->direction, rect, indicatorRect);
2732#if QT_CONFIG(itemviews)
2733 case SE_ItemViewItemCheckIndicator: {
2734 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
2735 if (!resolved.isValid())
2737 const auto &metrics = *resolved.metrics;
2738 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2739 const auto *indicator = resolved.indicator();
2740 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2743 const int w = qSaturateRound(resolvedWidth(
2746 - metrics.padding.left() - metrics.padding.right()
2747 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right()));
2748 const int h = qSaturateRound(resolvedHeight(
2750 rect.height() - metrics.padding.top() - metrics.padding.bottom()
2751 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom()));
2752 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft,
2754 const QRect indicatorRect = d->getAlignedRectInContainer(
2755 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
2756 return visualRect(opt->direction, rect, indicatorRect);
2758 case SE_ItemViewItemDecoration:
2759 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
2760 if (!(itemViewOption->features & QStyleOptionViewItem::HasDecoration))
2762 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
2763 if (!resolved.isValid())
2765 const auto &metrics = *resolved.metrics;
2766 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
2767 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator) {
2768 const QRect indicatorRect = subElementRect(
2769 SE_ItemViewItemCheckIndicator, opt, widget);
2770 const auto *checkIndicator = resolved.indicator();
2771 const uint checkAlign = checkIndicator
2772 ? resolvedAlignment(checkIndicator->alignment(), Qt::AlignLeft,
2774 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2775 if (checkAlign & Qt::AlignLeft) {
2776 contentsRect.setLeft(indicatorRect.right()
2777 + metrics.indicatorMargins.right() + metrics.spacing);
2778 }
else if (checkAlign & Qt::AlignRight) {
2779 contentsRect.setRight(indicatorRect.left()
2780 - metrics.indicatorMargins.left() - metrics.spacing);
2784 const QSize decorationSize = itemViewOption->decorationSize
2785 .boundedTo(contentsRect.size());
2786 QRect decorationRect;
2787 switch (itemViewOption->decorationPosition) {
2788 case QStyleOptionViewItem::Top:
2789 decorationRect = QRect(contentsRect.left(), contentsRect.top(),
2790 contentsRect.width(), decorationSize.height());
2792 case QStyleOptionViewItem::Bottom:
2793 decorationRect = QRect(contentsRect.left(),
2794 contentsRect.bottom() - decorationSize.height() + 1,
2795 contentsRect.width(), decorationSize.height());
2797 case QStyleOptionViewItem::Right:
2798 decorationRect = QRect(contentsRect.right() - decorationSize.width() + 1,
2799 contentsRect.top(), decorationSize.width(),
2800 contentsRect.height());
2802 case QStyleOptionViewItem::Left:
2804 decorationRect = QRect(contentsRect.left(), contentsRect.top(),
2805 decorationSize.width(), contentsRect.height());
2808 const uint decorationAlign = resolvedAlignment(itemViewOption->decorationAlignment,
2809 Qt::AlignLeft, Qt::AlignVCenter);
2810 decorationRect = d->getAlignedRectInContainer(
2811 decorationRect, decorationSize, decorationAlign, QMargins(0, 0, 0, 0),
2812 QMargins(0, 0, 0, 0));
2813 return visualRect(opt->direction, opt->rect, decorationRect);
2816 case SE_ItemViewItemText:
2817 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
2818 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
2819 if (!resolved.isValid())
2821 const auto &metrics = *resolved.metrics;
2822 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
2823 const int spacing = metrics.spacing;
2825 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator) {
2826 const QRect indicatorRect = subElementRect(
2827 SE_ItemViewItemCheckIndicator, opt, widget);
2828 const auto *checkIndicator = resolved.indicator();
2829 const uint checkAlign = checkIndicator
2830 ? resolvedAlignment(checkIndicator->alignment(), Qt::AlignLeft,
2832 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2833 if (checkAlign & Qt::AlignLeft) {
2834 contentsRect.setLeft(
2835 indicatorRect.right() + metrics.indicatorMargins.right() + spacing);
2836 }
else if (checkAlign & Qt::AlignRight) {
2837 contentsRect.setRight(
2838 indicatorRect.left() - metrics.indicatorMargins.left() - spacing);
2842 QRect textRect = contentsRect;
2843 if (itemViewOption->features & QStyleOptionViewItem::HasDecoration) {
2844 const QRect decorationRect = subElementRect(
2845 SE_ItemViewItemDecoration, opt, widget);
2846 switch (itemViewOption->decorationPosition) {
2847 case QStyleOptionViewItem::Top:
2848 textRect.setTop(decorationRect.bottom() + spacing);
2850 case QStyleOptionViewItem::Bottom:
2851 textRect.setBottom(decorationRect.top() - spacing);
2853 case QStyleOptionViewItem::Right:
2854 textRect.setRight(decorationRect.left() - spacing);
2856 case QStyleOptionViewItem::Left:
2858 textRect.setLeft(decorationRect.right() + spacing);
2863 const auto *textProps = resolved.text();
2864 const uint textAlign = textProps
2865 ? resolvedAlignment(textProps->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
2866 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2867 if (textAlign & Qt::AlignLeft) {
2868 textRect.setLeft(textRect.left() + metrics.textPadding.left());
2869 }
else if (textAlign & Qt::AlignHCenter) {
2870 textRect.setLeft(textRect.left() + metrics.textPadding.left() / 2);
2871 textRect.setRight(textRect.right() - metrics.textPadding.right() / 2);
2873 textRect.setRight(textRect.right() - metrics.textPadding.right());
2875 if (textAlign & Qt::AlignTop) {
2876 textRect.setTop(textRect.top() + metrics.textPadding.top());
2877 }
else if (textAlign & Qt::AlignVCenter) {
2878 textRect.setTop(textRect.top() + metrics.textPadding.top() / 2);
2879 textRect.setBottom(textRect.bottom() - metrics.textPadding.bottom() / 2);
2881 textRect.setBottom(textRect.bottom() - metrics.textPadding.bottom());
2883 return visualRect(opt->direction, opt->rect, textRect);
2887 case SE_PushButtonFocusRect:
2888 case SE_CheckBoxClickRect:
2889 case SE_RadioButtonClickRect:
2891#if QT_CONFIG(progressbar)
2892 case SE_ProgressBarGroove: {
2893 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar,
2895 if (!resolved.isValid())
2897 const auto &metrics = *resolved.metrics;
2898 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2899 const auto *indicator = resolved.indicator();
2900 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2903 const int w = qSaturateRound(resolvedWidth(
2905 rect.width() - metrics.padding.left() - metrics.padding.right()
2906 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right()));
2907 const int h = qSaturateRound(resolvedHeight(
2909 rect.height() - metrics.padding.top() - metrics.padding.bottom()
2910 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom()));
2911 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft,
2913 const QRect indicatorRect = d->getAlignedRectInContainer(
2914 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
2915 return visualRect(opt->direction, rect, indicatorRect);
2917 case SE_ProgressBarContents: {
2918 if (qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
2919 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar,
2921 if (!resolved.isValid())
2923 const auto *foreground = resolved.indicator()
2924 ? resolved.indicator()->foreground()
2926 if (!foreground || !foreground->visible() || foreground->opacity() == 0)
2929 QRect indicatorRect = subElementRect(SE_ProgressBarGroove, opt, widget);
2930 const int foregroundW = qSaturateRound(resolvedWidth(
2932 indicatorRect.width() - foreground->leftMargin() - foreground->rightMargin()));
2933 const int foregroundH = qSaturateRound(resolvedHeight(
2935 indicatorRect.height() - foreground->topMargin() - foreground->bottomMargin()));
2936 const uint foregroundAlign = resolvedAlignment(foreground->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
2937 const QMargins foregroundMargins = elementMargins(foreground);
2938 const QRect foregroundRect = d->getAlignedRectInContainer(
2939 indicatorRect, QSize(foregroundW, foregroundH), foregroundAlign,
2940 QMargins(0, 0, 0, 0), foregroundMargins);
2941 return visualRect(opt->direction, opt->rect, foregroundRect);
2946 case SE_LineEditContents:
2947 if (qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
2948#if QT_CONFIG(spinbox)
2949 const bool isInSpinBox = widget && qobject_cast<
const QSpinBox *>(widget->parentWidget());
2951 const bool isInSpinBox =
false;
2953 const auto controlType = isInSpinBox ? QQStyleKitReader::ControlType::SpinBox
2954 : QQStyleKitReader::ControlType::TextField;
2955 const auto resolved = d->resolveLayout(controlType, opt->state);
2956 if (!resolved.isValid())
2958 const auto &metrics = *resolved.metrics;
2959 QRect contentsRect = opt->rect.marginsRemoved(metrics.padding);
2960 const auto *textProps = resolved.text();
2961 const uint textAlign = resolvedAlignment(textProps ? textProps->alignment() : 0u,
2962 Qt::AlignLeft, Qt::AlignVCenter);
2963 if (textAlign & Qt::AlignLeft)
2964 contentsRect.setLeft(contentsRect.left() + metrics.textPadding.left());
2965 else if (textAlign & Qt::AlignHCenter) {
2966 contentsRect.setLeft(contentsRect.left() + metrics.textPadding.left() / 2);
2967 contentsRect.setRight(contentsRect.right() - metrics.textPadding.right() / 2);
2969 contentsRect.setRight(contentsRect.right() - metrics.textPadding.right());
2971 if (textAlign & Qt::AlignTop)
2972 contentsRect.setTop(contentsRect.top() + metrics.textPadding.top());
2973 else if (textAlign & Qt::AlignVCenter) {
2974 contentsRect.setTop(contentsRect.top() + metrics.textPadding.top() / 2);
2975 contentsRect.setBottom(contentsRect.bottom() - metrics.textPadding.bottom() / 2);
2977 contentsRect.setBottom(contentsRect.bottom() - metrics.textPadding.bottom());
2979 return visualRect(opt->direction, opt->rect, contentsRect);
2982 case SE_ShapedFrameContents:
2983#if QT_CONFIG(combobox)
2984 if (widget && widget->inherits(
"QComboBoxPrivateContainer")) {
2985 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Popup,
2987 if (!resolved.isValid())
2989 const auto &metrics = *resolved.metrics;
2990 QRect contentsRect = opt->rect.marginsRemoved(
2991 metrics.margins + metrics.padding + metrics.textPadding);
2992 return visualRect(opt->direction, opt->rect, contentsRect);
2995#if QT_CONFIG(textedit)
2996 if (qobject_cast<
const QTextEdit *>(widget)) {
2997 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::TextArea,
2999 if (!resolved.isValid())
3001 const auto &metrics = *resolved.metrics;
3002 QRect contentsRect = opt->rect.marginsRemoved(
3003 metrics.margins + metrics.padding + metrics.textPadding);
3004 return visualRect(opt->direction, opt->rect, contentsRect);
3008#if QT_CONFIG(tabbar)
3009 case SE_TabBarTabText:
3010 if (
const auto *tab = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
3011 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::TabButton,
3013 if (!resolved.isValid())
3015 const auto &metrics = *resolved.metrics;
3016 QRect rect = tab->rect.marginsRemoved(
3017 metrics.margins + metrics.padding + metrics.textPadding);
3018 if (!tab->icon.isNull())
3019 rect.setLeft(rect.left() + tab->iconSize.width() + metrics.spacing);
3020 return visualRect(tab->direction, tab->rect, rect);
3023 case SE_TabBarTearIndicatorRight:
3024 case SE_TabBarTearIndicatorLeft:
3025 case SE_TabBarScrollLeftButton:
3026 case SE_TabBarScrollRightButton:
3030#if QT_CONFIG(tabwidget)
3031 case SE_TabWidgetTabContents:
3032 if (qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(opt)) {
3034 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Page, opt->state);
3035 if (!resolved.isValid())
3037 const QRect paneRect = subElementRect(SE_TabWidgetTabPane, opt, widget);
3038 const QRect rect = paneRect.marginsRemoved(resolved.metrics->padding);
3039 return visualRect(opt->direction, opt->rect, rect);
3043#if QT_CONFIG(toolbar)
3044 case SE_ToolBarHandle:
3051 return QCommonStyle::subElementRect(r, opt, widget);
3055void QStyleKitStyle::drawComplexControl(ComplexControl cc,
const QStyleOptionComplex *opt,
3056 QPainter *p,
const QWidget *w)
const
3058 Q_D(
const QStyleKitStyle);
3061#if QT_CONFIG(slider)
3063 if (
const QStyleOptionSlider *slider = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3064 const auto r = d->resolve(w, QQStyleKitReader::ControlType::Slider, slider->state);
3067 const auto &metrics = *r.metrics;
3068 QRect backgroundRect = opt->rect.marginsRemoved(metrics.margins);
3071 d->drawStyledItemRect(r.background(), backgroundRect, p);
3074 if (slider->subControls & SC_SliderGroove) {
3076 const auto grooveRect = proxy()->subControlRect(CC_Slider, opt, SC_SliderGroove, w);
3077 const auto *indicator = r.indicator();
3078 d->drawStyledItemRect(indicator, grooveRect, p);
3081 const auto *foreground = indicator ? indicator->foreground() :
nullptr;
3082 if (foreground && foreground->visible() && foreground->opacity() > 0) {
3083 const bool isHorizontal = slider->orientation == Qt::Horizontal;
3084 const qreal availableW = grooveRect.width()
3085 - foreground->leftMargin() - foreground->rightMargin();
3086 const qreal availableH = grooveRect.height()
3087 - foreground->topMargin() - foreground->bottomMargin();
3089 const qreal range = slider->maximum - slider->minimum;
3090 const qreal ratio = range > 0
3091 ? (slider->sliderPosition - slider->minimum) / range
3094 const auto hAlign = foreground->alignment() & Qt::AlignHorizontal_Mask;
3095 const auto vAlign = foreground->alignment() & Qt::AlignVertical_Mask;
3096 const qreal fgW = resolvedWidth(foreground, availableW);
3097 const qreal fgH = resolvedHeight(foreground, availableH);
3098 const qreal fgX = hAlign & Qt::AlignRight
3099 ? grooveRect.left() + foreground->leftMargin() + availableW - fgW
3100 : hAlign & Qt::AlignHCenter
3101 ? grooveRect.left() + foreground->leftMargin() + (availableW - fgW) / 2
3102 : grooveRect.left() + foreground->leftMargin();
3103 const qreal fgY = vAlign & Qt::AlignBottom
3104 ? grooveRect.top() + foreground->topMargin() + availableH - fgH
3105 : vAlign & Qt::AlignVCenter
3106 ? grooveRect.top() + foreground->topMargin() + (availableH - fgH) / 2
3107 : grooveRect.top() + foreground->topMargin();
3109 const qreal minW = foreground->minimumWidth();
3112 const qreal trackW = foreground->fillWidth()
3113 ? minW + ratio * (fgW - minW)
3115 trackRect = QRectF(fgX, fgY, trackW, fgH);
3117 const qreal trackH = foreground->fillHeight()
3118 ? minW + ratio * (fgH - minW)
3120 const qreal trackY = fgY
3121 + (1.0 - ratio) * (foreground->fillHeight() ? fgH - minW : fgH);
3122 trackRect = QRectF(fgX, trackY, fgW, trackH);
3126 const QRect foregroundBox = visualRect(
3127 opt->direction, grooveRect, QRectF(fgX, fgY, fgW, fgH).toAlignedRect());
3128 QPainterStateGuard stateGuard(p);
3129 if (applyDelegateTransform(p, indicator, grooveRect)
3130 && applyDelegateTransform(p, foreground, foregroundBox)) {
3131 d->drawStyledItemContents(
3133 visualRect(opt->direction, grooveRect, trackRect.toAlignedRect()), p);
3139 if (slider->subControls & SC_SliderHandle) {
3140 QStyleOptionSlider handleOpt(*slider);
3141 handleOpt.rect = subControlRect(CC_Slider, opt, SC_SliderHandle, w);
3142 const auto *handle = r.handle();
3143 if (handle && handle->visible() && handle->opacity() > 0)
3144 d->drawStyledItemRect(handle, handleOpt.rect, p);
3150#if QT_CONFIG(combobox)
3152 if (
const QStyleOptionComboBox *combo =
3153 qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
3155 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, combo->state);
3158 QRect frameRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxFrame, w);
3159 d->drawStyledItemRect(r.background(), frameRect, p);
3162 if (combo->subControls & SC_ComboBoxArrow) {
3163 QStyleOptionComboBox indicatorOpt(*combo);
3164 indicatorOpt.rect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
3165 proxy()->drawPrimitive(PE_IndicatorArrowDown, &indicatorOpt, p, w);
3170 if (
auto *cb = qobject_cast<
const QComboBox *>(w); cb && cb->isEditable()) {
3171 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
3172 QPalette stylePalette;
3173 stylePalette.setColor(QPalette::Text, txt->color());
3174 d->setStylePalette(cb->lineEdit(), stylePalette);
3181#if QT_CONFIG(spinbox)
3183 if (
const QStyleOptionSpinBox *spin = qstyleoption_cast<
const QStyleOptionSpinBox *>(opt)) {
3184 const auto r = d->resolve(w, QQStyleKitReader::ControlType::SpinBox, spin->state);
3187 QRect frameRect = opt->rect.marginsRemoved(r.metrics->margins);
3189 d->drawStyledItemRect(r.background(), frameRect, p);
3191 if (spin->subControls & SC_SpinBoxUp) {
3192 QStyleOptionSpinBox upOpt(*spin);
3193 upOpt.rect = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w);
3194 proxy()->drawPrimitive(PE_IndicatorSpinUp, &upOpt, p, w);
3196 if (spin->subControls & SC_SpinBoxDown) {
3197 QStyleOptionSpinBox downOpt(*spin);
3198 downOpt.rect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
3199 proxy()->drawPrimitive(PE_IndicatorSpinDown, &downOpt, p, w);
3203 if (
auto *sb = qobject_cast<
const QSpinBox *>(w)) {
3204 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
3205 QLineEdit *lineEdit = sb->findChild<QLineEdit *>();
3207 QPalette p = lineEdit->palette();
3208 if (p.color(QPalette::Text) != txt->color()) {
3209 p.setColor(QPalette::Text, txt->color());
3210 lineEdit->setPalette(p);
3219#if QT_CONFIG(groupbox)
3221 if (
const QStyleOptionGroupBox *groupBox =
3222 qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
3223 const auto r = d->resolve(w, QQStyleKitReader::ControlType::GroupBox, groupBox->state);
3228 if (groupBox->subControls & SC_GroupBoxFrame) {
3229 QStyleOptionFrame frameOpt;
3230 frameOpt.QStyleOption::operator=(*groupBox);
3231 frameOpt.rect = subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, w);
3232 drawPrimitive(PE_FrameGroupBox, &frameOpt, p, w);
3236 if (groupBox->subControls & SC_GroupBoxLabel && !groupBox->text.isEmpty()) {
3237 const auto *textProps = r.text();
3238 const QFont textFont = r.font();
3239 QRect titleRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w);
3240 d->drawControlText(textProps, textFont,
3241 titleRect.marginsRemoved(r.metrics->textPadding), groupBox->text,
3242 Qt::TextShowMnemonic, p, Qt::AlignLeft | Qt::AlignVCenter);
3250#if QT_CONFIG(scrollbar)
3252 if (
const auto *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3253 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ScrollBar,
3259 if (scrollbar->subControls & SC_ScrollBarGroove) {
3260 QRect backgroundRect = proxy()->subControlRect(
3261 CC_ScrollBar, opt, SC_ScrollBarGroove, w);
3262 d->drawStyledItemRect(r.background(), backgroundRect, p);
3269 if (scrollbar->subControls & SC_ScrollBarSlider) {
3270 QStyleOptionSlider newScrollbar(*scrollbar);
3271 newScrollbar.rect = proxy()->subControlRect(
3272 CC_ScrollBar, opt, SC_ScrollBarSlider, w);
3273 proxy()->drawControl(CE_ScrollBarSlider, &newScrollbar, p, w);
3279#if QT_CONFIG(toolbutton)
3281 if (
const QStyleOptionToolButton *tool =
3282 qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
3283 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolButton, tool->state);
3288 d->drawStyledItemRect(r.background(), opt->rect, p);
3292 & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay))
3293 == QStyleOptionToolButton::MenuButtonPopup
3294 && (tool->subControls & SC_ToolButtonMenu)) {
3295 const QRect menuRect = subControlRect(CC_ToolButton, opt, SC_ToolButtonMenu, w);
3296 d->drawControlIndicator(r.indicator(), menuRect, p);
3300 State bflags = tool->state & ~State_Sunken;
3301 if (bflags & State_AutoRaise) {
3302 if (!(bflags & State_MouseOver) || !(bflags & State_Enabled))
3303 bflags &= ~State_Raised;
3305 if (tool->state & State_Sunken && tool->activeSubControls & SC_ToolButton)
3306 bflags |= State_Sunken;
3307 QStyleOptionToolButton label = *tool;
3308 label.state = bflags;
3309 label.rect = subControlRect(CC_ToolButton, opt, SC_ToolButton, w);
3310 proxy()->drawControl(CE_ToolButtonLabel, &label, p, w);
3318 QCommonStyle::drawComplexControl(cc, opt, p, w);
3322QStyle::SubControl QStyleKitStyle::hitTestComplexControl(ComplexControl cc,
3323 const QStyleOptionComplex *opt,
3324 const QPoint &pt,
const QWidget *w)
const
3326 return QCommonStyle::hitTestComplexControl(cc, opt, pt, w);
3330QRect QStyleKitStyle::subControlRect(ComplexControl cc,
const QStyleOptionComplex *opt,
3331 SubControl sc,
const QWidget *w)
const
3333 using QtPrivate::qSaturateRound;
3334 Q_D(
const QStyleKitStyle);
3337#if QT_CONFIG(slider)
3339 if (
const QStyleOptionSlider *slider = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3340 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Slider,
3342 if (!resolved.isValid())
3344 const auto &metrics = *resolved.metrics;
3345 const bool horizontal = slider->orientation == Qt::Horizontal;
3346 QRect contentsRect = opt->rect
3347 .marginsRemoved(metrics.margins)
3348 .marginsRemoved(metrics.padding);
3350 const auto *indicator = resolved.indicator();
3352 return contentsRect;
3354 case SC_SliderGroove: {
3355 const auto availableW = contentsRect.width()
3356 - indicator->leftMargin() - indicator->rightMargin();
3357 const auto availableH = contentsRect.height()
3358 - indicator->topMargin() - indicator->bottomMargin();
3359 const qreal grooveW = resolvedWidth(indicator, availableW);
3360 const qreal grooveH = resolvedHeight(indicator, availableH);
3362 QRectF grooveRect(0, 0, grooveW, grooveH);
3363 const uint rawHAlign = indicator->alignment() & Qt::AlignHorizontal_Mask;
3364 const uint rawVAlign = indicator->alignment() & Qt::AlignVertical_Mask;
3365 const uint hAlign = rawHAlign
3366 ?
static_cast<Qt::Alignment>(rawHAlign)
3368 const uint vAlign = rawVAlign
3369 ?
static_cast<Qt::Alignment>(rawVAlign)
3372 if (hAlign & Qt::AlignLeft) {
3373 grooveRect.moveLeft(contentsRect.x() + indicator->leftMargin());
3374 }
else if (hAlign & Qt::AlignHCenter) {
3375 const qreal availableWidth = contentsRect.width()
3376 - indicator->leftMargin() - indicator->rightMargin();
3377 grooveRect.moveLeft(contentsRect.x() + indicator->leftMargin()
3378 + (availableWidth - grooveW) / 2.0);
3380 grooveRect.moveLeft(contentsRect.x() + contentsRect.width()
3381 - indicator->rightMargin() - grooveW);
3384 if (vAlign & Qt::AlignTop) {
3385 grooveRect.moveTop(contentsRect.y() + indicator->topMargin());
3386 }
else if (vAlign & Qt::AlignVCenter) {
3387 const qreal availableHeight = contentsRect.height()
3388 - indicator->topMargin() - indicator->bottomMargin();
3389 grooveRect.moveTop(contentsRect.y()
3390 + indicator->topMargin()
3391 + (availableHeight - grooveH) / 2.0);
3393 grooveRect.moveTop(contentsRect.y()
3394 + contentsRect.height()
3395 - indicator->bottomMargin() - grooveH);
3397 return visualRect(opt->direction, opt->rect, grooveRect.toAlignedRect());
3399 case SC_SliderHandle: {
3400 const auto *handle = resolved.handle();
3401 if (!handle || !handle->visible() || handle->opacity() == 0)
3402 return contentsRect;
3404 const qreal handleW = resolvedWidth(
3405 handle, contentsRect.width() - handle->leftMargin() - handle->rightMargin());
3406 const qreal handleH = resolvedHeight(
3407 handle, contentsRect.height() - handle->topMargin() - handle->bottomMargin());
3408 QRectF handleRect(0, 0, handleW, handleH);
3410 const int range = qSaturateRound(contentsRect.width()
3411 - handle->leftMargin() - handle->rightMargin() - handleW);
3412 const int sliderPos = QStyle::sliderPositionFromValue(
3413 slider->minimum, slider->maximum, slider->sliderPosition, range,
false);
3414 handleRect.moveLeft(contentsRect.x() + handle->leftMargin() + sliderPos);
3415 handleRect.moveTop(contentsRect.y()
3416 + handle->topMargin() - handle->bottomMargin()
3417 + (contentsRect.height() - handleH) / 2.0);
3419 const int range = qSaturateRound(contentsRect.height()
3420 - handle->topMargin() - handle->bottomMargin() - handleH);
3421 const int sliderPos = QStyle::sliderPositionFromValue(
3422 slider->minimum, slider->maximum, slider->sliderPosition, range,
true);
3423 handleRect.moveLeft(contentsRect.x()
3424 + handle->leftMargin() - handle->rightMargin()
3425 + (contentsRect.width() - handleW) / 2.0);
3426 handleRect.moveTop(contentsRect.y() + handle->topMargin() + sliderPos);
3428 return visualRect(opt->direction, opt->rect, handleRect.toAlignedRect());
3436#if QT_CONFIG(combobox)
3438 if (
const QStyleOptionComboBox *combo =
3439 qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
3440 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::ComboBox, combo->state);
3443 const auto &metrics = *r.metrics;
3444 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3446 case SC_ComboBoxFrame:
3447 return visualRect(opt->direction, opt->rect, frameRect);
3448 case SC_ComboBoxEditField: {
3449 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3450 QRect indicatorRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
3451 const int spacing = metrics.spacing;
3452 const auto *indicator = r.indicator();
3453 const uint indicatorAlign = indicator
3454 ? resolvedAlignment(indicator->alignment(), Qt::AlignRight, Qt::AlignVCenter)
3455 : uint(Qt::AlignRight | Qt::AlignVCenter);
3456 if (indicatorAlign & Qt::AlignLeft) {
3457 contentsRect.setLeft(indicatorRect.right() + spacing);
3458 }
else if (indicatorAlign & Qt::AlignRight) {
3459 contentsRect.setRight(indicatorRect.left() - spacing);
3461 return visualRect(opt->direction, opt->rect, contentsRect);
3463 case SC_ComboBoxArrow: {
3464 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3465 const auto *indicator = r.indicator();
3466 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
3469 const int w = qSaturateRound(resolvedWidth(
3471 contentsRect.width() - indicator->leftMargin() - indicator->rightMargin()));
3472 const int h = qSaturateRound(resolvedHeight(
3474 contentsRect.height() - indicator->topMargin() - indicator->bottomMargin()));
3475 const uint indicatorAlign = resolvedAlignment(
3476 indicator->alignment(), Qt::AlignRight, Qt::AlignVCenter);
3477 const QMargins indicatorMargins = elementMargins(indicator);
3479 opt->direction, opt->rect,
3480 d->getAlignedRectInContainer(contentsRect, QSize(w, h),
3481 indicatorAlign, QMargins(),
3484 case SC_ComboBoxListBoxPopup: {
3485 QRect popupRect = opt->rect;
3486 popupRect.setTop(opt->rect.bottom());
3487 return visualRect(opt->direction, opt->rect, popupRect);
3495#if QT_CONFIG(spinbox)
3497 if (
const QStyleOptionSpinBox *spinBox =
3498 qstyleoption_cast<
const QStyleOptionSpinBox *>(opt)) {
3499 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::SpinBox, spinBox->state);
3502 const auto &metrics = *r.metrics;
3503 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3504 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3506 case SC_SpinBoxFrame:
3507 return visualRect(opt->direction, opt->rect, frameRect);
3508 case SC_SpinBoxEditField: {
3509 QRect upIndicatorRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w);
3510 QRect downIndicatorRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
3511 const int spacing = metrics.spacing;
3512 const auto *upIndicator = r.indicator() ? r.indicator()->first() :
nullptr;
3513 const auto *downIndicator = r.indicator() ? r.indicator()->second() :
nullptr;
3514 const bool hasUpIndicator = upIndicator
3515 && upIndicator->visible() && upIndicator->opacity() > 0;
3516 const bool hasDownIndicator = downIndicator
3517 && downIndicator->visible() && downIndicator->opacity() > 0;
3518 const uint upAlign = hasUpIndicator
3519 ? resolvedAlignment(upIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
3520 : uint(Qt::AlignLeft | Qt::AlignVCenter);
3521 const uint downAlign = hasDownIndicator
3522 ? resolvedAlignment(downIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
3523 : uint(Qt::AlignLeft | Qt::AlignVCenter);
3524 if (hasUpIndicator && hasDownIndicator) {
3525 if ((upAlign & Qt::AlignLeft) && (downAlign & Qt::AlignRight)) {
3526 contentsRect.setLeft(upIndicatorRect.right() + spacing);
3527 contentsRect.setRight(downIndicatorRect.left() - spacing);
3528 }
else if ((upAlign & Qt::AlignRight) && (downAlign & Qt::AlignLeft)) {
3529 contentsRect.setRight(upIndicatorRect.left() - spacing);
3530 contentsRect.setLeft(downIndicatorRect.right() + spacing);
3532 }
else if (hasUpIndicator) {
3533 if (upAlign & Qt::AlignLeft) {
3534 contentsRect.setLeft(upIndicatorRect.right() + spacing);
3535 }
else if (upAlign & Qt::AlignRight) {
3536 contentsRect.setRight(upIndicatorRect.left() - spacing);
3538 }
else if (hasDownIndicator) {
3539 if (downAlign & Qt::AlignLeft) {
3540 contentsRect.setLeft(downIndicatorRect.right() + spacing);
3541 }
else if (downAlign & Qt::AlignRight) {
3542 contentsRect.setRight(downIndicatorRect.left() - spacing);
3545 return visualRect(opt->direction, opt->rect, contentsRect);
3547 case SC_SpinBoxUp: {
3548 const auto *upIndicator = r.indicator() ? r.indicator()->first() :
nullptr;
3549 if (!upIndicator || !upIndicator->visible() || upIndicator->opacity() == 0)
3550 return contentsRect;
3552 const int w = qSaturateRound(resolvedWidth(
3554 contentsRect.width() - upIndicator->leftMargin() - upIndicator->rightMargin()));
3555 const int h = qSaturateRound(resolvedHeight(
3557 contentsRect.height() - upIndicator->topMargin() - upIndicator->bottomMargin()));
3558 const uint upAlign = resolvedAlignment(
3559 upIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
3560 const QMargins upMargins = elementMargins(upIndicator);
3561 return visualRect(opt->direction, opt->rect,
3562 d->getAlignedRectInContainer(contentsRect, QSize(w, h), upAlign,
3563 QMargins(), upMargins));
3565 case SC_SpinBoxDown: {
3566 const auto *downIndicator = r.indicator() ? r.indicator()->second() :
nullptr;
3567 if (!downIndicator || !downIndicator->visible() || downIndicator->opacity() == 0)
3570 const int w = qSaturateRound(resolvedWidth(
3572 contentsRect.width()
3573 - downIndicator->leftMargin() - downIndicator->rightMargin()));
3574 const int h = qSaturateRound(resolvedHeight(
3576 contentsRect.height()
3577 - downIndicator->topMargin() - downIndicator->bottomMargin()));
3578 const uint downAlign = resolvedAlignment(downIndicator->alignment(), Qt::AlignLeft,
3580 const QMargins downMargins = elementMargins(downIndicator);
3581 return visualRect(opt->direction, opt->rect,
3582 d->getAlignedRectInContainer(contentsRect, QSize(w, h), downAlign,
3583 QMargins(), downMargins));
3591#if QT_CONFIG(groupbox)
3593 if (
const QStyleOptionGroupBox *groupBox =
3594 qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
3595 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::GroupBox,
3599 const auto &metrics = *r.metrics;
3600 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3602 case SC_GroupBoxFrame:
3603 return visualRect(opt->direction, opt->rect, frameRect);
3604 case SC_GroupBoxLabel: {
3605 const int fontHeight = opt->fontMetrics.height();
3606 const int labelHeight = metrics.textPadding.top()
3607 + fontHeight + metrics.textPadding.bottom();
3608 const QRect labelContainer(opt->rect.left(), opt->rect.top(), opt->rect.width(),
3610 return visualRect(opt->direction, opt->rect, labelContainer);
3612 case SC_GroupBoxCheckBox: {
3616 case SC_GroupBoxContents: {
3617 const auto labelHeight = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w)
3619 const auto offset = metrics.padding.top()
3620 + qMax(labelHeight, metrics.margins.top() + metrics.spacing);
3622 opt->rect.left() + metrics.padding.left(), opt->rect.top() + offset,
3623 opt->rect.width() - metrics.padding.left() - metrics.padding.right(),
3624 opt->rect.bottom() - opt->rect.top() - offset - metrics.padding.bottom());
3625 return visualRect(opt->direction, opt->rect, contentsRect);
3633#if QT_CONFIG(scrollbar)
3635 if (
const auto *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3636 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ScrollBar,
3638 if (!resolved.isValid())
3640 const auto &metrics = *resolved.metrics;
3641 const bool horizontal = scrollbar->orientation == Qt::Horizontal;
3642 const QRectF grooveRect = opt->rect.marginsRemoved(metrics.margins);
3646 case SC_ScrollBarAddLine:
3647 case SC_ScrollBarSubLine:
3648 case SC_ScrollBarSubPage:
3649 case SC_ScrollBarAddPage:
3651 case SC_ScrollBarGroove:
3652 return visualRect(opt->direction, opt->rect, grooveRect.toAlignedRect());
3653 case SC_ScrollBarSlider: {
3654 const auto *indicator = resolved.indicator();
3655 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
3657 const QRectF contentsRect = grooveRect.marginsRemoved(metrics.padding);
3659 const qreal availableW = contentsRect.width()
3660 - indicator->leftMargin() - indicator->rightMargin();
3661 const qreal availableH = contentsRect.height()
3662 - indicator->topMargin() - indicator->bottomMargin();
3664 const int totalRange = scrollbar->maximum
3665 - scrollbar->minimum + scrollbar->pageStep;
3666 const qreal ratio = totalRange > 0 ? qreal(scrollbar->pageStep) / totalRange : 1.0;
3670 const qreal sliderW = qMax(
3671 qreal(metrics.indicatorImplicitSize.width()), availableW * ratio);
3672 const qreal sliderH = resolvedHeight(indicator, availableH);
3673 const qreal travelRange = qMax(0.0, availableW - sliderW);
3674 const int sliderPos = QStyle::sliderPositionFromValue(
3675 scrollbar->minimum, scrollbar->maximum, scrollbar->sliderPosition,
3676 int(travelRange), scrollbar->upsideDown);
3677 sliderRect = QRectF(
3678 contentsRect.x() + indicator->leftMargin() + sliderPos,
3679 contentsRect.y() + indicator->topMargin() + (availableH - sliderH) / 2.0,
3682 const qreal sliderH = qMax(
3683 qreal(metrics.indicatorImplicitSize.width()), availableH * ratio);
3684 const qreal sliderW = resolvedWidth(indicator, availableW);
3685 const qreal travelRange = qMax(0.0, availableH - sliderH);
3686 const int sliderPos = QStyle::sliderPositionFromValue(
3687 scrollbar->minimum, scrollbar->maximum, scrollbar->sliderPosition,
3688 int(travelRange), scrollbar->upsideDown);
3689 sliderRect = QRectF(
3690 contentsRect.x() + indicator->leftMargin() + (availableW - sliderW) / 2.0,
3691 contentsRect.y() + indicator->topMargin() + sliderPos, sliderW, sliderH);
3693 return visualRect(opt->direction, opt->rect, sliderRect.toAlignedRect());
3701#if QT_CONFIG(toolbutton)
3703 if (
const auto *tool = qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
3704 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolButton,
3706 if (!resolved.isValid())
3708 const auto &metrics = *resolved.metrics;
3709 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3711 case SC_ToolButton: {
3712 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3713 const bool hasMenuButton = (tool->features
3714 & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::HasMenu))
3716 const auto *indicator = resolved.indicator();
3717 if (hasMenuButton && indicator && indicator->visible()
3718 && indicator->opacity() > 0) {
3719 const QRect menuRect = subControlRect(CC_ToolButton, opt, SC_ToolButtonMenu, w);
3720 const int spacing = metrics.spacing;
3721 const uint indicatorAlign = resolvedAlignment(indicator->alignment(),
3722 Qt::AlignRight, Qt::AlignVCenter);
3723 if (indicatorAlign & Qt::AlignLeft)
3724 contentsRect.setLeft(menuRect.right() + spacing);
3725 else if (indicatorAlign & Qt::AlignRight)
3726 contentsRect.setRight(menuRect.left() - spacing);
3728 return visualRect(opt->direction, opt->rect, contentsRect);
3730 case SC_ToolButtonMenu: {
3731 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3733 & (QStyleOptionToolButton::MenuButtonPopup
3734 | QStyleOptionToolButton::PopupDelay))
3735 != QStyleOptionToolButton::MenuButtonPopup) {
3739 const auto *indicator = resolved.indicator();
3740 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
3743 const int w = qSaturateRound(resolvedWidth(
3745 contentsRect.width() - indicator->leftMargin() - indicator->rightMargin()));
3746 const int h = qSaturateRound(resolvedHeight(
3748 contentsRect.height() - indicator->topMargin() - indicator->bottomMargin()));
3749 const uint indicatorAlign = resolvedAlignment(indicator->alignment(),
3750 Qt::AlignRight, Qt::AlignVCenter);
3751 const QMargins indicatorMargins = elementMargins(indicator);
3752 return visualRect(opt->direction, opt->rect,
3753 d->getAlignedRectInContainer(contentsRect, QSize(w, h), indicatorAlign, QMargins(), indicatorMargins));
3764 return QCommonStyle::subControlRect(cc, opt, sc, w);
3768QSize QStyleKitStyle::sizeFromContents(ContentsType ct,
const QStyleOption *opt,
3769 const QSize &contentsSize,
const QWidget *widget)
const
3771 Q_D(
const QStyleKitStyle);
3774#if QT_CONFIG(pushbutton)
3777#if QT_CONFIG(toolbutton)
3778 case CT_ToolButton: {
3779 auto controlType = QQStyleKitReader::ControlType::ToolButton;
3780 if (
const auto *buttonOpt = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
3781 controlType = (buttonOpt->features & QStyleOptionButton::Flat)
3782 ? QQStyleKitReader::ControlType::FlatButton
3783 : QQStyleKitReader::ControlType::Button;
3785 const auto resolved = d->resolveLayout(controlType, opt->state);
3786 if (!resolved.isValid())
3789 const auto &metrics = *resolved.metrics;
3790 const QSize contentSize = contentsSize
3791 + QSize(metrics.padding.left() + metrics.padding.right(),
3792 metrics.padding.top() + metrics.padding.bottom())
3793 + QSize(metrics.textPadding.left() + metrics.textPadding.right(),
3794 metrics.textPadding.top() + metrics.textPadding.bottom());
3795 const QSize bgSize = metrics.bgImplicitSize
3796 + QSize(metrics.margins.left() + metrics.margins.right(),
3797 metrics.margins.top() + metrics.margins.bottom());
3798 return contentSize.expandedTo(bgSize);
3802 case CT_RadioButton:
3803 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
3804 const auto controlType = ct == CT_CheckBox ? QQStyleKitReader::ControlType::CheckBox
3805 : QQStyleKitReader::ControlType::RadioButton;
3806 const auto resolved = d->resolveLayout(controlType, opt->state);
3807 if (!resolved.isValid())
3809 const auto &metrics = *resolved.metrics;
3810 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, btn->text);
3811 const int bgWidth = metrics.bgImplicitSize.width()
3812 + metrics.margins.left() + metrics.margins.right();
3813 const int bgHeight = metrics.bgImplicitSize.height()
3814 + metrics.margins.top() + metrics.margins.bottom();
3815 const int contentWidth = std::max(textSize.width(), contentsSize.width())
3816 + metrics.padding.left() + metrics.padding.right() + metrics.textPadding.left()
3817 + metrics.textPadding.right();
3818 const int contentHeight = std::max(textSize.height(), contentsSize.height())
3819 + metrics.padding.top() + metrics.padding.bottom() + metrics.textPadding.top()
3820 + metrics.textPadding.bottom();
3821 const int indicatorWidth = metrics.indicatorImplicitSize.width()
3822 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
3823 const int indicatorHeight = metrics.indicatorImplicitSize.height()
3824 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
3825 return QSize(std::max({ contentWidth + indicatorWidth + metrics.spacing, bgWidth }),
3826 std::max({ contentHeight, indicatorHeight, bgHeight }));
3829#if QT_CONFIG(itemviews)
3830 case CT_ItemViewItem:
3831 if (
const auto *item = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
3832 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
3833 if (!resolved.isValid())
3835 const auto &metrics = *resolved.metrics;
3836 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, item->text);
3837 const int bgWidth = metrics.bgImplicitSize.width()
3838 + metrics.margins.left() + metrics.margins.right();
3839 const int bgHeight = metrics.bgImplicitSize.height()
3840 + metrics.margins.top() + metrics.margins.bottom();
3841 const int contentWidth = std::max(textSize.width(), contentsSize.width())
3842 + metrics.padding.left() + metrics.padding.right() + metrics.textPadding.left()
3843 + metrics.textPadding.right();
3844 const int contentHeight = std::max(textSize.height(), contentsSize.height())
3845 + metrics.padding.top() + metrics.padding.bottom() + metrics.textPadding.top()
3846 + metrics.textPadding.bottom();
3847 const int indicatorWidth = metrics.indicatorImplicitSize.width()
3848 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
3849 const int indicatorHeight = metrics.indicatorImplicitSize.height()
3850 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
3851 return QSize(std::max({ contentWidth + indicatorWidth + metrics.spacing, bgWidth }),
3852 std::max({ contentHeight, indicatorHeight, bgHeight }));
3856 case CT_ProgressBar:
3857 if (qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
3858 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar,
3860 if (!resolved.isValid())
3862 const auto &metrics = *resolved.metrics;
3863 const auto indicatorW = metrics.indicatorImplicitSize.width()
3864 + metrics.indicatorMargins.left()
3865 + metrics.indicatorMargins.right();
3866 const auto indicatorH = metrics.indicatorImplicitSize.height()
3867 + metrics.indicatorMargins.top()
3868 + metrics.indicatorMargins.bottom();
3869 const int bgW = metrics.bgImplicitSize.width()
3870 + metrics.margins.left() + metrics.margins.right();
3871 const int bgH = metrics.bgImplicitSize.height()
3872 + metrics.margins.top() + metrics.margins.bottom();
3874 const int contentW = indicatorW + metrics.padding.left() + metrics.padding.right();
3875 const int contentH = indicatorH + metrics.padding.top() + metrics.padding.bottom();
3876 return QSize(std::max(contentW, bgW), std::max(contentH, bgH));
3880 if (qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3881 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Slider,
3883 if (!resolved.isValid())
3885 const auto &metrics = *resolved.metrics;
3887 const int bgW = std::max(
3888 metrics.padding.left() + metrics.padding.right()
3889 + metrics.indicatorImplicitSize.width()
3890 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right(),
3891 metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right());
3892 const int bgH = std::max(
3893 metrics.padding.top() + metrics.padding.bottom()
3894 + metrics.indicatorImplicitSize.height()
3895 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom(),
3896 metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom());
3897 const int handleW = metrics.handleImplicitSize.width()
3898 + metrics.padding.left()
3899 + metrics.padding.right();
3900 const int handleH = metrics.handleImplicitSize.height()
3901 + metrics.padding.top()
3902 + metrics.padding.bottom();
3903 return QSize(std::max(handleW, bgW), std::max(handleH, bgH));
3906#if QT_CONFIG(lineedit)
3908 if (
const auto *lineEdit = qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
3909 QStyleOption lineEditOpt(*lineEdit);
3910 lineEditOpt.state &= ~QStyle::State_Sunken;
3911# if QT_CONFIG(spinbox)
3912 const bool isInSpinBox = widget && qobject_cast<
const QSpinBox *>(widget->parent());
3914 const bool isInSpinBox =
false;
3916 auto controlType = isInSpinBox ? QQStyleKitReader::ControlType::SpinBox
3917 : QQStyleKitReader::ControlType::TextField;
3918 const auto resolved = d->resolveLayout(controlType, lineEditOpt.state);
3919 if (!resolved.isValid())
3921 const auto &metrics = *resolved.metrics;
3925 bgSize = metrics.bgImplicitSize.grownBy(metrics.margins);
3926 const QSize contentSizeWithPadding = contentsSize
3927 .grownBy(metrics.textPadding)
3928 .grownBy(metrics.padding);
3929 return contentSizeWithPadding.expandedTo(bgSize);
3933#if QT_CONFIG(combobox)
3935 if (
const auto *comboBox = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
3936 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ComboBox,
3938 if (!resolved.isValid())
3940 const auto &metrics = *resolved.metrics;
3941 const QSize textSize = opt->fontMetrics.size(
3942 Qt::TextShowMnemonic, comboBox->currentText);
3943 const int bgW = metrics.bgImplicitSize.width()
3944 + metrics.margins.left() + metrics.margins.right();
3945 const int bgH = metrics.bgImplicitSize.height()
3946 + metrics.margins.top() + metrics.margins.bottom();
3947 const int contentW = textSize.width()
3948 + metrics.padding.left() + metrics.padding.right()
3949 + metrics.textPadding.left() + metrics.textPadding.right();
3950 const int contentH = textSize.height()
3951 + metrics.padding.top() + metrics.padding.bottom()
3952 + metrics.textPadding.top() + metrics.textPadding.bottom();
3953 const int indicatorW = metrics.indicatorImplicitSize.width()
3954 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
3955 const int indicatorH = metrics.indicatorImplicitSize.height()
3956 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
3957 return QSize(std::max({ contentW + indicatorW + metrics.spacing, bgW }),
3958 std::max({ contentH, indicatorH, bgH }));
3962#if QT_CONFIG(spinbox)
3964 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::SpinBox, opt->state);
3965 if (!resolved.isValid())
3967 const auto &metrics = *resolved.metrics;
3968 const int bgW = metrics.bgImplicitSize.width()
3969 + metrics.margins.left() + metrics.margins.right();
3970 const int bgH = metrics.bgImplicitSize.height()
3971 + metrics.margins.top() + metrics.margins.bottom();
3972 const int contentW = contentsSize.width()
3973 + metrics.padding.left() + metrics.padding.right()
3974 + metrics.textPadding.left() + metrics.textPadding.right();
3975 const int contentH = contentsSize.height()
3976 + metrics.padding.top() + metrics.padding.bottom()
3977 + metrics.textPadding.top() + metrics.textPadding.bottom();
3981 const int indicatorW = (metrics.indicatorImplicitSize.width()
3982 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right()) * 2;
3983 const int indicatorH = metrics.indicatorImplicitSize.height()
3984 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
3985 return QSize(std::max({ contentW + indicatorW + metrics.spacing, bgW }),
3986 std::max({ contentH, indicatorH, bgH }));
3989#if QT_CONFIG(tabbar)
3991 if (qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
3992 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::TabButton,
3994 if (!resolved.isValid())
3996 const auto &m = *resolved.metrics;
3997 const auto bgSize = m.bgImplicitSize.grownBy(m.margins);
3998 const auto contentSizeWithPadding = contentsSize.grownBy(m.padding + m.textPadding);
3999 return contentSizeWithPadding.expandedTo(bgSize);
4003#if QT_CONFIG(tabwidget)
4005 if (qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(opt)) {
4007 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Page, opt->state);
4008 if (!resolved.isValid())
4010 const auto &m = *resolved.metrics;
4011 const auto bgSize = m.bgImplicitSize.grownBy(m.margins);
4012 const auto contentSizeWithPadding = contentsSize.grownBy(m.padding);
4013 return contentSizeWithPadding.expandedTo(bgSize);
4017#if QT_CONFIG(groupbox)
4019 if (
const auto *groupBox = qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
4020 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::GroupBox,
4022 if (!resolved.isValid())
4024 const auto &metrics = *resolved.metrics;
4025 const QSize bgSize = metrics.bgImplicitSize
4026 + QSize(metrics.margins.left() + metrics.margins.right(),
4027 metrics.margins.top() + metrics.margins.bottom());
4028 const QSize contentSize = contentsSize.grownBy(metrics.padding);
4029 const QSize textSize = opt->fontMetrics
4030 .size(Qt::TextShowMnemonic, groupBox->text)
4031 .grownBy(metrics.textPadding);
4032 return textSize.expandedTo(contentSize).expandedTo(bgSize);
4036#if QT_CONFIG(scrollbar)
4038 if (qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
4039 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ScrollBar, opt->state);
4040 if (!resolved.isValid())
4042 const auto &metrics = *resolved.metrics;
4044 const int iH = metrics.indicatorImplicitSize.height()
4045 + metrics.padding.top() + metrics.padding.bottom()
4046 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
4047 const int iW = metrics.indicatorImplicitSize.width()
4048 + metrics.padding.left() + metrics.padding.right()
4049 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
4050 const int bgH = metrics.bgImplicitSize.height()
4051 + metrics.margins.top() + metrics.margins.bottom();
4052 const int bgW = metrics.bgImplicitSize.width()
4053 + metrics.margins.left() + metrics.margins.right();
4054 return QSize(std::max(iW, bgW), std::max(iH, bgH));
4060 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
4064 const auto menuType = widget && widget->inherits(
"QComboBoxPrivateContainer")
4065 ? QQStyleKitReader::ControlType::Popup
4066 : QQStyleKitReader::ControlType::Menu;
4067 const auto menuResolved = d->resolveLayout(menuType, opt->state);
4069 if (menuResolved.isValid()) {
4070 const auto &mm = *menuResolved.metrics;
4071 minMenuW = mm.bgImplicitSize.width()
4072 + mm.margins.left() + mm.margins.right() - 2 * mm.padding.left();
4075 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
4076 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuSeparator,
4078 if (!resolved.isValid())
4080 const auto &m = *resolved.metrics;
4081 const int bgWidth = m.bgImplicitSize.width()
4082 + m.margins.left() + m.margins.right();
4083 const int bgHeight = m.bgImplicitSize.height()
4084 + m.margins.top() + m.margins.bottom();
4085 return QSize(std::max(bgWidth, minMenuW), bgHeight);
4088 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuItem, opt->state);
4089 if (!resolved.isValid())
4091 const auto &m = *resolved.metrics;
4092 const auto *indicator = resolved.indicator();
4093 const auto *first = indicator ? indicator->first() :
nullptr;
4094 const auto *second = indicator ? indicator->second() :
nullptr;
4097 using QtPrivate::qSaturateRound;
4098 if (first && menuItem->checkType != QStyleOptionMenuItem::NotCheckable) {
4099 indicatorW += qSaturateRound(
4100 first->leftMargin() + first->width() + first->rightMargin()) + m.spacing;
4101 indicatorH = std::max(
4102 qSaturateRound(first->topMargin() + first->bottomMargin() + first->height()),
4105 if (second && menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {
4106 indicatorW += qSaturateRound(
4107 second->leftMargin() + second->width() + second->rightMargin()) + m.spacing;
4108 indicatorH = std::max(
4109 qSaturateRound(second->topMargin() + second->bottomMargin() + second->height()),
4112 const int bgH = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
4113 const int iconReserved = menuItem->maxIconWidth > 0
4114 ? menuItem->maxIconWidth + m.spacing
4116 const int contentW = contentsSize.width()
4117 + m.padding.left() + m.padding.right()
4118 + m.textPadding.left() + m.textPadding.right()
4119 + indicatorW + iconReserved;
4120 const int contentH = contentsSize.height()
4121 + m.padding.top() + m.padding.bottom()
4122 + m.textPadding.top() + m.textPadding.bottom();
4123 return QSize(std::max(contentW, minMenuW), std::max({ contentH, indicatorH, bgH }));
4127 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Menu, opt->state);
4128 if (!resolved.isValid())
4130 const auto &m = *resolved.metrics;
4131 const int height = std::max(contentsSize.height(), m.bgImplicitSize.height())
4132 + m.margins.top() + m.margins.bottom();
4133 return QSize(contentsSize.width(), height);
4136#if QT_CONFIG(menubar)
4138 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuBar, opt->state);
4139 if (!resolved.isValid())
4141 const auto &m = *resolved.metrics;
4142 const int bgWidth = m.bgImplicitSize.width() + m.margins.left() + m.margins.right();
4143 const int bgHeight = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
4144 const int contentW = contentsSize.width() + m.padding.left() + m.padding.right();
4145 const int contentH = contentsSize.height() + m.padding.top() + m.padding.bottom();
4146 return QSize(std::max(contentW, bgWidth), std::max(contentH, bgHeight));
4148 case CT_MenuBarItem: {
4149 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuBarItem,
4151 if (!resolved.isValid())
4153 const auto &m = *resolved.metrics;
4154 const int bgWidth = m.bgImplicitSize.width() + m.margins.left() + m.margins.right();
4155 const int bgHeight = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
4156 const int contentW = contentsSize.width()
4157 + m.padding.left() + m.padding.right()
4158 + m.textPadding.left() + m.textPadding.right();
4159 const int contentH = contentsSize.height()
4160 + m.padding.top() + m.padding.bottom()
4161 + m.textPadding.top() + m.textPadding.bottom();
4162 return QSize(std::max(contentW, bgWidth), std::max(contentH, bgHeight));
4168 return QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget);
4172int QStyleKitStyle::pixelMetric(PixelMetric m,
const QStyleOption *opt,
const QWidget *widget)
const
4174 Q_D(
const QStyleKitStyle);
4177 case PM_MenuPanelWidth:
4180 case PM_MenuTearoffHeight:
4181 case PM_MenuScrollerHeight:
4183 case PM_MenuHMargin:
4184 case PM_MenuVMargin: {
4185 const auto controlType = widget && widget->inherits(
"QComboBoxPrivateContainer")
4186 ? QQStyleKitReader::ControlType::Popup
4187 : QQStyleKitReader::ControlType::Menu;
4188 const auto resolved = d->resolveLayout(controlType, opt ? opt->state : QStyle::State_None);
4189 if (!resolved.isValid())
4191 return m == PM_MenuHMargin ? resolved.metrics->padding.left()
4192 : resolved.metrics->padding.top();
4195#if QT_CONFIG(menubar)
4196 case PM_MenuBarItemSpacing: {
4197 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuBarItem,
4198 opt ? opt->state : QStyle::State_None);
4199 if (resolved.isValid())
4200 return resolved.metrics->spacing;
4204#if QT_CONFIG(toolbar)
4205 case PM_ToolBarFrameWidth:
4208 case PM_ToolBarItemMargin: {
4209 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolBar,
4210 opt ? opt->state : QStyle::State_None);
4211 if (!resolved.isValid())
4213 return resolved.metrics->padding.left();
4215 case PM_ToolBarItemSpacing: {
4216 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolBar,
4217 opt ? opt->state : QStyle::State_None);
4218 if (resolved.isValid())
4219 return resolved.metrics->spacing;
4222 case PM_ToolBarHandleExtent: {
4225 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolBar,
4226 opt ? opt->state : QStyle::State_None);
4227 if (!resolved.isValid())
4229 const auto &metrics = *resolved.metrics;
4230 const bool horizontal = !opt || (opt->state & State_Horizontal);
4231 const int crossImplicit = horizontal
4232 ? metrics.bgImplicitSize.height()
4233 : metrics.bgImplicitSize.width();
4234 const int crossMargins = horizontal
4235 ? metrics.margins.top() + metrics.margins.bottom()
4236 : metrics.margins.left() + metrics.margins.right();
4237 const int crossPadding = horizontal
4238 ? metrics.padding.top() + metrics.padding.bottom()
4239 : metrics.padding.left() + metrics.padding.right();
4240 return qMax(0, crossImplicit + crossMargins - crossPadding);
4243#if QT_CONFIG(tabbar)
4244 case PM_TabBarTabHSpace:
4245 case PM_TabBarTabVSpace:
4246 case PM_TabBarTabOverlap:
4248 case PM_TabCloseIndicatorWidth:
4249 case PM_TabCloseIndicatorHeight:
4255 return QCommonStyle::pixelMetric(m, opt, widget);
4259int QStyleKitStyle::styleHint(StyleHint sh,
const QStyleOption *opt,
const QWidget *w,
4260 QStyleHintReturn *shret)
const
4264 case SH_SpinBox_SelectOnStep:
4265 case SH_ToolBar_Movable:
4266 case SH_TabBar_PreferNoArrows:
4268 case SH_Menu_MouseTracking:
4269 case SH_MenuBar_MouseTracking:
4270 case SH_Menu_Scrollable:
4275 return QCommonStyle::styleHint(sh, opt, w, shret);
4279QPalette QStyleKitStyle::standardPalette()
const
4281 return QCommonStyle::standardPalette();
4285void QStyleKitStyle::polish(QWidget *widget)
4290 Q_D(QStyleKitStyle);
4295 d->ensureDefaultStyle();
4297 widget->setAttribute(Qt::WA_Hover);
4299#if QT_CONFIG(scrollbar)
4303 if (qobject_cast<QScrollBar *>(widget))
4304 widget->setAttribute(Qt::WA_OpaquePaintEvent,
false);
4308 const bool isInteractiveControl =
false
4309#if QT_CONFIG(pushbutton)
4310 || qobject_cast<
const QPushButton *>(widget)
4312#if QT_CONFIG(checkbox)
4313 || qobject_cast<
const QCheckBox *>(widget)
4315#if QT_CONFIG(radiobutton)
4316 || qobject_cast<
const QRadioButton *>(widget)
4318#if QT_CONFIG(combobox)
4319 || qobject_cast<
const QComboBox *>(widget)
4320 || (widget && widget->inherits(
"QComboBoxPrivateContainer"))
4322#if QT_CONFIG(lineedit)
4323 || qobject_cast<
const QLineEdit *>(widget)
4325#if QT_CONFIG(textedit)
4326 || qobject_cast<
const QTextEdit *>(widget)
4327 || qobject_cast<
const QPlainTextEdit *>(widget)
4330 || qobject_cast<
const QLabel *>(widget)
4332#if QT_CONFIG(progressbar)
4333 || qobject_cast<
const QProgressBar *>(widget)
4335#if QT_CONFIG(slider)
4336 || qobject_cast<
const QSlider *>(widget)
4338#if QT_CONFIG(scrollbar)
4339 || qobject_cast<
const QScrollBar *>(widget)
4341#if QT_CONFIG(spinbox)
4342 || qobject_cast<
const QSpinBox *>(widget)
4344#if QT_CONFIG(tabbar)
4345 || qobject_cast<
const QTabBar *>(widget)
4347#if QT_CONFIG(tabwidget)
4348 || qobject_cast<
const QTabWidget *>(widget)
4351 || qobject_cast<
const QMenu *>(widget)
4352 || qobject_cast<
const QMenuBar *>(widget)
4355 if (isInteractiveControl)
4356 d->readerForWidget(widget);
4361 if (QWidget *vp = managedViewport(widget); vp && vp->autoFillBackground()) {
4362 vp->setAutoFillBackground(
false);
4363 d->bgFillDisabledWidgets.insert(widget);
4366 if (qobject_cast<QMenu *>(widget)
4367# if QT_CONFIG(combobox)
4368 || widget->inherits(
"QComboBoxPrivateContainer")
4373 if (!widget->testAttribute(Qt::WA_TranslucentBackground)) {
4374 widget->setAttribute(Qt::WA_TranslucentBackground,
true);
4375 d->bgFillDisabledWidgets.insert(widget);
4380#if QT_CONFIG(lineedit)
4381 if (
auto *lineEdit = qobject_cast<QLineEdit *>(widget)) {
4382 if (!lineEdit->property(
"_q_stylekit_alignment_set").toBool()) {
4383 QQStyleKitReader *r = d->readerForWidget(widget);
4385 const QWidget *target = containerWidget(widget);
4386 QQStyleKitReader::ControlType ct = controlTypeForWidget(target);
4387 r->setControlType(ct);
4388 const auto *textProps = r->global()->text();
4390 const uint align = resolvedAlignment(
4391 textProps->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
4392 lineEdit->setAlignment(Qt::Alignment(align));
4399 d->refreshStyleFont(widget);
4400 d->refreshStylePalette(widget);
4402 bool needsEventFilter = isSelfPaintingWidget(widget);
4405 needsEventFilter = needsEventFilter || qobject_cast<QMenu *>(widget);
4407 if (needsEventFilter)
4408 widget->installEventFilter(
this);
4410 QCommonStyle::polish(widget);
4414void QStyleKitStyle::polish(QApplication *app)
4416 QCommonStyle::polish(app);
4420void QStyleKitStyle::polish(QPalette &palette)
4422 QCommonStyle::polish(palette);
4426void QStyleKitStyle::unpolish(QWidget *widget)
4428 Q_D(QStyleKitStyle);
4429 d->unsetStylePalette(widget);
4430 d->unsetStyleFont(widget);
4431 bool hasEventFilter = isSelfPaintingWidget(widget);
4433 hasEventFilter = hasEventFilter || qobject_cast<QMenu *>(widget);
4436 widget->removeEventFilter(
this);
4437 if (d->bgFillDisabledWidgets.remove(widget)) {
4438 if (QWidget *vp = managedViewport(widget))
4439 vp->setAutoFillBackground(
true);
4441 else if (qobject_cast<QMenu *>(widget)
4442# if QT_CONFIG(combobox)
4443 || widget->inherits(
"QComboBoxPrivateContainer")
4446 widget->setAttribute(Qt::WA_TranslucentBackground,
false);
4450 d->cleanupWidgetReader(widget);
4451#if QT_CONFIG(scrollbar)
4452 if (qobject_cast<QScrollBar *>(widget))
4453 widget->setAttribute(Qt::WA_OpaquePaintEvent);
4455 QCommonStyle::unpolish(widget);
4459void QStyleKitStyle::unpolish(QApplication *app)
4461 Q_D(QStyleKitStyle);
4462 d->clearMetricsCache();
4463 QCommonStyle::unpolish(app);
4467bool QStyleKitStyle::eventFilter(QObject *obj, QEvent *event)
4469 Q_D(QStyleKitStyle);
4470 switch (event->type()) {
4471 case QEvent::EnabledChange:
4472 case QEvent::HoverEnter:
4473 case QEvent::HoverLeave:
4474 case QEvent::FocusIn:
4475 case QEvent::FocusOut:
4476 if (
auto *w = qobject_cast<QWidget *>(obj)) {
4477 if (d->customPaletteWidgets.contains(w))
4478 d->refreshStylePalette(w);
4479 if (d->customFontWidgets.contains(w))
4480 d->refreshStyleFont(w);
4485 if (
auto *menu = qobject_cast<QMenu *>(obj))
4486 d->cleanupSubElements(menu);
4492 return QCommonStyle::eventFilter(obj, event);
4496bool QStyleKitStyle::event(QEvent *event)
4498 return QCommonStyle::event(event);
4503#include "moc_qstylekitstyle.cpp"
Combined button and popup list for selecting options.
static QWidget * paintTarget(const QWidget *widget)
static bool applyDelegateTransform(QPainter *painter, const QQStyleKitDelegateProperties *element, const QRectF &box)
static QWidget * managedViewport(QWidget *widget)
static QMargins elementMargins(const QQStyleKitDelegateProperties *element)
static uint resolvedAlignment(uint raw, Qt::Alignment hDefault, Qt::Alignment vDefault)
static qreal resolvedWidth(const QQStyleKitDelegateProperties *element, qreal availableW)
static bool isSelfPaintingWidget(const QWidget *widget)
static qreal resolvedHeight(const QQStyleKitDelegateProperties *element, qreal availableH)
static QUrl urlFromStylePath(const QString &filePath)
static const QWidget * containerWidget(const QWidget *w)