2164void QStyleKitStyle::drawControl(ControlElement element,
const QStyleOption *opt, QPainter *p,
2165 const QWidget *w)
const
2167 Q_D(
const QStyleKitStyle);
2171 if (
const QStyleOptionButton *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2172 proxy()->drawControl(CE_PushButtonBevel, btn, p, w);
2173 QStyleOptionButton btnContent(*btn);
2174 btnContent.rect = subElementRect(SE_PushButtonContents, btn, w);
2175 proxy()->drawControl(CE_PushButtonLabel, &btnContent, p, w);
2178 case CE_PushButtonBevel:
2179 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2180 QStyleOptionButton btnBg(*btn);
2181 btnBg.rect = subElementRect(SE_PushButtonBevel, btn, w);
2182 proxy()->drawPrimitive(PE_FrameButtonBevel, &btnBg, p, w);
2185 case CE_PushButtonLabel:
2186 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2187 const auto controlType = btn->features & QStyleOptionButton::Flat
2188 ? QQStyleKitReader::ControlType::FlatButton
2189 : QQStyleKitReader::ControlType::Button;
2190 const auto r = d->resolve(w, controlType, btn->state);
2193 const auto metrics = r.metrics;
2195 QRect textRect = opt->rect;
2196 uint textFlags = Qt::TextShowMnemonic;
2197 if (!styleHint(SH_UnderlineShortcut, opt, w))
2198 textFlags |= Qt::TextHideMnemonic;
2200 if (btn->features & QStyleOptionButton::HasMenu) {
2201 int indicatorSize = pixelMetric(PM_MenuButtonIndicator, btn, w);
2202 if (btn->direction == Qt::LeftToRight)
2203 textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
2205 textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
2209 const QIcon icon = btn->icon;
2210 if (!icon.isNull()) {
2211 const auto *textProps = r.text();
2212 uint iconTextFlags = textFlags;
2213 iconTextFlags |= textProps
2214 ? resolvedAlignment(textProps->alignment(), Qt::AlignHCenter, Qt::AlignVCenter)
2215 : uint(Qt::AlignHCenter | Qt::AlignVCenter);
2216 QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
2217 if (mode == QIcon::Normal && btn->state & State_HasFocus)
2218 mode = QIcon::Active;
2219 QIcon::State iconState = btn->state & State_On ? QIcon::On : QIcon::Off;
2220 const auto paintDeviceDpr = p->device()->devicePixelRatio();
2221 QPixmap pixmap = icon.pixmap(btn->iconSize, paintDeviceDpr, mode, iconState);
2222 int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
2223 int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
2224 int labelWidth = pixmapWidth;
2225 int iconSpacing = metrics->spacing;
2226 int textWidth = QFontMetrics(r.font().resolve(p->font()))
2227 .boundingRect(opt->rect, iconTextFlags, btn->text)
2229 if (!btn->text.isEmpty())
2230 labelWidth += textWidth + iconSpacing;
2233 if (iconTextFlags & Qt::AlignLeft) {
2234 iconRect = QRect(textRect.x(),
2235 textRect.y() + (textRect.height() - pixmapHeight) / 2,
2236 pixmapWidth, pixmapHeight);
2237 }
else if (iconTextFlags & Qt::AlignHCenter) {
2238 iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
2239 textRect.y() + (textRect.height() - pixmapHeight) / 2,
2240 pixmapWidth, pixmapHeight);
2242 iconRect = QRect(textRect.x() + textRect.width() - labelWidth,
2243 textRect.y() + (textRect.height() - pixmapHeight) / 2,
2244 pixmapWidth, pixmapHeight);
2246 iconRect = visualRect(btn->direction, textRect, iconRect);
2249 if (btn->direction == Qt::RightToLeft) {
2250 textRect.setRight(iconRect.left() - iconSpacing);
2251 textRect.setLeft(textRect.right() - textWidth + 1);
2253 textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing);
2254 textRect.setWidth(textWidth);
2257 p->drawPixmap(iconRect, pixmap);
2260 r.drawText(textRect, btn->text, textFlags, p);
2265 case CE_RadioButton:
2266 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2267 const auto controlType = element == CE_CheckBox
2268 ? QQStyleKitReader::ControlType::CheckBox
2269 : QQStyleKitReader::ControlType::RadioButton;
2270 const auto r = d->resolve(w, controlType, btn->state);
2273 QRect backgroundRect = btn->rect.marginsRemoved(r.metrics->margins);
2275 r.drawBackground(backgroundRect, p);
2277 QStyleOptionButton btnContent(*btn);
2278 const auto contentElement = element == CE_CheckBox
2279 ? SE_CheckBoxContents
2280 : SE_RadioButtonContents;
2281 btnContent.rect = subElementRect(contentElement, btn, w);
2282 const auto labelElement = element == CE_CheckBox
2284 : CE_RadioButtonLabel;
2285 proxy()->drawControl(labelElement, &btnContent, p, w);
2287 QStyleOptionButton indicator(*btn);
2288 const auto indicatorElement = element == CE_CheckBox
2289 ? SE_CheckBoxIndicator
2290 : SE_RadioButtonIndicator;
2291 indicator.rect = subElementRect(indicatorElement, btn, w);
2292 const auto primitiveElement = element == CE_CheckBox
2293 ? PE_IndicatorCheckBox
2294 : PE_IndicatorRadioButton;
2295 proxy()->drawPrimitive(primitiveElement, &indicator, p, w);
2299 case CE_CheckBoxLabel:
2300 case CE_RadioButtonLabel:
2301 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2302 const auto controlType = element == CE_CheckBoxLabel
2303 ? QQStyleKitReader::ControlType::CheckBox
2304 : QQStyleKitReader::ControlType::RadioButton;
2305 const auto r = d->resolve(w, controlType, btn->state);
2308 uint textFlags = Qt::TextShowMnemonic;
2309 if (!styleHint(SH_UnderlineShortcut, opt, w))
2310 textFlags |= Qt::TextHideMnemonic;
2311 if (btn->icon.isNull()) {
2312 r.drawText(opt->rect, btn->text, textFlags, p);
2315 const QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
2316 const QIcon::State iconState = btn->state & State_On ? QIcon::On : QIcon::Off;
2317 const QPixmap pm = btn->icon.pixmap(btn->iconSize, p->device()->devicePixelRatio(),
2319 const QSize pmSize = pm.size() / pm.devicePixelRatio();
2321 const auto *textProps = r.text();
2322 const auto alignment = Qt::Alignment(resolvedAlignment(
2323 textProps ? textProps->alignment() : 0u, Qt::AlignHCenter, Qt::AlignVCenter));
2324 const QSize textSize = QFontMetrics(r.font().resolve(p->font()))
2325 .size(textFlags, btn->text);
2326 const int spacing = btn->text.isEmpty() ? 0 : r.metrics->spacing;
2327 const QSize labelSize(pmSize.width() + spacing + textSize.width(),
2328 qMax(pmSize.height(), textSize.height()));
2329 const QRect labelRect = alignedRect(btn->direction, alignment, labelSize, opt->rect);
2330 p->drawPixmap(alignedRect(btn->direction, Qt::AlignLeft | Qt::AlignVCenter, pmSize,
2333 r.drawText(alignedRect(btn->direction, Qt::AlignRight | Qt::AlignVCenter, textSize,
2335 btn->text, textFlags, p);
2339#if QT_CONFIG(combobox)
2340 case CE_ComboBoxLabel:
2341 if (
const auto *comboBox = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
2342 if (comboBox->editable && comboBox->currentIcon.isNull())
2344 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, comboBox->state);
2347 const QRect editRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, w);
2348 const QRect textRect = editRect.marginsRemoved(r.metrics->textPadding);
2349 uint textFlags = Qt::TextShowMnemonic;
2350 if (!styleHint(SH_UnderlineShortcut, opt, w))
2351 textFlags |= Qt::TextHideMnemonic;
2352 if (comboBox->currentIcon.isNull()) {
2353 r.drawText(textRect, comboBox->currentText, textFlags, p);
2356 const QIcon::Mode mode = comboBox->state & State_Enabled
2359 const QPixmap pm = comboBox->currentIcon.pixmap(
2360 comboBox->iconSize, p->device()->devicePixelRatio(), mode);
2361 const QSize pmSize = pm.size() / pm.devicePixelRatio();
2362 if (comboBox->editable) {
2364 const QRect iconSlot = alignedRect(
2365 comboBox->direction, Qt::AlignLeft | Qt::AlignVCenter,
2366 QSize(comboBox->iconSize.width() + 4, editRect.height()), editRect);
2367 p->drawPixmap(alignedRect(comboBox->direction, Qt::AlignCenter, pmSize, iconSlot),
2372 const auto *textProps = r.text();
2373 const auto alignment = Qt::Alignment(resolvedAlignment(
2374 textProps ? textProps->alignment() : 0u, Qt::AlignHCenter, Qt::AlignVCenter));
2375 const QSize textSize = QFontMetrics(r.font().resolve(p->font()))
2376 .size(textFlags, comboBox->currentText);
2377 const int spacing = comboBox->currentText.isEmpty() ? 0 : r.metrics->spacing;
2378 const QSize labelSize(pmSize.width() + spacing + textSize.width(),
2379 qMax(pmSize.height(), textSize.height()));
2380 const QRect labelRect = alignedRect(comboBox->direction, alignment, labelSize,
2382 p->drawPixmap(alignedRect(comboBox->direction, Qt::AlignLeft | Qt::AlignVCenter,
2385 r.drawText(alignedRect(comboBox->direction, Qt::AlignRight | Qt::AlignVCenter,
2386 textSize, labelRect),
2387 comboBox->currentText, textFlags, p);
2392#if QT_CONFIG(progressbar)
2393 case CE_ProgressBar:
2394 if (
const QStyleOptionProgressBar *progressBar =
2395 qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
2396 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar,
2397 progressBar->state);
2400 QRect backgroundRect = progressBar->rect.marginsRemoved(r.metrics->margins);
2402 r.drawBackground(backgroundRect, p);
2404 QStyleOptionProgressBar contents(*progressBar);
2405 contents.rect = subElementRect(SE_ProgressBarGroove, progressBar, w);
2406 const QRect grooveRect = contents.rect;
2407 proxy()->drawControl(CE_ProgressBarGroove, &contents, p, w);
2409 contents.rect = subElementRect(SE_ProgressBarContents, progressBar, w);
2412 QPainterStateGuard stateGuard(p);
2413 if (applyDelegateTransform(p, r.indicator(), grooveRect))
2414 proxy()->drawControl(CE_ProgressBarContents, &contents, p, w);
2419 case CE_ProgressBarGroove: {
2421 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar, opt->state);
2424 drawStyledItemRect(r.indicator(), opt->rect, p);
2427 case CE_ProgressBarContents:
2429 if (
const auto *progressBar = qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
2430 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ProgressBar,
2431 progressBar->state);
2434 const auto progress = progressBar->progress;
2435 const auto ratio = progressBar->maximum > progressBar->minimum
2436 ? (progress - progressBar->minimum)
2437 /
static_cast<qreal>(progressBar->maximum - progressBar->minimum)
2439 const auto width =
static_cast<
int>(progressBar->rect.width() * ratio);
2440 const auto x = progressBar->invertedAppearance
2441 ? progressBar->rect.right() - width
2442 : progressBar->rect.left();
2443 const auto contentsRect = QRect(x, progressBar->rect.y(),
2444 width, progressBar->rect.height());
2445 const auto *foreground = r.indicator() ? r.indicator()->foreground() :
nullptr;
2446 if (foreground && foreground->visible() && foreground->opacity() > 0) {
2447 QPainterStateGuard stateGuard(p);
2448 if (applyDelegateTransform(p, foreground, progressBar->rect))
2449 drawStyledItemContents(foreground, contentsRect, p);
2455#if QT_CONFIG(itemviews)
2456 case CE_ItemViewItem:
2457 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
2458 const auto r = d->resolveSubElement(w, opt, itemViewControlType(opt), opt->state);
2461 QStyleOptionViewItem optBg(*itemViewOption);
2462 optBg.rect = optBg.rect.marginsRemoved(r.metrics->margins);
2463 QRect indicatorRect = subElementRect(SE_ItemViewItemCheckIndicator, itemViewOption, w);
2464 QRect iconRect = subElementRect(SE_ItemViewItemDecoration, itemViewOption, w);
2465 QRect textRect = subElementRect(SE_ItemViewItemText, itemViewOption, w);
2468 const auto *itemTextProps = r.text();
2469 const QFont itemFont = r.font();
2472 proxy()->drawPrimitive(PE_PanelItemViewItem, &optBg, p, w);
2475 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator) {
2476 QStyleOptionViewItem option(*itemViewOption);
2477 option.rect = indicatorRect;
2478 option.state = option.state & ~QStyle::State_HasFocus;
2480 switch (itemViewOption->checkState) {
2482 option.state |= QStyle::State_Off;
2484 case Qt::PartiallyChecked:
2485 option.state |= QStyle::State_NoChange;
2488 option.state |= QStyle::State_On;
2491 proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, p, w);
2495 QIcon::Mode mode = QIcon::Normal;
2496 if (!(itemViewOption->state & QStyle::State_Enabled))
2497 mode = QIcon::Disabled;
2498 else if (itemViewOption->state & QStyle::State_Selected)
2499 mode = QIcon::Selected;
2500 QIcon::State state = itemViewOption->state & QStyle::State_Open
2503 itemViewOption->icon.paint(p, iconRect, itemViewOption->decorationAlignment, mode,
2507 uint textFlags = Qt::TextShowMnemonic;
2508 if (!styleHint(SH_UnderlineShortcut, opt, w))
2509 textFlags |= Qt::TextHideMnemonic;
2510 drawControlText(itemTextProps, itemFont, textRect, itemViewOption->text, textFlags,
2511 p, Qt::AlignLeft | Qt::AlignVCenter);
2517 case CE_ShapedFrame: {
2518# if QT_CONFIG(scrollarea)
2519 if (qobject_cast<
const QAbstractScrollArea *>(w))
2523 auto controlType = QQStyleKitReader::ControlType::Frame;
2524# if QT_CONFIG(combobox)
2525 if (w && w->inherits(
"QComboBoxPrivateContainer"))
2526 controlType = QQStyleKitReader::ControlType::Popup;
2528# if QT_CONFIG(textedit)
2529 else if (w && qobject_cast<
const QTextEdit *>(w))
2530 controlType = QQStyleKitReader::ControlType::TextArea;
2532# if QT_CONFIG(label)
2533 else if (w && qobject_cast<
const QLabel *>(w))
2534 controlType = QQStyleKitReader::ControlType::Label;
2537 if (qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
2538 const auto r = d->resolve(w, controlType, opt->state);
2541 QRect backgroundRect = opt->rect.marginsRemoved(r.metrics->margins);
2542 r.drawBackground(backgroundRect, p);
2548#if QT_CONFIG(scrollbar)
2549 case CE_ScrollBarSlider: {
2550 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ScrollBar, opt->state);
2553 r.drawIndicator(opt->rect, p);
2557#if QT_CONFIG(toolbutton)
2558 case CE_ToolButtonLabel:
2559 if (
const auto *tool = qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
2560 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolButton, tool->state);
2563 const auto *metrics = r.metrics;
2564 QRect rect = tool->rect.marginsRemoved(metrics->textPadding);
2566 uint textFlags = Qt::TextShowMnemonic;
2567 if (!styleHint(SH_UnderlineShortcut, opt, w))
2568 textFlags |= Qt::TextHideMnemonic;
2570 const bool hasArrow = tool->features & QStyleOptionToolButton::Arrow;
2571 if ((!hasArrow && tool->icon.isNull() && !tool->text.isEmpty())
2572 || tool->toolButtonStyle == Qt::ToolButtonTextOnly) {
2573 r.drawText(rect, tool->text, textFlags, p);
2579 if (!hasArrow && !tool->icon.isNull()) {
2580 const QIcon::State iconState = tool->state & State_On ? QIcon::On : QIcon::Off;
2582 if (!(tool->state & State_Enabled))
2583 mode = QIcon::Disabled;
2584 else if ((tool->state & State_MouseOver) && (tool->state & State_AutoRaise))
2585 mode = QIcon::Active;
2587 mode = QIcon::Normal;
2588 pm = tool->icon.pixmap(tool->iconSize, p->device()->devicePixelRatio(), mode,
2590 pmSize = pm.size() / pm.devicePixelRatio();
2593 const auto *textProps = r.text();
2594 const auto alignment = Qt::Alignment(resolvedAlignment(
2595 textProps ? textProps->alignment() : 0u, Qt::AlignHCenter, Qt::AlignVCenter));
2597 if (tool->toolButtonStyle == Qt::ToolButtonIconOnly || tool->text.isEmpty()) {
2599 p->drawPixmap(alignedRect(tool->direction, alignment, pmSize, rect), pm);
2604 const QSize textSize = QFontMetrics(r.font().resolve(p->font()))
2605 .size(textFlags, tool->text);
2607 if (tool->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
2609 const QSize labelSize(qMax(pmSize.width(), textSize.width()),
2610 pmSize.height() + metrics->spacing + textSize.height());
2611 const QRect labelRect = alignedRect(tool->direction, alignment, labelSize,
2613 p->drawPixmap(alignedRect(tool->direction, Qt::AlignHCenter | Qt::AlignTop,
2616 r.drawText(alignedRect(tool->direction, Qt::AlignHCenter | Qt::AlignBottom,
2617 textSize, labelRect),
2618 tool->text, textFlags, p, Qt::AlignCenter);
2620 r.drawText(rect, tool->text, textFlags, p, Qt::AlignCenter);
2624 const QSize labelSize(pmSize.width() + metrics->spacing + textSize.width(),
2625 qMax(pmSize.height(), textSize.height()));
2626 const QRect labelRect = alignedRect(tool->direction, alignment, labelSize,
2628 p->drawPixmap(alignedRect(tool->direction, Qt::AlignLeft | Qt::AlignVCenter,
2631 r.drawText(alignedRect(tool->direction, Qt::AlignRight | Qt::AlignVCenter,
2632 textSize, labelRect),
2633 tool->text, textFlags, p, Qt::AlignLeft | Qt::AlignVCenter);
2635 r.drawText(rect, tool->text, textFlags, p, Qt::AlignLeft | Qt::AlignVCenter);
2644 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
2645 using QtPrivate::qSaturateRound;
2647 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
2648 const auto r = d->resolve(w, QQStyleKitReader::ControlType::MenuSeparator,
2652 const auto metrics = r.metrics;
2653 QRect contentRect = opt->rect
2654 .marginsRemoved(metrics->margins)
2655 .marginsRemoved(metrics->padding);
2656 const auto *indicator = r.indicator();
2657 const QRect indicatorRect = delegateRect(
2658 indicator, contentRect, Qt::AlignHCenter, Qt::AlignVCenter);
2659 r.drawIndicator(visualRect(opt->direction, contentRect, indicatorRect), p);
2663 QStyle::State adjustedState = menuItem->state;
2664 if (adjustedState & State_Selected)
2665 adjustedState |= State_MouseOver;
2667 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::MenuItem,
2673 r.drawBackground(opt->rect.marginsRemoved(r.metrics->margins), p);
2676 const QRect contentRect = opt->rect.marginsRemoved(r.metrics->padding);
2677 const auto *indicator = r.indicator();
2678 const auto *first = indicator ? indicator->first() :
nullptr;
2679 const auto *second = indicator ? indicator->second() :
nullptr;
2680 int leftOffset = 0, rightOffset = 0;
2681 const int spacing = r.metrics->spacing;
2682 QRect firstDrawRect, secondDrawRect;
2683 auto placeSubIndicator = [&](
const QQStyleKitIndicatorProperties *sub,
2687 const QSize sz(qSaturateRound(sub->width()), qSaturateRound(sub->height()));
2688 const QMargins subMargins = elementMargins(sub);
2689 const int slotW = qSaturateRound(sub->leftMargin() + sub->width() + sub->rightMargin());
2690 if (sub->alignment() & Qt::AlignRight) {
2691 const QRect slot(contentRect.right() - rightOffset - slotW, contentRect.top(),
2692 slotW, contentRect.height());
2693 drawRect = alignedRectInContainer(
2694 slot, sz, Qt::AlignRight | Qt::AlignVCenter, { }, subMargins);
2695 rightOffset += slotW + spacing;
2697 const QRect slot(contentRect.left() + leftOffset, contentRect.top(), slotW,
2698 contentRect.height());
2699 drawRect = alignedRectInContainer(
2700 slot, sz, Qt::AlignLeft | Qt::AlignVCenter, { }, subMargins);
2701 leftOffset += slotW + spacing;
2704 if (menuItem->menuHasCheckableItems)
2705 placeSubIndicator(first, firstDrawRect);
2706 if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu)
2707 placeSubIndicator(second, secondDrawRect);
2709 if (first && menuItem->checkType != QStyleOptionMenuItem::NotCheckable
2710 && menuItem->checked) {
2712 true, visualRect(menuItem->direction, contentRect, firstDrawRect), p);
2715 if (second && menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {
2717 false, visualRect(menuItem->direction, contentRect, secondDrawRect), p);
2721 QRect textRect = contentRect
2722 .adjusted(leftOffset, 0, -rightOffset, 0)
2723 .marginsRemoved(r.metrics->textPadding);
2725 if (menuItem->maxIconWidth > 0) {
2726 const int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt, w);
2727 if (!menuItem->icon.isNull()) {
2728 const QIcon::Mode mode = (menuItem->state & State_Enabled)
2731 const QPixmap pm = menuItem->icon.pixmap(
2732 QSize(iconExtent, iconExtent), p->device()->devicePixelRatio(), mode);
2733 const QSize pmSize = pm.size() / pm.devicePixelRatio();
2734 const QRect iconColumn(textRect.left(), textRect.top(), iconExtent,
2736 p->drawPixmap(visualRect(menuItem->direction, textRect,
2737 alignedRect(Qt::LeftToRight, Qt::AlignCenter, pmSize,
2741 textRect.setLeft(textRect.left() + iconExtent + r.metrics->spacing);
2744 const int tabIdx = menuItem->text.indexOf(QLatin1Char(
'\t'));
2745 const QString label = tabIdx >= 0 ? menuItem->text.left(tabIdx) : menuItem->text;
2746 const QString shortcut = tabIdx >= 0 ? menuItem->text.mid(tabIdx + 1) : QString();
2747 uint textFlags = Qt::TextShowMnemonic;
2748 if (!styleHint(SH_UnderlineShortcut, opt, w))
2749 textFlags |= Qt::TextHideMnemonic;
2750 QRect labelRect = textRect;
2751 if (!shortcut.isEmpty() && menuItem->reservedShortcutWidth > 0) {
2752 const QRect shortcutRect(textRect.right() - menuItem->reservedShortcutWidth + 1,
2753 textRect.top(), menuItem->reservedShortcutWidth,
2755 labelRect.setRight(shortcutRect.left() - r.metrics->spacing - 1);
2756 const int shortcutFlags =
2757 int(QStyle::visualAlignment(menuItem->direction,
2758 Qt::AlignRight | Qt::AlignVCenter))
2761 p->setFont(r.font().resolve(p->font()));
2762 p->setBrush(Qt::NoBrush);
2763 if (
const auto *shortcutText = r.text())
2764 p->setPen(shortcutText->color());
2765 p->drawText(visualRect(menuItem->direction, textRect, shortcutRect), shortcutFlags,
2769 r.drawText(visualRect(menuItem->direction, textRect, labelRect), label, textFlags, p,
2770 Qt::AlignLeft | Qt::AlignVCenter);
2776 case CE_MenuScroller:
2777 case CE_MenuTearoff:
2779 case CE_MenuEmptyArea:
2782#if QT_CONFIG(menubar)
2783 case CE_MenuBarEmptyArea:
2785 case CE_MenuBarItem:
2786 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
2787 QStyle::State adjustedState = menuItem->state;
2788 if (adjustedState & State_Selected)
2789 adjustedState |= State_MouseOver;
2790 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::MenuBarItem,
2794 r.drawBackground(opt->rect.marginsRemoved(r.metrics->margins), p);
2795 const QRect textRect = opt->rect.marginsRemoved(
2796 r.metrics->margins + r.metrics->padding + r.metrics->textPadding);
2797 uint textFlags = Qt::TextShowMnemonic;
2798 if (!styleHint(SH_UnderlineShortcut, opt, w))
2799 textFlags |= Qt::TextHideMnemonic;
2800 if (menuItem->icon.isNull()) {
2801 r.drawText(textRect, menuItem->text, textFlags, p);
2805 const QIcon::Mode mode = menuItem->state & State_Enabled
2808 const int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt, w);
2809 const QPixmap pm = menuItem->icon.pixmap(QSize(iconExtent, iconExtent),
2810 p->device()->devicePixelRatio(), mode);
2811 const auto *textProps = r.text();
2812 const auto alignment = Qt::Alignment(resolvedAlignment(
2813 textProps ? textProps->alignment() : 0u, Qt::AlignHCenter, Qt::AlignVCenter));
2814 p->drawPixmap(alignedRect(menuItem->direction, alignment,
2815 pm.size() / pm.devicePixelRatio(), textRect),
2821#if QT_CONFIG(tabbar)
2823 if (
const auto *tab = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
2824 const auto r = d->resolveSubElement(w, opt, QQStyleKitReader::ControlType::TabButton,
2828 const auto &m = *r.metrics;
2830 const QRect backgroundRect = opt->rect.marginsRemoved(m.margins);
2831 r.drawBackground(backgroundRect, p);
2833 const QRect contentRect = backgroundRect.marginsRemoved(m.padding + m.textPadding);
2834 uint textFlags = Qt::TextShowMnemonic;
2835 if (!styleHint(SH_UnderlineShortcut, opt, w))
2836 textFlags |= Qt::TextHideMnemonic;
2838 if (!tab->icon.isNull()) {
2839 const QIcon::Mode mode = (tab->state & State_Enabled)
2842 const QIcon::State iconState = (tab->state & State_Selected)
2845 const QPixmap pm = tab->icon.pixmap(tab->iconSize, p->device()->devicePixelRatio(),
2847 const QSize pmSize = pm.size() / pm.devicePixelRatio();
2849 const auto *textProps = r.text();
2850 const auto alignment = Qt::Alignment(resolvedAlignment(
2851 textProps ? textProps->alignment() : 0u, Qt::AlignHCenter, Qt::AlignVCenter));
2852 const QSize textSize = QFontMetrics(r.font().resolve(p->font()))
2853 .size(textFlags, tab->text);
2854 const int spacing = tab->text.isEmpty() ? 0 : m.spacing;
2855 const QSize labelSize(pmSize.width() + spacing + textSize.width(),
2856 qMax(pmSize.height(), textSize.height()));
2857 const QRect labelRect = alignedRect(tab->direction, alignment, labelSize,
2859 p->drawPixmap(alignedRect(tab->direction, Qt::AlignLeft | Qt::AlignVCenter,
2862 r.drawText(alignedRect(tab->direction, Qt::AlignRight | Qt::AlignVCenter,
2863 textSize, labelRect),
2864 tab->text, textFlags, p, Qt::AlignCenter);
2866 r.drawText(contentRect, tab->text, textFlags, p, Qt::AlignCenter);
2872#if QT_CONFIG(toolbar)
2874 if (
const auto *toolBar = qstyleoption_cast<
const QStyleOptionToolBar *>(opt)) {
2875 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolBar, toolBar->state);
2878 r.drawBackground(opt->rect.marginsRemoved(r.metrics->margins), p);
2886 QCommonStyle::drawControl(element, opt, p, w);
2890QRect QStyleKitStyle::subElementRect(SubElement r,
const QStyleOption *opt,
2891 const QWidget *widget)
const
2893 using QtPrivate::qSaturateRound;
2894 Q_D(
const QStyleKitStyle);
2897 case SE_PushButtonBevel:
2898 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2899 const auto controlType = btn->features & QStyleOptionButton::Flat
2900 ? QQStyleKitReader::ControlType::FlatButton
2901 : QQStyleKitReader::ControlType::Button;
2902 const auto resolved = d->resolveLayout(controlType, opt->state);
2903 if (!resolved.isValid())
2905 const auto &metrics = *resolved.metrics;
2906 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2907 return visualRect(opt->direction, opt->rect, rect);
2910 case SE_PushButtonContents:
2911 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
2912 const auto controlType = btn->features & QStyleOptionButton::Flat
2913 ? QQStyleKitReader::ControlType::FlatButton
2914 : QQStyleKitReader::ControlType::Button;
2915 const auto resolved = d->resolveLayout(controlType, opt->state);
2916 if (!resolved.isValid())
2918 const auto &metrics = *resolved.metrics;
2919 QRect rect = opt->rect.marginsRemoved(
2920 metrics.margins + metrics.padding + metrics.textPadding);
2921 return visualRect(opt->direction, opt->rect, rect);
2924 case SE_CheckBoxContents:
2925 case SE_RadioButtonContents: {
2926 const auto controlType = r == SE_CheckBoxContents
2927 ? QQStyleKitReader::ControlType::CheckBox
2928 : QQStyleKitReader::ControlType::RadioButton;
2929 const auto resolved = d->resolveLayout(controlType, opt->state);
2930 if (!resolved.isValid())
2932 const auto &metrics = *resolved.metrics;
2933 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
2934 const auto subElement = r == SE_CheckBoxContents
2935 ? SE_CheckBoxIndicator
2936 : SE_RadioButtonIndicator;
2937 QRect indicatorRect = visualRect(opt->direction, opt->rect,
2938 subElementRect(subElement, opt, widget));
2939 const int spacing = metrics.spacing;
2940 const auto *indicator = resolved.indicator();
2941 const uint alignment = indicator
2942 ? resolvedAlignment(indicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
2943 : uint(Qt::AlignLeft | Qt::AlignVCenter);
2944 if (alignment & Qt::AlignLeft) {
2945 contentsRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
2946 }
else if (alignment & Qt::AlignHCenter) {
2947 contentsRect.setLeft(indicatorRect.right() + spacing + metrics.textPadding.left());
2948 contentsRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
2950 contentsRect.setRight(indicatorRect.left() - spacing - metrics.textPadding.right());
2952 return visualRect(opt->direction, opt->rect, contentsRect);
2954 case SE_CheckBoxIndicator:
2955 case SE_RadioButtonIndicator: {
2956 const auto controlType = r == SE_CheckBoxIndicator
2957 ? QQStyleKitReader::ControlType::CheckBox
2958 : QQStyleKitReader::ControlType::RadioButton;
2959 const auto resolved = d->resolveLayout(controlType, opt->state);
2960 if (!resolved.isValid())
2962 const auto &metrics = *resolved.metrics;
2963 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2964 const auto *indicator = resolved.indicator();
2965 if (!indicator || !indicator->visible())
2968 return visualRect(opt->direction, rect,
2969 delegateRect(indicator, rect, Qt::AlignLeft, Qt::AlignVCenter,
2972#if QT_CONFIG(itemviews)
2973 case SE_ItemViewItemCheckIndicator: {
2974 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
2975 if (!resolved.isValid())
2977 const auto &metrics = *resolved.metrics;
2978 QRect rect = opt->rect.marginsRemoved(metrics.margins);
2979 const auto *indicator = resolved.indicator();
2980 if (!indicator || !indicator->visible())
2983 return visualRect(opt->direction, rect,
2984 delegateRect(indicator, rect, Qt::AlignLeft, Qt::AlignVCenter,
2987 case SE_ItemViewItemDecoration:
2988 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
2989 if (!(itemViewOption->features & QStyleOptionViewItem::HasDecoration))
2991 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
2992 if (!resolved.isValid())
2994 const auto &metrics = *resolved.metrics;
2995 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
2996 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator) {
2997 const QRect indicatorRect = subElementRect(
2998 SE_ItemViewItemCheckIndicator, opt, widget);
2999 const auto *checkIndicator = resolved.indicator();
3000 const uint checkAlign = checkIndicator
3001 ? resolvedAlignment(checkIndicator->alignment(), Qt::AlignLeft,
3003 : uint(Qt::AlignLeft | Qt::AlignVCenter);
3004 if (checkAlign & Qt::AlignLeft) {
3005 contentsRect.setLeft(indicatorRect.right()
3006 + metrics.indicatorMargins.right() + metrics.spacing);
3007 }
else if (checkAlign & Qt::AlignRight) {
3008 contentsRect.setRight(indicatorRect.left()
3009 - metrics.indicatorMargins.left() - metrics.spacing);
3013 const QSize decorationSize = itemViewOption->decorationSize
3014 .boundedTo(contentsRect.size());
3015 QRect decorationRect;
3016 switch (itemViewOption->decorationPosition) {
3017 case QStyleOptionViewItem::Top:
3018 decorationRect = QRect(contentsRect.left(), contentsRect.top(),
3019 contentsRect.width(), decorationSize.height());
3021 case QStyleOptionViewItem::Bottom:
3022 decorationRect = QRect(contentsRect.left(),
3023 contentsRect.bottom() - decorationSize.height() + 1,
3024 contentsRect.width(), decorationSize.height());
3026 case QStyleOptionViewItem::Right:
3027 decorationRect = QRect(contentsRect.right() - decorationSize.width() + 1,
3028 contentsRect.top(), decorationSize.width(),
3029 contentsRect.height());
3031 case QStyleOptionViewItem::Left:
3033 decorationRect = QRect(contentsRect.left(), contentsRect.top(),
3034 decorationSize.width(), contentsRect.height());
3037 const uint decorationAlign = resolvedAlignment(itemViewOption->decorationAlignment,
3038 Qt::AlignLeft, Qt::AlignVCenter);
3039 decorationRect = alignedRectInContainer(
3040 decorationRect, decorationSize, decorationAlign, QMargins(0, 0, 0, 0),
3041 QMargins(0, 0, 0, 0));
3042 return visualRect(opt->direction, opt->rect, decorationRect);
3045 case SE_ItemViewItemText:
3046 if (
const auto *itemViewOption = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
3047 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
3048 if (!resolved.isValid())
3050 const auto &metrics = *resolved.metrics;
3051 QRect contentsRect = opt->rect.marginsRemoved(metrics.margins + metrics.padding);
3052 const int spacing = metrics.spacing;
3054 if (itemViewOption->features & QStyleOptionViewItem::HasCheckIndicator) {
3055 const QRect indicatorRect = subElementRect(
3056 SE_ItemViewItemCheckIndicator, opt, widget);
3057 const auto *checkIndicator = resolved.indicator();
3058 const uint checkAlign = checkIndicator
3059 ? resolvedAlignment(checkIndicator->alignment(), Qt::AlignLeft,
3061 : uint(Qt::AlignLeft | Qt::AlignVCenter);
3062 if (checkAlign & Qt::AlignLeft) {
3063 contentsRect.setLeft(
3064 indicatorRect.right() + metrics.indicatorMargins.right() + spacing);
3065 }
else if (checkAlign & Qt::AlignRight) {
3066 contentsRect.setRight(
3067 indicatorRect.left() - metrics.indicatorMargins.left() - spacing);
3071 QRect textRect = contentsRect;
3072 if (itemViewOption->features & QStyleOptionViewItem::HasDecoration) {
3073 const QRect decorationRect = subElementRect(
3074 SE_ItemViewItemDecoration, opt, widget);
3075 switch (itemViewOption->decorationPosition) {
3076 case QStyleOptionViewItem::Top:
3077 textRect.setTop(decorationRect.bottom() + spacing);
3079 case QStyleOptionViewItem::Bottom:
3080 textRect.setBottom(decorationRect.top() - spacing);
3082 case QStyleOptionViewItem::Right:
3083 textRect.setRight(decorationRect.left() - spacing);
3085 case QStyleOptionViewItem::Left:
3087 textRect.setLeft(decorationRect.right() + spacing);
3092 const auto *textProps = resolved.text();
3093 const uint textAlign = textProps
3094 ? resolvedAlignment(textProps->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
3095 : uint(Qt::AlignLeft | Qt::AlignVCenter);
3096 if (textAlign & Qt::AlignLeft) {
3097 textRect.setLeft(textRect.left() + metrics.textPadding.left());
3098 }
else if (textAlign & Qt::AlignHCenter) {
3099 textRect.setLeft(textRect.left() + metrics.textPadding.left() / 2);
3100 textRect.setRight(textRect.right() - metrics.textPadding.right() / 2);
3102 textRect.setRight(textRect.right() - metrics.textPadding.right());
3104 if (textAlign & Qt::AlignTop) {
3105 textRect.setTop(textRect.top() + metrics.textPadding.top());
3106 }
else if (textAlign & Qt::AlignVCenter) {
3107 textRect.setTop(textRect.top() + metrics.textPadding.top() / 2);
3108 textRect.setBottom(textRect.bottom() - metrics.textPadding.bottom() / 2);
3110 textRect.setBottom(textRect.bottom() - metrics.textPadding.bottom());
3112 return visualRect(opt->direction, opt->rect, textRect);
3116 case SE_PushButtonFocusRect:
3117 case SE_CheckBoxClickRect:
3118 case SE_RadioButtonClickRect:
3120#if QT_CONFIG(progressbar)
3121 case SE_ProgressBarGroove: {
3122 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar,
3124 if (!resolved.isValid())
3126 const auto &metrics = *resolved.metrics;
3127 QRect rect = opt->rect.marginsRemoved(metrics.margins);
3128 const auto *indicator = resolved.indicator();
3129 if (!indicator || !indicator->visible())
3132 return visualRect(opt->direction, rect,
3133 delegateRect(indicator, rect, Qt::AlignLeft, Qt::AlignVCenter,
3136 case SE_ProgressBarContents: {
3137 if (qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
3138 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar,
3140 if (!resolved.isValid())
3142 const auto *foreground = resolved.indicator()
3143 ? resolved.indicator()->foreground()
3145 if (!foreground || !foreground->visible())
3148 QRect indicatorRect = subElementRect(SE_ProgressBarGroove, opt, widget);
3149 const QRect foregroundRect = delegateRect(
3150 foreground, indicatorRect, Qt::AlignLeft, Qt::AlignVCenter);
3151 return visualRect(opt->direction, opt->rect, foregroundRect);
3156 case SE_LineEditContents:
3157 if (qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
3158#if QT_CONFIG(spinbox)
3159 const bool isInSpinBox = widget && qobject_cast<
const QSpinBox *>(widget->parentWidget());
3161 const bool isInSpinBox =
false;
3163 const auto controlType = isInSpinBox ? QQStyleKitReader::ControlType::SpinBox
3164 : QQStyleKitReader::ControlType::TextField;
3165 const auto resolved = d->resolveLayout(controlType, opt->state);
3166 if (!resolved.isValid())
3168 const auto &metrics = *resolved.metrics;
3169 QRect contentsRect = opt->rect.marginsRemoved(metrics.padding);
3170 const auto *textProps = resolved.text();
3171 const uint textAlign = resolvedAlignment(textProps ? textProps->alignment() : 0u,
3172 Qt::AlignLeft, Qt::AlignVCenter);
3173 if (textAlign & Qt::AlignLeft)
3174 contentsRect.setLeft(contentsRect.left() + metrics.textPadding.left());
3175 else if (textAlign & Qt::AlignHCenter) {
3176 contentsRect.setLeft(contentsRect.left() + metrics.textPadding.left() / 2);
3177 contentsRect.setRight(contentsRect.right() - metrics.textPadding.right() / 2);
3179 contentsRect.setRight(contentsRect.right() - metrics.textPadding.right());
3181 if (textAlign & Qt::AlignTop)
3182 contentsRect.setTop(contentsRect.top() + metrics.textPadding.top());
3183 else if (textAlign & Qt::AlignVCenter) {
3184 contentsRect.setTop(contentsRect.top() + metrics.textPadding.top() / 2);
3185 contentsRect.setBottom(contentsRect.bottom() - metrics.textPadding.bottom() / 2);
3187 contentsRect.setBottom(contentsRect.bottom() - metrics.textPadding.bottom());
3189 return visualRect(opt->direction, opt->rect, contentsRect);
3192 case SE_ShapedFrameContents:
3193#if QT_CONFIG(combobox)
3194 if (widget && widget->inherits(
"QComboBoxPrivateContainer")) {
3195 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Popup,
3197 if (!resolved.isValid())
3199 const auto &metrics = *resolved.metrics;
3200 QRect contentsRect = opt->rect.marginsRemoved(
3201 metrics.margins + metrics.padding + metrics.textPadding);
3202 return visualRect(opt->direction, opt->rect, contentsRect);
3205#if QT_CONFIG(textedit)
3206 if (qobject_cast<
const QTextEdit *>(widget)) {
3207 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::TextArea,
3209 if (!resolved.isValid())
3211 const auto &metrics = *resolved.metrics;
3212 QRect contentsRect = opt->rect.marginsRemoved(
3213 metrics.margins + metrics.padding + metrics.textPadding);
3214 return visualRect(opt->direction, opt->rect, contentsRect);
3218#if QT_CONFIG(tabbar)
3219 case SE_TabBarTabText:
3220 if (
const auto *tab = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
3221 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::TabButton,
3223 if (!resolved.isValid())
3225 const auto &metrics = *resolved.metrics;
3226 QRect rect = tab->rect.marginsRemoved(
3227 metrics.margins + metrics.padding + metrics.textPadding);
3228 if (!tab->icon.isNull())
3229 rect.setLeft(rect.left() + tab->iconSize.width() + metrics.spacing);
3230 return visualRect(tab->direction, tab->rect, rect);
3233 case SE_TabBarTearIndicatorRight:
3234 case SE_TabBarTearIndicatorLeft:
3235 case SE_TabBarScrollLeftButton:
3236 case SE_TabBarScrollRightButton:
3240#if QT_CONFIG(tabwidget)
3241 case SE_TabWidgetTabContents:
3242 if (qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(opt)) {
3244 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Page, opt->state);
3245 if (!resolved.isValid())
3247 const QRect paneRect = subElementRect(SE_TabWidgetTabPane, opt, widget);
3248 const QRect rect = paneRect.marginsRemoved(resolved.metrics->padding);
3249 return visualRect(opt->direction, opt->rect, rect);
3253#if QT_CONFIG(toolbar)
3254 case SE_ToolBarHandle:
3261 return QCommonStyle::subElementRect(r, opt, widget);
3265void QStyleKitStyle::drawComplexControl(ComplexControl cc,
const QStyleOptionComplex *opt,
3266 QPainter *p,
const QWidget *w)
const
3268 Q_D(
const QStyleKitStyle);
3271#if QT_CONFIG(slider)
3273 if (
const QStyleOptionSlider *slider = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3274 const auto r = d->resolve(w, QQStyleKitReader::ControlType::Slider, slider->state);
3277 const auto &metrics = *r.metrics;
3278 QRect backgroundRect = opt->rect.marginsRemoved(metrics.margins);
3281 r.drawBackground(backgroundRect, p);
3284 if (slider->subControls & SC_SliderGroove) {
3286 const auto grooveRect = proxy()->subControlRect(CC_Slider, opt, SC_SliderGroove, w);
3287 const auto *indicator = r.indicator();
3288 drawStyledItemRect(indicator, grooveRect, p);
3291 const auto *foreground = indicator ? indicator->foreground() :
nullptr;
3292 if (foreground && foreground->visible()) {
3293 const bool isHorizontal = slider->orientation == Qt::Horizontal;
3294 const qreal availableW = grooveRect.width()
3295 - foreground->leftMargin() - foreground->rightMargin();
3296 const qreal availableH = grooveRect.height()
3297 - foreground->topMargin() - foreground->bottomMargin();
3299 const qreal range = slider->maximum - slider->minimum;
3300 const qreal ratio = range > 0
3301 ? (slider->sliderPosition - slider->minimum) / range
3304 const auto hAlign = foreground->alignment() & Qt::AlignHorizontal_Mask;
3305 const auto vAlign = foreground->alignment() & Qt::AlignVertical_Mask;
3306 const qreal fgW = resolvedWidth(foreground, availableW);
3307 const qreal fgH = resolvedHeight(foreground, availableH);
3308 const qreal fgX = hAlign & Qt::AlignRight
3309 ? grooveRect.left() + foreground->leftMargin() + availableW - fgW
3310 : hAlign & Qt::AlignHCenter
3311 ? grooveRect.left() + foreground->leftMargin() + (availableW - fgW) / 2
3312 : grooveRect.left() + foreground->leftMargin();
3313 const qreal fgY = vAlign & Qt::AlignBottom
3314 ? grooveRect.top() + foreground->topMargin() + availableH - fgH
3315 : vAlign & Qt::AlignVCenter
3316 ? grooveRect.top() + foreground->topMargin() + (availableH - fgH) / 2
3317 : grooveRect.top() + foreground->topMargin();
3319 const qreal minW = foreground->minimumWidth();
3322 const qreal trackW = foreground->fillWidth()
3323 ? minW + ratio * (fgW - minW)
3325 trackRect = QRectF(fgX, fgY, trackW, fgH);
3327 const qreal trackH = foreground->fillHeight()
3328 ? minW + ratio * (fgH - minW)
3330 const qreal trackY = fgY
3331 + (1.0 - ratio) * (foreground->fillHeight() ? fgH - minW : fgH);
3332 trackRect = QRectF(fgX, trackY, fgW, trackH);
3336 const QRect foregroundBox = visualRect(
3337 opt->direction, grooveRect, QRectF(fgX, fgY, fgW, fgH).toAlignedRect());
3338 QPainterStateGuard stateGuard(p);
3339 if (applyDelegateTransform(p, indicator, grooveRect)
3340 && applyDelegateTransform(p, foreground, foregroundBox)) {
3341 drawStyledItemContents(
3343 visualRect(opt->direction, grooveRect, trackRect.toAlignedRect()), p);
3349 if (slider->subControls & SC_SliderHandle) {
3350 QStyleOptionSlider handleOpt(*slider);
3351 handleOpt.rect = subControlRect(CC_Slider, opt, SC_SliderHandle, w);
3352 r.drawHandle(handleOpt.rect, p);
3360 if (
const QStyleOptionSlider *dial = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3361 const auto r = d->resolve(w, QQStyleKitReader::ControlType::Dial, dial->state);
3364 const QRectF backgroundRect = QRectF(opt->rect).marginsRemoved(r.metrics->margins);
3365 r.drawBackground(backgroundRect, p);
3367 const auto *handle = r.handle();
3368 if (handle && handle->visible() && handle->opacity() > 0) {
3369 QPainterStateGuard stateGuard(p);
3370 p->translate(backgroundRect.center());
3371 p->rotate(dialAngle(dial));
3372 p->translate(dialHandleOffset(backgroundRect, handle));
3373 drawStyledItemRect(handle, QRectF(-handle->width() / 2, -handle->height() / 2,
3374 handle->width(), handle->height()), p);
3380#if QT_CONFIG(combobox)
3382 if (
const QStyleOptionComboBox *combo =
3383 qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
3385 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ComboBox, combo->state);
3388 QRect frameRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxFrame, w);
3389 r.drawBackground(frameRect, p);
3392 if (combo->subControls & SC_ComboBoxArrow) {
3393 QStyleOptionComboBox indicatorOpt(*combo);
3394 indicatorOpt.rect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
3395 proxy()->drawPrimitive(PE_IndicatorArrowDown, &indicatorOpt, p, w);
3400 if (
auto *cb = qobject_cast<
const QComboBox *>(w); cb && cb->isEditable()) {
3401 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
3402 QPalette stylePalette;
3403 stylePalette.setColor(QPalette::Text, txt->color());
3404 d->setStylePalette(cb->lineEdit(), stylePalette);
3411#if QT_CONFIG(spinbox)
3413 if (
const QStyleOptionSpinBox *spin = qstyleoption_cast<
const QStyleOptionSpinBox *>(opt)) {
3414 const auto r = d->resolve(w, QQStyleKitReader::ControlType::SpinBox, spin->state);
3417 QRect frameRect = opt->rect.marginsRemoved(r.metrics->margins);
3419 r.drawBackground(frameRect, p);
3421 if (spin->subControls & SC_SpinBoxUp) {
3422 QStyleOptionSpinBox upOpt(*spin);
3423 upOpt.rect = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w);
3424 proxy()->drawPrimitive(PE_IndicatorSpinUp, &upOpt, p, w);
3426 if (spin->subControls & SC_SpinBoxDown) {
3427 QStyleOptionSpinBox downOpt(*spin);
3428 downOpt.rect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
3429 proxy()->drawPrimitive(PE_IndicatorSpinDown, &downOpt, p, w);
3433 if (
auto *sb = qobject_cast<
const QSpinBox *>(w)) {
3434 if (
const auto *txt = r.text(); txt && txt->isDefined(QQSK::Property::Color)) {
3435 QLineEdit *lineEdit = sb->findChild<QLineEdit *>();
3437 QPalette p = lineEdit->palette();
3438 if (p.color(QPalette::Text) != txt->color()) {
3439 p.setColor(QPalette::Text, txt->color());
3440 lineEdit->setPalette(p);
3449#if QT_CONFIG(groupbox)
3451 if (
const QStyleOptionGroupBox *groupBox =
3452 qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
3453 const auto r = d->resolve(w, QQStyleKitReader::ControlType::GroupBox, groupBox->state);
3458 if (groupBox->subControls & SC_GroupBoxFrame) {
3459 QStyleOptionFrame frameOpt;
3460 frameOpt.QStyleOption::operator=(*groupBox);
3461 frameOpt.rect = subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, w);
3462 drawPrimitive(PE_FrameGroupBox, &frameOpt, p, w);
3466 if (groupBox->subControls & SC_GroupBoxLabel && !groupBox->text.isEmpty()) {
3467 const auto *textProps = r.text();
3468 const QFont textFont = r.font();
3469 QRect titleRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w);
3470 drawControlText(textProps, textFont,
3471 titleRect.marginsRemoved(r.metrics->textPadding), groupBox->text,
3472 Qt::TextShowMnemonic, p, Qt::AlignLeft | Qt::AlignVCenter);
3480#if QT_CONFIG(scrollbar)
3482 if (
const auto *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3483 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ScrollBar,
3489 if (scrollbar->subControls & SC_ScrollBarGroove) {
3490 QRect backgroundRect = proxy()->subControlRect(
3491 CC_ScrollBar, opt, SC_ScrollBarGroove, w);
3492 r.drawBackground(backgroundRect, p);
3499 if (scrollbar->subControls & SC_ScrollBarSlider) {
3500 QStyleOptionSlider newScrollbar(*scrollbar);
3501 newScrollbar.rect = proxy()->subControlRect(
3502 CC_ScrollBar, opt, SC_ScrollBarSlider, w);
3503 proxy()->drawControl(CE_ScrollBarSlider, &newScrollbar, p, w);
3509#if QT_CONFIG(toolbutton)
3511 if (
const QStyleOptionToolButton *tool =
3512 qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
3513 const auto r = d->resolve(w, QQStyleKitReader::ControlType::ToolButton, tool->state);
3518 r.drawBackground(opt->rect, p);
3522 & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay))
3523 == QStyleOptionToolButton::MenuButtonPopup
3524 && (tool->subControls & SC_ToolButtonMenu)) {
3525 const QRect menuRect = subControlRect(CC_ToolButton, opt, SC_ToolButtonMenu, w);
3526 r.drawIndicator(menuRect, p);
3530 State bflags = tool->state & ~State_Sunken;
3531 if (bflags & State_AutoRaise) {
3532 if (!(bflags & State_MouseOver) || !(bflags & State_Enabled))
3533 bflags &= ~State_Raised;
3535 if (tool->state & State_Sunken && tool->activeSubControls & SC_ToolButton)
3536 bflags |= State_Sunken;
3537 QStyleOptionToolButton label = *tool;
3538 label.state = bflags;
3539 label.rect = subControlRect(CC_ToolButton, opt, SC_ToolButton, w);
3540 proxy()->drawControl(CE_ToolButtonLabel, &label, p, w);
3548 QCommonStyle::drawComplexControl(cc, opt, p, w);
3560QRect QStyleKitStyle::subControlRect(ComplexControl cc,
const QStyleOptionComplex *opt,
3561 SubControl sc,
const QWidget *w)
const
3563 using QtPrivate::qSaturateRound;
3564 Q_D(
const QStyleKitStyle);
3567#if QT_CONFIG(slider)
3569 if (
const QStyleOptionSlider *slider = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3570 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Slider,
3572 if (!resolved.isValid())
3574 const auto &metrics = *resolved.metrics;
3575 const bool horizontal = slider->orientation == Qt::Horizontal;
3576 QRect contentsRect = opt->rect
3577 .marginsRemoved(metrics.margins)
3578 .marginsRemoved(metrics.padding);
3580 const auto *indicator = resolved.indicator();
3582 return contentsRect;
3584 case SC_SliderGroove: {
3585 const auto availableW = contentsRect.width()
3586 - indicator->leftMargin() - indicator->rightMargin();
3587 const auto availableH = contentsRect.height()
3588 - indicator->topMargin() - indicator->bottomMargin();
3589 const qreal grooveW = resolvedWidth(indicator, availableW);
3590 const qreal grooveH = resolvedHeight(indicator, availableH);
3592 QRectF grooveRect(0, 0, grooveW, grooveH);
3593 const uint rawHAlign = indicator->alignment() & Qt::AlignHorizontal_Mask;
3594 const uint rawVAlign = indicator->alignment() & Qt::AlignVertical_Mask;
3595 const uint hAlign = rawHAlign
3596 ?
static_cast<Qt::Alignment>(rawHAlign)
3598 const uint vAlign = rawVAlign
3599 ?
static_cast<Qt::Alignment>(rawVAlign)
3602 if (hAlign & Qt::AlignLeft) {
3603 grooveRect.moveLeft(contentsRect.x() + indicator->leftMargin());
3604 }
else if (hAlign & Qt::AlignHCenter) {
3605 const qreal availableWidth = contentsRect.width()
3606 - indicator->leftMargin() - indicator->rightMargin();
3607 grooveRect.moveLeft(contentsRect.x() + indicator->leftMargin()
3608 + (availableWidth - grooveW) / 2.0);
3610 grooveRect.moveLeft(contentsRect.x() + contentsRect.width()
3611 - indicator->rightMargin() - grooveW);
3614 if (vAlign & Qt::AlignTop) {
3615 grooveRect.moveTop(contentsRect.y() + indicator->topMargin());
3616 }
else if (vAlign & Qt::AlignVCenter) {
3617 const qreal availableHeight = contentsRect.height()
3618 - indicator->topMargin() - indicator->bottomMargin();
3619 grooveRect.moveTop(contentsRect.y()
3620 + indicator->topMargin()
3621 + (availableHeight - grooveH) / 2.0);
3623 grooveRect.moveTop(contentsRect.y()
3624 + contentsRect.height()
3625 - indicator->bottomMargin() - grooveH);
3627 return visualRect(opt->direction, opt->rect, grooveRect.toAlignedRect());
3629 case SC_SliderHandle: {
3630 const auto *handle = resolved.handle();
3631 if (!handle || !handle->visible())
3632 return contentsRect;
3634 const qreal handleW = resolvedWidth(
3635 handle, contentsRect.width() - handle->leftMargin() - handle->rightMargin());
3636 const qreal handleH = resolvedHeight(
3637 handle, contentsRect.height() - handle->topMargin() - handle->bottomMargin());
3638 QRectF handleRect(0, 0, handleW, handleH);
3640 const int range = qSaturateRound(contentsRect.width()
3641 - handle->leftMargin() - handle->rightMargin() - handleW);
3642 const int sliderPos = QStyle::sliderPositionFromValue(
3643 slider->minimum, slider->maximum, slider->sliderPosition, range,
false);
3644 handleRect.moveLeft(contentsRect.x() + handle->leftMargin() + sliderPos);
3645 handleRect.moveTop(contentsRect.y()
3646 + handle->topMargin() - handle->bottomMargin()
3647 + (contentsRect.height() - handleH) / 2.0);
3649 const int range = qSaturateRound(contentsRect.height()
3650 - handle->topMargin() - handle->bottomMargin() - handleH);
3651 const int sliderPos = QStyle::sliderPositionFromValue(
3652 slider->minimum, slider->maximum, slider->sliderPosition, range,
true);
3653 handleRect.moveLeft(contentsRect.x()
3654 + handle->leftMargin() - handle->rightMargin()
3655 + (contentsRect.width() - handleW) / 2.0);
3656 handleRect.moveTop(contentsRect.y() + handle->topMargin() + sliderPos);
3658 return visualRect(opt->direction, opt->rect, handleRect.toAlignedRect());
3668 if (
const QStyleOptionSlider *dial = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3669 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Dial, opt->state);
3670 if (!resolved.isValid())
3672 const auto &metrics = *resolved.metrics;
3673 const QRectF backgroundRect(opt->rect.marginsRemoved(metrics.margins));
3674 if (sc == SC_DialGroove)
3675 return visualRect(opt->direction, opt->rect, backgroundRect.toAlignedRect());
3676 if (sc != SC_DialHandle) {
3677 return sc == SC_DialTickmarks
3678 ? QRect() : QRectF(opt->rect.marginsRemoved(metrics.padding)).toAlignedRect();
3681 const auto *handle = resolved.handle();
3684 const QPointF offset = dialHandleOffset(backgroundRect, handle);
3685 const QPointF center = backgroundRect.center()
3686 + QTransform().rotate(dialAngle(dial)).map(offset);
3687 const QRectF handleRect(center.x() - handle->width() / 2,
3688 center.y() - handle->height() / 2,
3689 handle->width(), handle->height());
3690 return visualRect(opt->direction, opt->rect, handleRect.toAlignedRect());
3694#if QT_CONFIG(combobox)
3696 if (
const QStyleOptionComboBox *combo =
3697 qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
3698 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::ComboBox, combo->state);
3701 const auto &metrics = *r.metrics;
3702 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3704 case SC_ComboBoxFrame:
3705 return visualRect(opt->direction, opt->rect, frameRect);
3706 case SC_ComboBoxEditField: {
3707 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3708 QRect indicatorRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
3709 const int spacing = metrics.spacing;
3710 const auto *indicator = r.indicator();
3711 const uint indicatorAlign = indicator
3712 ? resolvedAlignment(indicator->alignment(), Qt::AlignRight, Qt::AlignVCenter)
3713 : uint(Qt::AlignRight | Qt::AlignVCenter);
3714 if (indicatorAlign & Qt::AlignLeft) {
3715 contentsRect.setLeft(indicatorRect.right() + spacing);
3716 }
else if (indicatorAlign & Qt::AlignRight) {
3717 contentsRect.setRight(indicatorRect.left() - spacing);
3719 return visualRect(opt->direction, opt->rect, contentsRect);
3721 case SC_ComboBoxArrow: {
3722 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3723 const auto *indicator = r.indicator();
3724 if (!indicator || !indicator->visible())
3727 return visualRect(opt->direction, opt->rect,
3728 delegateRect(indicator, contentsRect, Qt::AlignRight,
3731 case SC_ComboBoxListBoxPopup: {
3732 QRect popupRect = opt->rect;
3733 popupRect.setTop(opt->rect.bottom());
3734 return visualRect(opt->direction, opt->rect, popupRect);
3742#if QT_CONFIG(spinbox)
3744 if (
const QStyleOptionSpinBox *spinBox =
3745 qstyleoption_cast<
const QStyleOptionSpinBox *>(opt)) {
3746 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::SpinBox, spinBox->state);
3749 const auto &metrics = *r.metrics;
3750 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3751 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3753 case SC_SpinBoxFrame:
3754 return visualRect(opt->direction, opt->rect, frameRect);
3755 case SC_SpinBoxEditField: {
3756 QRect upIndicatorRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w);
3757 QRect downIndicatorRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
3758 const int spacing = metrics.spacing;
3759 const auto *upIndicator = r.indicator() ? r.indicator()->first() :
nullptr;
3760 const auto *downIndicator = r.indicator() ? r.indicator()->second() :
nullptr;
3761 const bool hasUpIndicator = upIndicator && upIndicator->visible();
3762 const bool hasDownIndicator = downIndicator && downIndicator->visible();
3763 const uint upAlign = hasUpIndicator
3764 ? resolvedAlignment(upIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
3765 : uint(Qt::AlignLeft | Qt::AlignVCenter);
3766 const uint downAlign = hasDownIndicator
3767 ? resolvedAlignment(downIndicator->alignment(), Qt::AlignLeft, Qt::AlignVCenter)
3768 : uint(Qt::AlignLeft | Qt::AlignVCenter);
3769 if (hasUpIndicator && hasDownIndicator) {
3770 if ((upAlign & Qt::AlignLeft) && (downAlign & Qt::AlignRight)) {
3771 contentsRect.setLeft(upIndicatorRect.right() + spacing);
3772 contentsRect.setRight(downIndicatorRect.left() - spacing);
3773 }
else if ((upAlign & Qt::AlignRight) && (downAlign & Qt::AlignLeft)) {
3774 contentsRect.setRight(upIndicatorRect.left() - spacing);
3775 contentsRect.setLeft(downIndicatorRect.right() + spacing);
3777 }
else if (hasUpIndicator) {
3778 if (upAlign & Qt::AlignLeft) {
3779 contentsRect.setLeft(upIndicatorRect.right() + spacing);
3780 }
else if (upAlign & Qt::AlignRight) {
3781 contentsRect.setRight(upIndicatorRect.left() - spacing);
3783 }
else if (hasDownIndicator) {
3784 if (downAlign & Qt::AlignLeft) {
3785 contentsRect.setLeft(downIndicatorRect.right() + spacing);
3786 }
else if (downAlign & Qt::AlignRight) {
3787 contentsRect.setRight(downIndicatorRect.left() - spacing);
3790 return visualRect(opt->direction, opt->rect, contentsRect);
3792 case SC_SpinBoxUp: {
3793 const auto *upIndicator = r.indicator() ? r.indicator()->first() :
nullptr;
3794 if (!upIndicator || !upIndicator->visible())
3795 return contentsRect;
3797 return visualRect(opt->direction, opt->rect,
3798 delegateRect(upIndicator, contentsRect, Qt::AlignLeft,
3801 case SC_SpinBoxDown: {
3802 const auto *downIndicator = r.indicator() ? r.indicator()->second() :
nullptr;
3803 if (!downIndicator || !downIndicator->visible())
3806 return visualRect(opt->direction, opt->rect,
3807 delegateRect(downIndicator, contentsRect, Qt::AlignLeft,
3816#if QT_CONFIG(groupbox)
3818 if (
const QStyleOptionGroupBox *groupBox =
3819 qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
3820 const auto r = d->resolveLayout(QQStyleKitReader::ControlType::GroupBox,
3824 const auto &metrics = *r.metrics;
3825 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3827 case SC_GroupBoxFrame:
3828 return visualRect(opt->direction, opt->rect, frameRect);
3829 case SC_GroupBoxLabel: {
3830 const int fontHeight = opt->fontMetrics.height();
3831 const int labelHeight = metrics.textPadding.top()
3832 + fontHeight + metrics.textPadding.bottom();
3833 const QRect labelContainer(opt->rect.left(), opt->rect.top(), opt->rect.width(),
3835 return visualRect(opt->direction, opt->rect, labelContainer);
3837 case SC_GroupBoxCheckBox: {
3841 case SC_GroupBoxContents: {
3842 const auto labelHeight = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w)
3844 const auto offset = metrics.padding.top()
3845 + qMax(metrics.margins.top(), labelHeight + metrics.spacing);
3847 opt->rect.left() + metrics.padding.left(), opt->rect.top() + offset,
3848 opt->rect.width() - metrics.padding.left() - metrics.padding.right(),
3849 opt->rect.bottom() - opt->rect.top() - offset - metrics.padding.bottom());
3850 return visualRect(opt->direction, opt->rect, contentsRect);
3858#if QT_CONFIG(scrollbar)
3860 if (
const auto *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
3861 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ScrollBar,
3863 if (!resolved.isValid())
3865 const auto &metrics = *resolved.metrics;
3866 const bool horizontal = scrollbar->orientation == Qt::Horizontal;
3867 const QRectF grooveRect = opt->rect.marginsRemoved(metrics.margins);
3871 case SC_ScrollBarAddLine:
3872 case SC_ScrollBarSubLine:
3873 case SC_ScrollBarSubPage:
3874 case SC_ScrollBarAddPage:
3876 case SC_ScrollBarGroove:
3877 return visualRect(opt->direction, opt->rect, grooveRect.toAlignedRect());
3878 case SC_ScrollBarSlider: {
3879 const auto *indicator = resolved.indicator();
3880 if (!indicator || !indicator->visible())
3882 const QRectF contentsRect = grooveRect.marginsRemoved(metrics.padding);
3884 const qreal availableW = contentsRect.width()
3885 - indicator->leftMargin() - indicator->rightMargin();
3886 const qreal availableH = contentsRect.height()
3887 - indicator->topMargin() - indicator->bottomMargin();
3889 const int totalRange = scrollbar->maximum
3890 - scrollbar->minimum + scrollbar->pageStep;
3891 const qreal ratio = totalRange > 0 ? qreal(scrollbar->pageStep) / totalRange : 1.0;
3895 const qreal sliderW = qMax(
3896 qreal(metrics.indicatorImplicitSize.width()), availableW * ratio);
3897 const qreal sliderH = resolvedHeight(indicator, availableH);
3898 const qreal travelRange = qMax(0.0, availableW - sliderW);
3899 const int sliderPos = QStyle::sliderPositionFromValue(
3900 scrollbar->minimum, scrollbar->maximum, scrollbar->sliderPosition,
3901 int(travelRange), scrollbar->upsideDown);
3902 sliderRect = QRectF(
3903 contentsRect.x() + indicator->leftMargin() + sliderPos,
3904 contentsRect.y() + indicator->topMargin() + (availableH - sliderH) / 2.0,
3907 const qreal sliderH = qMax(
3908 qreal(metrics.indicatorImplicitSize.width()), availableH * ratio);
3909 const qreal sliderW = resolvedWidth(indicator, availableW);
3910 const qreal travelRange = qMax(0.0, availableH - sliderH);
3911 const int sliderPos = QStyle::sliderPositionFromValue(
3912 scrollbar->minimum, scrollbar->maximum, scrollbar->sliderPosition,
3913 int(travelRange), scrollbar->upsideDown);
3914 sliderRect = QRectF(
3915 contentsRect.x() + indicator->leftMargin() + (availableW - sliderW) / 2.0,
3916 contentsRect.y() + indicator->topMargin() + sliderPos, sliderW, sliderH);
3918 return visualRect(opt->direction, opt->rect, sliderRect.toAlignedRect());
3926#if QT_CONFIG(toolbutton)
3928 if (
const auto *tool = qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
3929 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ToolButton,
3931 if (!resolved.isValid())
3933 const auto &metrics = *resolved.metrics;
3934 QRect frameRect = opt->rect.marginsRemoved(metrics.margins);
3936 case SC_ToolButton: {
3937 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3938 const bool hasMenuButton = (tool->features
3939 & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::HasMenu))
3941 const auto *indicator = resolved.indicator();
3942 if (hasMenuButton && indicator && indicator->visible()) {
3943 const QRect menuRect = subControlRect(CC_ToolButton, opt, SC_ToolButtonMenu, w);
3944 const int spacing = metrics.spacing;
3945 const uint indicatorAlign = resolvedAlignment(indicator->alignment(),
3946 Qt::AlignRight, Qt::AlignVCenter);
3947 if (indicatorAlign & Qt::AlignLeft)
3948 contentsRect.setLeft(menuRect.right() + spacing);
3949 else if (indicatorAlign & Qt::AlignRight)
3950 contentsRect.setRight(menuRect.left() - spacing);
3952 return visualRect(opt->direction, opt->rect, contentsRect);
3954 case SC_ToolButtonMenu: {
3955 QRect contentsRect = frameRect.marginsRemoved(metrics.padding);
3957 & (QStyleOptionToolButton::MenuButtonPopup
3958 | QStyleOptionToolButton::PopupDelay))
3959 != QStyleOptionToolButton::MenuButtonPopup) {
3963 const auto *indicator = resolved.indicator();
3964 if (!indicator || !indicator->visible())
3967 return visualRect(opt->direction, opt->rect,
3968 delegateRect(indicator, contentsRect, Qt::AlignRight,
3980 return QCommonStyle::subControlRect(cc, opt, sc, w);
3984QSize QStyleKitStyle::sizeFromContents(ContentsType ct,
const QStyleOption *opt,
3985 const QSize &contentsSize,
const QWidget *widget)
const
3987 Q_D(
const QStyleKitStyle);
3990#if QT_CONFIG(pushbutton)
3993#if QT_CONFIG(toolbutton)
3994 case CT_ToolButton: {
3995 auto controlType = QQStyleKitReader::ControlType::ToolButton;
3996 if (
const auto *buttonOpt = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
3997 controlType = (buttonOpt->features & QStyleOptionButton::Flat)
3998 ? QQStyleKitReader::ControlType::FlatButton
3999 : QQStyleKitReader::ControlType::Button;
4001 const auto resolved = d->resolveLayout(controlType, opt->state);
4002 if (!resolved.isValid())
4005 const auto &metrics = *resolved.metrics;
4006 const QSize contentSize = contentsSize
4007 + QSize(metrics.padding.left() + metrics.padding.right(),
4008 metrics.padding.top() + metrics.padding.bottom())
4009 + QSize(metrics.textPadding.left() + metrics.textPadding.right(),
4010 metrics.textPadding.top() + metrics.textPadding.bottom());
4011 const QSize bgSize = metrics.bgImplicitSize
4012 + QSize(metrics.margins.left() + metrics.margins.right(),
4013 metrics.margins.top() + metrics.margins.bottom());
4014 return contentSize.expandedTo(bgSize);
4018 case CT_RadioButton:
4019 if (
const auto *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
4020 const auto controlType = ct == CT_CheckBox ? QQStyleKitReader::ControlType::CheckBox
4021 : QQStyleKitReader::ControlType::RadioButton;
4022 const auto resolved = d->resolveLayout(controlType, opt->state);
4023 if (!resolved.isValid())
4025 const auto &metrics = *resolved.metrics;
4026 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, btn->text);
4027 const int bgWidth = metrics.bgImplicitSize.width()
4028 + metrics.margins.left() + metrics.margins.right();
4029 const int bgHeight = metrics.bgImplicitSize.height()
4030 + metrics.margins.top() + metrics.margins.bottom();
4031 const int contentWidth = std::max(textSize.width(), contentsSize.width())
4032 + metrics.padding.left() + metrics.padding.right() + metrics.textPadding.left()
4033 + metrics.textPadding.right();
4034 const int contentHeight = std::max(textSize.height(), contentsSize.height())
4035 + metrics.padding.top() + metrics.padding.bottom() + metrics.textPadding.top()
4036 + metrics.textPadding.bottom();
4037 const int indicatorWidth = metrics.indicatorImplicitSize.width()
4038 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
4039 const int indicatorHeight = metrics.indicatorImplicitSize.height()
4040 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
4041 return QSize(std::max({ contentWidth + indicatorWidth + metrics.spacing, bgWidth }),
4042 std::max({ contentHeight, indicatorHeight, bgHeight }));
4045#if QT_CONFIG(itemviews)
4046 case CT_ItemViewItem:
4047 if (
const auto *item = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
4048 const auto resolved = d->resolveLayout(itemViewControlType(opt), opt->state);
4049 if (!resolved.isValid())
4051 const auto &metrics = *resolved.metrics;
4052 const QSize textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, item->text);
4053 const int bgWidth = metrics.bgImplicitSize.width()
4054 + metrics.margins.left() + metrics.margins.right();
4055 const int bgHeight = metrics.bgImplicitSize.height()
4056 + metrics.margins.top() + metrics.margins.bottom();
4057 const int contentWidth = std::max(textSize.width(), contentsSize.width())
4058 + metrics.padding.left() + metrics.padding.right() + metrics.textPadding.left()
4059 + metrics.textPadding.right();
4060 const int contentHeight = std::max(textSize.height(), contentsSize.height())
4061 + metrics.padding.top() + metrics.padding.bottom() + metrics.textPadding.top()
4062 + metrics.textPadding.bottom();
4063 const int indicatorWidth = metrics.indicatorImplicitSize.width()
4064 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
4065 const int indicatorHeight = metrics.indicatorImplicitSize.height()
4066 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
4067 return QSize(std::max({ contentWidth + indicatorWidth + metrics.spacing, bgWidth }),
4068 std::max({ contentHeight, indicatorHeight, bgHeight }));
4072 case CT_ProgressBar:
4073 if (qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
4074 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ProgressBar,
4076 if (!resolved.isValid())
4078 const auto &metrics = *resolved.metrics;
4079 const auto indicatorW = metrics.indicatorImplicitSize.width()
4080 + metrics.indicatorMargins.left()
4081 + metrics.indicatorMargins.right();
4082 const auto indicatorH = metrics.indicatorImplicitSize.height()
4083 + metrics.indicatorMargins.top()
4084 + metrics.indicatorMargins.bottom();
4085 const int bgW = metrics.bgImplicitSize.width()
4086 + metrics.margins.left() + metrics.margins.right();
4087 const int bgH = metrics.bgImplicitSize.height()
4088 + metrics.margins.top() + metrics.margins.bottom();
4090 const int contentW = indicatorW + metrics.padding.left() + metrics.padding.right();
4091 const int contentH = indicatorH + metrics.padding.top() + metrics.padding.bottom();
4092 return QSize(std::max(contentW, bgW), std::max(contentH, bgH));
4096 if (qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
4097 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Slider,
4099 if (!resolved.isValid())
4101 const auto &metrics = *resolved.metrics;
4103 const int bgW = std::max(
4104 metrics.padding.left() + metrics.padding.right()
4105 + metrics.indicatorImplicitSize.width()
4106 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right(),
4107 metrics.bgImplicitSize.width() + metrics.margins.left() + metrics.margins.right());
4108 const int bgH = std::max(
4109 metrics.padding.top() + metrics.padding.bottom()
4110 + metrics.indicatorImplicitSize.height()
4111 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom(),
4112 metrics.bgImplicitSize.height() + metrics.margins.top() + metrics.margins.bottom());
4113 const int handleW = metrics.handleImplicitSize.width()
4114 + metrics.padding.left()
4115 + metrics.padding.right();
4116 const int handleH = metrics.handleImplicitSize.height()
4117 + metrics.padding.top()
4118 + metrics.padding.bottom();
4119 return QSize(std::max(handleW, bgW), std::max(handleH, bgH));
4122#if QT_CONFIG(lineedit)
4124 if (
const auto *lineEdit = qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
4125 QStyleOption lineEditOpt(*lineEdit);
4126 lineEditOpt.state &= ~QStyle::State_Sunken;
4127# if QT_CONFIG(spinbox)
4128 const bool isInSpinBox = widget && qobject_cast<
const QSpinBox *>(widget->parent());
4130 const bool isInSpinBox =
false;
4132 auto controlType = isInSpinBox ? QQStyleKitReader::ControlType::SpinBox
4133 : QQStyleKitReader::ControlType::TextField;
4134 const auto resolved = d->resolveLayout(controlType, lineEditOpt.state);
4135 if (!resolved.isValid())
4137 const auto &metrics = *resolved.metrics;
4141 bgSize = metrics.bgImplicitSize.grownBy(metrics.margins);
4142 const QSize contentSizeWithPadding = contentsSize
4143 .grownBy(metrics.textPadding)
4144 .grownBy(metrics.padding);
4145 return contentSizeWithPadding.expandedTo(bgSize);
4149#if QT_CONFIG(combobox)
4151 if (
const auto *comboBox = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
4152 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ComboBox,
4154 if (!resolved.isValid())
4156 const auto &metrics = *resolved.metrics;
4157 QSize textSize = opt->fontMetrics.size(
4158 Qt::TextShowMnemonic, comboBox->currentText);
4159 if (!comboBox->currentIcon.isNull()) {
4160 textSize.rwidth() += comboBox->iconSize.width() + metrics.spacing;
4161 textSize.setHeight(qMax(textSize.height(), comboBox->iconSize.height()));
4163 const int bgW = metrics.bgImplicitSize.width()
4164 + metrics.margins.left() + metrics.margins.right();
4165 const int bgH = metrics.bgImplicitSize.height()
4166 + metrics.margins.top() + metrics.margins.bottom();
4167 const int contentW = textSize.width()
4168 + metrics.padding.left() + metrics.padding.right()
4169 + metrics.textPadding.left() + metrics.textPadding.right();
4170 const int contentH = textSize.height()
4171 + metrics.padding.top() + metrics.padding.bottom()
4172 + metrics.textPadding.top() + metrics.textPadding.bottom();
4173 const int indicatorW = metrics.indicatorImplicitSize.width()
4174 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
4175 const int indicatorH = metrics.indicatorImplicitSize.height()
4176 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
4177 return QSize(std::max({ contentW + indicatorW + metrics.spacing, bgW }),
4178 std::max({ contentH, indicatorH, bgH }));
4182#if QT_CONFIG(spinbox)
4184 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::SpinBox, opt->state);
4185 if (!resolved.isValid())
4187 const auto &metrics = *resolved.metrics;
4188 const int bgW = metrics.bgImplicitSize.width()
4189 + metrics.margins.left() + metrics.margins.right();
4190 const int bgH = metrics.bgImplicitSize.height()
4191 + metrics.margins.top() + metrics.margins.bottom();
4192 const int contentW = contentsSize.width()
4193 + metrics.padding.left() + metrics.padding.right()
4194 + metrics.textPadding.left() + metrics.textPadding.right();
4195 const int contentH = contentsSize.height()
4196 + metrics.padding.top() + metrics.padding.bottom()
4197 + metrics.textPadding.top() + metrics.textPadding.bottom();
4201 const int indicatorW = (metrics.indicatorImplicitSize.width()
4202 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right()) * 2;
4203 const int indicatorH = metrics.indicatorImplicitSize.height()
4204 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
4205 return QSize(std::max({ contentW + indicatorW + metrics.spacing, bgW }),
4206 std::max({ contentH, indicatorH, bgH }));
4209#if QT_CONFIG(tabbar)
4211 if (qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
4212 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::TabButton,
4214 if (!resolved.isValid())
4216 const auto &m = *resolved.metrics;
4217 const auto bgSize = m.bgImplicitSize.grownBy(m.margins);
4218 const auto contentSizeWithPadding = contentsSize.grownBy(m.padding + m.textPadding);
4219 return contentSizeWithPadding.expandedTo(bgSize);
4223#if QT_CONFIG(tabwidget)
4225 if (qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(opt)) {
4227 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Page, opt->state);
4228 if (!resolved.isValid())
4230 const auto &m = *resolved.metrics;
4231 const auto bgSize = m.bgImplicitSize.grownBy(m.margins);
4232 const auto contentSizeWithPadding = contentsSize.grownBy(m.padding);
4233 return contentSizeWithPadding.expandedTo(bgSize);
4237#if QT_CONFIG(groupbox)
4239 if (
const auto *groupBox = qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
4240 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::GroupBox,
4242 if (!resolved.isValid())
4244 const auto &metrics = *resolved.metrics;
4245 const QSize bgSize = metrics.bgImplicitSize
4246 + QSize(metrics.margins.left() + metrics.margins.right(),
4247 metrics.margins.top() + metrics.margins.bottom());
4248 const QSize contentSize = contentsSize.grownBy(metrics.padding);
4249 const QSize textSize = opt->fontMetrics
4250 .size(Qt::TextShowMnemonic, groupBox->text)
4251 .grownBy(metrics.textPadding);
4252 return textSize.expandedTo(contentSize).expandedTo(bgSize);
4256#if QT_CONFIG(scrollbar)
4258 if (qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
4259 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::ScrollBar, opt->state);
4260 if (!resolved.isValid())
4262 const auto &metrics = *resolved.metrics;
4264 const int iH = metrics.indicatorImplicitSize.height()
4265 + metrics.padding.top() + metrics.padding.bottom()
4266 + metrics.indicatorMargins.top() + metrics.indicatorMargins.bottom();
4267 const int iW = metrics.indicatorImplicitSize.width()
4268 + metrics.padding.left() + metrics.padding.right()
4269 + metrics.indicatorMargins.left() + metrics.indicatorMargins.right();
4270 const int bgH = metrics.bgImplicitSize.height()
4271 + metrics.margins.top() + metrics.margins.bottom();
4272 const int bgW = metrics.bgImplicitSize.width()
4273 + metrics.margins.left() + metrics.margins.right();
4274 return QSize(std::max(iW, bgW), std::max(iH, bgH));
4280 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
4284 const auto menuType = widget && widget->inherits(
"QComboBoxPrivateContainer")
4285 ? QQStyleKitReader::ControlType::Popup
4286 : QQStyleKitReader::ControlType::Menu;
4287 const auto menuResolved = d->resolveLayout(menuType, opt->state);
4289 if (menuResolved.isValid()) {
4290 const auto &mm = *menuResolved.metrics;
4291 minMenuW = mm.bgImplicitSize.width()
4292 + mm.margins.left() + mm.margins.right() - 2 * mm.padding.left();
4295 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
4296 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuSeparator,
4298 if (!resolved.isValid())
4300 const auto &m = *resolved.metrics;
4301 const int bgWidth = m.bgImplicitSize.width()
4302 + m.margins.left() + m.margins.right();
4303 const int bgHeight = m.bgImplicitSize.height()
4304 + m.margins.top() + m.margins.bottom();
4305 return QSize(std::max(bgWidth, minMenuW), bgHeight);
4308 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuItem, opt->state);
4309 if (!resolved.isValid())
4311 const auto &m = *resolved.metrics;
4312 const auto *indicator = resolved.indicator();
4313 const auto *first = indicator ? indicator->first() :
nullptr;
4314 const auto *second = indicator ? indicator->second() :
nullptr;
4317 using QtPrivate::qSaturateRound;
4318 if (first && menuItem->menuHasCheckableItems) {
4319 indicatorW += qSaturateRound(
4320 first->leftMargin() + first->width() + first->rightMargin()) + m.spacing;
4321 indicatorH = std::max(
4322 qSaturateRound(first->topMargin() + first->bottomMargin() + first->height()),
4325 if (second && menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {
4326 indicatorW += qSaturateRound(
4327 second->leftMargin() + second->width() + second->rightMargin()) + m.spacing;
4328 indicatorH = std::max(
4329 qSaturateRound(second->topMargin() + second->bottomMargin() + second->height()),
4332 const int bgH = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
4333 const int iconReserved = menuItem->maxIconWidth > 0
4334 ? proxy()->pixelMetric(PM_SmallIconSize, opt, widget) + m.spacing
4336 const int contentW = contentsSize.width()
4337 + m.padding.left() + m.padding.right()
4338 + m.textPadding.left() + m.textPadding.right()
4339 + indicatorW + iconReserved;
4340 const int contentH = contentsSize.height()
4341 + m.padding.top() + m.padding.bottom()
4342 + m.textPadding.top() + m.textPadding.bottom();
4343 return QSize(std::max(contentW, minMenuW), std::max({ contentH, indicatorH, bgH }));
4347 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::Menu, opt->state);
4348 if (!resolved.isValid())
4350 const auto &m = *resolved.metrics;
4351 const int height = std::max(contentsSize.height(), m.bgImplicitSize.height())
4352 + m.margins.top() + m.margins.bottom();
4353 return QSize(contentsSize.width(), height);
4356#if QT_CONFIG(menubar)
4358 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuBar, opt->state);
4359 if (!resolved.isValid())
4361 const auto &m = *resolved.metrics;
4362 const int bgWidth = m.bgImplicitSize.width() + m.margins.left() + m.margins.right();
4363 const int bgHeight = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
4364 const int contentW = contentsSize.width() + m.padding.left() + m.padding.right();
4365 const int contentH = contentsSize.height() + m.padding.top() + m.padding.bottom();
4366 return QSize(std::max(contentW, bgWidth), std::max(contentH, bgHeight));
4368 case CT_MenuBarItem: {
4369 const auto resolved = d->resolveLayout(QQStyleKitReader::ControlType::MenuBarItem,
4371 if (!resolved.isValid())
4373 const auto &m = *resolved.metrics;
4374 const int bgWidth = m.bgImplicitSize.width() + m.margins.left() + m.margins.right();
4375 const int bgHeight = m.bgImplicitSize.height() + m.margins.top() + m.margins.bottom();
4376 const int contentW = contentsSize.width()
4377 + m.padding.left() + m.padding.right()
4378 + m.textPadding.left() + m.textPadding.right();
4379 const int contentH = contentsSize.height()
4380 + m.padding.top() + m.padding.bottom()
4381 + m.textPadding.top() + m.textPadding.bottom();
4382 return QSize(std::max(contentW, bgWidth), std::max(contentH, bgHeight));
4388 return QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget);