From 45680953bb309a21bd72e1ab393e886f76695f67 Mon Sep 17 00:00:00 2001 From: Noah Davis Date: Fri, 16 Sep 2022 13:35:05 -0400 Subject: [PATCH] KStyle: fix text-only toolbuttons, check icon/text rects accurately Do not use QRect::isEmpty() to check if the rect size is less than or equal to 0x0. It does not work that way. --- kstyle/breezestyle.cpp | 159 +++++++++++++++++++++++------------------ 1 file changed, 88 insertions(+), 71 deletions(-) diff --git a/kstyle/breezestyle.cpp b/kstyle/breezestyle.cpp index 5d3a8def..81cbe2cf 100644 --- a/kstyle/breezestyle.cpp +++ b/kstyle/breezestyle.cpp @@ -4627,17 +4627,25 @@ bool Style::drawToolButtonLabelControl(const QStyleOption *option, QPainter *pai else hasFocus = enabled && !mouseOver && (option->state & (State_HasFocus | State_Sunken)); - const bool hasArrow(toolButtonOption->features & QStyleOptionToolButton::Arrow); - const bool hasIcon(!(hasArrow || toolButtonOption->icon.isNull())); - const bool hasText(!toolButtonOption->text.isEmpty()); - // contents auto contentsRect(rect); - // icon size - const QSize iconSize(toolButtonOption->iconSize); + const auto menuStyle = BreezePrivate::toolButtonMenuArrowStyle(option); + if (menuStyle == BreezePrivate::ToolButtonMenuArrowStyle::InlineLarge) { + // Place contents to the left of the menu arrow. + const auto arrowRect = toolButtonSubControlRect(toolButtonOption, SC_ToolButtonMenu, widget); + contentsRect.setRight(contentsRect.right() - arrowRect.width()); + } - // text size + const auto toolButtonStyle = toolButtonOption->toolButtonStyle; + const bool hasArrow = toolButtonOption->features & QStyleOptionToolButton::Arrow; + bool hasIcon = toolButtonStyle != Qt::ToolButtonTextOnly + && (!toolButtonOption->icon.isNull() || !toolButtonOption->iconSize.isEmpty() || hasArrow); + bool hasText = toolButtonStyle != Qt::ToolButtonIconOnly && !toolButtonOption->text.isEmpty(); + const bool textUnderIcon = hasIcon && hasText && toolButtonStyle == Qt::ToolButtonTextUnderIcon; + + const QSize &availableSize = contentsRect.size(); + const QSize &iconSize = toolButtonOption->iconSize; int textFlags(_mnemonics->textFlags()); const QSize textSize(option->fontMetrics.size(textFlags, toolButtonOption->text)); @@ -4645,46 +4653,55 @@ bool Style::drawToolButtonLabelControl(const QStyleOption *option, QPainter *pai QRect iconRect; QRect textRect; - const auto menuStyle = BreezePrivate::toolButtonMenuArrowStyle(option); - if (menuStyle == BreezePrivate::ToolButtonMenuArrowStyle::InlineLarge) { - // Place contents to the left of the menu arrow. - const auto arrowRect = toolButtonSubControlRect(toolButtonOption, SC_ToolButtonMenu, widget); - contentsRect.setRight(contentsRect.right() - arrowRect.width()); + if (availableSize.isEmpty()) { + hasIcon = false; + hasText = false; } - if (hasText && (!(hasArrow || hasIcon) || toolButtonOption->toolButtonStyle == Qt::ToolButtonTextOnly)) { - // text only + if (hasIcon && !hasText) { // icon only + iconRect = centerRect(contentsRect, iconSize); + } else if (!hasIcon && hasText) { // text only textRect = contentsRect; textFlags |= Qt::AlignCenter; - - } else if ((hasArrow || hasIcon) && (!hasText || toolButtonOption->toolButtonStyle == Qt::ToolButtonIconOnly)) { - // icon only - iconRect = contentsRect; - - } else if (toolButtonOption->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { + } else if (textUnderIcon) { const int contentsHeight(iconSize.height() + textSize.height() + Metrics::ToolButton_ItemSpacing); - iconRect = QRect( - QPoint(contentsRect.left() + (contentsRect.width() - iconSize.width()) / 2, contentsRect.top() + (contentsRect.height() - contentsHeight) / 2), - iconSize); - textRect = QRect(QPoint(contentsRect.left() + (contentsRect.width() - textSize.width()) / 2, iconRect.bottom() + Metrics::ToolButton_ItemSpacing + 1), - textSize); + iconRect = { + QPoint(contentsRect.left() + (contentsRect.width() - iconSize.width()) / 2, + contentsRect.top() + (contentsRect.height() - contentsHeight) / 2), + iconSize + }; + textRect = { + QPoint(contentsRect.left() + (contentsRect.width() - textSize.width()) / 2, + iconRect.bottom() + Metrics::ToolButton_ItemSpacing + 1), + textSize + }; textFlags |= Qt::AlignCenter; - - } else { + } else if (hasIcon && hasText) { const bool leftAlign(widget && widget->property(PropertyNames::toolButtonAlignment).toInt() == Qt::AlignLeft); if (leftAlign) { const int marginWidth(Metrics::Button_MarginWidth + Metrics::Frame_FrameWidth + 1); - iconRect = QRect(QPoint(contentsRect.left() + marginWidth, contentsRect.top() + (contentsRect.height() - iconSize.height()) / 2), iconSize); + iconRect = { + QPoint(contentsRect.left() + marginWidth, + contentsRect.top() + (contentsRect.height() - iconSize.height()) / 2), + iconSize + }; } else { const int contentsWidth(iconSize.width() + textSize.width() + Metrics::ToolButton_ItemSpacing); - iconRect = QRect( - QPoint(contentsRect.left() + (contentsRect.width() - contentsWidth) / 2, contentsRect.top() + (contentsRect.height() - iconSize.height()) / 2), - iconSize); + iconRect = { + QPoint(contentsRect.left() + (contentsRect.width() - contentsWidth) / 2, + contentsRect.top() + (contentsRect.height() - iconSize.height()) / 2), + iconSize + }; } const int padding = (contentsRect.height() - textSize.height()) / 2; - textRect = QRect(QPoint(iconRect.right() + Metrics::ToolButton_ItemSpacing + 1, contentsRect.top() + padding), - QPoint(contentsRect.right(), contentsRect.bottom() - padding)); + textRect = { + QPoint(iconRect.right() + Metrics::ToolButton_ItemSpacing + 1, contentsRect.top() + padding), + QPoint(contentsRect.right(), contentsRect.bottom() - padding) + }; + + // Don't use QRect::isEmpty(). It does not return true if size is 0x0. + hasText = !textRect.size().isEmpty(); // handle right to left layouts iconRect = visualRect(option, iconRect); @@ -4693,50 +4710,50 @@ bool Style::drawToolButtonLabelControl(const QStyleOption *option, QPainter *pai textFlags |= Qt::AlignLeft | Qt::AlignVCenter; } - // make sure there is enough room for icon - if (iconRect.isValid()) - iconRect = centerRect(iconRect, iconSize); - // render arrow or icon - if (hasArrow && iconRect.isValid()) { - QStyleOptionToolButton copy(*toolButtonOption); - copy.rect = iconRect; - switch (toolButtonOption->arrowType) { - case Qt::LeftArrow: - drawPrimitive(PE_IndicatorArrowLeft, ©, painter, widget); - break; - case Qt::RightArrow: - drawPrimitive(PE_IndicatorArrowRight, ©, painter, widget); - break; - case Qt::UpArrow: - drawPrimitive(PE_IndicatorArrowUp, ©, painter, widget); - break; - case Qt::DownArrow: - drawPrimitive(PE_IndicatorArrowDown, ©, painter, widget); - break; - default: - break; - } + if (hasIcon) { + if (hasArrow) { + QStyleOptionToolButton copy(*toolButtonOption); + copy.rect = iconRect; + switch (toolButtonOption->arrowType) { + case Qt::LeftArrow: + drawPrimitive(PE_IndicatorArrowLeft, ©, painter, widget); + break; + case Qt::RightArrow: + drawPrimitive(PE_IndicatorArrowRight, ©, painter, widget); + break; + case Qt::UpArrow: + drawPrimitive(PE_IndicatorArrowUp, ©, painter, widget); + break; + case Qt::DownArrow: + drawPrimitive(PE_IndicatorArrowDown, ©, painter, widget); + break; + default: + break; + } - } else if (hasIcon && iconRect.isValid()) { - // icon state and mode - const QIcon::State iconState(sunken ? QIcon::On : QIcon::Off); - QIcon::Mode iconMode; - if (!enabled) - iconMode = QIcon::Disabled; - else if (!flat && hasFocus) - iconMode = QIcon::Selected; - else if (mouseOver && flat) - iconMode = QIcon::Active; - else - iconMode = QIcon::Normal; + } else { + // icon state and mode + const QIcon::State iconState(sunken ? QIcon::On : QIcon::Off); + QIcon::Mode iconMode; + if (!enabled) + iconMode = QIcon::Disabled; + else if (!flat && hasFocus) + iconMode = QIcon::Selected; + else if (mouseOver && flat) + iconMode = QIcon::Active; + else + iconMode = QIcon::Normal; - const QPixmap pixmap = _helper->coloredIcon(toolButtonOption->icon, toolButtonOption->palette, iconSize, iconMode, iconState); - drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); + const QPixmap pixmap = _helper->coloredIcon(toolButtonOption->icon, + toolButtonOption->palette, + iconSize, iconMode, iconState); + drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); + } } // render text - if (hasText && textRect.isValid()) { + if (hasText) { QPalette::ColorRole textRole(QPalette::ButtonText); if (flat) textRole = QPalette::WindowText;