From 9da8d67b3bca1d40ae221a9c6be218fe57759724 Mon Sep 17 00:00:00 2001 From: Wladimir Leuschner Date: Thu, 1 Jun 2023 14:45:47 +0300 Subject: [PATCH] Introduce Windows 11 styled ComboBox in QWindows11Style QComboBox is adapted to use the WinUI3 style. Task-number: QTBUG-113513 Change-Id: I300157a7ce9162be73ccd4acfc50b12f7166dc2d Reviewed-by: Oliver Wolff --- .../styles/modernwindows/qwindows11style.cpp | 49 ++++++++++++++++++- src/widgets/widgets/qcombobox.cpp | 23 ++++++++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp index 7ba6af6dbf..5ba27aa60e 100644 --- a/src/plugins/styles/modernwindows/qwindows11style.cpp +++ b/src/plugins/styles/modernwindows/qwindows11style.cpp @@ -8,6 +8,8 @@ #include #include #include +#include + #include "qdrawutil.h" QT_BEGIN_NAMESPACE @@ -80,6 +82,30 @@ void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOpt painter->save(); painter->setRenderHint(QPainter::Antialiasing); switch (control) { +#if QT_CONFIG(combobox) + case CC_ComboBox: + if (const QStyleOptionComboBox *sb = qstyleoption_cast(option)) { + QBrush fillColor = state & State_MouseOver && !(state & State_HasFocus) ? QBrush(subtleHighlightColor) : option->palette.brush(QPalette::Base); + QRectF rect = option->rect.adjusted(2,2,-2,-2); + painter->setBrush(fillColor); + painter->setPen(frameColorLight); + painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius); + if (sub & SC_ComboBoxArrow) { + QRectF rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget).adjusted(0, 0, 0, 1); + painter->setFont(assetFont); + painter->setPen(sb->palette.text().color()); + painter->drawText(rect,"\uE019", Qt::AlignVCenter | Qt::AlignHCenter); + } + if (sb->editable) { + QColor lineColor = state & State_HasFocus ? option->palette.accent().color() : QColor(0,0,0); + painter->setPen(QPen(lineColor)); + painter->drawLine(rect.bottomLeft() + QPoint(2,1), rect.bottomRight() + QPoint(-2,1)); + if (state & State_HasFocus) + painter->drawLine(rect.bottomLeft() + QPoint(3,2), rect.bottomRight() + QPoint(-3,2)); + } + } + break; +#endif // QT_CONFIG(combobox) case QStyle::CC_ScrollBar: if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(option)) { QRectF rect = scrollbar->rect; @@ -186,6 +212,12 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption if (frame->frameShape == QFrame::NoFrame) break; QRect rect = option->rect.adjusted(2,2,-2,-2); + if (widget && widget->inherits("QComboBoxPrivateContainer")) { + painter->setPen(Qt::NoPen); + painter->setBrush(menuPanelFill); + painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius); + + } painter->setBrush(option->palette.base()); painter->setPen(QPen(frameColorLight)); painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius); @@ -353,7 +385,7 @@ int QWindows11Style::styleHint(StyleHint hint, const QStyleOption *opt, void QWindows11Style::polish(QWidget* widget) { QWindowsVistaStyle::polish(widget); - if (widget->inherits("QScrollBar")) { + if (widget->inherits("QScrollBar") || widget->inherits("QComboBoxPrivateContainer")) { bool wasCreated = widget->testAttribute(Qt::WA_WState_Created); widget->setAttribute(Qt::WA_OpaquePaintEvent,false); widget->setAttribute(Qt::WA_TranslucentBackground); @@ -364,6 +396,21 @@ void QWindows11Style::polish(QWidget* widget) pal.setColor(widget->backgroundRole(), Qt::transparent); widget->setPalette(pal); } + if (widget->inherits("QComboBoxPrivateContainer")) { + QGraphicsDropShadowEffect* dropshadow = new QGraphicsDropShadowEffect(widget); + dropshadow->setBlurRadius(3); + dropshadow->setXOffset(3); + dropshadow->setYOffset(3); + widget->setGraphicsEffect(dropshadow); + } + if (widget->inherits("QComboBox")) { + + QComboBox* cb = qobject_cast(widget); + if (cb->isEditable()) { + QLineEdit *le = cb->lineEdit(); + le->setFrame(false); + } + } if (widget->inherits("QGraphicsView") && !widget->inherits("QTextEdit")) { QPalette pal = widget->palette(); pal.setColor(QPalette::Base, pal.window().color()); diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index b7a084364b..937076a7b5 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -761,7 +761,9 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e) QModelIndex indexUnderMouse = view->indexAt(m->position().toPoint()); if (indexUnderMouse.isValid() && !QComboBoxDelegate::isSeparator(indexUnderMouse)) { - view->setCurrentIndex(indexUnderMouse); + // Request for comments: To show selected item with AccentColor bar indicator and hovered + // items in the flyout, the next line needs to be removed. + //view->setCurrentIndex(indexUnderMouse); } } break; @@ -2969,9 +2971,26 @@ void QComboBox::changeEvent(QEvent *e) Q_D(QComboBox); switch (e->type()) { case QEvent::StyleChange: - if (d->container) + if (d->container) { +// If on Windows, force recreation of ComboBox container, since +// windows11 style depends on WA_TranslucentBackground +#ifdef Q_OS_WIN + auto delegate = itemDelegate(); + d->container->deleteLater(); + // d->container needs to be set explicitly to nullptr + // since QComboBoxPrivate::viewContainer() only + // creates a new QComboBoxPrivateContainer when + // d->container has the value of nullptr + d->container = nullptr; + d->container = d->viewContainer(); + delegate->setParent(d->container); + setItemDelegate(delegate); + +#endif d->container->updateStyleSettings(); + } d->updateDelegate(); + #ifdef Q_OS_MAC case QEvent::MacSizeChange: #endif