diff --git a/kstyle/breezemetrics.h b/kstyle/breezemetrics.h index e3ff0b6d..87752f80 100644 --- a/kstyle/breezemetrics.h +++ b/kstyle/breezemetrics.h @@ -53,7 +53,6 @@ struct Metrics { static constexpr int MenuItem_ExtraLeftMargin = 4; static constexpr int MenuItem_MarginHeight = 3; static constexpr int MenuItem_ItemSpacing = 4; - static constexpr int MenuItem_SeparatorPadding = 3; static constexpr int MenuItem_AcceleratorSpace = 16; static constexpr int MenuButton_IndicatorWidth = 20; diff --git a/kstyle/breezepropertynames.cpp b/kstyle/breezepropertynames.cpp index 9de69615..672028b2 100644 --- a/kstyle/breezepropertynames.cpp +++ b/kstyle/breezepropertynames.cpp @@ -14,7 +14,6 @@ const char PropertyNames::netWMForceShadow[] = "_KDE_NET_WM_FORCE_SHADOW"; const char PropertyNames::netWMSkipShadow[] = "_KDE_NET_WM_SKIP_SHADOW"; const char PropertyNames::sidePanelView[] = "_kde_side_panel_view"; const char PropertyNames::toolButtonAlignment[] = "_kde_toolButton_alignment"; -const char PropertyNames::menuTitle[] = "_breeze_toolButton_menutitle"; const char PropertyNames::alteredBackground[] = "_breeze_altered_background"; const char PropertyNames::highlightNeutral[] = "_kde_highlight_neutral"; const char PropertyNames::noSeparator[] = "_breeze_no_separator"; diff --git a/kstyle/breezepropertynames.h b/kstyle/breezepropertynames.h index 3125b0ab..64aa351f 100644 --- a/kstyle/breezepropertynames.h +++ b/kstyle/breezepropertynames.h @@ -16,7 +16,6 @@ struct PropertyNames { static const char netWMSkipShadow[]; static const char sidePanelView[]; static const char toolButtonAlignment[]; - static const char menuTitle[]; static const char alteredBackground[]; static const char highlightNeutral[]; static const char noSeparator[]; diff --git a/kstyle/breezestyle.cpp b/kstyle/breezestyle.cpp index 71ad6425..abdf5a54 100644 --- a/kstyle/breezestyle.cpp +++ b/kstyle/breezestyle.cpp @@ -3132,21 +3132,6 @@ QSize Style::pushButtonSizeFromContents(const QStyleOption *option, const QSize return expandSize(size, Metrics::Frame_FrameWidth); } -static QStyleOptionToolButton toolButtonMenuTitleOption(const QStyleOptionToolButton &option) -{ - QStyleOptionToolButton copy = QStyleOptionToolButton(option); - copy.font.setBold(false); - copy.state = Style::State_Enabled; - return copy; -} - -static QFont menuTitleFont(const QStyleOptionToolButton &option) -{ - auto font = option.font; - font.setPointSize(qRound(font.pointSize() * 1.1)); - return font; -} - //______________________________________________________________ QSize Style::toolButtonSizeFromContents(const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const { @@ -3159,12 +3144,6 @@ QSize Style::toolButtonSizeFromContents(const QStyleOption *option, const QSize // copy size QSize size = contentsSize; - if (isMenuTitle(widget)) { - const QStyleOptionToolButton copy = toolButtonMenuTitleOption(*toolButtonOption); - const QFontMetrics fm(menuTitleFont(copy)); - size.setWidth(std::max(size.width(), fm.size(Qt::TextShowMnemonic, copy.text).width())); - } - // get relevant state flags const State &state(option->state); const bool autoRaise(state & State_AutoRaise); @@ -3248,27 +3227,40 @@ QSize Style::menuItemSizeFromContents(const QStyleOption *option, const QSize &c } case QStyleOptionMenuItem::Separator: { - if (menuItemOption->text.isEmpty() && menuItemOption->icon.isNull()) { - return expandSize(QSize(0, 1), Metrics::MenuItem_MarginWidth, Metrics::MenuItem_SeparatorPadding); - - } else { - // build toolbutton option - const QStyleOptionToolButton toolButtonOption(separatorMenuItemOption(menuItemOption, widget)); - const QFontMetrics fm(menuTitleFont(toolButtonOption)); - - // make sure height is large enough for icon and text - const int iconWidth(menuItemOption->maxIconWidth); - const int textHeight(fm.height()); - if (!menuItemOption->icon.isNull()) { - size.setHeight(qMax(size.height(), iconWidth)); + // contentsSize for separators in QMenuPrivate::updateActionRects() is {2,2} + // We choose to override that. + // Have at least 1px for separator line. + int w = 1; + int h = 1; + + // If the menu item is a section, add width for text + // and make height the same as other menu items, plus extra top padding. + if (!menuItemOption->text.isEmpty()) { + auto font = menuItemOption->font; + font.setBold(true); + QFontMetrics fm(font); + QRect textRect = fm.boundingRect({}, Qt::TextSingleLine | Qt::TextHideMnemonic, + menuItemOption->text); + w = qMax(w, textRect.width()); + h = qMax(h, fm.height()); + + if (showIconsInMenuItems()) { + int iconWidth = menuItemOption->maxIconWidth; + if (isQtQuickControl(option, widget)) { + iconWidth = qMax(pixelMetric(PM_SmallIconSize, option, widget), iconWidth); + } + h = qMax(h, iconWidth); } - if (!menuItemOption->text.isEmpty()) { - size.setHeight(qMax(size.height(), textHeight)); - size.setWidth(qMax(size.width(), fm.boundingRect(menuItemOption->text).width())); + + if (menuItemOption->menuHasCheckableItems) { + h = qMax(h, Metrics::CheckBox_Size); } - return sizeFromContents(CT_ToolButton, &toolButtonOption, size, widget); + h = qMax(h, Metrics::MenuButton_IndicatorWidth); + h += Metrics::MenuItem_MarginHeight; // extra top padding } + + return {w + Metrics::MenuItem_MarginWidth * 2, h + Metrics::MenuItem_MarginHeight * 2}; } // for all other cases, return input @@ -5192,45 +5184,63 @@ bool Style::drawMenuItemControl(const QStyleOption *option, QPainter *painter, c return true; } - // copy rect and palette - const auto &rect(option->rect); - const auto &palette(option->palette); + // Size should be from sizeFromContents(CT_MenuItem, ...), + // but with width set to the widest menu item width. + // see QMenuPrivate::updateActionRects() + const auto &rect = option->rect; + const auto &palette = option->palette; + + // store state + const State &state = option->state; + const bool enabled = state & State_Enabled; + const bool selected = enabled && (state & State_Selected); + const bool sunken = enabled && (state & (State_Sunken)); + const bool reverseLayout = option->direction == Qt::RightToLeft; + const bool useStrongFocus = StyleConfigData::menuItemDrawStrongFocus(); // deal with separators if (menuItemOption->menuItemType == QStyleOptionMenuItem::Separator) { - // normal separator - if (menuItemOption->text.isEmpty() && menuItemOption->icon.isNull()) { - auto color(_helper->separatorColor(palette)); - QRect copy(rect); - - if (StyleConfigData::menuOpacity() < 100) { - color = _helper->alphaColor(palette.color(QPalette::WindowText), 0.25); - // don`t overlap with menu border - copy.adjust(1, 0, -1, 0); - } - - _helper->renderSeparator(painter, copy, color); - return true; - + auto contentsRect = rect.adjusted(Metrics::MenuItem_MarginWidth, 0, + -Metrics::MenuItem_MarginWidth, 0); + QColor separatorColor; + if (StyleConfigData::menuOpacity() < 100) { + separatorColor = _helper->alphaColor(palette.color(QPalette::WindowText), 0.25); } else { - /* - * separator can have a title and an icon - * in that case they are rendered as menu title buttons - */ - QStyleOptionToolButton copy(separatorMenuItemOption(menuItemOption, widget)); - renderMenuTitle(©, painter, widget); + separatorColor = _helper->separatorColor(palette); + } - return true; + if (!menuItemOption->text.isEmpty()) { // icon is ignored on purpose + contentsRect.adjust(0, Metrics::MenuItem_MarginHeight, 0, 0); + int flags = visualAlignment(option->direction, Qt::AlignLeft) | Qt::AlignVCenter; + flags |= Qt::TextSingleLine | Qt::TextHideMnemonic | Qt::TextDontClip; + auto font = menuItemOption->font; + font.setBold(true); + QFontMetrics fm(font); + auto textRect = fm.boundingRect(contentsRect, flags, menuItemOption->text); + const auto &labelColor = palette.color(QPalette::Current, QPalette::WindowText); + painter->setFont(font); + painter->setBrush(Qt::NoBrush); + // 0.7 is from Kirigami ListSectionHeader. + // Not using painter->setOpacity() because it disables text antialiasing. + painter->setPen(_helper->alphaColor(labelColor, 0.7)); + painter->drawText(textRect, flags, menuItemOption->text); + // Make spacing between label and line the same as + // the margin from the label to the left menu outline. + // This is intentionally not factored into CT_MenuItem + // size calculations since the line is meant to fill the + // remaining available area after the label has been rendered. + const qreal spacing = pixelMetric(PM_MenuHMargin, option, widget) + + Metrics::MenuItem_MarginWidth - 1; + if (reverseLayout) { + contentsRect.setRight(textRect.left() - spacing); + } else { + contentsRect.setLeft(textRect.right() + spacing); + } } - } - // store state - const State &state(option->state); - const bool enabled(state & State_Enabled); - const bool selected(enabled && (state & State_Selected)); - const bool sunken(enabled && (state & (State_Sunken))); - const bool reverseLayout(option->direction == Qt::RightToLeft); - const bool useStrongFocus(StyleConfigData::menuItemDrawStrongFocus()); + _helper->renderSeparator(painter, contentsRect, separatorColor); + return true; + } // render hover and focus if (useStrongFocus && (selected || sunken)) { @@ -6728,15 +6738,6 @@ bool Style::drawToolButtonComplexControl(const QStyleOptionComplex *option, QPai // detect buttons in tabbar, for which special rendering is needed const bool inTabBar(widget && qobject_cast(widget->parentWidget())); - const bool isMenuTitle(this->isMenuTitle(widget)); - if (isMenuTitle) { - // copy option to adjust state, and set font as not-bold - const QStyleOptionToolButton copy = toolButtonMenuTitleOption(*toolButtonOption); - - // render - renderMenuTitle(©, painter, widget); - return true; - } // copy option and alter palette QStyleOptionToolButton copy(*toolButtonOption); @@ -7441,24 +7442,6 @@ void Style::renderSpinBoxArrow(const SubControl &subControl, const QStyleOptionS _helper->renderArrow(painter, arrowRect, color, orientation); } -//______________________________________________________________________________ -void Style::renderMenuTitle(const QStyleOptionToolButton *option, QPainter *painter, const QWidget *) const -{ - // render a background rect for the title - const auto &palette(option->palette); - QColor bgColor = palette.color(QPalette::Text); - bgColor.setAlphaF(0.04); - const auto separatorColor(_helper->separatorColor(palette)); - _helper->renderMenuFrame(painter, option->rect, bgColor, separatorColor, true); - - // render text in the center of the rect - // icon is discarded on purpose - // make text the same size as a level 4 heading so it looks more title-ish - painter->setFont(menuTitleFont(*option)); - const auto contentsRect = insideMargin(option->rect, Metrics::MenuItem_MarginWidth, (isTabletMode() ? 2 : 1) * Metrics::MenuItem_MarginHeight); - drawItemText(painter, contentsRect, Qt::AlignCenter, palette, true, option->text, QPalette::WindowText); -} - //______________________________________________________________________________ qreal Style::dialAngle(const QStyleOptionSlider *sliderOption, int value) const { @@ -7833,36 +7816,6 @@ bool Style::showIconsOnPushButtons() const return g.readEntry("ShowIconsOnPushButtons", true); } -//____________________________________________________________________ -bool Style::isMenuTitle(const QWidget *widget) const -{ - // check widget - if (!widget) { - return false; - } - - // check property - const QVariant property(widget->property(PropertyNames::menuTitle)); - if (property.isValid()) { - return property.toBool(); - } - - // detect menu toolbuttons - QWidget *parent = widget->parentWidget(); - if (qobject_cast(parent)) { - foreach (auto child, parent->findChildren()) { - if (child->defaultWidget() != widget) { - continue; - } - const_cast(widget)->setProperty(PropertyNames::menuTitle, true); - return true; - } - } - - const_cast(widget)->setProperty(PropertyNames::menuTitle, false); - return false; -} - //____________________________________________________________________ bool Style::hasAlteredBackground(const QWidget *widget) const { diff --git a/kstyle/breezestyle.h b/kstyle/breezestyle.h index 10be6f3b..7f5ceab8 100644 --- a/kstyle/breezestyle.h +++ b/kstyle/breezestyle.h @@ -343,9 +343,6 @@ private: //* spinbox arrows void renderSpinBoxArrow(const SubControl &, const QStyleOptionSpinBox *, QPainter *, const QWidget *) const; - //* menu title - void renderMenuTitle(const QStyleOptionToolButton *, QPainter *, const QWidget *) const; - //* return dial angle based on option and value qreal dialAngle(const QStyleOptionSlider *, int) const; @@ -489,9 +486,6 @@ private: //* return true if icons should be shown on buttons bool showIconsOnPushButtons() const; - //* return true if passed widget is a menu title (KMenu::addTitle) - bool isMenuTitle(const QWidget *) const; - //* return true if passed widget is a menu title (KMenu::addTitle) bool hasAlteredBackground(const QWidget *) const;