7#include <QtWidgets/qstyleoption.h>
8#include <QtWidgets/qstyle.h>
9#include <QtWidgets/qapplication.h>
10#if QT_CONFIG(scrollarea)
11#include <QtWidgets/qabstractscrollarea.h>
13#if QT_CONFIG(itemviews)
14#include <QtWidgets/qabstractitemview.h>
16#if QT_CONFIG(lineedit)
17#include <QtWidgets/qlineedit.h>
19#if QT_CONFIG(pushbutton)
20#include <QtWidgets/qpushbutton.h>
22#if QT_CONFIG(checkbox)
23#include <QtWidgets/qcheckbox.h>
25#if QT_CONFIG(radiobutton)
26#include <QtWidgets/qradiobutton.h>
28#if QT_CONFIG(combobox)
29#include <QtWidgets/qcombobox.h>
32#include <QtWidgets/qslider.h>
34#if QT_CONFIG(scrollbar)
35#include <QtWidgets/qscrollbar.h>
38#include <QtWidgets/qspinbox.h>
40#if QT_CONFIG(progressbar)
41#include <QtWidgets/qprogressbar.h>
43#if QT_CONFIG(textedit)
44#include <QtWidgets/qtextedit.h>
45#include <QtWidgets/qplaintextedit.h>
48#include <QtWidgets/qtabbar.h>
51#include <QtWidgets/qtoolbar.h>
53#if QT_CONFIG(groupbox)
54#include <QtWidgets/qgroupbox.h>
57#include <QtWidgets/qmenu.h>
60#include <QtWidgets/qlabel.h>
62#include <QtWidgets/private/qwidget_p.h>
63#include <QtGui/qpainter.h>
64#include <QtGui/qpainterpath.h>
65#include <QtGui/qpainterstateguard.h>
66#include <QtGui/qstylehints.h>
67#include <QtCore/qloggingcategory.h>
68#include <QtQml/private/qqmlcomponent_p.h>
69#include <QtQml/qqmlengine.h>
70#include <QtLabsStyleKit/private/qqstylekit_p.h>
71#include <QtLabsStyleKit/private/qqstylekitcontrolproperties_p.h>
72#include <QtLabsStyleKit/private/qqstylekitstyle_p.h>
76Q_STATIC_LOGGING_CATEGORY(lcStyleKit,
"qt.labs.stylekit")
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
227
228
229
230
231
232
233
234
235
236
239
240
241
242
243
244
245
246
249
250
251
252
253
254
257
258
259
260
261
262
263
264
265
267static QQStyleKitReader::ControlType controlTypeForWidget(
const QWidget *widget)
270 return QQStyleKitReader::Control;
272#if QT_CONFIG(pushbutton)
273 if (qobject_cast<
const QPushButton *>(widget))
274 return QQStyleKitReader::Button;
276#if QT_CONFIG(checkbox)
277 if (qobject_cast<
const QCheckBox *>(widget))
278 return QQStyleKitReader::CheckBox;
280#if QT_CONFIG(radiobutton)
281 if (qobject_cast<
const QRadioButton *>(widget))
282 return QQStyleKitReader::RadioButton;
284#if QT_CONFIG(combobox)
285 if (qobject_cast<
const QComboBox *>(widget))
286 return QQStyleKitReader::ComboBox;
289 if (qobject_cast<
const QSlider *>(widget))
290 return QQStyleKitReader::Slider;
292#if QT_CONFIG(scrollbar)
293 if (qobject_cast<
const QScrollBar *>(widget))
294 return QQStyleKitReader::ScrollBar;
296#if QT_CONFIG(spinbox)
297 if (qobject_cast<
const QSpinBox *>(widget) || qobject_cast<
const QDoubleSpinBox *>(widget))
298 return QQStyleKitReader::SpinBox;
300#if QT_CONFIG(itemviews)
301 if (qobject_cast<
const QAbstractItemView *>(widget))
302 return QQStyleKitReader::ItemDelegate;
304#if QT_CONFIG(progressbar)
305 if (qobject_cast<
const QProgressBar *>(widget))
306 return QQStyleKitReader::ProgressBar;
308#if QT_CONFIG(lineedit)
309 if (qobject_cast<
const QLineEdit *>(widget))
310 return QQStyleKitReader::TextField;
312#if QT_CONFIG(textedit)
313 if (qobject_cast<
const QTextEdit *>(widget) || qobject_cast<
const QPlainTextEdit *>(widget))
314 return QQStyleKitReader::TextArea;
317 if (qobject_cast<
const QTabBar *>(widget))
318 return QQStyleKitReader::TabBar;
320#if QT_CONFIG(toolbar)
321 if (qobject_cast<
const QToolBar *>(widget))
322 return QQStyleKitReader::ToolBar;
324#if QT_CONFIG(groupbox)
325 if (qobject_cast<
const QGroupBox *>(widget))
326 return QQStyleKitReader::GroupBox;
328 if (widget->windowType() & Qt::Popup)
329 return QQStyleKitReader::Popup;
330 if (widget->windowType() & Qt::Dialog)
331 return QQStyleKitReader::Dialog;
332 if (widget->windowType() & Qt::Window)
333 return QQStyleKitReader::ApplicationWindow;
335 if (qobject_cast<
const QFrame *>(widget))
336 return QQStyleKitReader::Frame;
339 return QQStyleKitReader::Control;
348 || qobject_cast<
const QLabel *>(widget)
350#if QT_CONFIG(textedit)
351 || qobject_cast<
const QTextEdit *>(widget)
352 || qobject_cast<
const QPlainTextEdit *>(widget)
354#if QT_CONFIG(lineedit)
355 || qobject_cast<
const QLineEdit *>(widget)
362#if QT_CONFIG(textedit)
363 if (
auto *textEdit = qobject_cast<QTextEdit *>(widget))
364 return textEdit->viewport();
365 if (
auto *plainTextEdit = qobject_cast<QPlainTextEdit *>(widget))
366 return plainTextEdit->viewport();
368#if QT_CONFIG(itemviews) && QT_CONFIG(combobox)
369 if (
auto *view = qobject_cast<QAbstractItemView *>(widget)) {
370 if (
auto *p = view->parentWidget(); p && p->inherits(
"QComboBoxPrivateContainer"))
371 return view->viewport();
380 const uint h = raw & Qt::AlignHorizontal_Mask;
381 const uint v = raw & Qt::AlignVertical_Mask;
382 result |= h ? h : uint(hDefault);
383 result |= v ? v : uint(vDefault);
389 return element->fillWidth() ? availableW : qMax(0.0, element->implicitWidth());
394 return element->fillHeight() ? avilableH : qMax(0.0, element->implicitHeight());
399 return QMargins(element->leftMargin(), element->topMargin(),
400 element->rightMargin(), element->bottomMargin());
406#if QT_CONFIG(lineedit)
407 if (qobject_cast<
const QLineEdit *>(w)) {
409 QWidget *parent = w->parentWidget();
411#if QT_CONFIG(combobox)
412 || qobject_cast<
const QComboBox *>(parent)
414#if QT_CONFIG(spinbox)
415 || qobject_cast<
const QAbstractSpinBox *>(parent)
423#if QT_CONFIG(scrollarea)
424 if (
const QAbstractScrollArea *sa = qobject_cast<
const QAbstractScrollArea *>(w->parentWidget())) {
425 if (sa->viewport() == w)
426 return w->parentWidget();
434 : QCommonStylePrivate()
440 return filePath.startsWith(QLatin1Char(
':'))
441 ? QUrl(QLatin1String(
"qrc") + filePath)
442 : QUrl::fromLocalFile(filePath);
449 qmlEngine =
new QQmlEngine(q);
452 qWarning(
"QStyleKitStyle: No QML engine available to load style.");
455 const QUrl url = stylePath.isEmpty() ? QUrl() : urlFromStylePath(stylePath);
456 if (stylePath.isEmpty() || !url.isValid()) {
457 qWarning(
"QStyleKitStyle: No valid style path provided: %s", qPrintable(stylePath));
460 QQmlComponent component(qmlEngine, url);
461 if (component.isError()) {
462 qWarning(
"QStyleKitStyle: Failed to load style from %s: %s",
463 qPrintable(stylePath), qPrintable(component.errorString()));
468 QQmlComponentPrivate *componentPrivate = QQmlComponentPrivate::get(&component);
469 const auto compilationUnit = componentPrivate->compilationUnit();
470 const auto propertyCache = compilationUnit ? compilationUnit->rootPropertyCache() :
nullptr;
471 const auto firstMetaObject = propertyCache ? propertyCache->firstCppMetaObject() :
nullptr;
472 if (!firstMetaObject || !firstMetaObject->inherits(&QQStyleKitStyle::staticMetaObject)) {
473 qWarning(
"QStyleKitStyle: Failed to load style from %s: component is not a StyleKit Style.",
474 qPrintable(stylePath));
477 QQStyleKitStyle *styleObject = qobject_cast<QQStyleKitStyle *>(component.create());
479 qWarning(
"QStyleKitStyle: Failed to create style object from %s: component is not a StyleKit style.",
480 qPrintable(stylePath));
483 const bool isReload = style !=
nullptr;
489 QObject::connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, q, [
this]() {
490 if (style && style->themeName() == QLatin1String(
"System")) {
491 style->recreateTheme();
498 QQStyleKitReader::resetReadersForStyle(style);
504
505
506
514 qmlEngine =
new QQmlEngine(q);
516 QQmlComponent component(qmlEngine);
517 component.loadFromModule(
"Qt.labs.StyleKit",
"Style");
518 if (component.isError()) {
519 qWarning(
"QStyleKitStyle: Failed to create default fallback style: %s",
520 qPrintable(component.errorString()));
523 defaultStyle = qobject_cast<QQStyleKitStyle *>(component.create());
525 defaultStyle->setParent(q);
526 qCDebug(lcStyleKit,
"No style set; using a default fallback style. "
527 "Set stylePath to load a StyleKit Style.");
533
534
535
538 return style ? style : defaultStyle;
545 QQStyleKitStyle *effective = effectiveStyle();
547 if (sharedReader && sharedReader->style() != effective)
548 sharedReader->setExplicitStyle(effective);
550 for (
const auto &byItem : std::as_const(itemViewItemReaders)) {
551 for (
auto *reader : std::as_const(byItem)) {
552 if (reader && reader->style() != effective)
553 reader->setExplicitStyle(effective);
557 for (
auto *wr : std::as_const(widgetReaders)) {
558 if (wr->style() != effective)
559 wr->setExplicitStyle(effective);
562 if (!QWidgetPrivate::allWidgets)
565 for (
auto *widget : std::as_const(*QWidgetPrivate::allWidgets)) {
566 if (customFontWidgets.contains(widget))
567 unsetStyleFont(widget);
568 refreshStyleFont(widget);
569 if (customPaletteWidgets.contains(widget))
570 unsetStylePalette(widget);
571 refreshStylePalette(widget);
574 QEvent styleChange(QEvent::StyleChange);
575 for (
auto *widget : std::as_const(*QWidgetPrivate::allWidgets)) {
576 QApplication::sendEvent(widget, &styleChange);
584 auto it = customFontWidgets.find(widget);
585 if (it == customFontWidgets.end())
588 auto customFont = std::move(*it);
589 customFontWidgets.erase(it);
590 widget->setFont(std::move(customFont).reverted(widget->font()));
595 if (!effectiveStyle() || !widget)
598 const auto styleMask = styleFont.resolveMask();
599 auto it = customFontWidgets.find(widget);
601 if (it == customFontWidgets.end()) {
604 it = customFontWidgets.insert(widget, { QWidgetPrivate::get(widget)->localFont(), 0 });
605 QObject::connect(widget, &QObject::destroyed, widget, [
this, widget]() {
606 customFontWidgets.remove(widget);
610 it->resolveMask = styleMask;
612 const QFont &baseline = it->oldWidgetValue;
613 QFont merged = styleFont.resolve(baseline);
614 merged.setResolveMask(baseline.resolveMask() | styleMask);
615 if (widget->font() != merged)
616 widget->setFont(merged);
621 if (!effectiveStyle() || !widget)
624 const QWidget *targetWidget = containerWidget(widget);
625 QQStyleKitReader::ControlType controlType = controlTypeForWidget(targetWidget);
627 auto *shared = ensureSharedReader();
632 opt.initFrom(targetWidget);
633 const QQSK::State currentState = resolvedStateFor(controlType, opt.state);
635 shared->setControlTypeAndState(controlType, currentState);
636 setStyleFont(widget, shared->font());
641 auto it = customPaletteWidgets.find(widget);
642 if (it == customPaletteWidgets.end())
645 auto customPalette = std::move(*it);
646 customPaletteWidgets.erase(it);
647 widget->setPalette(std::move(customPalette).reverted(widget->palette()));
652 if (!effectiveStyle() || !widget)
655 const quint64 styleMask = stylePalette.resolveMask();
659 if (!customPaletteWidgets.contains(widget)) {
660 customPaletteWidgets.insert(widget, { widget->palette(), 0 });
661 QObject::connect(widget, &QObject::destroyed, widget, [
this, widget]() {
662 customPaletteWidgets.remove(widget);
666 customPaletteWidgets[widget].resolveMask |= styleMask;
667 QPalette merged = stylePalette.resolve(widget->palette());
668 merged.setResolveMask(widget->palette().resolveMask() | styleMask);
669 widget->setPalette(merged);
676 if (!effectiveStyle() || !widget)
679 const bool isWindow = widget->windowType() & (Qt::Popup | Qt::Window | Qt::Dialog);
680 const bool isPaletteManaged = isSelfPaintingWidget(widget) || isWindow;
681 if (!isPaletteManaged)
684 const QWidget *targetWidget = containerWidget(widget);
685 QQStyleKitReader::ControlType controlType = controlTypeForWidget(targetWidget);
687 auto *shared = ensureSharedReader();
692 opt.initFrom(targetWidget);
693 const QQSK::State currentState = resolvedStateFor(controlType, opt.state);
695 QPalette stylePalette;
698 shared->setControlTypeAndState(controlType, currentState);
699 if (
const auto *bg = shared->global()->background(); bg && bg->isDefined(QQSK::Property::Color))
700 stylePalette.setColor(QPalette::Window, bg->color());
701 shared->setControlTypeAndState(controlType, QQSK::StateFlag::Disabled);
702 if (
const auto *dbg = shared->global()->background(); dbg && dbg->isDefined(QQSK::Property::Color))
703 stylePalette.setColor(QPalette::Disabled, QPalette::Window, dbg->color());
706 shared->setControlTypeAndState(controlType, currentState);
707 if (
const auto *text = shared->global()->text(); text && text->isDefined(QQSK::Property::Color)) {
708 stylePalette.setColor(QPalette::Text, text->color());
709 stylePalette.setColor(QPalette::WindowText, text->color());
711 shared->setControlTypeAndState(controlType, QQSK::StateFlag::Disabled);
712 if (
const auto *dt = shared->global()->text(); dt && dt->isDefined(QQSK::Property::Color)) {
713 stylePalette.setColor(QPalette::Disabled, QPalette::Text, dt->color());
714 stylePalette.setColor(QPalette::Disabled, QPalette::WindowText, dt->color());
718 setStylePalette(widget, stylePalette);
722
723
726 Q_Q(
const QStyleKitStyle);
727 QQStyleKitStyle *effective = effectiveStyle();
728 if (!effective || !widget)
731 if (
auto it = widgetReaders.find(widget); it != widgetReaders.end())
734 auto *widgetReader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
735 widgetReader->setExplicitStyle(effective);
736 widgetReader->setTarget(
const_cast<QWidget *>(widget));
737 widgetReader->setCompleted(
true);
738 widgetReaders.insert(widget, widgetReader);
739 QObject::connect(widget, &QObject::destroyed, q, [
this, widget]() {
740 cleanupWidgetReader(widget);
747 if (
auto *reader = widgetReaders.take(widget))
748 reader->deleteLater();
749 cleanupItemViewItemReaders(widget);
753
754
755
758 if (
const auto *viewOpt = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
759 const auto &idx = viewOpt->index;
764 return qHashMulti(0, idx.row(), idx.column(), quint64(idx.internalId()));
770
771
772
774 const QWidget *widget, quint64 itemKey)
const
776 Q_Q(
const QStyleKitStyle);
777 QQStyleKitStyle *effective = effectiveStyle();
781 auto &byItem = itemViewItemReaders[widget];
782 if (
auto it = byItem.find(itemKey); it != byItem.end())
785 auto *reader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
786 reader->setExplicitStyle(effective);
787 reader->setTarget(
const_cast<QWidget *>(widget));
788 reader->setCompleted(
true);
789 byItem.insert(itemKey, reader);
795 const auto readers = itemViewItemReaders.take(widget);
796 for (
auto *reader : readers)
797 reader->deleteLater();
801
802
803
805 QQStyleKitReader::ControlType type, QStyle::State state)
const
808 flags.setFlag(QQSK::StateFlag::Disabled, !(state & QStyle::State_Enabled));
809 flags.setFlag(QQSK::StateFlag::Hovered, (state & QStyle::State_MouseOver));
810 flags.setFlag(QQSK::StateFlag::Pressed, state & QStyle::State_Sunken);
811 flags.setFlag(QQSK::StateFlag::Checked, state & QStyle::State_On);
812 flags.setFlag(QQSK::StateFlag::Focused, state & QStyle::State_HasFocus);
813 flags.setFlag(QQSK::StateFlag::Highlighted, state & QStyle::State_Selected);
814 flags.setFlag(QQSK::StateFlag::Vertical, !(state & QStyle::State_Horizontal));
818 if (type == QQStyleKitReader::ControlType::ComboBox)
819 flags.setFlag(QQSK::StateFlag::Checked,
false);
822 if (type == QQStyleKitReader::ControlType::Popup)
823 flags.setFlag(QQSK::StateFlag::Hovered,
false);
829
830
831
833 QQStyleKitReader::ControlType type, QQSK::State state)
const
835 if (
auto it = metricsCache.find({type, state}); it != metricsCache.end())
838 auto *reader = ensureSharedReader();
840 reader->setControlTypeAndState(type, state);
841 return *metricsCache.insert({type, state}, metricsForReader(reader));
845
846
847
849 const QWidget *w, QQStyleKitReader::ControlType type, QStyle::State state)
const
851 QQStyleKitResolved out;
854 auto *reader = readerForWidget(w);
858 const QQSK::State resolvedState = resolvedStateFor(type, state);
859 reader->setControlTypeAndState(type, resolvedState);
862 out.metrics = &metricsFor(type, resolvedState);
867
868
869
870
872 const QWidget *w,
const QStyleOption *opt,
873 QQStyleKitReader::ControlType type, QStyle::State state)
const
879 const quint64 itemKey = itemViewItemKeyForOption(opt);
881 return resolve(w, type, state);
883 auto *reader = readerForItemViewItem(w, itemKey);
885 return resolve(w, type, state);
887 const QQSK::State resolvedState = resolvedStateFor(type, state);
888 reader->setControlTypeAndState(type, resolvedState);
890 QQStyleKitResolved out;
893 out.metrics = &metricsFor(type, resolvedState);
899 return reader ? reader->text() :
nullptr;
904 return reader ? reader->background() :
nullptr;
909 return reader ? reader->handle() :
nullptr;
914 return reader ? reader->indicator() :
nullptr;
919 return reader ? reader->font() : QFont();
927 Q_Q(
const QStyleKitStyle);
928 QQStyleKitStyle *effective = effectiveStyle();
931 sharedReader =
new QQStyleKitReader(
const_cast<QStyleKitStyle *>(q));
933 sharedReader->setTransitionsEnabled(
false);
934 sharedReader->setExplicitStyle(effective);
935 sharedReader->setCompleted(
true);
940
941
942
943
945 QQStyleKitReader::ControlType type, QStyle::State state)
const
947 QQStyleKitLayoutResolved out;
948 auto *reader = ensureSharedReader();
952 const QQSK::State resolvedState = resolvedStateFor(type, state);
953 out.metrics = &metricsFor(type, resolvedState);
957 reader->setControlTypeAndState(type, resolvedState);
958 out.staticProps = reader->global();
959 out.staticFont = reader->font();
965 return staticProps ? staticProps->text() :
nullptr;
968const QQStyleKitDelegateProperties *
QStyleKitStylePrivate::QQStyleKitLayoutResolved::background()
const
970 return staticProps ? staticProps->background() :
nullptr;
975 return staticProps ? staticProps->handle() :
nullptr;
980 return staticProps ? staticProps->indicator() :
nullptr;
985 metricsCache.clear();
988void QStyleKitStylePrivate::drawControlIndicator(
const QQStyleKitDelegateProperties *indicator,
const QRectF &rect, QPainter *painter)
const
990 if (!indicator || !rect.isValid())
994 QRectF indicatorRect = rect;
995 if (indicator->visible() && indicator->opacity() > 0)
996 drawStyledItemRect(indicator, indicatorRect, painter);
998 const QQStyleKitDelegateProperties *foreground =
nullptr;
999 if (
auto *indicatorWithSubTypes = qobject_cast<
const QQStyleKitIndicatorWithSubTypes *>(indicator)) {
1000 foreground = indicatorWithSubTypes->foreground();
1001 }
else if (
auto *indicatorProps = qobject_cast<
const QQStyleKitIndicatorProperties *>(indicator)) {
1002 foreground = indicatorProps->foreground();
1006 if (!foreground || !foreground->visible() || foreground->opacity() <= 0)
1010 QRectF foregroundRect;
1011 const uint foregroundAlign = resolvedAlignment(foreground->alignment(), Qt::AlignHCenter, Qt::AlignVCenter);
1012 const auto foregroundW = resolvedImplicitWidth(foreground,
1013 indicatorRect.width() - foreground->leftMargin() - foreground->rightMargin());
1014 const auto foregroundH = resolvedImplicitHeight(foreground,
1015 indicatorRect.height() - foreground->topMargin() - foreground->bottomMargin());
1016 foregroundRect.setSize(QSizeF(foregroundW, foregroundH));
1017 if (foregroundAlign & Qt::AlignLeft)
1018 foregroundRect.moveLeft(indicatorRect.left() + foreground->leftMargin());
1019 else if (foregroundAlign & Qt::AlignHCenter)
1020 foregroundRect.moveLeft(indicatorRect.left() + (indicatorRect.width() - foregroundW) / 2.0);
1021 else if (foregroundAlign & Qt::AlignRight)
1022 foregroundRect.moveLeft(indicatorRect.right() - foreground->rightMargin() - foregroundW);
1023 if (foregroundAlign & Qt::AlignTop)
1024 foregroundRect.moveTop(indicatorRect.top() + foreground->topMargin());
1025 else if (foregroundAlign & Qt::AlignVCenter)
1026 foregroundRect.moveTop(indicatorRect.top() + (indicatorRect.height() - foregroundH) / 2.0);
1027 else if (foregroundAlign & Qt::AlignBottom)
1028 foregroundRect.moveTop(indicatorRect.bottom() - foreground->bottomMargin() - foregroundH);
1029 drawStyledItemRect(foreground, foregroundRect, painter);
1033 const QFont &font,
const QRect &rect,
1034 const QString &text, uint textFlags,
1035 QPainter *p, Qt::Alignment defaultAlignment)
const
1037 uint flags = textFlags;
1039 ? resolvedAlignment(textProps->alignment(),
1040 defaultAlignment & Qt::AlignHorizontal_Mask,
1041 defaultAlignment & Qt::AlignVertical_Mask)
1042 : uint(defaultAlignment);
1044 const QFont oldFont = p->font();
1045 p->setFont(font.resolve(oldFont));
1046 p->setBrush(Qt::NoBrush);
1047 p->setPen(textProps ? textProps->color() : QColor());
1048 p->drawText(rect, flags, text,
nullptr);
1051void QStyleKitStylePrivate::drawStyledItemRect(
const QQStyleKitDelegateProperties *props,
const QRectF &rect, QPainter *painter)
const
1053 if (!props || !props->visible() || props->opacity() <= 0 || !rect.isValid())
1056 QPainterStateGuard stateGuard(painter);
1057 painter->setRenderHint(QPainter::Antialiasing,
true);
1058 painter->setClipping(props->clip());
1061 const auto opacity = props->opacity();
1064 const auto *border = props->border();
1065 auto borderWidth = 0;
1069 borderWidth = border->width();
1070 borderColor = border->color();
1071 inset = borderWidth / 2.0;
1073 if (borderWidth > 0 && borderColor.isValid() && borderColor.alpha() > 0) {
1074 QPen pen(borderColor, borderWidth);
1075 painter->setPen(pen);
1077 painter->setPen(Qt::NoPen);
1082 const qreal minDimension = qMin(rect.width(), rect.height());
1083 const qreal xRadius = qMax(0.0, qMin(props->topLeftRadius() - inset, minDimension / 2.0));
1084 const qreal yRadius = qMax(0.0, qMin(props->bottomLeftRadius() - inset, minDimension / 2.0));
1086 QRectF adjustedRect = rect.adjusted(inset, inset, -inset, -inset);
1089 if (props->rotation() != 0) {
1090 const auto center = rect.center();
1091 painter->translate(center);
1092 painter->rotate(props->rotation());
1093 painter->translate(-center);
1098 QColor color = props->color();
1099 QBrush colorBrush(color);
1100 painter->setBrush(colorBrush);
1101 if (color.isValid()) {
1102 painter->setOpacity(opacity);
1103 painter->drawRoundedRect(adjustedRect, xRadius, yRadius, Qt::AbsoluteSize);
1105 if (QQuickGradient *gradient = props->gradient()) {
1106 QLinearGradient linearGradient(rect.topLeft(), rect.bottomLeft());
1107 QQmlListProperty<QQuickGradientStop> stops = gradient->stops();
1108 const int stopCount = stops.count(&stops);
1109 for (
int i = 0; i < stopCount; i++) {
1110 QQuickGradientStop *stop =
static_cast<QQuickGradientStop*>(stops.at(&stops, i));
1111 linearGradient.setColorAt(stop->position(), stop->color());
1113 QBrush gradientBrush(linearGradient);
1114 painter->setBrush(gradientBrush);
1115 painter->setOpacity(opacity);
1116 painter->drawRoundedRect(adjustedRect, xRadius, yRadius, Qt::AbsoluteSize);
1120 drawStyledItemImage(props->image(), adjustedRect, opacity, painter);
1123void QStyleKitStylePrivate::drawStyledItemImage(
const QQStyleKitImageProperties *image,
const QRectF &rect,
1124 qreal opacity, QPainter *painter)
const
1126 if (!image || image->source().isEmpty() || image->color().alpha() <= 0)
1129 QString imageSource = image->source().toString();
1130 if (imageSource.startsWith(QLatin1String(
"qrc:/")))
1131 imageSource = imageSource.mid(3);
1132 QUrl imageUrl(imageSource);
1133 QString imagePath = imageUrl.isLocalFile() ? imageUrl.toLocalFile() : imageSource;
1134 QPixmap pixmap(imagePath);
1135 if (pixmap.isNull())
1138 if (image->color().isValid()) {
1139 QImage coloredImage = pixmap.toImage();
1140 QPainter imagePainter(&coloredImage);
1141 imagePainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
1142 imagePainter.fillRect(coloredImage.rect(), image->color());
1144 pixmap = QPixmap::fromImage(coloredImage);
1146 painter->setOpacity(opacity);
1147 const QSizeF pixmapSize = pixmap.deviceIndependentSize();
1149 switch (image->fillMode()) {
1150 case QQuickImage::PreserveAspectFit: {
1151 const QSize scaled = pixmapSize.scaled(rect.size(), Qt::KeepAspectRatio).toSize();
1152 const QPointF topLeft(
1153 rect.x() + (rect.width() - scaled.width()) / 2.0,
1154 rect.y() + (rect.height() - scaled.height()) / 2.0
1156 painter->drawPixmap(QRectF(topLeft, scaled), pixmap, QRectF(QPointF(0, 0), pixmapSize));
1159 case QQuickImage::PreserveAspectCrop: {
1160 const QSize scaled = pixmapSize.scaled(rect.size(), Qt::KeepAspectRatioByExpanding).toSize();
1161 const QPointF topLeft(
1162 rect.x() + (rect.width() - scaled.width()) / 2.0,
1163 rect.y() + (rect.height() - scaled.height()) / 2.0
1165 QPainterStateGuard stateGuard(painter);
1166 painter->setClipRect(rect);
1167 painter->drawPixmap(QRectF(topLeft, scaled), pixmap, QRectF(QPointF(0, 0), pixmapSize));
1171 case QQuickImage::Stretch:
1173 painter->drawPixmap(rect, pixmap, QRectF(QPointF(0, 0), pixmapSize));
1179 uint alignment,
const QMargins &padding,
1180 const QMargins &margins)
const
1182 QRect r(QPoint(0, 0), size);
1184 if (alignment & Qt::AlignLeft)
1185 r.moveLeft(container.x() + padding.left() + margins.left());
1186 else if (alignment & Qt::AlignHCenter)
1187 r.moveLeft(container.x() + (container.width() - size.width()) / 2);
1189 r.moveLeft(container.x() + container.width() - padding.right() - margins.right() - size.width());
1191 if (alignment & Qt::AlignTop)
1192 r.moveTop(container.y() + padding.top() + margins.top());
1193 else if (alignment & Qt::AlignVCenter)
1194 r.moveTop(container.y() + (container.height() - size.height()) / 2);
1196 r.moveTop(container.y() + container.height() - padding.bottom() - margins.bottom() - size.height());
1201QStyleKitStylePrivate::ControlMetrics
QStyleKitStylePrivate::metricsForReader(QQStyleKitReader *reader)
const
1204 const QQStyleKitControlProperties *props = reader->global();
1205 ControlMetrics metrics;
1206 metrics.bgImplicitSize = QSize(0, 0);
1207 metrics.textPadding = QMargins(0, 0, 0, 0);
1208 metrics.padding = QMargins(props->leftPadding(), props->topPadding(),
1209 props->rightPadding(), props->bottomPadding());
1210 metrics.spacing = props->spacing();
1211 metrics.margins = QMargins(0, 0, 0, 0);
1212 metrics.indicatorImplicitSize = QSize(0, 0);
1213 metrics.indicatorMargins = QMargins(0, 0, 0, 0);
1214 metrics.foregroundImplicitSize = QSize(0, 0);
1215 metrics.foregroundMargins = QMargins(0, 0, 0, 0);
1216 const auto *background = props->background();
1218 auto scale = background->scale();
1221 metrics.bgImplicitSize = QSize(
static_cast<
int>(background->implicitWidth()),
static_cast<
int>(background->implicitHeight())) * scale;
1222 metrics.margins = elementMargins(background);
1224 const auto *textProps = props->text();
1226 metrics.textPadding = QMargins(textProps->leftPadding(), textProps->topPadding(),textProps->rightPadding(), textProps->bottomPadding());
1227 const auto *indicator = props->indicator();
1229 auto scale = indicator->scale();
1232 metrics.indicatorMargins = elementMargins(indicator);
1233 metrics.indicatorImplicitSize = QSize(std::max(.0, indicator->implicitWidth()),
1234 std::max(.0, indicator->implicitHeight())) * scale;
1236 const auto *foreground = indicator->foreground();
1238 auto scale = foreground->scale();
1241 metrics.foregroundMargins = elementMargins(foreground);
1242 const auto foregroundW = resolvedImplicitWidth(foreground,
1243 std::max(.0, qreal(metrics.indicatorImplicitSize.width() - metrics.foregroundMargins.left() - metrics.foregroundMargins.right())));
1244 const auto foregroundH = resolvedImplicitHeight(foreground,
1245 std::max(.0, qreal(metrics.indicatorImplicitSize.height() - metrics.foregroundMargins.top() - metrics.foregroundMargins.bottom())));
1246 metrics.foregroundImplicitSize = QSize(foregroundW, foregroundH) * scale;
1249 const auto *handle = props->handle();
1251 auto scale = handle->scale();
1254 metrics.handleImplicitSize = QSize(std::max(.0, handle->implicitWidth()),
1255 std::max(.0, handle->implicitHeight())) * scale;
1256 metrics.handleMargins = elementMargins(handle);
1262
1263
1264
1265
1266
1267QStyleKitStyle::QStyleKitStyle()
1268 : QCommonStyle(*
new QStyleKitStylePrivate())
1273
1274
1275
1276
1277
1278
1279
1280
1281QStyleKitStyle::QStyleKitStyle(
const QString &filePath)
1282 : QCommonStyle(*
new QStyleKitStylePrivate())
1284 Q_D(QStyleKitStyle);
1285 d->stylePath = filePath;
1286 if (!d->loadStyle()) {
1287 qWarning(
"QStyleKitStyle: Failed to load style from %s", qPrintable(filePath));
1292
1293
1294QStyleKitStyle::~QStyleKitStyle()
1299
1300
1301
1302
1303QString QStyleKitStyle::stylePath()
const
1305 Q_D(
const QStyleKitStyle);
1306 return d->stylePath;
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321void QStyleKitStyle::setStylePath(
const QString &filePath)
1323 Q_D(QStyleKitStyle);
1324 if (d->stylePath == filePath)
1326 d->stylePath = filePath;
1329 emit stylePathChanged();
1333
1334
1335
1336
1337
1338QString QStyleKitStyle::themeName()
const
1340 Q_D(
const QStyleKitStyle);
1341 return d->style ? d->style->themeName() : QString();
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354void QStyleKitStyle::setThemeName(
const QString &themeName)
1356 Q_D(QStyleKitStyle);
1358 qWarning(
"QStyleKitStyle: No style loaded, cannot set theme name.");
1361 if (d->style->themeName() == themeName)
1363 d->style->setThemeName(themeName);
1365 emit themeNameChanged();
1369
1370
1371
1372
1373
1374
1375
1376QStringList QStyleKitStyle::themeNames()
const
1378 Q_D(
const QStyleKitStyle);
1379 return d->style ? d->style->themeNames() : QStringList();
1383
1384
1385
1386
1387
1388
1389QStringList QStyleKitStyle::customThemeNames()
const
1391 Q_D(
const QStyleKitStyle);
1392 return d->style ? d->style->customThemeNames() : QStringList();
1396void QStyleKitStyle::drawPrimitive(PrimitiveElement pe,
const QStyleOption *opt, QPainter *p,
1397 const QWidget *w)
const
1399 Q_D(
const QStyleKitStyle);
1402 case PE_FrameButtonBevel:
1403 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1404 const auto controlType = btn->features & QStyleOptionButton::Flat
1405 ? QQStyleKitReader::ControlType::FlatButton
1406 : QQStyleKitReader::ControlType::Button;
1407 const auto r = d->resolve(w, controlType, btn->state);
1410 d->drawStyledItemRect(r.background(), opt->rect, p);
1415 QQStyleKitReader::ControlType controlType;
1416 const bool isPopup = w && (
false
1418 || qobject_cast<
const QMenu *>(w)
1420#if QT_CONFIG(combobox)
1421 || (w && w->inherits(
"QComboBoxPrivateContainer"))
1425 controlType = QQStyleKitReader::ControlType::Popup;
1426#if QT_CONFIG(lineedit)
1427 else if (qobject_cast<
const QLineEdit *>(w))
1428 controlType = QQStyleKitReader::ControlType::TextField;
1431 controlType = QQStyleKitReader::ControlType::Frame;
1432 const auto r = d->resolve(w, controlType, opt->state);
1435 d->drawStyledItemRect(r.background(), opt->rect, p);
1438#if QT_CONFIG(lineedit)
1439 case PE_PanelLineEdit:
1440 if (
const auto *lineEdit = qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
1443 QStyleOption lineEditOpt(*lineEdit);
1444 lineEditOpt.state &= ~QStyle::State_Sunken;
1445 const auto r = d->resolve(w, QQStyleKitReader::ControlType::TextField, lineEditOpt.state);
1450 if (
auto *le = qobject_cast<
const QLineEdit *>(w)) {
1451 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
1452 QPalette stylePalette;
1453 stylePalette.setColor(QPalette::Text, txt->color());
1454 d->setStylePalette(
const_cast<QLineEdit *>(le), stylePalette);
1456 const_cast<QStyleKitStylePrivate *>(d)->setStyleFont(
const_cast<QLineEdit *>(le), r.font());
1459 const QObject *parent = w ? w->parent() :
nullptr;
1460#if QT_CONFIG(spinbox)
1461 const bool isInSpinBox = qobject_cast<
const QAbstractSpinBox *>(parent);
1463 const bool isInSpinBox =
false;
1465#if QT_CONFIG(combobox)
1466 const bool isInComboBox = qobject_cast<
const QComboBox *>(parent);
1468 const bool isInComboBox =
false;
1471 if (isInSpinBox || isInComboBox)
1474 d->drawStyledItemRect(r.background(), opt->rect, p);
1479#if QT_CONFIG(itemviews)
1480 case PE_PanelItemViewItem: {
1481 const auto r = d->resolveItemViewItem(w, opt, QQStyleKitReader::ControlType::ItemDelegate, opt->state);
1484 d->drawStyledItemRect(r.background(), opt->rect, p);
1488 case PE_IndicatorCheckBox:
1489 case PE_IndicatorRadioButton: {
1490 const auto controlType = pe == PE_IndicatorCheckBox
1491 ? QQStyleKitReader::ControlType::CheckBox
1492 : QQStyleKitReader::ControlType::RadioButton;
1493 const auto r = d->resolve(w, controlType, opt->state);
1496 d->drawControlIndicator(r.indicator(), opt->rect, p);
1499 case PE_IndicatorArrowDown: {
1500 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, opt->state);
1503 d->drawControlIndicator(r.indicator(), opt->rect, p);
1506 case PE_IndicatorItemViewItemCheck: {
1507 const auto r = d->resolveItemViewItem(w, opt, QQStyleKitReader::ControlType::ItemDelegate, opt->state);
1510 d->drawControlIndicator(r.indicator(), opt->rect, p);
1513#if QT_CONFIG(spinbox)
1514 case PE_IndicatorSpinUp:
1515 case PE_IndicatorSpinDown: {
1516 const auto r = d->resolve(w, QQStyleKitReader::ControlType::SpinBox, opt->state);
1519 const auto *indicator = r.indicator();
1520 const auto *upDownIndicator = indicator ? (pe == PE_IndicatorSpinUp ? indicator->first() : indicator->second()) :
nullptr;
1521 d->drawControlIndicator(upDownIndicator, opt->rect, p);
1525#if QT_CONFIG(groupbox)
1526 case PE_FrameGroupBox: {
1527 const auto r = d->resolve(w, QQStyleKitReader::ControlType::GroupBox, opt->state);
1530 d->drawStyledItemRect(r.background(), opt->rect, p);
1537 QCommonStyle::drawPrimitive(pe, opt, p, w);
1541void QStyleKitStyle::drawControl(ControlElement element,
const QStyleOption *opt, QPainter *p,
1542 const QWidget *w)
const
1544 Q_D(
const QStyleKitStyle);
1548 if (
const QStyleOptionButton *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1549 proxy()->drawControl(CE_PushButtonBevel, btn, p, w);
1550 QStyleOptionButton btnContent(*btn);
1551 btnContent.rect = subElementRect(SE_PushButtonContents, btn, w);
1552 proxy()->drawControl(CE_PushButtonLabel, &btnContent, p, w);
1555 case CE_PushButtonBevel:
1556 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1557 QStyleOptionButton btnBg(*btn);
1558 btnBg.rect = subElementRect(SE_PushButtonBevel, btn, w);
1559 proxy()->drawPrimitive(PE_FrameButtonBevel, &btnBg, p, w);
1562 case CE_PushButtonLabel:
1563 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1564 const auto controlType = btn->features & QStyleOptionButton::Flat ? QQStyleKitReader::ControlType::FlatButton : QQStyleKitReader::ControlType::Button;
1565 const auto r = d->resolve(w, controlType, btn->state);
1568 const auto metrics = r.metrics;
1570 QRect textRect = opt->rect;
1571 uint textFlags = Qt::TextShowMnemonic;
1572 if (!styleHint(SH_UnderlineShortcut, opt, w))
1573 textFlags |= Qt::TextHideMnemonic;
1576 const QIcon icon = btn->icon;
1577 if (!icon.isNull()) {
1578 const auto *textProps = r.text();
1579 uint iconTextFlags = textFlags;
1580 iconTextFlags |= textProps
1581 ? resolvedAlignment(textProps->alignment(), Qt::AlignHCenter, Qt::AlignVCenter)
1582 : uint(Qt::AlignHCenter | Qt::AlignVCenter);
1583 QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
1584 if (mode == QIcon::Normal && btn->state & State_HasFocus)
1585 mode = QIcon::Active;
1586 QIcon::State iconState = btn->state & State_On ? QIcon::On : QIcon::Off;
1587 const auto paintDeviceDpr = p->device()->devicePixelRatio();
1588 QPixmap pixmap = icon.pixmap(btn->iconSize, paintDeviceDpr, mode, iconState);
1589 int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
1590 int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
1591 int labelWidth = pixmapWidth;
1592 int iconSpacing = metrics->spacing;
1593 int textWidth = btn->fontMetrics.boundingRect(opt->rect, iconTextFlags, btn->text).width();
1594 if (!btn->text.isEmpty())
1595 labelWidth += (textWidth + iconSpacing + textProps->leftPadding() + textProps->rightPadding());
1598 if (iconTextFlags & Qt::AlignLeft) {
1599 iconRect = QRect(textRect.x(), textRect.y() + (textRect.height() - pixmapHeight) / 2,
1600 pixmapWidth, pixmapHeight);
1601 }
else if (iconTextFlags & Qt::AlignHCenter) {
1602 iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
1603 textRect.y() + (textRect.height() - pixmapHeight) / 2,
1604 pixmapWidth, pixmapHeight);
1606 iconRect = QRect(textRect.x() + textRect.width() - labelWidth,
1607 textRect.y() + (textRect.height() - pixmapHeight) / 2,
1608 pixmapWidth, pixmapHeight);
1610 iconRect = visualRect(btn->direction, textRect, iconRect);
1613 textFlags &= ~Qt::AlignHorizontal_Mask;
1614 textFlags |= Qt::AlignLeft;
1615 if (btn->direction == Qt::RightToLeft)
1616 textRect.setRight(iconRect.left() - iconSpacing);
1618 textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing);
1620 p->drawPixmap(iconRect, pixmap);
1623 if (btn->features & QStyleOptionButton::HasMenu) {
1624 int indicatorSize = pixelMetric(PM_MenuButtonIndicator, btn, w);
1625 if (btn->direction == Qt::LeftToRight)
1626 textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
1628 textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
1630 d->drawControlText(r.text(), r.font(), textRect, btn->text, textFlags, p);
1635 case CE_RadioButton:
1636 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1637 const auto controlType = element == CE_CheckBox ? QQStyleKitReader::ControlType::CheckBox
1638 : QQStyleKitReader::ControlType::RadioButton;
1639 const auto r = d->resolve(w, controlType, btn->state);
1642 QRect backgroundRect = btn->rect.marginsRemoved(r.metrics->margins);
1644 d->drawStyledItemRect(r.background(), backgroundRect, p);
1646 QStyleOptionButton btnContent(*btn);
1647 const auto contentElement = element == CE_CheckBox ? SE_CheckBoxContents : SE_RadioButtonContents;
1648 btnContent.rect = subElementRect(contentElement, btn, w);
1649 const auto labelElement = element == CE_CheckBox ? CE_CheckBoxLabel : CE_RadioButtonLabel;
1650 proxy()->drawControl(labelElement, &btnContent, p, w);
1652 QStyleOptionButton indicator(*btn);
1653 const auto indicatorElement = element == CE_CheckBox ? SE_CheckBoxIndicator : SE_RadioButtonIndicator;
1654 indicator.rect = subElementRect(indicatorElement, btn, w);
1655 const auto primitiveElement = element == CE_CheckBox ? PE_IndicatorCheckBox : PE_IndicatorRadioButton;
1656 proxy()->drawPrimitive(primitiveElement, &indicator, p, w);
1660 case CE_CheckBoxLabel:
1661 case CE_RadioButtonLabel:
1662 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1663 const auto controlType = element == CE_CheckBoxLabel ? QQStyleKitReader::ControlType::CheckBox
1664 : QQStyleKitReader::ControlType::RadioButton;
1665 const auto r = d->resolve(w, controlType, btn->state);
1668 uint textFlags = Qt::TextShowMnemonic;
1669 if (!styleHint(SH_UnderlineShortcut, opt, w))
1670 textFlags |= Qt::TextHideMnemonic;
1671 d->drawControlText(r.text(), r.font(), opt->rect, btn->text, textFlags, p);
1675#if QT_CONFIG(combobox)
1676 case CE_ComboBoxLabel:
1677 if (
const auto *comboBox = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
1678 if (comboBox->editable)
1680 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, comboBox->state);
1683 const QRect textRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, w)
1684 .marginsRemoved(r.metrics->textPadding);
1685 uint textFlags = Qt::TextShowMnemonic;
1686 if (!styleHint(SH_UnderlineShortcut, opt, w))
1687 textFlags |= Qt::TextHideMnemonic;
1688 d->drawControlText(r.text(), r.font(), textRect, comboBox->currentText, textFlags, p);
1693#if QT_CONFIG(progressbar)
1694 case CE_ProgressBar:
1695 if (
const QStyleOptionProgressBar *progressBar = qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
1696 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar, progressBar->state);
1699 QRect backgroundRect = progressBar->rect.marginsRemoved(r.metrics->margins);
1701 d->drawStyledItemRect(r.background(), backgroundRect, p);
1703 QStyleOptionProgressBar contents(*progressBar);
1704 contents.rect = subElementRect(SE_ProgressBarGroove, progressBar, w);
1705 proxy()->drawControl(CE_ProgressBarGroove, &contents, p, w);
1707 contents.rect = subElementRect(SE_ProgressBarContents, progressBar, w);
1708 proxy()->drawControl(CE_ProgressBarContents, &contents, p, w);
1713 case CE_ProgressBarGroove: {
1715 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar, opt->state);
1718 d->drawStyledItemRect(r.indicator(), opt->rect, p);
1721 case CE_ProgressBarContents:
1723 if (
const auto *progressBar = qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
1724 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar, progressBar->state);
1727 const auto progress = progressBar->progress;
1728 const auto ratio = progressBar->maximum > progressBar->minimum ? (progress - progressBar->minimum) /
static_cast<qreal>(progressBar->maximum - progressBar->minimum) : 0;
1729 const auto width =
static_cast<
int>(progressBar->rect.width() * ratio);
1730 const auto x = progressBar->invertedAppearance ? progressBar->rect.right() - width : progressBar->rect.left();
1731 const auto contentsRect = QRect(x, progressBar->rect.y(), width, progressBar->rect.height());
1732 const auto *foreground = r.indicator() ? r.indicator()->foreground() :
nullptr;
1733 if (foreground && foreground->visible() && foreground->opacity() > 0)
1734 d->drawStyledItemRect(foreground, contentsRect, p);
1739#if QT_CONFIG(itemviews)
1740 case CE_ItemViewItem:
1741 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
1742 const auto r = d->resolveItemViewItem(w, opt, QQStyleKitReader::ControlType::ItemDelegate, opt->state);
1745 QStyleOptionViewItem optBg(*itemViewOption);
1746 optBg.rect = optBg.rect.marginsRemoved(r.metrics->margins);
1747 QRect indicatorRect = subElementRect(SE_ItemViewItemCheckIndicator, itemViewOption, w);
1748 QRect iconRect = subElementRect(SE_ItemViewItemDecoration, itemViewOption, w);
1749 QRect textRect = subElementRect(SE_ItemViewItemText, itemViewOption, w);
1752 const auto *itemTextProps = r.text();
1753 const QFont itemFont = r.font();
1756 proxy()->drawPrimitive(PE_PanelItemViewItem, &optBg, p, w);
1759 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator) {
1760 QStyleOptionViewItem option(*itemViewOption);
1761 option.rect = indicatorRect;
1762 option.state = option.state & ~QStyle::State_HasFocus;
1764 switch (itemViewOption->checkState) {
1766 option.state |= QStyle::State_Off;
1768 case Qt::PartiallyChecked:
1769 option.state |= QStyle::State_NoChange;
1772 option.state |= QStyle::State_On;
1775 proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, p, w);
1779 QIcon::Mode mode = QIcon::Normal;
1780 if (!(itemViewOption->state & QStyle::State_Enabled))
1781 mode = QIcon::Disabled;
1782 else if (itemViewOption->state & QStyle::State_Selected)
1783 mode = QIcon::Selected;
1784 QIcon::State state = itemViewOption->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
1785 itemViewOption->icon.paint(p, iconRect, itemViewOption->decorationAlignment, mode, state);
1788 uint textFlags = Qt::TextShowMnemonic;
1789 if (!styleHint(SH_UnderlineShortcut, opt, w))
1790 textFlags |= Qt::TextHideMnemonic;
1791 d->drawControlText(itemTextProps, itemFont, textRect, itemViewOption->text, textFlags, p,
1792 Qt::AlignLeft | Qt::AlignVCenter);
1798 case CE_ShapedFrame:
1799#if QT_CONFIG(combobox)
1800 if (w && w->inherits(
"QComboBoxPrivateContainer")) {
1801 const auto r = d->resolve(w, QQStyleKitReader::ControlType::Popup, opt->state);
1804 QRect backgroundRect = opt->rect.marginsRemoved(r.metrics->margins);
1805 d->drawStyledItemRect(r.background(), backgroundRect, p);
1809#if QT_CONFIG(textedit)
1810 if (qobject_cast<
const QTextEdit *>(w)) {
1811 const auto r = d->resolve(w, QQStyleKitReader::ControlType::TextArea, opt->state);
1814 QRect backgroundRect = opt->rect.marginsRemoved(r.metrics->margins);
1815 d->drawStyledItemRect(r.background(), backgroundRect, p);
1820#if QT_CONFIG(scrollbar)
1821 case CE_ScrollBarSlider: {
1822 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ScrollBar, opt->state);
1825 d->drawControlIndicator(r.indicator(), opt->rect, p);
1833 QCommonStyle::drawControl(element, opt, p, w);
1837QRect QStyleKitStyle::subElementRect(SubElement r,
const QStyleOption *opt,
const QWidget *widget)
const
1839 Q_D(
const QStyleKitStyle);
1842 case SE_PushButtonLayoutItem:
1843 case SE_PushButtonBevel:
1844 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1845 const auto controlType = btn->features & QStyleOptionButton::Flat
1846 ? QQStyleKitReader::ControlType::FlatButton
1847 : QQStyleKitReader::ControlType::Button;
1848 const auto resolved = d->resolveLayout(controlType, opt->state);
1849 if (!resolved.isValid())
1851 const auto &metrics = *resolved.metrics;
1852 QRect rect = opt->rect.marginsRemoved(metrics.margins);
1853 return visualRect(opt->direction, opt->rect, rect);
1856 case SE_PushButtonContents:
1857 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
1858 const auto controlType = btn->features & QStyleOptionButton::Flat
1859 ? QQStyleKitReader::ControlType::FlatButton
1860 : QQStyleKitReader::ControlType::Button;
1861 const auto resolved = d->resolveLayout(controlType, opt->state);
1862 if (!resolved.isValid())
1864 const auto &metrics = *resolved.metrics;
1865 QRect rect = opt->rect.marginsRemoved(metrics.margins + metrics.padding + metrics.textPadding);
1866 return visualRect(opt->direction, opt->rect, rect);
1869 case SE_CheckBoxContents:
1870 case SE_RadioButtonContents: {
1871 const auto controlType = r == SE_CheckBoxContents ? QQStyleKitReader::ControlType::CheckBox
1872 : QQStyleKitReader::ControlType::RadioButton;
1873 const auto resolved = d->resolveLayout(controlType, opt->state);
1874 if (!resolved.isValid())
1876 const auto &metrics = *resolved.metrics;
1877 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
1878 const auto subElement = r == SE_CheckBoxContents ? SE_CheckBoxIndicator : SE_RadioButtonIndicator;
1879 QRect indicatorRect = visualRect(opt->direction, opt->rect, subElementRect(subElement, opt, widget));
1880 const int spacing = metrics.spacing;
1881 const auto *indicator = resolved.indicator();
1882 const uint alignment = indicator
1883 ? resolvedAlignment(indicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
1884 : uint(Qt::AlignLeft | Qt::AlignVCenter);
1885 if (alignment & Qt::AlignLeft) {
1886 contentsRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
1887 }
else if (alignment & Qt::AlignHCenter) {
1888 contentsRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
1889 contentsRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
1891 contentsRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
1893 return visualRect(opt->direction, opt->rect, contentsRect);
1895 case SE_CheckBoxIndicator:
1896 case SE_RadioButtonIndicator: {
1897 const auto controlType = r == SE_CheckBoxIndicator
1898 ? QQStyleKitReader::ControlType::CheckBox
1899 : QQStyleKitReader::ControlType::RadioButton;
1900 const auto resolved = d->resolveLayout(controlType, opt->state);
1901 if (!resolved.isValid())
1903 const auto &metrics = *resolved.metrics;
1904 QRect rect = opt->rect.marginsRemoved(metrics.margins);
1905 const auto *indicator = resolved.indicator();
1906 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
1909 const int w = resolvedImplicitWidth(indicator,
1910 rect.width() - metrics.padding.left() - metrics.padding.right()
1911 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right());
1912 const int h = resolvedImplicitHeight(indicator,
1913 rect.height() - metrics.padding.top() - metrics.padding.bottom()
1914 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom());
1915 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
1916 const QRect indicatorRect = d->getAlignedRectInContainer(
1917 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
1918 return visualRect(opt->direction, rect, indicatorRect);
1920#if QT_CONFIG(itemviews)
1921 case SE_ItemViewItemCheckIndicator: {
1922 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ItemDelegate, opt->state);
1923 if (!resolved.isValid())
1925 const auto &metrics = *resolved.metrics;
1926 QRect rect = opt->rect.marginsRemoved(metrics.margins);
1927 const auto *indicator = resolved.indicator();
1928 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
1931 const int w = resolvedImplicitWidth(indicator,
1932 rect.width() - metrics.padding.left() - metrics.padding.right()
1933 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right());
1934 const int h = resolvedImplicitHeight(indicator,
1935 rect.height() - metrics.padding.top() - metrics.padding.bottom()
1936 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom());
1937 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
1938 const QRect indicatorRect = d->getAlignedRectInContainer(
1939 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
1940 return visualRect(opt->direction, rect, indicatorRect);
1942 case SE_ItemViewItemText:
1943 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
1944 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ItemDelegate, opt->state);
1945 if (!resolved.isValid())
1947 const auto &metrics = *resolved.metrics;
1948 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
1949 QRect indicatorRect;
1950 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator)
1951 indicatorRect = subElementRect(SE_ItemViewItemCheckIndicator, opt, widget);
1952 const int spacing = metrics.spacing;
1953 QRect textRect = contentsRect;
1954 const auto *textProps = resolved.text();
1957 textAlign = resolvedAlignment(textProps->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
1959 textAlign = Qt::AlignLeft | Qt::AlignVCenter;
1960 if (indicatorRect.isValid()) {
1961 if (textAlign & Qt::AlignLeft) {
1962 textRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
1963 }
else if (textAlign & Qt::AlignHCenter) {
1964 textRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
1965 textRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
1967 textRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
1970 if (textAlign & Qt::AlignLeft) {
1971 textRect.setLeft(textRect.left() + metrics.textPadding.left());
1972 }
else if (textAlign & Qt::AlignHCenter) {
1973 textRect.setLeft(textRect.left() + metrics.textPadding.left() / 2);
1974 textRect.setRight(textRect.right() - metrics.textPadding.right() / 2);
1976 textRect.setRight(textRect.right() - metrics.textPadding.right());
1979 if (textAlign & Qt::AlignTop) {
1980 textRect.setTop(textRect.top() + metrics.textPadding.top());
1981 }
else if (textAlign & Qt::AlignVCenter) {
1982 textRect.setTop(textRect.top() + metrics.textPadding.top() / 2);
1983 textRect.setBottom(textRect.bottom() - metrics.textPadding.bottom() / 2);
1985 textRect.setBottom(textRect.bottom() - metrics.textPadding.bottom());
1987 return visualRect(opt->direction, opt->rect, textRect);
1991 case SE_PushButtonFocusRect:
1992 case SE_CheckBoxClickRect:
1993 case SE_RadioButtonClickRect:
1995#if QT_CONFIG(progressbar)
1996 case SE_ProgressBarGroove: {
1997 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar, opt->state);
1998 if (!resolved.isValid())
2000 const auto &metrics = *resolved.metrics;
2001 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2002 const auto *indicator = resolved.indicator();
2003 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2006 const int w = resolvedImplicitWidth(indicator,
2007 rect.width() - metrics.padding.left() - metrics.padding.right()
2008 - metrics.indicatorMargins.left() - metrics.indicatorMargins.right());
2009 const int h = resolvedImplicitHeight(indicator,
2010 rect.height() - metrics.padding.top() - metrics.padding.bottom()
2011 - metrics.indicatorMargins.top() - metrics.indicatorMargins.bottom());
2012 const uint alignment = resolvedAlignment(indicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
2013 const QRect indicatorRect = d->getAlignedRectInContainer(
2014 rect, QSize(w, h), alignment, metrics.padding, metrics.indicatorMargins);
2015 return visualRect(opt->direction, rect, indicatorRect);
2017 case SE_ProgressBarContents: {
2018 if (qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
2019 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar, opt->state);
2020 if (!resolved.isValid())
2022 const auto *foreground = resolved.indicator() ? resolved.indicator()->foreground() :
nullptr;
2023 if (!foreground || !foreground->visible() || foreground->opacity() == 0)
2026 QRect indicatorRect = subElementRect(SE_ProgressBarGroove, opt, widget);
2027 const auto foregroundW = resolvedImplicitWidth(foreground,
2028 indicatorRect.width() - foreground->leftMargin() - foreground->rightMargin());
2029 const auto foregroundH = resolvedImplicitHeight(foreground,
2030 indicatorRect.height() - foreground->topMargin() - foreground->bottomMargin());
2031 const uint foregroundAlign = resolvedAlignment(foreground->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
2032 const QMargins foregroundMargins = elementMargins(foreground);
2033 const QRect foregroundRect = d->getAlignedRectInContainer(
2034 indicatorRect, QSize(foregroundW, foregroundH), foregroundAlign, QMargins(0, 0, 0, 0), foregroundMargins);
2035 return visualRect(opt->direction, opt->rect, foregroundRect);
2040 case SE_LineEditContents:
2041 if (qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
2042#if QT_CONFIG(spinbox)
2043 const bool isInSpinBox = widget && qobject_cast<
const QSpinBox *>(widget->parentWidget());
2045 const bool isInSpinBox =
false;
2047 const auto controlType = isInSpinBox ? QQStyleKitReader::ControlType::SpinBox : QQStyleKitReader::ControlType::TextField;
2048 const auto resolved = d->resolveLayout(controlType, opt->state);
2049 if (!resolved.isValid())
2051 const auto &metrics = *resolved.metrics;
2052 QRect contentsRect = opt->rect.marginsRemoved(metrics.padding);
2053 const auto *textProps = resolved.text();
2054 const uint textAlign = resolvedAlignment(
2055 textProps ? textProps->alignment() : 0u, Qt::AlignLeft, Qt::AlignVCenter);
2056 if (textAlign & Qt::AlignLeft)
2057 contentsRect.setLeft(contentsRect.left() + metrics.textPadding.left());
2058 else if (textAlign & Qt::AlignHCenter) {
2059 contentsRect.setLeft(contentsRect.left() + metrics.textPadding.left() / 2);
2060 contentsRect.setRight(contentsRect.right() - metrics.textPadding.right() / 2);
2062 contentsRect.setRight(contentsRect.right() - metrics.textPadding.right());
2064 if (textAlign & Qt::AlignTop)
2065 contentsRect.setTop(contentsRect.top() + metrics.textPadding.top());
2066 else if (textAlign & Qt::AlignVCenter) {
2067 contentsRect.setTop(contentsRect.top() + metrics.textPadding.top() / 2);
2068 contentsRect.setBottom(contentsRect.bottom() - metrics.textPadding.bottom() / 2);
2070 contentsRect.setBottom(contentsRect.bottom() - metrics.textPadding.bottom());
2072 return visualRect(opt->direction, opt->rect, contentsRect);
2075 case SE_ShapedFrameContents:
2076#if QT_CONFIG(combobox)
2077 if (widget && widget->inherits(
"QComboBoxPrivateContainer")) {
2078 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Popup, opt->state);
2079 if (!resolved.isValid())
2081 const auto &metrics = *resolved.metrics;
2082 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding + metrics.textPadding);
2083 return visualRect(opt->direction, opt->rect, contentsRect);
2086#if QT_CONFIG(textedit)
2087 if (qobject_cast<
const QTextEdit *>(widget)) {
2088 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::TextArea, opt->state);
2089 if (!resolved.isValid())
2091 const auto &metrics = *resolved.metrics;
2092 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding + metrics.textPadding);
2093 return visualRect(opt->direction, opt->rect, contentsRect);
2100 return QCommonStyle::subElementRect(r, opt, widget);
2104void QStyleKitStyle::drawComplexControl(ComplexControl cc,
const QStyleOptionComplex *opt, QPainter *p,
2105 const QWidget *w)
const
2107 Q_D(
const QStyleKitStyle);
2110#if QT_CONFIG(slider)
2112 if (
const QStyleOptionSlider *slider = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
2113 const auto r = d->resolve(w, QQStyleKitReader::ControlType::Slider, slider->state);
2116 const auto &metrics = *r.metrics;
2117 QRect backgroundRect = opt->rect.marginsRemoved(metrics.margins);
2120 d->drawStyledItemRect(r.background(), backgroundRect, p);
2123 if (slider->subControls & SC_SliderGroove) {
2125 const auto grooveRect = proxy()->subControlRect(CC_Slider, opt, SC_SliderGroove, w);
2126 const auto *indicator = r.indicator();
2127 d->drawStyledItemRect(indicator, grooveRect, p);
2130 const auto *foreground = indicator ? indicator->foreground() :
nullptr;
2131 if (foreground && foreground->visible() && foreground->opacity() > 0) {
2132 const bool isHorizontal = slider->orientation == Qt::Horizontal;
2133 const qreal availableW = grooveRect.width() - foreground->leftMargin() - foreground->rightMargin();
2134 const qreal availableH = grooveRect.height() - foreground->topMargin() - foreground->bottomMargin();
2136 const qreal range = slider->maximum - slider->minimum;
2137 const qreal ratio = range > 0 ? (slider->sliderPosition - slider->minimum) / range : 0;
2139 const auto hAlign = foreground->alignment() & Qt::AlignHorizontal_Mask;
2140 const auto vAlign = foreground->alignment() & Qt::AlignVertical_Mask;
2141 const qreal fgW = resolvedImplicitWidth(foreground, availableW);
2142 const qreal fgH = resolvedImplicitHeight(foreground, availableH);
2143 const qreal fgX = hAlign & Qt::AlignRight
2144 ? grooveRect.left() + foreground->leftMargin() + availableW - fgW
2145 : hAlign & Qt::AlignHCenter
2146 ? grooveRect.left() + foreground->leftMargin() + (availableW - fgW) / 2
2147 : grooveRect.left() + foreground->leftMargin();
2148 const qreal fgY = vAlign & Qt::AlignBottom
2149 ? grooveRect.top() + foreground->topMargin() + availableH - fgH
2150 : vAlign & Qt::AlignVCenter
2151 ? grooveRect.top() + foreground->topMargin() + (availableH - fgH) / 2
2152 : grooveRect.top() + foreground->topMargin();
2154 const qreal minW = foreground->minimumWidth();
2157 const qreal trackW = foreground->fillWidth()
2158 ? minW + ratio * (fgW - minW)
2160 trackRect = QRectF(fgX, fgY, trackW, fgH);
2162 const qreal trackH = foreground->fillHeight()
2163 ? minW + ratio * (fgH - minW)
2165 const qreal trackY = fgY + (1.0 - ratio) * (foreground->fillHeight() ? fgH - minW : fgH);
2166 trackRect = QRectF(fgX, trackY, fgW, trackH);
2168 d->drawStyledItemRect(foreground, visualRect(opt->direction, grooveRect, trackRect.toAlignedRect()), p);
2173 if (slider->subControls & SC_SliderHandle) {
2174 QStyleOptionSlider handleOpt(*slider);
2175 handleOpt.rect = subControlRect(CC_Slider, opt, SC_SliderHandle, w);
2176 const auto *handle = r.handle();
2177 if (handle && handle->visible() && handle->opacity() > 0)
2178 d->drawStyledItemRect(handle, handleOpt.rect, p);
2184#if QT_CONFIG(combobox)
2186 if (
const QStyleOptionComboBox *combo = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
2188 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, combo->state);
2191 QRect frameRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxFrame, w);
2192 d->drawStyledItemRect(r.background(), frameRect, p);
2195 if (combo->subControls & SC_ComboBoxArrow) {
2196 QStyleOptionComboBox indicatorOpt(*combo);
2197 indicatorOpt.rect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
2198 proxy()->drawPrimitive(PE_IndicatorArrowDown, &indicatorOpt, p, w);
2203 if (
auto *cb = qobject_cast<
const QComboBox *>(w); cb && cb->isEditable()) {
2204 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
2205 QPalette stylePalette;
2206 stylePalette.setColor(QPalette::Text, txt->color());
2207 d->setStylePalette(cb->lineEdit(), stylePalette);
2214#if QT_CONFIG(spinbox)
2216 if (
const QStyleOptionSpinBox *spin = qstyleoption_cast<
const QStyleOptionSpinBox *>(opt)) {
2217 const auto r = d->resolve(w, QQStyleKitReader::ControlType::SpinBox, spin->state);
2220 QRect frameRect = opt->rect.marginsRemoved(r.metrics->margins);
2222 d->drawStyledItemRect(r.background(), frameRect, p);
2224 if (spin->subControls & SC_SpinBoxUp) {
2225 QStyleOptionSpinBox upOpt(*spin);
2226 upOpt.rect = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w);
2227 proxy()->drawPrimitive(PE_IndicatorSpinUp, &upOpt, p, w);
2229 if (spin->subControls & SC_SpinBoxDown) {
2230 QStyleOptionSpinBox downOpt(*spin);
2231 downOpt.rect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
2232 proxy()->drawPrimitive(PE_IndicatorSpinDown, &downOpt, p, w);
2236 if (
auto *sb = qobject_cast<
const QSpinBox *>(w)) {
2237 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
2238 QLineEdit *lineEdit = sb->findChild<QLineEdit *>();
2240 QPalette p = lineEdit->palette();
2241 if (p.color(QPalette::Text) != txt->color()) {
2242 p.setColor(QPalette::Text, txt->color());
2243 lineEdit->setPalette(p);
2252#if QT_CONFIG(groupbox)
2254 if (
const QStyleOptionGroupBox *groupBox = qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
2255 const auto r = d->resolve(w, QQStyleKitReader::ControlType::GroupBox, groupBox->state);
2260 if (groupBox->subControls & SC_GroupBoxFrame) {
2261 QStyleOptionFrame frameOpt;
2262 frameOpt.QStyleOption::operator=(*groupBox);
2263 frameOpt.rect = subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, w);
2264 drawPrimitive(PE_FrameGroupBox, &frameOpt, p, w);
2268 if (groupBox->subControls & SC_GroupBoxLabel && !groupBox->text.isEmpty()) {
2269 const auto *textProps = r.text();
2270 const QFont textFont = r.font();
2271 QRect titleRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w);
2272 d->drawControlText(textProps, textFont, titleRect.marginsRemoved(r.metrics->textPadding),
2273 groupBox->text, Qt::TextShowMnemonic, p, Qt::AlignLeft | Qt::AlignVCenter);
2281#if QT_CONFIG(scrollbar)
2283 if (
const auto *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
2284 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ScrollBar, scrollbar->state);
2289 if (scrollbar->subControls & SC_ScrollBarGroove) {
2290 QRect backgroundRect = proxy()->subControlRect(CC_ScrollBar, opt, SC_ScrollBarGroove, w);
2291 d->drawStyledItemRect(r.background(), backgroundRect, p);
2298 if (scrollbar->subControls & SC_ScrollBarSlider) {
2299 QStyleOptionSlider newScrollbar(*scrollbar);
2300 newScrollbar.rect = proxy()->subControlRect(CC_ScrollBar, opt, SC_ScrollBarSlider, w);
2301 proxy()->drawControl(CE_ScrollBarSlider, &newScrollbar, p, w);
2309 QCommonStyle::drawComplexControl(cc, opt, p, w);
2313QStyle::SubControl QStyleKitStyle::hitTestComplexControl(ComplexControl cc,
const QStyleOptionComplex *opt,
2314 const QPoint &pt,
const QWidget *w)
const
2316 return QCommonStyle::hitTestComplexControl(cc, opt, pt, w);
2320QRect QStyleKitStyle::subControlRect(ComplexControl cc,
const QStyleOptionComplex *opt, SubControl sc,
2321 const QWidget *w)
const
2323 Q_D(
const QStyleKitStyle);
2326#if QT_CONFIG(slider)
2328 if (
const QStyleOptionSlider *slider = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
2329 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Slider, opt->state);
2330 if (!resolved.isValid())
2332 const auto &metrics = *resolved.metrics;
2333 const bool horizontal = slider->orientation == Qt::Horizontal;
2334 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins).marginsRemoved(metrics.padding);
2336 const auto *indicator = resolved.indicator();
2338 return contentsRect;
2340 case SC_SliderGroove: {
2341 const auto availableW = contentsRect.width() - indicator->leftMargin() - indicator->rightMargin();
2342 const auto availableH = contentsRect.height() - indicator->topMargin() - indicator->bottomMargin();
2343 const qreal grooveW = resolvedImplicitWidth(indicator, availableW);
2344 const qreal grooveH = resolvedImplicitHeight(indicator, availableH);
2346 QRectF grooveRect(0, 0, grooveW, grooveH);
2347 const uint rawHAlign = indicator->alignment() & Qt::AlignHorizontal_Mask;
2348 const uint rawVAlign = indicator->alignment() & Qt::AlignVertical_Mask;
2349 const uint hAlign = rawHAlign ?
static_cast<Qt::Alignment>(rawHAlign) : Qt::AlignLeft;
2350 const uint vAlign = rawVAlign ?
static_cast<Qt::Alignment>(rawVAlign) : Qt::AlignVCenter;
2352 if (hAlign & Qt::AlignLeft) {
2353 grooveRect.moveLeft(contentsRect.x() + indicator->leftMargin());
2354 }
else if (hAlign & Qt::AlignHCenter) {
2355 const int availableWidth = contentsRect.width()
2356 - indicator->leftMargin()
2357 - indicator->rightMargin();
2358 grooveRect.moveLeft(contentsRect.x() + indicator->leftMargin()
2359 + (availableWidth - grooveW) / 2.0);
2361 grooveRect.moveLeft(contentsRect.x() + contentsRect.width()
2362 - indicator->rightMargin() - grooveW);
2365 if (vAlign & Qt::AlignTop) {
2366 grooveRect.moveTop(contentsRect.y() + indicator->topMargin());
2367 }
else if (vAlign & Qt::AlignVCenter) {
2368 const int availableHeight = contentsRect.height()
2369 - indicator->topMargin()
2370 - indicator->bottomMargin();
2371 grooveRect.moveTop(contentsRect.y() + indicator->topMargin()
2372 + (availableHeight - grooveH) / 2.0);
2374 grooveRect.moveTop(contentsRect.y() + contentsRect.height()
2375 - indicator->bottomMargin() - grooveH);
2377 return visualRect(opt->direction, opt->rect, grooveRect.toAlignedRect());
2379 case SC_SliderHandle: {
2380 const auto *handle = resolved.handle();
2381 if (!handle || !handle->visible() || handle->opacity() == 0)
2382 return contentsRect;
2385 const auto handleW = resolvedImplicitWidth(handle,
2386 contentsRect.width() - handle->leftMargin() - handle->rightMargin());
2387 const auto handleH = resolvedImplicitHeight(handle,
2388 contentsRect.height() - handle->topMargin() - handle->bottomMargin());
2390 const int range = contentsRect.width()
2391 - handle->leftMargin() - handle->rightMargin() - handleW;
2392 const int sliderPos = QStyle::sliderPositionFromValue(
2393 slider->minimum, slider->maximum, slider->sliderPosition, range,
false);
2395 contentsRect.x() + handle->leftMargin() + sliderPos,
2396 contentsRect.y() + handle->topMargin() - handle->bottomMargin()
2397 + (contentsRect.height() - handleH) / 2,
2400 const int range = contentsRect.height()
2401 - handle->topMargin() - handle->bottomMargin() - handleH;
2402 const int sliderPos = QStyle::sliderPositionFromValue(
2403 slider->minimum, slider->maximum, slider->sliderPosition, range,
true);
2405 contentsRect.x() + handle->leftMargin() - handle->rightMargin()
2406 + (contentsRect.width() - handleW) / 2,
2407 contentsRect.y() + handle->topMargin() + sliderPos,
2410 return visualRect(opt->direction, opt->rect, handleRect);
2418#if QT_CONFIG(combobox)
2420 if (
const QStyleOptionComboBox *combo = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
2421 QRect frameRect = combo->rect;
2422 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::ComboBox, combo->state);
2425 const auto &metrics = *r.metrics;
2426 frameRect = frameRect.marginsRemoved(metrics.margins);
2428 case SC_ComboBoxFrame:
2429 return visualRect(opt->direction, opt->rect, frameRect);
2430 case SC_ComboBoxEditField: {
2431 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
2432 QRect indicatorRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
2433 const int spacing = metrics.spacing;
2434 const auto *indicator = r.indicator();
2435 const uint indicatorAlign = indicator
2436 ? resolvedAlignment(indicator->alignment(), Qt::AlignRight, Qt::AlignVCenter)
2437 : uint(Qt::AlignRight | Qt::AlignVCenter);
2438 if (indicatorAlign & Qt::AlignLeft) {
2439 contentsRect.setLeft(indicatorRect.right() + spacing);
2440 }
else if (indicatorAlign & Qt::AlignRight) {
2441 contentsRect.setRight(indicatorRect.left() - spacing);
2443 return visualRect(opt->direction, opt->rect, contentsRect);
2445 case SC_ComboBoxArrow: {
2446 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
2447 const auto *indicator = r.indicator();
2448 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2449 return contentsRect;
2451 const int w = resolvedImplicitWidth(indicator,
2452 contentsRect.width() - indicator->leftMargin() - indicator->rightMargin());
2453 const int h = resolvedImplicitHeight(indicator,
2454 contentsRect.height() - indicator->topMargin() - indicator->bottomMargin());
2455 const uint indicatorAlign = resolvedAlignment(indicator->alignment(), Qt::AlignRight, Qt::AlignVCenter);
2456 const QMargins indicatorMargins = elementMargins(indicator);
2457 return visualRect(opt->direction, opt->rect,
2458 d->getAlignedRectInContainer(contentsRect, QSize(w, h), indicatorAlign, QMargins(), indicatorMargins));
2460 case SC_ComboBoxListBoxPopup: {
2461 QRect popupRect = opt->rect;
2462 popupRect.setTop(opt->rect.bottom());
2463 return visualRect(opt->direction, opt->rect, popupRect);
2471#if QT_CONFIG(spinbox)
2473 if (
const QStyleOptionSpinBox *spinBox = qstyleoption_cast<
const QStyleOptionSpinBox *>(opt)) {
2474 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::SpinBox, spinBox->state);
2477 const auto &metrics = *r.metrics;
2478 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
2479 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
2481 case SC_SpinBoxFrame:
2482 return visualRect(opt->direction, opt->rect, frameRect);
2483 case SC_SpinBoxEditField: {
2484 QRect upIndicatorRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w);
2485 QRect downIndicatorRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
2486 const int spacing = metrics.spacing;
2487 const auto *upIndicator = r.indicator() ? r.indicator()->first() :
nullptr;
2488 const auto *downIndicator = r.indicator() ? r.indicator()->second() :
nullptr;
2489 const bool hasUpIndicator = upIndicator && upIndicator->visible() && upIndicator->opacity() > 0;
2490 const bool hasDownIndicator = downIndicator && downIndicator->visible() && downIndicator->opacity() > 0;
2491 const uint upAlign = hasUpIndicator
2492 ? resolvedAlignment(upIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
2493 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2494 const uint downAlign = hasDownIndicator
2495 ? resolvedAlignment(downIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
2496 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2497 if (hasUpIndicator && hasDownIndicator) {
2498 if ((upAlign & Qt::AlignLeft) && (downAlign & Qt::AlignRight)) {
2499 contentsRect.setLeft(upIndicatorRect.right() + spacing);
2500 contentsRect.setRight(downIndicatorRect.left() - spacing);
2501 }
else if ((upAlign & Qt::AlignRight) && (downAlign & Qt::AlignLeft)) {
2502 contentsRect.setRight(upIndicatorRect.left() - spacing);
2503 contentsRect.setLeft(downIndicatorRect.right() + spacing);
2505 }
else if (hasUpIndicator) {
2506 if (upAlign & Qt::AlignLeft) {
2507 contentsRect.setLeft(upIndicatorRect.right() + spacing);
2508 }
else if (upAlign & Qt::AlignRight) {
2509 contentsRect.setRight(upIndicatorRect.left() - spacing);
2511 }
else if (hasDownIndicator) {
2512 if (downAlign & Qt::AlignLeft) {
2513 contentsRect.setLeft(downIndicatorRect.right() + spacing);
2514 }
else if (downAlign & Qt::AlignRight) {
2515 contentsRect.setRight(downIndicatorRect.left() - spacing);
2518 return visualRect(opt->direction, opt->rect, contentsRect);
2520 case SC_SpinBoxUp: {
2521 const auto *upIndicator = r.indicator() ? r.indicator()->first() :
nullptr;
2522 if (!upIndicator || !upIndicator->visible() || upIndicator->opacity() == 0)
2523 return contentsRect;
2525 const int w = resolvedImplicitWidth(upIndicator,
2526 contentsRect.width() - upIndicator->leftMargin() - upIndicator->rightMargin());
2527 const int h = resolvedImplicitHeight(upIndicator,
2528 contentsRect.height() - upIndicator->topMargin() - upIndicator->bottomMargin());
2529 const uint upAlign = resolvedAlignment(upIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
2530 const QMargins upMargins = elementMargins(upIndicator);
2531 return visualRect(opt->direction, opt->rect,
2532 d->getAlignedRectInContainer(contentsRect, QSize(w, h), upAlign, QMargins(), upMargins));
2534 case SC_SpinBoxDown: {
2535 const auto *downIndicator = r.indicator() ? r.indicator()->second() :
nullptr;
2536 if (!downIndicator || !downIndicator->visible() || downIndicator->opacity() == 0)
2539 const int w = resolvedImplicitWidth(downIndicator,
2540 contentsRect.width() - downIndicator->leftMargin() - downIndicator->rightMargin());
2541 const int h = resolvedImplicitHeight(downIndicator,
2542 contentsRect.height() - downIndicator->topMargin() - downIndicator->bottomMargin());
2543 const uint downAlign = resolvedAlignment(downIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
2544 const QMargins downMargins = elementMargins(downIndicator);
2545 return visualRect(opt->direction, opt->rect,
2546 d->getAlignedRectInContainer(contentsRect, QSize(w, h), downAlign, QMargins(), downMargins));
2554#if QT_CONFIG(groupbox)
2556 if (
const QStyleOptionGroupBox *groupBox = qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
2557 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::GroupBox, groupBox->state);
2560 const auto &metrics = *r.metrics;
2561 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
2563 case SC_GroupBoxFrame:
2564 return visualRect(opt->direction, opt->rect, frameRect);
2565 case SC_GroupBoxLabel: {
2566 const int fontHeight = opt->fontMetrics.height();
2567 const int labelHeight = metrics.textPadding.top() + fontHeight
2568 + metrics.textPadding.bottom();
2569 const QRect labelContainer(opt->rect.left(), opt->rect.top(),
2572 return visualRect(opt->direction, opt->rect, labelContainer);
2574 case SC_GroupBoxCheckBox: {
2578 case SC_GroupBoxContents: {
2579 const auto labelHeight = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w).height();
2580 const auto offset = metrics.padding.top() + qMax(labelHeight, metrics.margins.top() + metrics.spacing);
2581 QRect contentsRect(opt->rect.left() + metrics.padding.left(),
2582 opt->rect.top() + offset,
2583 opt->rect.width() - metrics.padding.left() - metrics.padding.right(),
2584 opt->rect.bottom() - opt->rect.top() - offset - metrics.padding.bottom());
2585 return visualRect(opt->direction, opt->rect, contentsRect);
2593#if QT_CONFIG(scrollbar)
2595 if (
const auto *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
2596 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ScrollBar, opt->state);
2597 if (!resolved.isValid())
2599 const auto &metrics = *resolved.metrics;
2600 const bool horizontal = scrollbar->orientation == Qt::Horizontal;
2601 const QRectF grooveRect = opt->rect.marginsRemoved(metrics.margins);
2605 case SC_ScrollBarAddLine:
2606 case SC_ScrollBarSubLine:
2607 case SC_ScrollBarSubPage:
2608 case SC_ScrollBarAddPage:
2610 case SC_ScrollBarGroove:
2611 return visualRect(opt->direction, opt->rect, grooveRect.toAlignedRect());
2612 case SC_ScrollBarSlider: {
2613 const auto *indicator = resolved.indicator();
2614 if (!indicator || !indicator->visible() || indicator->opacity() == 0)
2616 const QRectF contentsRect = grooveRect.marginsRemoved(metrics.padding);
2618 const qreal availableW = contentsRect.width() - indicator->leftMargin() - indicator->rightMargin();
2619 const qreal availableH = contentsRect.height() - indicator->topMargin() - indicator->bottomMargin();
2621 const int totalRange = scrollbar->maximum - scrollbar->minimum + scrollbar->pageStep;
2622 const qreal ratio = totalRange > 0 ? qreal(scrollbar->pageStep) / totalRange : 1.0;
2626 const qreal sliderW = qMax(qreal(metrics.indicatorImplicitSize.width()), availableW * ratio);
2627 const qreal sliderH = resolvedImplicitHeight(indicator, availableH);
2628 const qreal travelRange = qMax(0.0, availableW - sliderW);
2629 const int sliderPos = QStyle::sliderPositionFromValue(
2630 scrollbar->minimum, scrollbar->maximum,
2631 scrollbar->sliderPosition,
int(travelRange), scrollbar->upsideDown);
2632 sliderRect = QRectF(
2633 contentsRect.x() + indicator->leftMargin() + sliderPos,
2634 contentsRect.y() + indicator->topMargin() + (availableH - sliderH) / 2.0,
2637 const qreal sliderH = qMax(qreal(metrics.indicatorImplicitSize.width()), availableH * ratio);
2638 const qreal sliderW = resolvedImplicitWidth(indicator, availableW);
2639 const qreal travelRange = qMax(0.0, availableH - sliderH);
2640 const int sliderPos = QStyle::sliderPositionFromValue(
2641 scrollbar->minimum, scrollbar->maximum,
2642 scrollbar->sliderPosition,
int(travelRange), scrollbar->upsideDown);
2643 sliderRect = QRectF(
2644 contentsRect.x() + indicator->leftMargin() + (availableW - sliderW) / 2.0,
2645 contentsRect.y() + indicator->topMargin() + sliderPos,
2648 return visualRect(opt->direction, opt->rect, sliderRect.toAlignedRect());
2659 return QCommonStyle::subControlRect(cc, opt, sc, w);
2663QSize QStyleKitStyle::sizeFromContents(ContentsType ct,
const QStyleOption *opt,
2664 const QSize &contentsSize,
const QWidget *widget)
const
2666 Q_D(
const QStyleKitStyle);
2670 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2671 const auto controlType = btn->features & QStyleOptionButton::Flat
2672 ? QQStyleKitReader::ControlType::FlatButton
2673 : QQStyleKitReader::ControlType::Button;
2674 const auto resolved = d->resolveLayout(controlType, opt->state);
2675 if (!resolved.isValid())
2677 const auto &metrics = *resolved.metrics;
2678 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, btn->text);
2679 const QSize contentSizeWithPadding = textSize.expandedTo(contentsSize)
2680 + QSize(metrics.padding.left() + metrics.padding.right(),
2681 metrics.padding.top() + metrics.padding.bottom())
2682 + QSize(metrics.textPadding.left() + metrics.textPadding.right(),
2683 metrics.textPadding.top() + metrics.textPadding.bottom());
2684 const QSize bgSizeWithMargins = metrics.bgImplicitSize + QSize(metrics.margins.left() + metrics.margins.right(),
2685 metrics.margins.top() + metrics.margins.bottom());
2686 return contentSizeWithPadding.expandedTo(bgSizeWithMargins);
2690 case CT_RadioButton:
2691 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2692 const auto controlType = ct == CT_CheckBox ? QQStyleKitReader::ControlType::CheckBox
2693 : QQStyleKitReader::ControlType::RadioButton;
2694 const auto resolved = d->resolveLayout(controlType, opt->state);
2695 if (!resolved.isValid())
2697 const auto &metrics = *resolved.metrics;
2698 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, btn->text);
2699 const int bgWidth = metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right();
2700 const int bgHeight = metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom();
2701 const int contentWidth = std::max(textSize.width(), contentsSize.width()) + metrics.padding.left() + metrics.padding.right()
2702 + metrics.textPadding.left() + metrics.textPadding.right();
2703 const int contentHeight = std::max(textSize.height(), contentsSize.height()) + metrics.padding.top() + metrics.padding.bottom()
2704 + metrics.textPadding.top() + metrics.textPadding.bottom();
2705 const int indicatorWidth = metrics.indicatorImplicitSize.width() + metrics.indicatorMargins.left()
2706 + metrics.indicatorMargins.right();
2707 const int indicatorHeight = metrics.indicatorImplicitSize.height() + metrics.indicatorMargins.top()
2708 + metrics.indicatorMargins.bottom();
2709 return QSize(std::max({contentWidth + indicatorWidth + metrics.spacing, bgWidth}),
2710 std::max({contentHeight, indicatorHeight, bgHeight}));
2713#if QT_CONFIG(itemviews)
2714 case CT_ItemViewItem:
2715 if (
const auto *item = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
2716 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ItemDelegate, opt->state);
2717 if (!resolved.isValid())
2719 const auto &metrics = *resolved.metrics;
2720 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, item->text);
2721 const int bgWidth = metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right();
2722 const int bgHeight = metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom();
2723 const int contentWidth = std::max(textSize.width(), contentsSize.width()) + metrics.padding.left() + metrics.padding.right()
2724 + metrics.textPadding.left() + metrics.textPadding.right();
2725 const int contentHeight = std::max(textSize.height(), contentsSize.height()) + metrics.padding.top() + metrics.padding.bottom()
2726 + metrics.textPadding.top() + metrics.textPadding.bottom();
2727 const int indicatorWidth = metrics.indicatorImplicitSize.width() + metrics.indicatorMargins.left()
2728 + metrics.indicatorMargins.right();
2729 const int indicatorHeight = metrics.indicatorImplicitSize.height() + metrics.indicatorMargins.top()
2730 + metrics.indicatorMargins.bottom();
2731 return QSize(std::max({contentWidth + indicatorWidth + metrics.spacing, bgWidth}),
2732 std::max({contentHeight, indicatorHeight, bgHeight}));
2736 case CT_ProgressBar:
2737 if (qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
2738 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar, opt->state);
2739 if (!resolved.isValid())
2741 const auto &metrics = *resolved.metrics;
2742 const auto indicatorW = std::max(metrics.indicatorImplicitSize.width()
2743 + metrics.indicatorMargins.left()
2744 + metrics.indicatorMargins.right(),
2745 metrics.foregroundImplicitSize.width()
2746 + metrics.foregroundMargins.left()
2747 + metrics.foregroundMargins.right());
2748 const auto indicatorH = std::max(metrics.indicatorImplicitSize.height()
2749 + metrics.indicatorMargins.top()
2750 + metrics.indicatorMargins.bottom(),
2751 metrics.foregroundImplicitSize.height()
2752 + metrics.foregroundMargins.top()
2753 + metrics.foregroundMargins.bottom());
2754 const int bgW = metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right();
2755 const int bgH = metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom();
2757 const int contentW = indicatorW + metrics.padding.left() + metrics.padding.right();
2758 const int contentH = indicatorH + metrics.padding.top() + metrics.padding.bottom();
2759 return QSize(std::max(contentW, bgW), std::max(contentH, bgH));
2763 if (qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
2764 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Slider, opt->state);
2765 if (!resolved.isValid())
2767 const auto &metrics = *resolved.metrics;
2769 const int bgW = std::max(
2770 metrics.padding.left() + metrics.padding.right()
2771 + metrics.indicatorImplicitSize.width()
2772 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right(),
2773 metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right());
2774 const int bgH = std::max(
2775 metrics.padding.top() + metrics.padding.bottom()
2776 + metrics.indicatorImplicitSize.height()
2777 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom(),
2778 metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom());
2779 const int handleW = metrics.handleImplicitSize.width() + metrics.padding.left() + metrics.padding.right();
2780 const int handleH = metrics.handleImplicitSize.height() + metrics.padding.top() + metrics.padding.bottom();
2781 return QSize(std::max(handleW, bgW), std::max(handleH, bgH));
2784#if QT_CONFIG(lineedit)
2786 if (
const auto *lineEdit = qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
2787 QStyleOption lineEditOpt(*lineEdit);
2788 lineEditOpt.state &= ~QStyle::State_Sunken;
2789#if QT_CONFIG(spinbox)
2790 const bool isInSpinBox = widget && qobject_cast<
const QSpinBox *>(widget->parent());
2792 const bool isInSpinBox =
false;
2794 auto controlType = isInSpinBox ? QQStyleKitReader::ControlType::SpinBox : QQStyleKitReader::ControlType::TextField;
2795 const auto resolved = d->resolveLayout(controlType, lineEditOpt.state);
2796 if (!resolved.isValid())
2798 const auto &metrics = *resolved.metrics;
2802 bgSize = metrics.bgImplicitSize.grownBy(metrics.margins);
2803 const QSize contentSizeWithPadding = contentsSize.grownBy(metrics.textPadding).grownBy(metrics.padding);
2804 return contentSizeWithPadding.expandedTo(bgSize);
2808#if QT_CONFIG(combobox)
2810 if (
const auto *comboBox = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
2811 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ComboBox, opt->state);
2812 if (!resolved.isValid())
2814 const auto &metrics = *resolved.metrics;
2815 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, comboBox->currentText);
2816 const int bgW = metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right();
2817 const int bgH = metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom();
2818 const int contentW = textSize.width() + metrics.padding.left() + metrics.padding.right()
2819 + metrics.textPadding.left() + metrics.textPadding.right();
2820 const int contentH = textSize.height() + metrics.padding.top() + metrics.padding.bottom()
2821 + metrics.textPadding.top() + metrics.textPadding.bottom();
2822 const int indicatorW = metrics.indicatorImplicitSize.width() + metrics.indicatorMargins.left()
2823 + metrics.indicatorMargins.right();
2824 const int indicatorH = metrics.indicatorImplicitSize.height() + metrics.indicatorMargins.top()
2825 + metrics.indicatorMargins.bottom();
2826 return QSize(std::max({contentW + indicatorW + metrics.spacing, bgW}),
2827 std::max({contentH, indicatorH, bgH}));
2831#if QT_CONFIG(spinbox)
2833 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::SpinBox, opt->state);
2834 if (!resolved.isValid())
2836 const auto &metrics = *resolved.metrics;
2837 const int bgW = metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right();
2838 const int bgH = metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom();
2839 const int contentW = contentsSize.width() + metrics.padding.left() + metrics.padding.right()
2840 + metrics.textPadding.left() + metrics.textPadding.right();
2841 const int contentH = contentsSize.height() + metrics.padding.top() + metrics.padding.bottom()
2842 + metrics.textPadding.top() + metrics.textPadding.bottom();
2845 const int indicatorW = (metrics.indicatorImplicitSize.width() + metrics.indicatorMargins.left()
2846 + metrics.indicatorMargins.right()) * 2;
2847 const int indicatorH = metrics.indicatorImplicitSize.height() + metrics.indicatorMargins.top()
2848 + metrics.indicatorMargins.bottom();
2849 return QSize(std::max({contentW + indicatorW + metrics.spacing, bgW}),
2850 std::max({contentH, indicatorH, bgH}));
2853#if QT_CONFIG(groupbox)
2855 if (
const auto *groupBox = qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
2856 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::GroupBox, opt->state);
2857 if (!resolved.isValid())
2859 const auto &metrics = *resolved.metrics;
2860 const QSize bgSize = metrics.bgImplicitSize + QSize(metrics.margins.left() + metrics.margins.right(),
2861 metrics.margins.top() + metrics.margins.bottom());
2862 const QSize contentSize = contentsSize.grownBy(metrics.padding);
2863 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, groupBox->text).grownBy(metrics.textPadding);
2864 return textSize.expandedTo(contentSize).expandedTo(bgSize);
2868#if QT_CONFIG(scrollbar)
2870 if (qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
2871 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ScrollBar, opt->state);
2872 if (!resolved.isValid())
2874 const auto &metrics = *resolved.metrics;
2876 const int iH = metrics.indicatorImplicitSize.height()
2877 + metrics.padding.top() + metrics.padding.bottom()
2878 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
2879 const int iW = metrics.indicatorImplicitSize.width()
2880 + metrics.padding.left() + metrics.padding.right()
2881 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
2882 const int bgH = metrics.bgImplicitSize.height()
2883 + metrics.margins.top() + metrics.margins.bottom();
2884 const int bgW = metrics.bgImplicitSize.width()
2885 + metrics.margins.left() + metrics.margins.right();
2886 return QSize(std::max(iW, bgW), std::max(iH, bgH));
2893 return QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget);
2897int QStyleKitStyle::pixelMetric(PixelMetric m,
const QStyleOption *opt,
const QWidget *widget)
const
2904 return QCommonStyle::pixelMetric(m, opt, widget);
2908int QStyleKitStyle::styleHint(StyleHint sh,
const QStyleOption *opt,
const QWidget *w,
2909 QStyleHintReturn *shret)
const
2912 case SH_SpinBox_SelectOnStep:
2917 return QCommonStyle::styleHint(sh, opt, w, shret);
2921QPalette QStyleKitStyle::standardPalette()
const
2923 return QCommonStyle::standardPalette();
2927void QStyleKitStyle::polish(QWidget *widget)
2932 Q_D(QStyleKitStyle);
2937 d->ensureDefaultStyle();
2939 widget->setAttribute(Qt::WA_Hover);
2941#if QT_CONFIG(scrollbar)
2945 if (qobject_cast<QScrollBar *>(widget))
2946 widget->setAttribute(Qt::WA_OpaquePaintEvent,
false);
2950 const bool isInteractiveControl =
false
2951#if QT_CONFIG(pushbutton)
2952 || qobject_cast<
const QPushButton *>(widget)
2954#if QT_CONFIG(checkbox)
2955 || qobject_cast<
const QCheckBox *>(widget)
2957#if QT_CONFIG(radiobutton)
2958 || qobject_cast<
const QRadioButton *>(widget)
2960#if QT_CONFIG(combobox)
2961 || qobject_cast<
const QComboBox *>(widget)
2962 || (widget && widget->inherits(
"QComboBoxPrivateContainer"))
2964#if QT_CONFIG(lineedit)
2965 || qobject_cast<
const QLineEdit *>(widget)
2967#if QT_CONFIG(textedit)
2968 || qobject_cast<
const QTextEdit *>(widget)
2969 || qobject_cast<
const QPlainTextEdit *>(widget)
2972 || qobject_cast<
const QLabel *>(widget)
2974#if QT_CONFIG(progressbar)
2975 || qobject_cast<
const QProgressBar *>(widget)
2977#if QT_CONFIG(slider)
2978 || qobject_cast<
const QSlider *>(widget)
2980#if QT_CONFIG(scrollbar)
2981 || qobject_cast<
const QScrollBar *>(widget)
2983#if QT_CONFIG(spinbox)
2984 || qobject_cast<
const QSpinBox *>(widget)
2986#if QT_CONFIG(tabbar)
2987 || qobject_cast<
const QTabBar *>(widget)
2990 if (isInteractiveControl)
2991 d->readerForWidget(widget);
2996 if (QWidget *vp = managedViewport(widget); vp && vp->autoFillBackground()) {
2997 vp->setAutoFillBackground(
false);
2998 d->autoFillDisabledWidgets.insert(widget);
3001#if QT_CONFIG(lineedit)
3002 if (
auto *lineEdit = qobject_cast<QLineEdit *>(widget)) {
3003 if (!lineEdit->property(
"_q_stylekit_alignment_set").toBool()) {
3004 QQStyleKitReader *r = d->readerForWidget(widget);
3006 const QWidget *target = containerWidget(widget);
3007 QQStyleKitReader::ControlType ct = controlTypeForWidget(target);
3008 r->setControlType(ct);
3009 const auto *textProps = r->global()->text();
3011 const uint align = resolvedAlignment(
3012 textProps->alignment(), Qt::AlignLeft, Qt::AlignVCenter);
3013 lineEdit->setAlignment(Qt::Alignment(align));
3020 d->refreshStyleFont(widget);
3021 d->refreshStylePalette(widget);
3023 if (isSelfPaintingWidget(widget))
3024 widget->installEventFilter(
this);
3026 QCommonStyle::polish(widget);
3030void QStyleKitStyle::polish(QApplication *app)
3032 QCommonStyle::polish(app);
3036void QStyleKitStyle::polish(QPalette &palette)
3038 QCommonStyle::polish(palette);
3042void QStyleKitStyle::unpolish(QWidget *widget)
3044 Q_D(QStyleKitStyle);
3045 d->unsetStylePalette(widget);
3046 d->unsetStyleFont(widget);
3047 if (isSelfPaintingWidget(widget))
3048 widget->removeEventFilter(
this);
3049 if (d->autoFillDisabledWidgets.remove(widget)) {
3050 if (QWidget *vp = managedViewport(widget))
3051 vp->setAutoFillBackground(
true);
3053 d->cleanupWidgetReader(widget);
3054#if QT_CONFIG(scrollbar)
3055 if (qobject_cast<QScrollBar *>(widget))
3056 widget->setAttribute(Qt::WA_OpaquePaintEvent);
3058 QCommonStyle::unpolish(widget);
3062void QStyleKitStyle::unpolish(QApplication *app)
3064 Q_D(QStyleKitStyle);
3065 d->clearMetricsCache();
3066 QCommonStyle::unpolish(app);
3070bool QStyleKitStyle::eventFilter(QObject *obj, QEvent *event)
3072 Q_D(QStyleKitStyle);
3073 switch (event->type()) {
3074 case QEvent::EnabledChange:
3075 case QEvent::HoverEnter:
3076 case QEvent::HoverLeave:
3077 case QEvent::FocusIn:
3078 case QEvent::FocusOut:
3079 if (
auto *w = qobject_cast<QWidget *>(obj)) {
3080 if (d->customPaletteWidgets.contains(w))
3081 d->refreshStylePalette(w);
3082 if (d->customFontWidgets.contains(w))
3083 d->refreshStyleFont(w);
3089 return QCommonStyle::eventFilter(obj, event);
3093bool QStyleKitStyle::event(QEvent *event)
3095 return QCommonStyle::event(event);
3100#include "moc_qstylekitstyle.cpp"
Combined button and popup list for selecting options.
static qreal resolvedImplicitWidth(const QQStyleKitDelegateProperties *element, qreal availableW)
static QWidget * managedViewport(QWidget *widget)
static QMargins elementMargins(const QQStyleKitDelegateProperties *element)
static uint resolvedAlignment(uint raw, Qt::Alignment hDefault, Qt::Alignment vDefault)
static bool isSelfPaintingWidget(const QWidget *widget)
static qreal resolvedImplicitHeight(const QQStyleKitDelegateProperties *element, qreal avilableH)
static QUrl urlFromStylePath(const QString &filePath)
static const QWidget * containerWidget(const QWidget *w)