From e329c29f37416f09da7462f6695d991fdcc32561 Mon Sep 17 00:00:00 2001 From: czyt1988 Date: Sun, 5 Jan 2025 18:05:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8C=89=E9=92=AE=E5=AE=BD?= =?UTF-8?q?=E9=AB=98=E6=AF=94=E8=AE=BE=E7=BD=AE=EF=BC=8C=E5=8F=AF=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E6=8C=89=E9=92=AE=E7=9A=84=E6=9C=80=E5=A4=A7=E5=AE=BD?= =?UTF-8?q?=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SARibbonBar/SARibbonBar.cpp | 32 +++++- src/SARibbonBar/SARibbonBar.h | 4 + src/SARibbonBar/SARibbonToolButton.cpp | 136 +++++++++++++++++-------- src/SARibbonBar/SARibbonToolButton.h | 27 ++--- 4 files changed, 140 insertions(+), 59 deletions(-) diff --git a/src/SARibbonBar/SARibbonBar.cpp b/src/SARibbonBar/SARibbonBar.cpp index 7ee1974..2fac66f 100644 --- a/src/SARibbonBar/SARibbonBar.cpp +++ b/src/SARibbonBar/SARibbonBar.cpp @@ -185,8 +185,8 @@ int SARibbonBar::PrivateData::systemTabBarHeight() const */ int SARibbonBar::PrivateData::calcTabBarHeight() { - int defaultHeight = systemTabBarHeight(); - int fontHeight = q_ptr->fontMetrics().lineSpacing(); // 不要用height,像宋体这种字体,height=12,lineSpacing=14,有些就无法显示 + int defaultHeight = systemTabBarHeight(); + int fontHeight = q_ptr->fontMetrics().lineSpacing(); // 不要用height,像宋体这种字体,height=12,lineSpacing=14,有些就无法显示 int defaultHeight2 = fontHeight * 1.6; if (defaultHeight2 < fontHeight + 10) { defaultHeight2 = fontHeight + 10; // 主要为了满足office2021主题,tab下有个4px的横杠 @@ -1732,7 +1732,33 @@ void SARibbonBar::setEnableWordWrap(bool on) */ bool SARibbonBar::isEnableWordWrap() const { - return SARibbonToolButton::isEnableWordWrap(); + return SARibbonToolButton::isEnableWordWrap(); +} + +/** + * @brief 文本宽度估算时的宽度比高度系数 + * @param fac 系数,默认为1.4,此系数越大,按钮允许的宽度越宽 + * + * 超过此系数的宽度时,开始尝试换行,例如按钮高度为h,如果单行文本的宽度大于h*系数,则按钮将不进行横向拉伸,类似于maxwidth效果 + * + * 此系数和maxwidth取最小值 + */ +void SARibbonBar::setButtonTextEllipsisAspectFactor(qreal fac) +{ + SARibbonToolButton::setTextEllipsisAspectFactor(fac); + updateRibbonGeometry(); +} + +/** + * @brief 文本宽度估算时的宽度比高度系数 + * + * 超过此系数的宽度时,开始尝试换行,例如按钮高度为h,如果单行文本的宽度大于h*系数,则按钮将不进行横向拉伸,类似于maxwidth效果 + * + * 此系数和maxwidth取最小值 + */ +qreal SARibbonBar::buttonTextEllipsisAspectFactor() const +{ + return SARibbonToolButton::textEllipsisAspectFactor(); } /** diff --git a/src/SARibbonBar/SARibbonBar.h b/src/SARibbonBar/SARibbonBar.h index 41e382e..6e7c9c0 100644 --- a/src/SARibbonBar/SARibbonBar.h +++ b/src/SARibbonBar/SARibbonBar.h @@ -326,6 +326,10 @@ class SA_RIBBON_EXPORT SARibbonBar : public QMenuBar void setEnableWordWrap(bool on); bool isEnableWordWrap() const; + // 文本宽度估算时的宽度比高度系数,超过此系数的宽度时,开始尝试换行或者省略号显示 + void setButtonTextEllipsisAspectFactor(qreal fac = 1.4); + qreal buttonTextEllipsisAspectFactor() const; + // 设置pannel的标题栏高度 int pannelTitleHeight() const; void setPannelTitleHeight(int h); diff --git a/src/SARibbonBar/SARibbonToolButton.cpp b/src/SARibbonBar/SARibbonToolButton.cpp index df0e55b..ccba8df 100644 --- a/src/SARibbonBar/SARibbonToolButton.cpp +++ b/src/SARibbonBar/SARibbonToolButton.cpp @@ -15,42 +15,19 @@ #include #include -/** - * @def 定义文字换行时2行文本的矩形高度系数,此系数决定文字区域的高度 - * - * fontMetrics.lineSpacing*系数 = 文本区域高度 - */ -#define SARIBBONTOOLBUTTON_WORDWRAP_TEXT_FACTOR 2.05 - -/** - * @def 定义文字不换行时单行文本的矩形高度系数,此系数决定文字区域的高度 - * - * fontMetrics.lineSpacing*系数 = 文本区域高度 - */ -#define SARIBBONTOOLBUTTON_NOWORDWRAP_TEXT_FACTOR 1.2 - -/** - * @def 定义小按钮的矩形高度系数,此系数决定文字区域的高度 - * - * fontMetrics.lineSpacing*系数 = 文本区域高度 - */ -#define SARIBBONTOOLBUTTON_SMALLBUTTON_TEXT_FACTOR 1.4 - -/** - * @def 文本宽度估算时的宽度比高度系数 - * - * 超过此系数的宽度时,开始尝试换行,例如按钮高度为h,如果单行文本的宽度大于h*系数,则触发换行估算 - */ -#define SARIBBONTOOLBUTTON_WORDWRAP_WIDTH_PER_HEIGHT_RATIO 1.4 - /** * @def 开启此宏会打印一些常见信息 */ +#ifndef SA_RIBBON_TOOLBUTTON_DEBUG_PRINT #define SA_RIBBON_TOOLBUTTON_DEBUG_PRINT 0 +#endif +#ifndef SARIBBONTOOLBUTTON_DEBUG_DRAW #define SARIBBONTOOLBUTTON_DEBUG_DRAW 0 +#endif #if SARIBBONTOOLBUTTON_DEBUG_DRAW +#ifndef SARIBBONTOOLBUTTON_DEBUG_DRAW_RECT #define SARIBBONTOOLBUTTON_DEBUG_DRAW_RECT(p, rect) \ do { \ p.save(); \ @@ -59,10 +36,12 @@ p.drawRect(rect); \ p.restore(); \ } while (0) - +#endif #else +#ifndef SARIBBONTOOLBUTTON_DEBUG_DRAW_RECT #define SARIBBONTOOLBUTTON_DEBUG_DRAW_RECT(p, rect) #endif +#endif namespace SA { @@ -217,8 +196,7 @@ class SARibbonToolButton::PrivateData int textDrawRectHeight, const QString& text, const QFontMetrics& fm, - float widthHeightRatio = SARIBBONTOOLBUTTON_WORDWRAP_WIDTH_PER_HEIGHT_RATIO, - int maxTrycount = 3); + int maxTrycount = 3); QPixmap createIconPixmap(const QStyleOptionToolButton& opt, const QSize& iconsize) const; // 获取文字的对其方式 int getTextAlignment() const; @@ -240,11 +218,56 @@ class SARibbonToolButton::PrivateData QSize mSizeHint; ///< 保存计算好的sizehint bool mIsTextNeedWrap { false }; ///< 标记文字是否需要换行显示 public: - static bool s_enableWordWrap; ///< 在lite模式下是否允许文字换行,如果允许,则图标相对比较小,默认不允许 + /** + * @brief 在lite模式下是否允许文字换行 + * + * 如果允许,则图标相对比较小,默认不允许 + */ + static bool s_enableWordWrap; + + /** + * @brief 这个系数决定了文字换行时2行文本的矩形高度 + * + * 此值应该大于2 + * + * 文本区域高度 = fontMetrics.lineSpacing*系数 + */ + static qreal s_twoLineHeightFactor; + + /** + * @brief 这个系数决定了单行文本的行高度 + * + * 此值应该大于1 + * + * 文本区域高度 = fontMetrics.lineSpacing*系数 + */ + static qreal s_oneLineHeightFactor; + + /** + * @brief 这个系数决定了小按钮文本的行高度 + * + * 此值应该大于1 + * + * 文本区域高度 = fontMetrics.lineSpacing*系数 + */ + static qreal s_smallButtonHeightFactor; + + /** + * @brief 文本宽度估算时的宽度比高度系数 + * + * 超过此系数的宽度时,开始尝试换行,例如按钮高度为h,如果单行文本的宽度大于h*系数,则按钮将不进行横向拉伸,类似于maxwidth效果 + * + * 此系数和maxwidth取最小值 + */ + static qreal s_textEllipsisAspectFactor; }; // 静态参数初始化 -bool SARibbonToolButton::PrivateData::s_enableWordWrap = false; +bool SARibbonToolButton::PrivateData::s_enableWordWrap = false; +qreal SARibbonToolButton::PrivateData::s_twoLineHeightFactor = 2.05; +qreal SARibbonToolButton::PrivateData::s_oneLineHeightFactor = 1.2; +qreal SARibbonToolButton::PrivateData::s_smallButtonHeightFactor = 1.4; +qreal SARibbonToolButton::PrivateData::s_textEllipsisAspectFactor = 1.4; SARibbonToolButton::PrivateData::PrivateData(SARibbonToolButton* p) : q_ptr(p) { @@ -623,13 +646,13 @@ int SARibbonToolButton::PrivateData::calcTextDrawRectHeight(const QStyleOptionTo { if (SARibbonToolButton::LargeButton == mButtonType) { if (isEnableWordWrap()) { - return opt.fontMetrics.lineSpacing() * SARIBBONTOOLBUTTON_WORDWRAP_TEXT_FACTOR + opt.fontMetrics.leading(); + return opt.fontMetrics.lineSpacing() * s_twoLineHeightFactor + opt.fontMetrics.leading(); } else { - return opt.fontMetrics.lineSpacing() * SARIBBONTOOLBUTTON_NOWORDWRAP_TEXT_FACTOR; + return opt.fontMetrics.lineSpacing() * s_oneLineHeightFactor; } } // 小按钮 - return opt.fontMetrics.lineSpacing() * SARIBBONTOOLBUTTON_SMALLBUTTON_TEXT_FACTOR; + return opt.fontMetrics.lineSpacing() * s_smallButtonHeightFactor; } /** @@ -645,12 +668,12 @@ int SARibbonToolButton::PrivateData::estimateLargeButtonTextWidth(int buttonHeig int textDrawRectHeight, const QString& text, const QFontMetrics& fm, - float widthHeightRatio, int maxTrycount) { QSize textSize; - int space = SA_FONTMETRICS_WIDTH(fm, (QLatin1Char(' '))) * 2; - int hintMaxWidth = buttonHeight * widthHeightRatio; ///< 建议的宽度 + int space = SA_FONTMETRICS_WIDTH(fm, (QLatin1Char(' '))) * 2; + int hintMaxWidth = qMin(static_cast< int >(buttonHeight * SARibbonToolButton::PrivateData::s_textEllipsisAspectFactor), + q_ptr->maximumWidth()); ///< 建议的宽度 if (isEnableWordWrap()) { textSize = fm.size(Qt::TextShowMnemonic, text); textSize.setWidth(textSize.width() + space); @@ -709,10 +732,6 @@ int SARibbonToolButton::PrivateData::estimateLargeButtonTextWidth(int buttonHeig // 范围合理,直接返回 return textSize.width(); } - if (textSize.width() > q_ptr->maximumWidth()) { - // 超出了极限,就返回极限 - return q_ptr->maximumWidth(); - } return hintMaxWidth; } @@ -830,7 +849,7 @@ void SARibbonToolButton::mousePressEvent(QMouseEvent* e) d_ptr->mMenuButtonPressed = false; //! 注意这里要用QAbstractButton的mousePressEvent,而不是QToolButton的mousePressEvent //! QToolButton的mousePressEvent主要是为了弹出菜单,这里弹出菜单的方式是不一样的,因此不能执行QToolButton的mousePressEvent - QAbstractButton::mousePressEvent(e); + QToolButton::mousePressEvent(e); } void SARibbonToolButton::mouseReleaseEvent(QMouseEvent* e) @@ -1198,6 +1217,35 @@ bool SARibbonToolButton::isEnableWordWrap() return SARibbonToolButton::PrivateData::s_enableWordWrap; } +/** + * @brief 文本宽度估算时的宽度比高度系数 + * @param fac 系数,默认为1.4,此系数越大,按钮允许的宽度越宽 + * + * 超过此系数的宽度时,开始尝试换行,例如按钮高度为h,如果单行文本的宽度大于h*系数,则按钮将不进行横向拉伸,类似于maxwidth效果 + * + * 此系数和maxwidth取最小值 + */ +void SARibbonToolButton::setTextEllipsisAspectFactor(qreal fac) +{ + if (fac < 0 && qFuzzyIsNull(fac)) { + qWarning() << tr("The TextEllipsisAspectFactor parameter cannot be set to 0 or a negative number"); // cn:textEllipsisAspectFactor不能设置为0或者负数 + fac = 1.0; + } + SARibbonToolButton::PrivateData::s_textEllipsisAspectFactor = fac; +} + +/** + * @brief 文本宽度估算时的宽度比高度系数 + * + * 超过此系数的宽度时,开始尝试换行,例如按钮高度为h,如果单行文本的宽度大于h*系数,则按钮将不进行横向拉伸,类似于maxwidth效果 + * + * 此系数和maxwidth取最小值 + */ +qreal SARibbonToolButton::textEllipsisAspectFactor() +{ + return SARibbonToolButton::PrivateData::s_textEllipsisAspectFactor; +} + bool SARibbonToolButton::event(QEvent* e) { switch (e->type()) { diff --git a/src/SARibbonBar/SARibbonToolButton.h b/src/SARibbonBar/SARibbonToolButton.h index ae2987c..a8c472c 100644 --- a/src/SARibbonBar/SARibbonToolButton.h +++ b/src/SARibbonBar/SARibbonToolButton.h @@ -29,27 +29,30 @@ class SA_RIBBON_EXPORT SARibbonToolButton : public QToolButton explicit SARibbonToolButton(QWidget* parent = nullptr); explicit SARibbonToolButton(QAction* defaultAction, QWidget* parent = nullptr); ~SARibbonToolButton(); - //标记按钮的样式,按钮的样式有不同的渲染方式 + // 标记按钮的样式,按钮的样式有不同的渲染方式 RibbonButtonType buttonType() const; void setButtonType(const RibbonButtonType& buttonType); - //是否是小按钮 + // 是否是小按钮 bool isSmallRibbonButton() const; - //是否是大按钮 + // 是否是大按钮 bool isLargeRibbonButton() const; - //最小尺寸提示 + // 最小尺寸提示 virtual QSize minimumSizeHint() const Q_DECL_OVERRIDE; - //获取间距 + // 获取间距 int spacing() const; - //更新尺寸 + // 更新尺寸 void updateRect(); virtual QSize sizeHint() const Q_DECL_OVERRIDE; public: - //在lite模式下是否允许文字换行 + // 在lite模式下是否允许文字换行 static void setEnableWordWrap(bool on); static bool isEnableWordWrap(); + // 文本宽度估算时的宽度比高度系数,超过此系数的宽度时,开始尝试换行或者省略号显示 + static void setTextEllipsisAspectFactor(qreal fac = 1.4); + static qreal textEllipsisAspectFactor(); protected: virtual void paintEvent(QPaintEvent* e) Q_DECL_OVERRIDE; @@ -61,18 +64,18 @@ class SA_RIBBON_EXPORT SARibbonToolButton : public QToolButton virtual void leaveEvent(QEvent* e) Q_DECL_OVERRIDE; virtual bool hitButton(const QPoint& pos) const Q_DECL_OVERRIDE; virtual bool event(QEvent* e) Q_DECL_OVERRIDE; - //事件改变 - 主要为了捕获字体的改变 + // 事件改变 - 主要为了捕获字体的改变 virtual void changeEvent(QEvent* e) Q_DECL_OVERRIDE; virtual void actionEvent(QActionEvent* e) Q_DECL_OVERRIDE; protected: - //绘制按钮 + // 绘制按钮 virtual void paintButton(QPainter& p, const QStyleOptionToolButton& opt); - //绘制图标 + // 绘制图标 virtual void paintIcon(QPainter& p, const QStyleOptionToolButton& opt, const QRect& iconDrawRect); - //绘制文本 + // 绘制文本 virtual void paintText(QPainter& p, const QStyleOptionToolButton& opt, const QRect& textDrawRect); - //绘制Indicator + // 绘制Indicator virtual void paintIndicator(QPainter& p, const QStyleOptionToolButton& opt, const QRect& indicatorDrawRect); private: