284void QWindows11Style::drawComplexControl(ComplexControl control,
const QStyleOptionComplex *option,
285 QPainter *painter,
const QWidget *widget)
const
289 const auto drawTitleBarButton = [&](ComplexControl control, SubControl sc, Icon ico) {
291 const QRect buttonRect = proxy()->subControlRect(control, option, sc, widget);
292 if (buttonRect.isValid()) {
293 const bool hover = option->activeSubControls == sc && isHover(option);
296 painter->setPen(option->palette.color(QPalette::WindowText));
297 painter->drawText(buttonRect, Qt::AlignCenter, fluentIcon(ico));
300 const auto drawTitleBarCloseButton = [&](ComplexControl control, SubControl sc, Icon ico) {
302 const QRect buttonRect = proxy()->subControlRect(control, option, sc, widget);
303 if (buttonRect.isValid()) {
304 const auto state = (option->activeSubControls == sc) ? calcControlState(option)
305 : ControlState::Normal;
309 painter->fillRect(buttonRect, shellCaptionCloseFillColorPrimary);
310 pen = shellCaptionCloseTextFillColorPrimary;
313 painter->fillRect(buttonRect, shellCaptionCloseFillColorSecondary);
314 pen = shellCaptionCloseTextFillColorSecondary;
318 pen = option->palette.color(QPalette::WindowText);
322 painter->drawText(buttonRect, Qt::AlignCenter, fluentIcon(ico));
327 State state = option->state;
328 SubControls sub = option->subControls;
329 State flags = option->state;
330 if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow())
331 flags |= State_MouseOver;
333 QPainterStateGuard psg(
painter);
334 painter->setRenderHint(QPainter::Antialiasing);
335 if (d->transitionsEnabled() && option->styleObject) {
336 if (control == CC_Slider) {
337 if (
const auto *slider = qstyleoption_cast<
const QStyleOptionSlider *>(option)) {
338 QObject *styleObject = option->styleObject;
340 QRectF thumbRect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
341 const qreal outerRadius = qMin(8.0, (slider->orientation == Qt::Horizontal ? thumbRect.height() / 2.0 : thumbRect.width() / 2.0) - 1);
342 bool isInsideHandle = option->activeSubControls == SC_SliderHandle;
344 bool oldIsInsideHandle = styleObject->property(
"_q_insidehandle").toBool();
345 State oldState = State(styleObject->property(
"_q_stylestate").toInt());
346 SubControls oldActiveControls = SubControls(styleObject->property(
"_q_stylecontrols").toInt());
348 QRectF oldRect = styleObject->property(
"_q_stylerect").toRect();
349 styleObject->setProperty(
"_q_insidehandle", isInsideHandle);
350 styleObject->setProperty(
"_q_stylestate",
int(state));
351 styleObject->setProperty(
"_q_stylecontrols",
int(option->activeSubControls));
352 styleObject->setProperty(
"_q_stylerect", option->rect);
353 if (option->styleObject->property(
"_q_end_radius").isNull())
354 option->styleObject->setProperty(
"_q_end_radius", outerRadius * 0.43);
356 bool doTransition = (((state & State_Sunken) != (oldState & State_Sunken)
357 || (oldIsInsideHandle != isInsideHandle)
358 || (oldActiveControls != option->activeSubControls))
359 && state & State_Enabled);
361 if (oldRect != option->rect) {
362 doTransition =
false;
363 d->stopAnimation(styleObject);
364 styleObject->setProperty(
"_q_inner_radius", outerRadius * 0.43);
368 QNumberStyleAnimation *t =
new QNumberStyleAnimation(styleObject);
369 t->setStartValue(styleObject->property(
"_q_inner_radius").toFloat());
370 t->setEndValue(outerRadius * sliderInnerRadius(state, isInsideHandle));
371 styleObject->setProperty(
"_q_end_radius", t->endValue());
373 t->setStartTime(d->animationTime());
375 d->startAnimation(t);
378 }
else if (control == CC_ScrollBar) {
379 QObject *styleObject = option->styleObject;
380 State oldState = State(styleObject->property(
"_q_stylestate").toInt());
381 const bool wasMouseOver = oldState.testFlag(State_MouseOver);
382 const bool isMouseOver = state.testFlag(State_MouseOver);
384 if (wasMouseOver != isMouseOver) {
385 styleObject->setProperty(
"_q_stylestate",
int(state));
386 auto anim = qobject_cast<QNumberStyleAnimation *>(d->animation(styleObject));
387 constexpr int durationMS = 100;
388 qreal startValue = isMouseOver ? 0 : 1;
389 int curDurationMS = durationMS;
391 startValue = anim->currentValue();
392 curDurationMS = durationMS - (anim->duration() - anim->currentLoopTime());
393 d->stopAnimation(option->styleObject);
395 anim =
new QNumberStyleAnimation(styleObject);
396 anim->setStartValue(startValue);
397 anim->setEndValue(isMouseOver ? 1 : 0);
398 anim->setDuration(curDurationMS);
399 d->startAnimation(anim);
405#if QT_CONFIG(spinbox)
407 if (
const QStyleOptionSpinBox *sb = qstyleoption_cast<
const QStyleOptionSpinBox *>(option)) {
408 const auto frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
409 drawRoundedRect(painter, frameRect, Qt::NoPen, inputFillBrush(option, widget));
411 if (sb->frame && (sub & SC_SpinBoxFrame))
412 drawLineEditFrame(painter, frameRect, option);
414 const auto drawUpDown = [&](QStyle::SubControl sc,
415 QAbstractSpinBox::StepEnabledFlag flag) {
416 const bool isEnabled =
417 state.testFlag(QStyle::State_Enabled) && sb->stepEnabled.testFlag(flag);
418 const bool isUp = sc == SC_SpinBoxUp;
419 const QRect rect = proxy()->subControlRect(CC_SpinBox, option, sc, widget);
420 if (isEnabled && sb->activeSubControls & sc)
421 drawRoundedRect(painter, rect.adjusted(1, 1, -1, -2), Qt::NoPen,
422 winUI3Color(subtleHighlightColor));
423 painter->setFont(d->m_assetFont);
424 painter->setPen(sb->palette.color(isEnabled ? QPalette::Active : QPalette::Disabled,
425 QPalette::ButtonText));
426 painter->setBrush(Qt::NoBrush);
427 painter->drawText(rect, Qt::AlignCenter, fluentIcon(isUp ? Icon::ChevronUp : Icon::ChevronDown));
429 if (sub & SC_SpinBoxUp)
430 drawUpDown(SC_SpinBoxUp, QAbstractSpinBox::StepUpEnabled);
431 if (sub & SC_SpinBoxDown)
432 drawUpDown(SC_SpinBoxDown, QAbstractSpinBox::StepDownEnabled);
433 if (state & State_KeyboardFocusChange && state & State_HasFocus) {
434 QStyleOptionFocusRect fropt;
435 fropt.QStyleOption::operator=(*option);
436 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
443 if (
const auto *slider = qstyleoption_cast<
const QStyleOptionSlider *>(option)) {
444 const auto &slrect = slider->rect;
445 const bool isHorizontal = slider->orientation == Qt::Horizontal;
446 const QRectF handleRect(proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget));
447 const QPointF handleCenter(handleRect.center());
449 if (sub & SC_SliderGroove) {
450 QRectF rect = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
455 rect = QRectF(rect.left() + 2, rect.center().y() - 2, rect.width() - 2, 4);
456 leftRect = QRectF(rect.left(), rect.top(), handleCenter.x() - rect.left(),
458 rightRect = QRectF(handleCenter.x(), rect.top(),
459 rect.width() - handleCenter.x(),
462 rect = QRect(rect.center().x() - 2, rect.top() + 2, 4, rect.height() - 2);
463 leftRect = QRectF(rect.left(), rect.top(), rect.width(),
464 handleCenter.y() - rect.top());
465 rightRect = QRectF(rect.left(), handleCenter.y(), rect.width(),
466 rect.height() - handleCenter.y());
468 if (slider->upsideDown)
469 qSwap(leftRect, rightRect);
471 painter->setPen(Qt::NoPen);
472 painter->setBrush(calculateAccentColor(option));
473 painter->drawRoundedRect(leftRect,1,1);
474 painter->setBrush(WINUI3Colors[colorSchemeIndex][controlStrongFill]);
475 painter->drawRoundedRect(rightRect,1,1);
477 if (sub & SC_SliderTickmarks) {
478 int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
479 int ticks = slider->tickPosition;
480 int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
481 int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
482 int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
483 int interval = slider->tickInterval;
485 interval = slider->singleStep;
486 if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval,
488 - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
490 interval = slider->pageStep;
495 painter->setPen(slider->palette.text().color());
496 QVarLengthArray<QLineF, 32> lines;
497 int v = slider->minimum;
498 while (v <= slider->maximum + 1) {
499 if (v == slider->maximum + 1 && interval == 1)
501 const int v_ = qMin(v, slider->maximum);
502 int tickLength = (v_ == slider->minimum || v_ >= slider->maximum) ? 4 : 3;
503 int pos = QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, v_,
504 available, slider->upsideDown);
507 if (ticks & QSlider::TicksAbove) {
508 lines.append(QLineF(pos, tickOffset - 0.5,
509 pos, tickOffset - tickLength - 0.5));
512 if (ticks & QSlider::TicksBelow) {
513 lines.append(QLineF(pos, tickOffset + thickness + 0.5,
514 pos, tickOffset + thickness + tickLength + 0.5));
517 if (ticks & QSlider::TicksAbove) {
518 lines.append(QLineF(tickOffset - 0.5, pos,
519 tickOffset - tickLength - 0.5, pos));
522 if (ticks & QSlider::TicksBelow) {
523 lines.append(QLineF(tickOffset + thickness + 0.5, pos,
524 tickOffset + thickness + tickLength + 0.5, pos));
528 int nextInterval = v + interval;
529 if (nextInterval < v)
533 if (!lines.isEmpty()) {
534 QPainterStateGuard psg(painter);
535 painter->translate(slrect.topLeft());
536 painter->drawLines(lines.constData(), lines.size());
539 if (sub & SC_SliderHandle) {
540 const qreal outerRadius = qMin(8.0, (isHorizontal ? handleRect.height() / 2.0 : handleRect.width() / 2.0) - 1);
541 float innerRadius = outerRadius * 0.43;
543 if (option->styleObject) {
544 const QNumberStyleAnimation* animation = qobject_cast<QNumberStyleAnimation *>(d->animation(option->styleObject));
545 if (animation !=
nullptr) {
546 innerRadius = animation->currentValue();
547 option->styleObject->setProperty(
"_q_inner_radius", innerRadius);
549 bool isInsideHandle = option->activeSubControls == SC_SliderHandle;
550 innerRadius = outerRadius * sliderInnerRadius(state, isInsideHandle);
554 painter->setPen(Qt::NoPen);
555 painter->setBrush(winUI3Color(controlFillSolid));
556 painter->drawEllipse(handleCenter, outerRadius, outerRadius);
557 painter->setBrush(calculateAccentColor(option));
558 painter->drawEllipse(handleCenter, innerRadius, innerRadius);
560 painter->setPen(winUI3Color(controlStrokeSecondary));
561 painter->setBrush(Qt::NoBrush);
562 painter->drawEllipse(handleCenter, outerRadius + 0.5, outerRadius + 0.5);
564 if (slider->state & State_HasFocus) {
565 QStyleOptionFocusRect fropt;
566 fropt.QStyleOption::operator=(*slider);
567 fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget);
568 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
573#if QT_CONFIG(combobox)
575 if (
const QStyleOptionComboBox *combobox = qstyleoption_cast<
const QStyleOptionComboBox *>(option)) {
576 const auto frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
577 QStyleOption opt(*option);
578 opt.state.setFlag(QStyle::State_On,
false);
579 drawRoundedRect(painter, frameRect, Qt::NoPen,
580 combobox->editable ? inputFillBrush(option, widget)
581 : controlFillBrush(&opt, ControlType::Control));
584 drawLineEditFrame(painter, frameRect, combobox, combobox->editable);
586 const bool hasFocus = state & State_HasFocus;
588 if (sub & SC_ComboBoxArrow) {
589 QRectF rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
590 painter->setFont(d->m_assetFont);
591 painter->setPen(controlTextColor(option,
true));
592 painter->drawText(rect, Qt::AlignCenter, fluentIcon(Icon::ChevronDownMed));
594 if (state & State_KeyboardFocusChange && hasFocus) {
595 QStyleOptionFocusRect fropt;
596 fropt.QStyleOption::operator=(*option);
597 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
603 if (
const QStyleOptionSlider *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(option)) {
604 const bool vertical = scrollbar->orientation == Qt::Vertical;
605 const bool isMouseOver = state & State_MouseOver;
606 const auto prx = proxy();
608 QPainterStateGuard psg(
painter);
610 const auto anim = qobject_cast<QNumberStyleAnimation *>(d->animation(option->styleObject));
611 qreal widthFactor = isMouseOver ? 1.0 : 0.0;
613 widthFactor = anim->currentValue();
615 if (widthFactor > 0.6) {
616 const bool isRtl = option->direction == Qt::RightToLeft;
618 painter->setFont(d->assetFont(6));
619 painter->setPen(winUI3Color(controlStrongFill));
621 const QRectF rectAdd =
622 prx->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
623 const auto strAdd = vertical
624 ? Icon::CaretDownSolid8
625 : (isRtl ? Icon::CaretLeftSolid8 : Icon::CaretRightSolid8);
626 painter->drawText(rectAdd, Qt::AlignCenter, fluentIcon(strAdd));
628 const QRectF rectSub =
629 prx->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
630 const auto strSub = vertical
631 ? Icon::CaretUpSolid8
632 : (isRtl ? Icon::CaretRightSolid8 : Icon::CaretLeftSolid8);
633 painter->drawText(rectSub, Qt::AlignCenter, fluentIcon(strSub));
635 if (sub & SC_ScrollBarSlider) {
636 QRectF rect = prx->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
637 const QPointF center = rect.center();
639 auto w = rect.width() / 2. * widthFactor;
642 const auto ofs = rect.width() / 2 - w;
644 rect.moveCenter(QPointF(center.x() + ofs, center.y()));
647 auto h = rect.height() / 2. * widthFactor;
650 const auto ofs = rect.height() / 2 - h;
652 rect.moveCenter(QPointF(center.x(), center.y() + ofs));
654 drawRoundedRect(painter, rect, Qt::NoPen, winUI3Color(controlStrongFill), 3);
658 case CC_MdiControls:{
659 painter->setFont(d->assetFont(8));
660 drawTitleBarCloseButton(CC_MdiControls, SC_MdiCloseButton, Icon::ChromeClose);
661 drawTitleBarButton(CC_MdiControls, SC_MdiNormalButton, Icon::ChromeRestore);
662 drawTitleBarButton(CC_MdiControls, SC_MdiMinButton, Icon::ChromeMinimize);
666 if (
const auto* titlebar = qstyleoption_cast<
const QStyleOptionTitleBar*>(option)) {
667 painter->setPen(Qt::NoPen);
668 painter->setPen(WINUI3Colors[colorSchemeIndex][surfaceStroke]);
669 painter->setBrush(titlebar->palette.button());
670 painter->drawRect(titlebar->rect);
673 QRect textRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarLabel, widget);
674 QColor textColor = titlebar->palette.color(titlebar->titleBarState & Qt::WindowActive ? QPalette::Active : QPalette::Disabled,QPalette::WindowText);
675 painter->setPen(textColor);
677 QString title = painter->fontMetrics().elidedText(titlebar->text, Qt::ElideRight, textRect.width() - 14);
678 painter->drawText(textRect.adjusted(1, 1, -1, -1), title, QTextOption(Qt::AlignHCenter | Qt::AlignVCenter));
680 painter->setFont(d->assetFont(8));
681 auto shouldDrawButton = [titlebar](SubControl sc, Qt::WindowType flag) {
682 return (titlebar->subControls & sc) && (titlebar->titleBarFlags & flag);
686 if (shouldDrawButton(SC_TitleBarMinButton, Qt::WindowMinimizeButtonHint) &&
687 !(titlebar->titleBarState & Qt::WindowMinimized)) {
688 drawTitleBarButton(CC_TitleBar, SC_TitleBarMinButton, Icon::ChromeMinimize);
692 if (shouldDrawButton(SC_TitleBarMaxButton, Qt::WindowMaximizeButtonHint) &&
693 !(titlebar->titleBarState & Qt::WindowMaximized)) {
694 drawTitleBarButton(CC_TitleBar, SC_TitleBarMaxButton, Icon::ChromeMaximize);
698 if (shouldDrawButton(SC_TitleBarCloseButton, Qt::WindowSystemMenuHint))
699 drawTitleBarCloseButton(CC_TitleBar, SC_TitleBarCloseButton, Icon::ChromeClose);
702 if ((titlebar->subControls & SC_TitleBarNormalButton) &&
703 (((titlebar->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
704 (titlebar->titleBarState & Qt::WindowMinimized)) ||
705 ((titlebar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
706 (titlebar->titleBarState & Qt::WindowMaximized)))) {
707 drawTitleBarButton(CC_TitleBar, SC_TitleBarNormalButton, Icon::ChromeRestore);
711 if (shouldDrawButton(SC_TitleBarContextHelpButton, Qt::WindowContextHelpButtonHint))
712 drawTitleBarButton(CC_TitleBar, SC_TitleBarContextHelpButton, Icon::Help);
715 if (shouldDrawButton(SC_TitleBarShadeButton, Qt::WindowShadeButtonHint))
716 drawTitleBarButton(CC_TitleBar, SC_TitleBarShadeButton, Icon::ChevronUpSmall);
719 if (shouldDrawButton(SC_TitleBarUnshadeButton, Qt::WindowShadeButtonHint))
720 drawTitleBarButton(CC_TitleBar, SC_TitleBarUnshadeButton, Icon::ChevronDownSmall);
723 if (shouldDrawButton(SC_TitleBarSysMenu, Qt::WindowSystemMenuHint)) {
724 const QRect iconRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarSysMenu, widget);
725 if (iconRect.isValid()) {
726 if (!titlebar->icon.isNull()) {
727 titlebar->icon.paint(painter, iconRect);
729 QStyleOption tool = *titlebar;
730 const auto extent = proxy()->pixelMetric(PM_SmallIconSize, &tool, widget);
731 const auto dpr = QStyleHelper::getDpr(widget);
732 const auto icon = proxy()->standardIcon(SP_TitleBarMenuButton, &tool, widget);
733 const auto pm = icon.pixmap(QSize(extent, extent), dpr);
734 proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm);
740#if QT_CONFIG(toolbutton)
742 if (
const auto toolbutton = qstyleoption_cast<
const QStyleOptionToolButton *>(option)) {
744 const bool isSplitButton =
745 toolbutton->features.testFlag(QStyleOptionToolButton::MenuButtonPopup);
746 const auto fw = prx->pixelMetric(PM_DefaultFrameWidth, option, widget);
747 const auto buttonRect = prx->subControlRect(control, toolbutton, SC_ToolButton, widget);
748 const auto menuareaRect = isSplitButton
749 ? prx->subControlRect(control, toolbutton, SC_ToolButtonMenu, widget)
752 State bflags = toolbutton->state;
753 State mflags = toolbutton->state;
754 if (toolbutton->activeSubControls.testFlag(SC_ToolButton)) {
755 mflags &= ~(State_Sunken | State_MouseOver);
756 if (bflags.testFlag(State_Sunken))
757 mflags |= State_Raised;
759 if (toolbutton->activeSubControls.testFlag(SC_ToolButtonMenu)) {
760 bflags &= ~(State_Sunken | State_MouseOver);
761 if (mflags.testFlag(State_Sunken))
762 bflags |= State_Raised;
765 QStyleOption tool = *toolbutton;
766 if (toolbutton->subControls.testFlag(SC_ToolButton)) {
767 QPainterStateGuard psg(painter);
769 painter->setClipRect(buttonRect);
771 prx->drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
773 if (state.testFlag(State_Enabled)) {
774 painter->setPen(winUI3Color(controlStrokePrimary));
775 const auto top = buttonRect.topRight() + QPoint(0, fw + 1);
776 const auto btm = buttonRect.bottomRight() - QPoint(0, fw);
777 painter->drawLine(top, btm);
782 if (toolbutton->state.testFlag(State_HasFocus)) {
783 QStyleOptionFocusRect fr;
784 fr.QStyleOption::operator=(*toolbutton);
785 prx->drawPrimitive(PE_FrameFocusRect, &fr, painter, widget);
787 QStyleOptionToolButton label = *toolbutton;
788 label.state = bflags;
789 label.rect = buttonRect.marginsRemoved(QMargins(fw, fw, fw, fw));
791 if (toolbutton->subControls.testFlag(SC_ToolButtonMenu)) {
792 QPainterStateGuard psg(painter);
793 painter->setClipRect(menuareaRect);
795 prx->drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
797 const auto fontSize = QFontInfo(painter->font()).pointSizeF();
798 painter->setFont(d->assetFont(fontSize * 0.9f));
799 painter->setPen(controlTextColor(option));
800 const QRect textRect(menuareaRect.topLeft(), menuareaRect.size() - QSize(fw, 0));
801 painter->drawText(textRect, Qt::AlignCenter, fluentIcon(Icon::ChevronDownMed));
803 }
else if (toolbutton->features.testFlag(QStyleOptionToolButton::HasMenu)) {
804 const int mbi = qRound(prx->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget) * 0.3);
805 const QRect &ir = toolbutton->rect;
806 QRect rect(ir.right() - mbi - 2 * fw, ir.bottom() - mbi - fw, mbi,
808 rect = visualRect(toolbutton->direction, buttonRect, rect);
809 const QRect lblRect = label.rect - QMargins(0, 0, rect.width(), 0);
810 label.rect = visualRect(toolbutton->direction, buttonRect, lblRect);
811 painter->setFont(d->m_assetFont);
812 painter->setPen(controlTextColor(option));
813 painter->drawText(rect, Qt::AlignCenter, fluentIcon(Icon::ChevronDownMed));
815 prx->drawControl(CE_ToolButtonLabel, &label, painter, widget);
820 QWindowsVistaStyle::drawComplexControl(control, option, painter, widget);
824void QWindows11Style::drawPrimitive(PrimitiveElement element,
const QStyleOption *option,
826 const QWidget *widget)
const {
829 const State state = option->state;
830 QPainterStateGuard psg(
painter);
831 painter->setRenderHint(QPainter::Antialiasing);
832 if (d->transitionsEnabled() && option->styleObject && (element == PE_IndicatorCheckBox || element == PE_IndicatorRadioButton)) {
833 QObject *styleObject = option->styleObject;
834 int oldState = styleObject->property(
"_q_stylestate").toInt();
835 styleObject->setProperty(
"_q_stylestate",
int(option->state));
836 styleObject->setProperty(
"_q_stylerect", option->rect);
837 bool doTransition = (((state & State_Sunken) != (oldState & State_Sunken)
838 || ((state & State_MouseOver) != (oldState & State_MouseOver))
839 || (state & State_On) != (oldState & State_On))
840 && state & State_Enabled);
842 if (element == PE_IndicatorRadioButton) {
843 QNumberStyleAnimation *t =
new QNumberStyleAnimation(styleObject);
844 t->setStartValue(styleObject->property(
"_q_inner_radius").toFloat());
845 t->setEndValue(radioButtonInnerRadius(state));
846 styleObject->setProperty(
"_q_end_radius", t->endValue());
847 t->setStartTime(d->animationTime());
849 d->startAnimation(t);
851 else if (element == PE_IndicatorCheckBox) {
852 if ((oldState & State_Off && state & State_On) || (oldState & State_NoChange && state & State_On)) {
853 QNumberStyleAnimation *t =
new QNumberStyleAnimation(styleObject);
854 t->setStartValue(0.0f);
855 t->setEndValue(1.0f);
856 t->setStartTime(d->animationTime());
858 d->startAnimation(t);
865 case PE_IndicatorArrowUp:
866 case PE_IndicatorArrowDown:
867 case PE_IndicatorArrowRight:
868 case PE_IndicatorArrowLeft: {
869 const QRect &r = option->rect;
870 if (r.width() <= 1 || r.height() <= 1)
872 if (option->state.testFlag(State_Sunken)) {
873 const auto bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, option, widget);
874 const auto bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget);
875 if (bsx != 0 || bsy != 0)
876 painter->translate(bsx, bsy);
878 drawIndicatorArrow(painter, option->rect, element,
879 option->palette.color(QPalette::ButtonText));
882 case PE_FrameFocusRect: {
883 if (
const QStyleOptionFocusRect *fropt = qstyleoption_cast<
const QStyleOptionFocusRect *>(option)) {
884 if (!(fropt->state & State_KeyboardFocusChange))
886 QRectF focusRect = option->rect;
887 focusRect = focusRect.marginsRemoved(QMarginsF(1.5,1.5,1.5,1.5));
888 painter->setPen(winUI3Color(focusFrameInnerStroke));
889 painter->drawRoundedRect(focusRect,4,4);
891 focusRect = focusRect.marginsAdded(QMarginsF(1.0,1.0,1.0,1.0));
892 painter->setPen(QPen(winUI3Color(focusFrameOuterStroke),1));
893 painter->drawRoundedRect(focusRect,4,4);
897 case PE_PanelTipLabel: {
898 const auto rect = QRectF(option->rect).marginsRemoved(QMarginsF(0.5, 0.5, 0.5, 0.5));
899 const auto pen = highContrastTheme ? option->palette.buttonText().color()
900 : winUI3Color(frameColorLight);
901 drawRoundedRect(painter, rect, pen, option->palette.toolTipBase());
904 case PE_FrameTabWidget:
905#if QT_CONFIG(tabwidget)
906 if (
const QStyleOptionTabWidgetFrame *frame = qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(option)) {
907 const auto clipRegion = painter->clipRegion();
909 painter->setPen(highContrastTheme ? frame->palette.buttonText().color()
910 : winUI3Color(frameColorLight));
911 painter->setBrush(frame->palette.base());
913 const auto &rect = option->rect;
914 QRect upperRect = rect;
915 upperRect.setHeight(rect.height() / 2);
916 QRect lowerRect = rect;
917 lowerRect.setY(lowerRect.y() + rect.height() / 2);
918 painter->setClipRegion(clipRegion.isNull() ? upperRect : clipRegion & upperRect);
919 painter->drawRect(rect);
920 painter->setClipRegion(clipRegion.isNull() ? lowerRect : clipRegion & lowerRect);
921 painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
926 case PE_FrameGroupBox:
927 if (
const QStyleOptionFrame *frame = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
928 const auto pen = highContrastTheme ? frame->palette.buttonText().color()
929 : winUI3Color(frameColorStrong);
930 if (frame->features & QStyleOptionFrame::Flat) {
931 painter->setBrush(Qt::NoBrush);
932 painter->setPen(pen);
933 const QRect &fr = frame->rect;
934 QPoint p1(fr.x(), fr.y() + 1);
935 QPoint p2(fr.x() + fr.width(), p1.y());
936 painter->drawLine(p1, p2);
938 const auto frameRect = QRectF(frame->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
939 drawRoundedRect(painter, frameRect, pen, Qt::NoBrush);
943 case PE_IndicatorHeaderArrow:
944 if (
const QStyleOptionHeader *header = qstyleoption_cast<
const QStyleOptionHeader *>(option)) {
945 const auto indicator = header->sortIndicator;
946 if (indicator != QStyleOptionHeader::None) {
947 painter->setFont(d->assetFont(option->rect.height()));
948 painter->setPen(header->palette.text().color());
949 const auto ico = indicator == QStyleOptionHeader::SortUp ? Icon::ChevronDown
951 painter->drawText(option->rect, Qt::AlignCenter, fluentIcon(ico));
955 case PE_IndicatorCheckBox: {
956 const bool isOn = option->state & State_On;
957 const bool isPartial = option->state & State_NoChange;
959 const QRectF rect = option->rect;
960 const QPointF center = rect.center();
962 drawRoundedRect(painter, option->rect, borderPenControlAlt(option),
963 controlFillBrush(option, ControlType::ControlAlt));
966 painter->setFont(d->assetFont(8));
967 painter->setPen(controlTextColor(option));
968 const auto *animation =
969 qobject_cast<QNumberStyleAnimation *>(d->animation(option->styleObject));
970 const qreal clipWidth = animation ? animation->currentValue() : 1.0;
971 const QChar ico = fluentIcon(Icon::AcceptMedium);
972 QFontMetrics fm(d->m_assetFont);
973 QRectF clipRect = fm.boundingRect(ico);
974 clipRect.moveCenter(center);
975 clipRect.setLeft(rect.x() + (rect.width() - clipRect.width()) / 2.0 + 0.5);
976 clipRect.setWidth(clipWidth * clipRect.width());
977 painter->drawText(clipRect, Qt::AlignVCenter | Qt::AlignLeft, ico);
978 }
else if (isPartial) {
979 painter->setFont(d->assetFont(6));
980 painter->setPen(controlTextColor(option));
981 painter->drawText(rect, Qt::AlignCenter, fluentIcon(Icon::Dash12));
985 case PE_IndicatorBranch: {
986 if (option->state & State_Children) {
987 const QStyleOptionViewItem *vopt = qstyleoption_cast<
const QStyleOptionViewItem *>(option);
988 const bool isReverse = option->direction == Qt::RightToLeft;
989 const bool isOpen = option->state & QStyle::State_Open;
990 const QAbstractItemView *view = qobject_cast<
const QAbstractItemView *>(widget);
991 painter->setFont(d->assetFont(8));
992 if (view && view->alternatingRowColors() && vopt && vopt->state & State_Selected)
993 painter->setPen(winUI3Color(textOnAccentPrimary));
995 painter->setPen(option->palette.color(isOpen ? QPalette::Active : QPalette::Disabled,
996 QPalette::WindowText));
997 const auto ico = isOpen ? Icon::ChevronDownMed
998 : (isReverse ? Icon::ChevronLeftMed
999 : Icon::ChevronRightMed);
1000 painter->drawText(option->rect, Qt::AlignCenter, fluentIcon(ico));
1004 case PE_IndicatorRadioButton: {
1005 const auto *animation =
1006 qobject_cast<QNumberStyleAnimation *>(d->animation(option->styleObject));
1007 const qreal innerRadius =
1008 animation ? animation->currentValue() : radioButtonInnerRadius(state);
1009 const QRectF rect = option->rect;
1010 const QPointF center = rect.center();
1012 if (option->styleObject)
1013 option->styleObject->setProperty(
"_q_inner_radius", innerRadius);
1014 painter->setPen(borderPenControlAlt(option));
1015 painter->setBrush(controlFillBrush(option, ControlType::ControlAlt));
1016 if (option->state.testFlag(State_On)) {
1018 path.addEllipse(center, 7.5, 7.5);
1019 path.addEllipse(center, innerRadius, innerRadius);
1020 painter->drawPath(path);
1022 painter->setBrush(option->palette.window().color());
1023 painter->drawEllipse(center, innerRadius, innerRadius);
1025 painter->drawEllipse(center, 7.5, 7.5);
1029 case PE_PanelButtonTool:
1030 case PE_PanelButtonBevel:{
1031 const bool isEnabled = state & QStyle::State_Enabled;
1032 const bool isMouseOver = state & QStyle::State_MouseOver;
1033 const bool isAutoRaise = state & QStyle::State_AutoRaise;
1034 const int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
1035 const QRectF rect = option->rect.marginsRemoved(QMargins(fw, fw, fw, fw));
1036 if (element == PE_PanelButtonTool && ((!isMouseOver && isAutoRaise) || !isEnabled))
1037 painter->setPen(Qt::NoPen);
1039 painter->setPen(winUI3Color(controlStrokePrimary));
1040 painter->setBrush(controlFillBrush(option, ControlType::Control));
1041 if (element == PE_PanelButtonTool && widget) {
1042 const auto name = widget->objectName();
1043 if (name ==
"ScrollLeftButton"_L1 || name ==
"ScrollRightButton"_L1) {
1044 painter->setPen(Qt::NoPen);
1046 painter->setBrush(controlFillBrush(option, ControlType::ControlAlt));
1048 painter->setBrush(Qt::NoBrush);
1051 painter->drawRoundedRect(rect,
1052 secondLevelRoundingRadius, secondLevelRoundingRadius);
1055 case PE_FrameDefaultButton:
1056 painter->setPen(option->palette.accent().color());
1057 painter->setBrush(Qt::NoBrush);
1058 painter->drawRoundedRect(option->rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
1062 case PE_PanelMenu: {
1063 if (!d->nativeRoundedTopLevelWindows) {
1064 const QRect rect = option->rect.marginsRemoved(QMargins(2, 2, 2, 2));
1065 painter->setPen(highContrastTheme ? QPen(option->palette.windowText().color(), 2)
1066 : winUI3Color(frameColorLight));
1067 painter->setBrush(winUI3Color(menuPanelFill));
1068 painter->drawRoundedRect(rect, topLevelRoundingRadius, topLevelRoundingRadius);
1072 case PE_PanelLineEdit:
1073 if (
const auto *panel = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
1074 const bool isInSpinBox =
1075 widget && qobject_cast<
const QAbstractSpinBox *>(widget->parent()) !=
nullptr;
1076 const bool isInComboBox =
1077 widget && qobject_cast<
const QComboBox *>(widget->parent()) !=
nullptr;
1078 if (!isInSpinBox && !isInComboBox) {
1079 const auto frameRect =
1080 QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
1081 drawRoundedRect(painter, frameRect, Qt::NoPen, inputFillBrush(option, widget));
1082 if (panel->lineWidth > 0)
1083 proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
1087 case PE_FrameLineEdit: {
1088 const auto frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
1089 drawLineEditFrame(painter, frameRect, option);
1090 if (state & State_KeyboardFocusChange && state & State_HasFocus) {
1091 QStyleOptionFocusRect fropt;
1092 fropt.QStyleOption::operator=(*option);
1093 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
1098 if (
const auto *frame = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
1099 const auto rect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
1100 if (qobject_cast<
const QComboBoxPrivateContainer *>(widget)) {
1101 if (d->nativeRoundedTopLevelWindows)
1104 if (highContrastTheme)
1105 pen = QPen(option->palette.windowText().color(), 2);
1108 drawRoundedRect(painter, rect, pen, WINUI3Colors[colorSchemeIndex][menuPanelFill]);
1110 drawRoundedRect(painter, rect, Qt::NoPen, option->palette.brush(QPalette::Base));
1112 if (frame->frameShape == QFrame::NoFrame)
1115 const bool isEditable = qobject_cast<
const QTextEdit *>(widget) !=
nullptr
1116 || qobject_cast<
const QPlainTextEdit *>(widget) !=
nullptr;
1117 drawLineEditFrame(painter, rect, option, isEditable);
1121 case PE_PanelItemViewItem:
1122 if (
const QStyleOptionViewItem *vopt = qstyleoption_cast<
const QStyleOptionViewItem *>(option)) {
1123 if (vopt->backgroundBrush.style() != Qt::NoBrush) {
1124 painter->setBrushOrigin(vopt->rect.topLeft());
1125 painter->fillRect(vopt->rect, vopt->backgroundBrush);
1129 case PE_PanelItemViewRow:
1130 if (
const QStyleOptionViewItem *vopt = qstyleoption_cast<
const QStyleOptionViewItem *>(option)) {
1131 const QRect &rect = vopt->rect;
1132 const bool isRtl = option->direction == Qt::RightToLeft;
1133 if (rect.width() <= 0)
1136 if (vopt->features & QStyleOptionViewItem::Alternate) {
1137 QPalette::ColorGroup cg =
1138 (widget ? widget->isEnabled() : (vopt->state & QStyle::State_Enabled))
1140 : QPalette::Disabled;
1141 if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
1142 cg = QPalette::Inactive;
1143 painter->fillRect(rect, option->palette.brush(cg, QPalette::AlternateBase));
1146 if (option->state & State_Selected && !highContrastTheme) {
1148 const auto col = option->palette.accent().color();
1149 painter->setBrush(col);
1150 painter->setPen(col);
1151 const auto xPos = isRtl ? rect.right() - 4.5f : rect.left() + 3.5f;
1152 const auto yOfs = rect.height() / 4.;
1153 QRectF r(
QPointF(xPos, rect.y() + yOfs),
1154 QPointF(xPos + 1, rect.y() + rect.height() - yOfs));
1155 painter->drawRoundedRect(r, 1, 1);
1158 const bool isTreeDecoration = vopt->features.testFlag(
1159 QStyleOptionViewItem::IsDecorationForRootColumn);
1160 if (isTreeDecoration && vopt->state.testAnyFlags(State_Selected | State_MouseOver) &&
1161 vopt->showDecorationSelected) {
1162 const bool onlyOne = vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne ||
1163 vopt->viewItemPosition == QStyleOptionViewItem::Invalid;
1164 bool isFirst = vopt->viewItemPosition == QStyleOptionViewItem::Beginning;
1165 bool isLast = vopt->viewItemPosition == QStyleOptionViewItem::End;
1175 const QAbstractItemView *view = qobject_cast<
const QAbstractItemView *>(widget);
1176 painter->setBrush(view->alternatingRowColors() && state & State_Selected ? calculateAccentColor(option) : WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
1177 painter->setPen(Qt::NoPen);
1179 painter->setClipRect(rect);
1180 painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, -secondLevelRoundingRadius, 2)),
1181 secondLevelRoundingRadius, secondLevelRoundingRadius);
1182 }
else if (isLast) {
1183 painter->setClipRect(rect);
1184 painter->drawRoundedRect(rect.marginsRemoved(QMargins(-secondLevelRoundingRadius, 2, 2, 2)),
1185 secondLevelRoundingRadius, secondLevelRoundingRadius);
1187 painter->drawRect(vopt->rect.marginsRemoved(QMargins(0, 2, 0, 2)));
1194 case QStyle::PE_FrameWindow:
1195 if (
const auto *frm = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
1197 QRectF rect= option->rect;
1198 int fwidth =
int((frm->lineWidth + frm->midLineWidth) / QWindowsStylePrivate::nativeMetricScaleFactor(widget));
1200 QRectF bottomLeftCorner = QRectF(rect.left() + 1.0,
1201 rect.bottom() - 1.0 - secondLevelRoundingRadius,
1202 secondLevelRoundingRadius,
1203 secondLevelRoundingRadius);
1204 QRectF bottomRightCorner = QRectF(rect.right() - 1.0 - secondLevelRoundingRadius,
1205 rect.bottom() - 1.0 - secondLevelRoundingRadius,
1206 secondLevelRoundingRadius,
1207 secondLevelRoundingRadius);
1210 if (widget !=
nullptr) {
1211 QBitmap mask(widget->width(), widget->height());
1215 maskPainter.setRenderHint(QPainter::Antialiasing);
1216 maskPainter.setBrush(Qt::color1);
1217 maskPainter.setPen(Qt::NoPen);
1218 maskPainter.drawRoundedRect(option->rect,secondLevelRoundingRadius,secondLevelRoundingRadius);
1219 const_cast<QWidget*>(widget)->setMask(mask);
1223 painter->setPen(QPen(frm->palette.base(), fwidth));
1224 painter->drawLine(QPointF(rect.left(), rect.top()),
1225 QPointF(rect.left(), rect.bottom() - fwidth));
1226 painter->drawLine(QPointF(rect.left() + fwidth, rect.bottom()),
1227 QPointF(rect.right() - fwidth, rect.bottom()));
1228 painter->drawLine(QPointF(rect.right(), rect.top()),
1229 QPointF(rect.right(), rect.bottom() - fwidth));
1231 painter->setPen(WINUI3Colors[colorSchemeIndex][surfaceStroke]);
1232 painter->drawLine(QPointF(rect.left() + 0.5, rect.top() + 0.5),
1233 QPointF(rect.left() + 0.5, rect.bottom() - 0.5 - secondLevelRoundingRadius));
1234 painter->drawLine(QPointF(rect.left() + 0.5 + secondLevelRoundingRadius, rect.bottom() - 0.5),
1235 QPointF(rect.right() - 0.5 - secondLevelRoundingRadius, rect.bottom() - 0.5));
1236 painter->drawLine(QPointF(rect.right() - 0.5, rect.top() + 1.5),
1237 QPointF(rect.right() - 0.5, rect.bottom() - 0.5 - secondLevelRoundingRadius));
1239 painter->setPen(Qt::NoPen);
1240 painter->setBrush(frm->palette.base());
1241 painter->drawPie(bottomRightCorner.marginsAdded(QMarginsF(2.5,2.5,0.0,0.0)),
1243 painter->drawPie(bottomLeftCorner.marginsAdded(QMarginsF(0.0,2.5,2.5,0.0)),
1246 painter->setPen(WINUI3Colors[colorSchemeIndex][surfaceStroke]);
1247 painter->setBrush(Qt::NoBrush);
1248 painter->drawArc(bottomRightCorner,
1250 painter->drawArc(bottomLeftCorner,
1254#if QT_CONFIG(tabbar)
1255 case PE_FrameTabBarBase:
1256 if (
const auto *tab = qstyleoption_cast<
const QStyleOptionTabBarBase *>(option)) {
1257 const auto clipRegion = painter->clipRegion();
1259 painter->setPen(highContrastTheme ? tab->palette.buttonText().color()
1260 : winUI3Color(frameColorLight));
1261 painter->setBrush(tab->palette.base());
1262 QRect upperRect = tab->rect;
1263 upperRect.setHeight(tab->rect.height() / 2);
1264 QRect lowerRect = tab->rect;
1265 lowerRect.setY(lowerRect.y() + tab->rect.height() / 2);
1266 painter->setClipRegion(clipRegion.isNull() ? upperRect : clipRegion & upperRect);
1267 painter->drawRoundedRect(tab->rect, secondLevelRoundingRadius,
1268 secondLevelRoundingRadius);
1269 painter->setClipRegion(clipRegion.isNull() ? lowerRect : clipRegion & lowerRect);
1270 painter->drawRect(tab->rect);
1274 case PE_IndicatorTabTearLeft:
1275 case PE_IndicatorTabTearRight:
1278 QWindowsVistaStyle::drawPrimitive(element, option, painter, widget);
1285void QWindows11Style::drawControl(ControlElement element,
const QStyleOption *option,
1286 QPainter *painter,
const QWidget *widget)
const
1288 Q_D(
const QWindows11Style);
1290 QPainterStateGuard psg(
painter);
1291 painter->setRenderHint(QPainter::Antialiasing);
1293 case QStyle::CE_ComboBoxLabel:
1294#if QT_CONFIG(combobox)
1295 if (
const QStyleOptionComboBox *cb = qstyleoption_cast<
const QStyleOptionComboBox *>(option)) {
1296 painter->setPen(controlTextColor(option,
true));
1297 QStyleOptionComboBox newOption = *cb;
1298 newOption.rect.adjust(4,0,-4,0);
1299 QCommonStyle::drawControl(element, &newOption, painter, widget);
1303#if QT_CONFIG(tabbar)
1304 case CE_TabBarTabShape:
1305 if (
const QStyleOptionTab *tab = qstyleoption_cast<
const QStyleOptionTab *>(option)) {
1306 const bool isSelected = tab->state.testFlag(State_Selected);
1307 const auto clipRegion = painter->clipRegion();
1308 const bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab
1309 || tab->position == QStyleOptionTab::Moving;
1310 auto leftMargin = (tab->position == QStyleOptionTab::Beginning || onlyOne) ? 1 : 0;
1311 auto rightMargin = (tab->position == QStyleOptionTab::End || onlyOne) ? 1 : 0;
1312 if (QCommonStylePrivate::rtl(option))
1313 std::swap(leftMargin, rightMargin);
1315 QRectF tabRect = tab->rect.marginsRemoved(QMargins(leftMargin, 1, rightMargin, -3));
1316 painter->setPen(highContrastTheme ? tab->palette.buttonText().color() : winUI3Color(frameColorLight));
1317 painter->setBrush(tab->palette.base());
1319 painter->setBrush(winUI3Color(fillMicaAltDefault));
1321 if (tab->state.testFlag(State_Sunken))
1322 painter->setBrush(winUI3Color(fillMicaAltDefault));
1323 else if (tab->state.testFlag(State_MouseOver))
1324 painter->setBrush(winUI3Color(fillMicaAltSecondary));
1326 painter->setBrush(winUI3Color(fillMicaAltTransparent));
1328 QRect upperRect = tab->rect;
1329 upperRect.setHeight(tab->rect.height() / 2.);
1330 QRect lowerRect = tab->rect;
1331 lowerRect.setY(lowerRect.y() + tab->rect.height() / 2.);
1332 painter->setClipRegion(clipRegion.isNull() ? upperRect : clipRegion & upperRect);
1333 painter->drawRoundedRect(tabRect, secondLevelRoundingRadius, secondLevelRoundingRadius);
1334 painter->setClipRegion(clipRegion.isNull() ? lowerRect : clipRegion & lowerRect);
1335 painter->drawRect(tabRect);
1338 case CE_TabBarTabLabel:
1339 if (
const QStyleOptionTab *tab = qstyleoption_cast<
const QStyleOptionTab *>(option)) {
1340 const bool isEnabled = tab->state.testFlags(State_Enabled);
1341 const bool isSelected = tab->state.testFlags(State_Selected);
1343 QRect tr = tab->rect;
1344 bool verticalTabs = tab->shape == QTabBar::RoundedEast
1345 || tab->shape == QTabBar::RoundedWest || tab->shape == QTabBar::TriangularEast
1346 || tab->shape == QTabBar::TriangularWest;
1348 int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
1349 if (!proxy()->styleHint(SH_UnderlineShortcut, option, widget))
1350 alignment |= Qt::TextHideMnemonic;
1353 int newX, newY, newRot;
1354 if (tab->shape == QTabBar::RoundedEast || tab->shape == QTabBar::TriangularEast) {
1355 newX = tr.width() + tr.x();
1360 newY = tr.y() + tr.height();
1363 QTransform m = QTransform::fromTranslate(newX, newY);
1365 painter->setTransform(m,
true);
1368 d->tabLayout(tab, widget, &tr, &iconRect);
1371 if (tab->position != QStyleOptionTab::TabPosition::Moving)
1372 tr = proxy()->subElementRect(SE_TabBarTabText, option, widget);
1374 if (!tab->icon.isNull()) {
1375 const auto mode = isEnabled ? QIcon::Normal : QIcon::Disabled;
1376 const auto state = isSelected ? QIcon::On : QIcon::Off;
1377 tab->icon.paint(painter, iconRect, Qt::AlignCenter, mode, state);
1380 const auto textRole = widget ? widget->foregroundRole() : QPalette::WindowText;
1381 if (tab->palette.isBrushSet(QPalette::Current, textRole))
1382 painter->setPen(tab->palette.color(QPalette::Current, textRole));
1384 painter->setPen(winUI3Color(isSelected ? textPrimary : textSecondary));
1385 proxy()->drawItemText(painter, tr, alignment, tab->palette, isEnabled, tab->text);
1389 case CE_ToolButtonLabel:
1390#if QT_CONFIG(toolbutton)
1391 if (
const QStyleOptionToolButton *toolbutton
1392 = qstyleoption_cast<
const QStyleOptionToolButton *>(option)) {
1393 QRect rect = toolbutton->rect;
1396 if (toolbutton->state & (State_Sunken | State_On)) {
1397 shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, toolbutton, widget);
1398 shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, toolbutton, widget);
1401 bool hasArrow = toolbutton->features & QStyleOptionToolButton::Arrow;
1402 if (((!hasArrow && toolbutton->icon.isNull()) && !toolbutton->text.isEmpty())
1403 || toolbutton->toolButtonStyle == Qt::ToolButtonTextOnly) {
1404 int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
1405 if (!proxy()->styleHint(SH_UnderlineShortcut, toolbutton, widget))
1406 alignment |= Qt::TextHideMnemonic;
1407 rect.translate(shiftX, shiftY);
1408 painter->setFont(toolbutton->font);
1409 const QString text = d->toolButtonElideText(toolbutton, rect, alignment);
1410 painter->setPen(controlTextColor(option));
1411 proxy()->drawItemText(painter, rect, alignment, toolbutton->palette,
1412 toolbutton->state & State_Enabled, text);
1415 QSize pmSize = toolbutton->iconSize;
1416 if (!toolbutton->icon.isNull()) {
1417 QIcon::State state = toolbutton->state & State_On ? QIcon::On : QIcon::Off;
1419 if (!(toolbutton->state & State_Enabled))
1420 mode = QIcon::Disabled;
1421 else if ((toolbutton->state & State_MouseOver) && (toolbutton->state & State_AutoRaise))
1422 mode = QIcon::Active;
1424 mode = QIcon::Normal;
1425 pm = toolbutton->icon.pixmap(toolbutton->rect.size().boundedTo(toolbutton->iconSize), painter->device()->devicePixelRatio(),
1427 pmSize = pm.size() / pm.devicePixelRatio();
1430 if (toolbutton->toolButtonStyle != Qt::ToolButtonIconOnly) {
1431 painter->setFont(toolbutton->font);
1434 int alignment = Qt::TextShowMnemonic | Qt::AlignCenter;
1435 if (!proxy()->styleHint(SH_UnderlineShortcut, toolbutton, widget))
1436 alignment |= Qt::TextHideMnemonic;
1438 if (toolbutton->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
1439 pr.setHeight(pmSize.height() + 4);
1440 tr.adjust(0, pr.height() - 1, 0, -1);
1442 pr.setWidth(pmSize.width() + 4);
1443 tr.adjust(pr.width(), 0, 0, 0);
1445 pr.translate(shiftX, shiftY);
1447 drawIndicatorArrow(painter, pr, toolbutton, widget);
1449 const auto vr = QStyle::visualRect(toolbutton->direction, rect, pr);
1450 proxy()->drawItemPixmap(painter, vr, Qt::AlignCenter, pm);
1452 tr.translate(shiftX, shiftY);
1453 painter->setPen(controlTextColor(option));
1454 const QString text = d->toolButtonElideText(toolbutton, tr, alignment);
1455 const auto vr = QStyle::visualRect(toolbutton->direction, rect, tr);
1456 proxy()->drawItemText(painter, vr, alignment, toolbutton->palette,
1457 toolbutton->state & State_Enabled, text);
1459 rect.translate(shiftX, shiftY);
1461 drawIndicatorArrow(painter, rect, toolbutton, widget);
1463 proxy()->drawItemPixmap(painter, rect, Qt::AlignCenter, pm);
1469 case QStyle::CE_ShapedFrame:
1470 if (
const QStyleOptionFrame *f = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
1471 int frameShape = f->frameShape;
1472 int frameShadow = QFrame::Plain;
1473 if (f->state & QStyle::State_Sunken)
1474 frameShadow = QFrame::Sunken;
1475 else if (f->state & QStyle::State_Raised)
1476 frameShadow = QFrame::Raised;
1478 int lw = f->lineWidth;
1479 int mlw = f->midLineWidth;
1481 switch (frameShape) {
1483 if (frameShadow == QFrame::Plain)
1484 qDrawPlainRoundedRect(painter, f->rect, secondLevelRoundingRadius, secondLevelRoundingRadius, highContrastTheme ==
true ? f->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorStrong], lw);
1486 qDrawShadeRect(painter, f->rect, f->palette, frameShadow == QFrame::Sunken, lw, mlw);
1489 if (frameShadow == QFrame::Plain)
1490 qDrawPlainRoundedRect(painter, f->rect, secondLevelRoundingRadius, secondLevelRoundingRadius, highContrastTheme ==
true ? f->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorStrong], lw);
1492 qDrawShadePanel(painter, f->rect, f->palette, frameShadow == QFrame::Sunken, lw);
1495 QWindowsVistaStyle::drawControl(element, option, painter, widget);
1499#if QT_CONFIG(progressbar)
1500 case CE_ProgressBarGroove:
1501 if (
const auto baropt = qstyleoption_cast<
const QStyleOptionProgressBar*>(option)) {
1502 QRect rect = option->rect;
1503 QPointF center = rect.center();
1504 if (baropt->state & QStyle::State_Horizontal) {
1506 rect.moveTop(center.y());
1509 rect.moveLeft(center.x());
1511 painter->setPen(Qt::NoPen);
1512 painter->setBrush(Qt::gray);
1513 painter->drawRect(rect);
1516 case CE_ProgressBarContents:
1517 if (
const auto baropt = qstyleoption_cast<
const QStyleOptionProgressBar *>(option)) {
1518 QRectF rect = option->rect;
1519 painter->translate(rect.topLeft());
1520 rect.translate(-rect.topLeft());
1522 constexpr qreal progressBarThickness = 3;
1523 constexpr qreal progressBarHalfThickness = progressBarThickness / 2.0;
1525 const auto isIndeterminate = baropt->maximum == 0 && baropt->minimum == 0;
1526 const auto orientation =
1527 (baropt->state & QStyle::State_Horizontal) ? Qt::Horizontal : Qt::Vertical;
1528 const auto inverted = baropt->invertedAppearance;
1529 const auto reverse = (baropt->direction == Qt::RightToLeft) ^ inverted;
1533 if (orientation == Qt::Vertical) {
1534 rect = QRectF(rect.left(), rect.top(), rect.height(),
1539 m.translate(0, -rect.height() + 1);
1542 m.translate(-rect.width(), 0);
1544 painter->setTransform(m,
true);
1545 }
else if (reverse) {
1546 QTransform m = QTransform::fromScale(-1, 1);
1547 m.translate(-rect.width(), 0);
1548 painter->setTransform(m,
true);
1550 const qreal offset = (
int(rect.height()) % 2 == 0) ? 0.5f : 0.0f;
1552 if (isIndeterminate) {
1553#if QT_CONFIG(animation)
1554 auto anim = d->animation(option->styleObject);
1556 auto anim =
new QStyleAnimation(option->styleObject);
1557 anim->setFrameRate(QStyleAnimation::SixtyFps);
1558 d->startAnimation(anim);
1560 constexpr auto loopDurationMSec = 4000;
1561 const auto elapsedTime = std::chrono::time_point_cast<std::chrono::milliseconds>(
1562 std::chrono::system_clock::now());
1563 const auto elapsed = elapsedTime.time_since_epoch().count();
1564 const auto handleCenter = (elapsed % loopDurationMSec) /
float(loopDurationMSec);
1565 const auto isLongHandle = (elapsed / loopDurationMSec) % 2 == 0;
1566 const auto lengthFactor = (isLongHandle ? 33.0f : 25.0f) / 100.0f;
1568 constexpr auto handleCenter = 0.5f;
1569 constexpr auto lengthFactor = 1;
1571 const auto begin = qMax(handleCenter * (1 + lengthFactor) - lengthFactor, 0.0f);
1572 const auto end = qMin(handleCenter * (1 + lengthFactor), 1.0f);
1573 const auto barBegin = begin * rect.width();
1574 const auto barEnd = end * rect.width();
1575 rect = QRectF(QPointF(rect.left() + barBegin, rect.top()),
1576 QPointF(rect.left() + barEnd, rect.bottom()));
1578#if QT_CONFIG(animation)
1579 d->stopAnimation(option->styleObject);
1581 const auto fillPercentage = (
float(baropt->progress - baropt->minimum))
1582 / (
float(baropt->maximum - baropt->minimum));
1583 rect.setWidth(rect.width() * fillPercentage);
1585 const QPointF center = rect.center();
1586 rect.setHeight(progressBarThickness);
1587 rect.moveTop(center.y() - progressBarHalfThickness - offset);
1588 drawRoundedRect(painter, rect, Qt::NoPen, baropt->palette.accent());
1591 case CE_ProgressBarLabel:
1592 if (
const auto baropt = qstyleoption_cast<
const QStyleOptionProgressBar *>(option)) {
1593 const bool vertical = !(baropt->state & QStyle::State_Horizontal);
1595 proxy()->drawItemText(painter, baropt->rect, Qt::AlignCenter | Qt::TextSingleLine,
1596 baropt->palette, baropt->state & State_Enabled, baropt->text,
1602 case CE_PushButtonLabel:
1603 if (
const QStyleOptionButton *btn = qstyleoption_cast<
const QStyleOptionButton *>(option)) {
1604 QStyleOptionButton btnCopy(*btn);
1605 btnCopy.rect = btn->rect.marginsRemoved(QMargins(contentHMargin, 0, contentHMargin, 0));
1606 btnCopy.palette.setBrush(QPalette::ButtonText, controlTextColor(option));
1607 QCommonStyle::drawControl(element, &btnCopy, painter, widget);
1610 case CE_PushButtonBevel:
1611 if (
const QStyleOptionButton *btn = qstyleoption_cast<
const QStyleOptionButton *>(option)) {
1612 using namespace StyleOptionHelper;
1614 const auto rect = QRectF(btn->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
1615 if (btn->features.testFlag(QStyleOptionButton::Flat)) {
1616 const QBrush brush = isPressed(option)
1617 ? winUI3Color(subtlePressedColor)
1618 : (isHover(option) ? winUI3Color(subtleHighlightColor) : Qt::transparent);
1619 drawRoundedRect(painter, rect, Qt::NoPen, brush);
1621 const bool defaultButton = btn->features.testFlag(QStyleOptionButton::DefaultButton);
1622 const QPen pen = defaultButton ? option->palette.color(QPalette::Accent)
1623 : winUI3Color(controlStrokePrimary);
1624 drawRoundedRect(painter, rect, pen, controlFillBrush(option, ControlType::Control));
1626 if (btn->features.testFlag(QStyleOptionButton::HasMenu)) {
1628 const auto indSize = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget);
1629 const auto indRect =
1632 const auto vindRect = visualRect(btn->direction, btn->rect, indRect);
1633 textRect.setWidth(textRect.width() - indSize);
1635 const auto fontSize = QFontInfo(painter->font()).pointSizeF();
1636 painter->setFont(d->assetFont(fontSize * 0.9f));
1637 painter->setPen(controlTextColor(option));
1638 painter->drawText(vindRect, Qt::AlignCenter, fluentIcon(Icon::ChevronDownMed));
1642 case CE_MenuBarItem:
1643 if (
const auto *mbi = qstyleoption_cast<
const QStyleOptionMenuItem *>(option)) {
1644 using namespace StyleOptionHelper;
1646 constexpr int hPadding = 11;
1647 constexpr int topPadding = 4;
1648 constexpr int bottomPadding = 6;
1649 QStyleOptionMenuItem newMbi = *mbi;
1651 if (
auto mbiV2 = qstyleoption_cast<
const QStyleOptionMenuItemV2 *>(option))
1652 newMbi.state.setFlag(State_Sunken, mbiV2->mouseDown);
1654 newMbi.font.setPointSize(10);
1655 newMbi.palette.setColor(QPalette::ButtonText, controlTextColor(&newMbi));
1656 if (!isDisabled(&newMbi)) {
1657 QPen pen(Qt::NoPen);
1658 QBrush brush(Qt::NoBrush);
1659 if (highContrastTheme) {
1660 pen = QPen(newMbi.palette.highlight().color(), 2);
1661 brush = newMbi.palette.window();
1662 }
else if (isPressed(&newMbi)) {
1663 brush = winUI3Color(subtlePressedColor);
1664 }
else if (isHover(&newMbi)) {
1665 brush = winUI3Color(subtleHighlightColor);
1667 if (pen != Qt::NoPen || brush != Qt::NoBrush) {
1668 const QRect rect = mbi->rect.marginsRemoved(QMargins(5, 0, 5, 0));
1669 drawRoundedRect(painter, rect, pen, brush);
1672 newMbi.rect.adjust(hPadding,topPadding,-hPadding,-bottomPadding);
1673 painter->setFont(newMbi.font);
1674 QCommonStyle::drawControl(element, &newMbi, painter, widget);
1679 case CE_MenuEmptyArea:
1683 if (
const auto *menuitem = qstyleoption_cast<
const QStyleOptionMenuItem *>(option)) {
1684 using namespace StyleOptionHelper;
1686 const auto visualMenuRect = [&](
const QRect &rect) {
1687 return visualRect(option->direction, menuitem->rect, rect);
1690 const bool checked =
1691 menuitem->checkType != QStyleOptionMenuItem::NotCheckable && menuitem->checked;
1693 const QRect rect = menuitem->rect.marginsRemoved(QMargins(2,2,2,2));
1694 if (!isDisabled(menuitem)) {
1695 QPen pen(Qt::NoPen);
1696 QBrush brush(Qt::NoBrush);
1697 if (highContrastTheme) {
1698 pen = QPen(menuitem->palette.highlight().color(), 2);
1699 brush = menuitem->palette.window();
1700 }
else if (isPressed(menuitem)) {
1701 brush = winUI3Color(subtlePressedColor);
1702 }
else if (isSelected(menuitem)) {
1703 brush = winUI3Color(subtleHighlightColor);
1705 if (pen != Qt::NoPen || brush != Qt::NoBrush)
1706 drawRoundedRect(painter, rect, pen, brush);
1708 if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) {
1709 constexpr int yoff = 1;
1710 painter->setPen(highContrastTheme ? menuitem->palette.buttonText().color() : winUI3Color(dividerStrokeDefault));
1711 painter->drawLine(menuitem->rect.topLeft() + QPoint(0, yoff),
1712 menuitem->rect.topRight() + QPoint(0, yoff));
1716 int xOffset = contentHMargin;
1718 const auto checkMarkWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget);
1720 QRect vRect(visualMenuRect(QRect(rect.x() + xOffset, rect.y(),
1721 checkMarkWidth, rect.height())));
1722 QPainterStateGuard psg(painter);
1723 painter->setFont(d->m_assetFont);
1724 painter->setPen(option->palette.text().color());
1725 painter->drawText(vRect, Qt::AlignCenter, fluentIcon(Icon::CheckMark));
1727 if (menuitem->menuHasCheckableItems)
1728 xOffset += checkMarkWidth + contentItemHMargin;
1729 if (!menuitem->icon.isNull()) {
1731 QRect vRect(visualMenuRect(QRect(rect.x() + xOffset,
1733 menuitem->maxIconWidth - 4,
1735 const auto mode = isDisabled(menuitem)
1737 : (isSelected(menuitem) ? QIcon::Active : QIcon::Normal);
1738 const auto size = proxy()->pixelMetric(PM_SmallIconSize, option, widget);
1739 QRect pmr(QPoint(0, 0), QSize(size, size));
1740 pmr.moveCenter(vRect.center());
1741 menuitem->icon.paint(painter, pmr, Qt::AlignCenter, mode,
1742 checked ? QIcon::On : QIcon::Off);
1744 if (menuitem->maxIconWidth > 0)
1745 xOffset += menuitem->maxIconWidth - 4 + contentItemHMargin;
1747 QStringView s(menuitem->text);
1749 QPoint tl(rect.left() + xOffset, rect.top());
1750 QPoint br(rect.right() - menuitem->reservedShortcutWidth - contentHMargin,
1752 QRect textRect(tl, br);
1753 QRect vRect(visualMenuRect(textRect));
1756 if (highContrastTheme) {
1757 penColor = menuitem->palette.color(
1758 isSelected(menuitem) ? QPalette::HighlightedText : QPalette::Text);
1760 QStyleOption tmpOpt(*option);
1761 tmpOpt.state.setFlag(State_Sunken,
false);
1762 penColor = controlTextColor(&tmpOpt);
1764 painter->setPen(penColor);
1766 qsizetype t = s.indexOf(u'\t');
1767 int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1768 if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
1769 text_flags |= Qt::TextHideMnemonic;
1770 text_flags |= Qt::AlignLeft;
1772 if (t >= 0 && menuitem->menuItemType != QStyleOptionMenuItem::SubMenu) {
1773 QRect shortcutRect(QPoint(textRect.right(), textRect.top()),
1774 QPoint(rect.right(), textRect.bottom()));
1775 QRect vShortcutRect(visualMenuRect(shortcutRect));
1776 const QString textToDraw = s.mid(t + 1).toString();
1777 painter->drawText(vShortcutRect, text_flags, textToDraw);
1780 QFont font = menuitem->font;
1781 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
1783 painter->setFont(font);
1784 const QString textToDraw = s.left(t).toString();
1785 painter->drawText(vRect, text_flags, textToDraw);
1787 if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {
1788 const auto fontSize = QFontInfo(painter->font()).pointSizeF();
1789 painter->setFont(d->assetFont(fontSize * 0.9f));
1790 int yOfs = qRound(fontSize / 3.0f);
1791 QPoint tl(rect.right() - 2 * QWindowsStylePrivate::windowsArrowHMargin - contentItemHMargin,
1793 QRect submenuRect(tl, rect.bottomRight());
1794 QRect vSubMenuRect = visualMenuRect(submenuRect);
1795 painter->setPen(option->palette.text().color());
1796 const bool isReverse = option->direction == Qt::RightToLeft;
1797 const auto ico = isReverse ? Icon::ChevronLeftMed : Icon::ChevronRightMed;
1798 painter->drawText(vSubMenuRect, Qt::AlignCenter, fluentIcon(ico));
1803 case CE_MenuBarEmptyArea: {
1806 case CE_HeaderEmptyArea:
1808 case CE_HeaderSection: {
1809 if (
const QStyleOptionHeader *header = qstyleoption_cast<
const QStyleOptionHeader *>(option)) {
1810 painter->setPen(Qt::NoPen);
1811 painter->setBrush(header->palette.button());
1812 painter->drawRect(header->rect);
1813 const bool isRtl = option->direction == Qt::RightToLeft;
1814 const QPointF tr = isRtl ? option->rect.topLeft() : option->rect.topRight();
1815 const QPointF br = isRtl ? option->rect.bottomLeft() : option->rect.bottomRight();
1816 const QPointF bl = isRtl ? option->rect.bottomRight() : option->rect.bottomLeft();
1817 constexpr QPointF trOfs = QPointF(0.5, 0.0);
1818 constexpr QPointF brOfs = QPointF(0.5, 0.5);
1819 constexpr QPointF blOfs = QPointF(0.0, 0.5);
1820 const std::array<
QPointF, 3> points = { tr + trOfs, br + brOfs, bl + blOfs };
1821 QPen pen(highContrastTheme ? header->palette.buttonText().color()
1822 : winUI3Color(frameColorLight));
1823 pen.setJoinStyle(Qt::MiterJoin);
1824 painter->setPen(pen);
1825 painter->drawPolyline(points.data(),
int(points.size()));
1829 case CE_ItemViewItem: {
1830 if (
const QStyleOptionViewItem *vopt = qstyleoption_cast<
const QStyleOptionViewItem *>(option)) {
1831 const auto p = proxy();
1832 QRect checkRect = p->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget);
1833 QRect iconRect = p->subElementRect(SE_ItemViewItemDecoration, vopt, widget);
1834 QRect textRect = p->subElementRect(SE_ItemViewItemText, vopt, widget);
1837 proxy()->drawPrimitive(PE_PanelItemViewItem, option, painter, widget);
1839 const QRect &rect = vopt->rect;
1840 const bool isRtl = option->direction == Qt::RightToLeft;
1841 bool onlyOne = vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne ||
1842 vopt->viewItemPosition == QStyleOptionViewItem::Invalid;
1843 bool isFirst = vopt->viewItemPosition == QStyleOptionViewItem::Beginning;
1844 bool isLast = vopt->viewItemPosition == QStyleOptionViewItem::End;
1846 const QAbstractItemView *view = qobject_cast<
const QAbstractItemView *>(widget);
1847 if (qobject_cast<
const QTableView *>(view)) {
1851 if (vopt->features.testFlag(QStyleOptionViewItem::IsDecoratedRootColumn) &&
1852 vopt->showDecorationSelected) {
1864 }
else if (isLast) {
1871 const bool highlightCurrent = vopt->state.testAnyFlags(State_Selected | State_MouseOver);
1872 if (highlightCurrent) {
1873 if (highContrastTheme) {
1874 painter->setBrush(vopt->palette.highlight());
1876 painter->setBrush(view && view->alternatingRowColors() && vopt->state & State_Selected
1877 ? calculateAccentColor(option)
1878 : winUI3Color(subtleHighlightColor));
1881 painter->setBrush(vopt->backgroundBrush);
1883 painter->setPen(Qt::NoPen);
1886 painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, 2, 2)),
1887 secondLevelRoundingRadius, secondLevelRoundingRadius);
1888 }
else if (isFirst) {
1889 QPainterStateGuard psg(
painter);
1890 painter->setClipRect(rect);
1891 painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, -secondLevelRoundingRadius, 2)),
1892 secondLevelRoundingRadius, secondLevelRoundingRadius);
1893 }
else if (isLast) {
1894 QPainterStateGuard psg(
painter);
1895 painter->setClipRect(rect);
1896 painter->drawRoundedRect(rect.marginsRemoved(QMargins(-secondLevelRoundingRadius, 2, 2, 2)),
1897 secondLevelRoundingRadius, secondLevelRoundingRadius);
1899 painter->drawRect(rect.marginsRemoved(QMargins(0, 2, 0, 2)));
1903 if (vopt->features & QStyleOptionViewItem::HasCheckIndicator) {
1904 QStyleOptionViewItem option(*vopt);
1905 option.rect = checkRect;
1906 option.state = option.state & ~QStyle::State_HasFocus;
1908 switch (vopt->checkState) {
1910 option.state |= QStyle::State_Off;
1912 case Qt::PartiallyChecked:
1913 option.state |= QStyle::State_NoChange;
1916 option.state |= QStyle::State_On;
1919 proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, painter, widget);
1923 if (iconRect.isValid()) {
1924 QIcon::Mode mode = QIcon::Normal;
1925 if (!(vopt->state & QStyle::State_Enabled))
1926 mode = QIcon::Disabled;
1927 else if (vopt->state & QStyle::State_Selected)
1928 mode = QIcon::Selected;
1929 QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
1930 vopt->icon.paint(painter, iconRect, vopt->decorationAlignment, mode, state);
1933 if (highlightCurrent && highContrastTheme) {
1934 painter->setPen(vopt->palette.base().color());
1935 }
else if ((view && view->alternatingRowColors() && highlightCurrent && vopt->state & State_Selected)) {
1936 painter->setPen(winUI3Color(textOnAccentPrimary));
1938 painter->setPen(vopt->palette.text().color());
1940 d->viewItemDrawText(painter, vopt, textRect);
1943 if (vopt->state & State_Selected && !highContrastTheme) {
1944 if (
const QListView *lv = qobject_cast<
const QListView *>(widget);
1945 lv && lv->viewMode() != QListView::IconMode) {
1946 const auto col = vopt->palette.accent().color();
1947 painter->setBrush(col);
1948 painter->setPen(col);
1949 const auto xPos = isRtl ? rect.right() - 4.5f : rect.left() + 3.5f;
1950 const auto yOfs = rect.height() / 4.;
1951 QRectF r(
QPointF(xPos, rect.y() + yOfs),
1952 QPointF(xPos + 1, rect.y() + rect.height() - yOfs));
1953 painter->drawRoundedRect(r, 1, 1);
1960 QWindowsVistaStyle::drawControl(element, option, painter, widget);
2140QRect QWindows11Style::subControlRect(ComplexControl control,
const QStyleOptionComplex *option,
2141 SubControl subControl,
const QWidget *widget)
const
2146#if QT_CONFIG(spinbox)
2148 if (
const QStyleOptionSpinBox *spinbox = qstyleoption_cast<
const QStyleOptionSpinBox *>(option)) {
2149 const bool hasButtons = spinbox->buttonSymbols != QAbstractSpinBox::NoButtons;
2150 const int fw = spinbox->frame
2151 ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget)
2153 int textFieldLength = spinbox->rect.width() - 2 * fw;
2154 int buttonHeight = 0;
2155 int buttonWidth = 0;
2157 const QWidget *w = qobject_cast<QWidget *>(spinbox->styleObject);
2159 ? widthFromChar(w->font(), Icon::ChevronUp, m_fontPoint2ChevronUpWidth)
2160 : spinbox->fontMetrics.horizontalAdvance(fluentIcon(Icon::ChevronUp));
2161 buttonHeight = spinbox->rect.height() - 4 * fw;
2162 textFieldLength -= 2 * (buttonWidth + fw) + 2 * fw;
2164 const QPoint topLeft(spinbox->rect.topLeft() + QPoint(fw, fw));
2165 switch (subControl) {
2167 case SC_SpinBoxDown: {
2170 const int yOfs = ((spinbox->rect.height() - 2 * fw) - buttonHeight) / 2;
2171 ret = QRect(topLeft.x() + textFieldLength + fw, topLeft.y() + yOfs, buttonWidth,
2173 if (subControl == SC_SpinBoxDown)
2174 ret.moveRight(ret.right() + buttonWidth + fw);
2177 case SC_SpinBoxEditField:
2178 ret = QRect(topLeft,
2179 QPoint(topLeft.x() + textFieldLength, spinbox->rect.bottom() - fw));
2181 case SC_SpinBoxFrame:
2182 ret = spinbox->rect;
2186 ret = visualRect(spinbox->direction, spinbox->rect, ret);
2190 if (
const QStyleOptionTitleBar *titlebar = qstyleoption_cast<
const QStyleOptionTitleBar *>(option)) {
2191 SubControl sc = subControl;
2192 ret = QCommonStyle::subControlRect(control, option, subControl, widget);
2193 static constexpr int indent = 3;
2194 static constexpr int controlWidthMargin = 2;
2195 const int controlHeight = titlebar->rect.height();
2196 const int controlWidth = 46;
2197 const int iconSize = proxy()->pixelMetric(QStyle::PM_TitleBarButtonIconSize, option, widget);
2198 int offset = -(controlWidthMargin + indent);
2200 bool isMinimized = titlebar->titleBarState & Qt::WindowMinimized;
2201 bool isMaximized = titlebar->titleBarState & Qt::WindowMaximized;
2204 case SC_TitleBarLabel:
2205 if (titlebar->titleBarFlags & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)) {
2206 ret = titlebar->rect;
2207 if (titlebar->titleBarFlags & Qt::WindowSystemMenuHint)
2208 ret.adjust(iconSize + controlWidthMargin + indent, 0, -controlWidth, 0);
2209 if (titlebar->titleBarFlags & Qt::WindowMinimizeButtonHint)
2210 ret.adjust(0, 0, -controlWidth, 0);
2211 if (titlebar->titleBarFlags & Qt::WindowMaximizeButtonHint)
2212 ret.adjust(0, 0, -controlWidth, 0);
2213 if (titlebar->titleBarFlags & Qt::WindowShadeButtonHint)
2214 ret.adjust(0, 0, -controlWidth, 0);
2215 if (titlebar->titleBarFlags & Qt::WindowContextHelpButtonHint)
2216 ret.adjust(0, 0, -controlWidth, 0);
2219 case SC_TitleBarContextHelpButton:
2220 if (titlebar->titleBarFlags & Qt::WindowContextHelpButtonHint)
2221 offset += controlWidth;
2223 case SC_TitleBarMinButton:
2224 if (!isMinimized && (titlebar->titleBarFlags & Qt::WindowMinimizeButtonHint))
2225 offset += controlWidth;
2226 else if (sc == SC_TitleBarMinButton)
2229 case SC_TitleBarNormalButton:
2230 if (isMinimized && (titlebar->titleBarFlags & Qt::WindowMinimizeButtonHint))
2231 offset += controlWidth;
2232 else if (isMaximized && (titlebar->titleBarFlags & Qt::WindowMaximizeButtonHint))
2233 offset += controlWidth;
2234 else if (sc == SC_TitleBarNormalButton)
2237 case SC_TitleBarMaxButton:
2238 if (!isMaximized && (titlebar->titleBarFlags & Qt::WindowMaximizeButtonHint))
2239 offset += controlWidth;
2240 else if (sc == SC_TitleBarMaxButton)
2243 case SC_TitleBarShadeButton:
2244 if (!isMinimized && (titlebar->titleBarFlags & Qt::WindowShadeButtonHint))
2245 offset += controlWidth;
2246 else if (sc == SC_TitleBarShadeButton)
2249 case SC_TitleBarUnshadeButton:
2250 if (isMinimized && (titlebar->titleBarFlags & Qt::WindowShadeButtonHint))
2251 offset += controlWidth;
2252 else if (sc == SC_TitleBarUnshadeButton)
2255 case SC_TitleBarCloseButton:
2256 if (titlebar->titleBarFlags & Qt::WindowSystemMenuHint)
2257 offset += controlWidth;
2258 else if (sc == SC_TitleBarCloseButton)
2260 ret.setRect(titlebar->rect.right() - offset, titlebar->rect.top(),
2261 controlWidth, controlHeight);
2263 case SC_TitleBarSysMenu:
2264 if (titlebar->titleBarFlags & Qt::WindowSystemMenuHint) {
2265 const auto yOfs = titlebar->rect.top() + (titlebar->rect.height() - iconSize) / 2;
2266 ret.setRect(titlebar->rect.left() + controlWidthMargin + indent, yOfs, iconSize,
2273 if (widget && isMinimized && titlebar->rect.width() < offset)
2274 const_cast<QWidget*>(widget)->resize(controlWidthMargin + indent + offset + iconSize + controlWidthMargin, controlWidth);
2275 ret = visualRect(titlebar->direction, titlebar->rect, ret);
2281 ret = QCommonStyle::subControlRect(control, option, subControl, widget);
2283 if (subControl == SC_ScrollBarAddLine || subControl == SC_ScrollBarSubLine) {
2284 if (
const QStyleOptionSlider *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(option)) {
2285 if (scrollbar->orientation == Qt::Vertical)
2286 ret = ret.adjusted(2,2,-2,-3);
2288 ret = ret.adjusted(3,2,-2,-2);
2294 if (
const auto *cb = qstyleoption_cast<
const QStyleOptionComboBox *>(option)) {
2295 const auto indicatorWidth =
2296 proxy()->pixelMetric(PM_MenuButtonIndicator, option, widget);
2297 switch (subControl) {
2298 case SC_ComboBoxArrow: {
2300 cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, cb, widget) : 0;
2301 const int buttonHeight =
2302 qMin(cb->rect.height() - 3 * fw, cb->fontMetrics.height() * 5 / 4);
2303 const QSize buttonSize(buttonHeight * 6 / 5, buttonHeight);
2304 const int textFieldLength = cb->rect.width() - 2 * fw - buttonSize.width();
2305 const QPoint topLeft(cb->rect.topLeft() + QPoint(fw, fw));
2306 const int yOfs = ((cb->rect.height() - 2 * fw) - buttonSize.height()) / 2;
2307 ret = QRect(topLeft.x() + textFieldLength, topLeft.y() + yOfs, buttonSize.width(),
2308 buttonSize.height());
2309 ret = visualRect(option->direction, option->rect, ret);
2312 case SC_ComboBoxEditField: {
2315 const int fw = proxy()->pixelMetric(PM_ComboBoxFrameWidth, cb, widget);
2316 ret = ret.marginsRemoved(QMargins(fw, fw, fw, fw));
2318 ret.setWidth(ret.width() - indicatorWidth - contentHMargin * 2);
2319 ret = visualRect(option->direction, option->rect, ret);
2323 ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget);
2329#if QT_CONFIG(groupbox)
2331 ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget);
2332 switch (subControl) {
2333 case SC_GroupBoxCheckBox:
2343 ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget);
2351QSize QWindows11Style::sizeFromContents(ContentsType type,
const QStyleOption *option,
2352 const QSize &size,
const QWidget *widget)
const
2354 QSize contentSize(size);
2358#if QT_CONFIG(menubar)
2359 case CT_MenuBarItem:
2360 if (!contentSize.isEmpty()) {
2361 constexpr int hMargin = 2 * 6;
2362 constexpr int hPadding = 2 * 11;
2363 constexpr int itemHeight = 32;
2364 contentSize.setWidth(contentSize.width() + hMargin + hPadding);
2365#if QT_CONFIG(tabwidget)
2366 if (widget->parent() && !qobject_cast<
const QTabWidget *>(widget->parent()))
2368 contentSize.setHeight(itemHeight);
2374 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(option)) {
2375 int width = size.width();
2377 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
2381 height = menuItem->fontMetrics.height() + 8;
2382 if (!menuItem->icon.isNull()) {
2383 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, option, widget);
2384 height = qMax(height,
2385 menuItem->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4);
2388 if (menuItem->text.contains(u'\t'))
2389 width += contentItemHMargin;
2390 if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu)
2391 width += 2 * QWindowsStylePrivate::windowsArrowHMargin + contentItemHMargin;
2392 if (menuItem->menuItemType == QStyleOptionMenuItem::DefaultItem) {
2393 const QFontMetrics fm(menuItem->font);
2394 QFont fontBold = menuItem->font;
2395 fontBold.setBold(
true);
2396 const QFontMetrics fmBold(fontBold);
2397 width += fmBold.horizontalAdvance(menuItem->text) - fm.horizontalAdvance(menuItem->text);
2400 if (menuItem->menuHasCheckableItems) {
2401 const auto checkMarkWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget);
2402 width += checkMarkWidth + contentItemHMargin * 2;
2406 if (menuItem->maxIconWidth > 0)
2407 width += contentItemHMargin * 2 + menuItem->maxIconWidth - 4;
2409 width += 2 * contentHMargin;
2412 contentSize = QSize(width, height);
2416#if QT_CONFIG(spinbox)
2418 if (
const auto *spinbox = qstyleoption_cast<
const QStyleOptionSpinBox *>(option)) {
2420 const bool hasButtons = (spinbox->buttonSymbols != QAbstractSpinBox::NoButtons);
2421 const int margins = 0;
2422 int buttonWidth = 0;
2424 buttonWidth = widget
2425 ? widthFromChar(widget->font(), Icon::ChevronUp, m_fontPoint2ChevronUpWidth)
2426 : spinbox->fontMetrics.horizontalAdvance(fluentIcon(Icon::ChevronUp));
2429 const int frameWidth = spinbox->frame
2430 ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget)
2433 contentSize += QSize(2 * (buttonWidth + frameWidth + margins + 4), 2 * frameWidth);
2438#if QT_CONFIG(combobox)
2440 if (
const auto *comboBoxOpt = qstyleoption_cast<
const QStyleOptionComboBox *>(option)) {
2441 contentSize = QWindowsStyle::sizeFromContents(type, option, size, widget);
2442 contentSize += QSize(0, 4);
2443 if (comboBoxOpt->subControls & SC_ComboBoxArrow) {
2444 const auto w = proxy()->pixelMetric(PM_MenuButtonIndicator, option, widget);
2445 contentSize.rwidth() += w + contentItemHMargin;
2451 if (qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
2452 contentSize = QWindowsStyle::sizeFromContents(type, option, size, widget);
2453 contentSize += QSize(0, 4);
2455 contentSize += QSize(2 * 4, 0);
2458 case CT_HeaderSection:
2461 contentSize = QWindowsStyle::sizeFromContents(type, option, size, widget);
2463 case CT_RadioButton:
2465 if (
const auto *buttonOpt = qstyleoption_cast<
const QStyleOptionButton *>(option)) {
2466 const auto p = proxy();
2467 const bool isRadio = (type == CT_RadioButton);
2469 const int width = p->pixelMetric(
2470 isRadio ? PM_ExclusiveIndicatorWidth : PM_IndicatorWidth, option, widget);
2471 const int height = p->pixelMetric(
2472 isRadio ? PM_ExclusiveIndicatorHeight : PM_IndicatorHeight, option, widget);
2475 if (!buttonOpt->icon.isNull() || !buttonOpt->text.isEmpty()) {
2476 margins += p->pixelMetric(isRadio ? PM_RadioButtonLabelSpacing
2477 : PM_CheckBoxLabelSpacing,
2481 contentSize += QSize(width + margins, 4);
2482 contentSize.setHeight(qMax(size.height(), height + 2 * contentItemHMargin));
2488 contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
2489 if (size.width() == 0)
2490 contentSize.rwidth() += 2;
2492 case CT_PushButton: {
2493 contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
2495 const int oldMargin = proxy()->pixelMetric(PM_ButtonMargin, option, widget);
2496 contentSize.rwidth() += 2 * contentHMargin - oldMargin;
2499 case CT_ToolButton: {
2501 if (
const auto tb = qstyleoption_cast<
const QStyleOptionToolButton *>(option)) {
2503 if (!tb->subControls.testFlag(SC_ToolButtonMenu)) {
2504 if (tb->features.testFlag(QStyleOptionToolButton::HasMenu))
2505 contentSize.rwidth() += 2;
2507 if (tb->toolButtonStyle == Qt::ToolButtonTextBesideIcon
2508 || tb->toolButtonStyle == Qt::ToolButtonIconOnly) {
2509 contentSize.rheight() = qMax(contentSize.height(), tb->iconSize.height() + 4);
2512 const auto fw = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
2513 contentSize += QSize(contentHMargin + 2 * fw, 2 * fw);
2516 case CT_ItemViewItem: {
2517 if (
const auto *viewItemOpt = qstyleoption_cast<
const QStyleOptionViewItem *>(option)) {
2518 if (
const QListView *lv = qobject_cast<
const QListView *>(widget);
2519 lv && lv->viewMode() != QListView::IconMode) {
2520 QStyleOptionViewItem vOpt(*viewItemOpt);
2524 vOpt.rect.setRight(vOpt.rect.right() - contentHMargin);
2525 contentSize = QWindowsVistaStyle::sizeFromContents(type, &vOpt, size, widget);
2526 contentSize.rwidth() += contentHMargin;
2527 contentSize.rheight() += 2 * contentHMargin;
2530 contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
2536 contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);