diff --git a/TeXmacs/misc/images/images.qrc b/TeXmacs/misc/images/images.qrc index a6e2005f9b..8275fcccb2 100644 --- a/TeXmacs/misc/images/images.qrc +++ b/TeXmacs/misc/images/images.qrc @@ -5,6 +5,9 @@ ocr-button/right-align.svg ocr-button/ocr.svg + tabpage/add.svg + tabpage/close.svg + ocr-button/left-align-white.svg @@ -12,6 +15,9 @@ ocr-button/right-align-white.svg ocr-button/ocr-white.svg + tabpage/add-white.svg + tabpage/close-white.svg + tutorial/ocr-tutorial.gif tutorial/magic-paste-tutorial.gif diff --git a/TeXmacs/misc/images/tabpage/add-white.svg b/TeXmacs/misc/images/tabpage/add-white.svg new file mode 100644 index 0000000000..601b5477cb --- /dev/null +++ b/TeXmacs/misc/images/tabpage/add-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/TeXmacs/misc/images/tabpage/add.svg b/TeXmacs/misc/images/tabpage/add.svg new file mode 100644 index 0000000000..d4b340345e --- /dev/null +++ b/TeXmacs/misc/images/tabpage/add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/TeXmacs/misc/images/tabpage/close-white.svg b/TeXmacs/misc/images/tabpage/close-white.svg new file mode 100644 index 0000000000..03a88d0a22 --- /dev/null +++ b/TeXmacs/misc/images/tabpage/close-white.svg @@ -0,0 +1 @@ + diff --git a/TeXmacs/misc/images/tabpage/close.svg b/TeXmacs/misc/images/tabpage/close.svg new file mode 100644 index 0000000000..e3182e3e6b --- /dev/null +++ b/TeXmacs/misc/images/tabpage/close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/TeXmacs/misc/themes/liii-night.css b/TeXmacs/misc/themes/liii-night.css index 9a1d0e04c8..2d893d8dc9 100644 --- a/TeXmacs/misc/themes/liii-night.css +++ b/TeXmacs/misc/themes/liii-night.css @@ -354,14 +354,9 @@ QDockWidget::title { ****************************************************************************/ /* Tab Page 基础样式 */ QTMTabPage { - padding: 8px 12px; color: #FFFFFF; background-color: transparent; border: 1px solid transparent; - border-top-left-radius: 10px; - border-top-right-radius: 10px; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; } QTMTabPage:hover { @@ -372,65 +367,35 @@ QTMTabPage:hover { QTMTabPage:checked { background-color: #333333; border: 1px solid #4c4c4c; - border-bottom: none; - border-top-left-radius: 10px; - border-top-right-radius: 10px; color: #FFFFFF; } -QTMTabPage QToolButton#tabpage-close-button { +QTMTabPage QPushButton#tabpage-close-button { background-color: transparent; border: none; - padding: 0; - margin-left: 6px; - border-radius: 4px; - min-width: 20px; - min-height: 20px; - max-width: 20px; - max-height: 20px; - color: #ffffff; -} - -QTMTabPage QToolButton#tabpage-close-button[platform="mac"] { - min-width: 16px; - min-height: 16px; - max-width: 16px; - max-height: 16px; - font-size: 12pt; + qproperty-iconNormal: url(":/tabpage/close-white.svg"); + qproperty-iconHovered: url(":/tabpage/close-white.svg"); } -QTMTabPage QToolButton#tabpage-close-button:hover { +QTMTabPage QPushButton#tabpage-close-button:hover { background-color: #E81123; - color: #FFFFFF; } -QTMTabPage QToolButton#tabpage-close-button:pressed { +QTMTabPage QPushButton#tabpage-close-button:pressed { background-color: #C50F1F; } -QTMTabPageContainer QToolButton#add-tab-button { +QTMTabPageContainer QPushButton#add-tab-button { background-color: transparent; border: none; - color: #FFFFFF; - font-weight: bold; - border-radius: 6px; - padding: 0; - font-size: 12pt; -} - -QTMTabPageContainer QToolButton#add-tab-button[platform="mac"] { - min-width: 20px; - min-height: 20px; - max-width: 20px; - max-height: 20px; - font-size: 11pt; + qproperty-iconNormal: url(":/tabpage/add-white.svg"); } -QTMTabPageContainer QToolButton#add-tab-button:hover { +QTMTabPageContainer QPushButton#add-tab-button:hover { background-color: rgba(255, 255, 255, 0.06); } -QTMTabPageContainer QToolButton#add-tab-button:pressed { +QTMTabPageContainer QPushButton#add-tab-button:pressed { background-color: rgba(255, 255, 255, 0.10); } diff --git a/TeXmacs/misc/themes/liii.css b/TeXmacs/misc/themes/liii.css index 202063396e..f6a4bce6a7 100644 --- a/TeXmacs/misc/themes/liii.css +++ b/TeXmacs/misc/themes/liii.css @@ -344,14 +344,9 @@ QDockWidget::title { ****************************************************************************/ /* Tab Page 基础样式 */ QTMTabPage { - padding: 8px 12px; color: #000000; background-color: transparent; border: 1px solid transparent; - border-top-left-radius: 10px; - border-top-right-radius: 10px; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; } QTMTabPage:hover { @@ -362,63 +357,34 @@ QTMTabPage:hover { QTMTabPage:checked { background-color: #FFFFFF; border: 1px solid #CFCFCF; - border-bottom: none; - border-top-left-radius: 10px; - border-top-right-radius: 10px; } -QTMTabPage QToolButton#tabpage-close-button { +QTMTabPage QPushButton#tabpage-close-button { background-color: transparent; border: none; - padding: 0; - margin-left: 6px; - border-radius: 4px; - min-width: 20px; - min-height: 20px; - max-width: 20px; - max-height: 20px; -} - -QTMTabPage QToolButton#tabpage-close-button[platform="mac"] { - min-width: 16px; - min-height: 16px; - max-width: 16px; - max-height: 16px; - font-size: 12pt; + qproperty-iconNormal: url(":/tabpage/close.svg"); + qproperty-iconHovered: url(":/tabpage/close-white.svg"); } -QTMTabPage QToolButton#tabpage-close-button:hover { +QTMTabPage QPushButton#tabpage-close-button:hover { background-color: #E81123; - color: #FFFFFF; } -QTMTabPage QToolButton#tabpage-close-button:pressed { +QTMTabPage QPushButton#tabpage-close-button:pressed { background-color: #C50F1F; } -QTMTabPageContainer QToolButton#add-tab-button { +QTMTabPageContainer QPushButton#add-tab-button { background-color: transparent; border: none; - color: #2c2c2c; - font-weight: bold; - border-radius: 6px; - padding: 0; - font-size: 12pt; -} - -QTMTabPageContainer QToolButton#add-tab-button[platform="mac"] { - min-width: 20px; - min-height: 20px; - max-width: 20px; - max-height: 20px; - font-size: 11pt; + qproperty-iconNormal: url(":/tabpage/add.svg"); } -QTMTabPageContainer QToolButton#add-tab-button:hover { +QTMTabPageContainer QPushButton#add-tab-button:hover { background-color: rgba(0, 0, 0, 0.08); } -QTMTabPageContainer QToolButton#add-tab-button:pressed { +QTMTabPageContainer QPushButton#add-tab-button:pressed { background-color: rgba(0, 0, 0, 0.12); } diff --git a/TeXmacs/progs/texmacs/menus/tabpage-menu.scm b/TeXmacs/progs/texmacs/menus/tabpage-menu.scm index 8900dc546f..9546de6880 100644 --- a/TeXmacs/progs/texmacs/menus/tabpage-menu.scm +++ b/TeXmacs/progs/texmacs/menus/tabpage-menu.scm @@ -45,6 +45,6 @@ ((balloon (eval `(verbatim ,tab-title)) (eval `(verbatim ,doc-path))) (window-set-view view-win view #t)) ;; #t stansd for focus - ((balloon "✕" "Close") (safely-kill-tabpage-by-url view-win view buf)) + ((balloon "" "Close") (safely-kill-tabpage-by-url view-win view buf)) (eval active?) )))) diff --git a/devel/222_75.md b/devel/222_75.md new file mode 100644 index 0000000000..954261afd1 --- /dev/null +++ b/devel/222_75.md @@ -0,0 +1,78 @@ +# 222_75 TabPage UI 重构:统一跨平台样式并引入 SVG 图标 + +## 如何测试 + +1. 编译:`xmake b stem` +2. 启动 Mogan,确认标签页栏(TabPage Bar)视觉正常。 +3. 确认关闭按钮和添加按钮显示为 SVG 图标(`×` 和 `+`),而非文字或原生按钮。 +4. 确认关闭按钮仅在鼠标 Hover 或标签处于选中状态时显示,移出后隐藏。 +5. 确认启动页(Startup Tab)标签文字居中对齐。 +6. 分别验证亮色/暗色主题下图标颜色正常(亮色主题关闭按钮 hover 变红,暗色主题图标为白色)。 +7. 验证标签页拖拽排序功能正常。 +8. 分别测试 macOS / Windows / Linux 下的标签页高度和按钮尺寸一致性。 + +## 2026/04/28 实现说明 + +### What + +对 TabPage 组件进行全面 UI 重构,将关闭按钮和添加按钮从 `QToolButton` 迁移到 `QWK::WindowButton`,引入 SVG 图标资源,并彻底移除 macOS / Windows / Linux 三平台硬编码差异,实现跨平台样式统一。 + +#### 修改文件 + +**src/Plugins/Qt/QTMTabPage.cpp / hpp** +- 关闭按钮 `m_closeBtn` 和添加按钮 `m_addTabButton` 类型从 `QToolButton*` 改为 `QWK::WindowButton*`。 +- 移除全部 `#ifdef Q_OS_MAC` 分支:包括 `TAB_CONTENT_VERTICAL_OFFSET`、`getScaledSystemBarHeight`、`getScaledSystemButtonHeight`、`getScaledTabCloseButtonSize` 等。 +- DPI 缩放统一使用 `DpiUtils::scaled()`,新增 `getScaledAddButtonHeight()` / `getScaledCloseButtonHeight()` 替代旧函数。 +- 新增 `ADD_BUTTON_SIZE = 20`、`CLOSE_BUTTON_SIZE = 18` 常量。 +- `STARTUP_TAB_MAX_WIDTH_BASE` 区分社区版(`IS_COMMUNITY`)和商业版:120 / 90。 +- 关闭按钮连接逻辑改为 `QPointer` 保护,防止 action 被释放后悬空触发。 +- `paintEvent` 中启动页标签文字改为 `Qt::AlignCenter`,普通标签保持 `Qt::AlignLeft`。 +- `updateCloseButtonVisibility` 增加条件:仅在 `underMouse() || isChecked()` 时显示关闭按钮。 +- 默认构造函数不再调用 `initializeCloseButton()`(`dummyTabPage` 不需要关闭按钮),并在所有访问 `m_closeBtn` 处补充空指针检查。 +- `m_closeBtn` 成员添加 `= nullptr` 默认初始化。 +- `enterEvent` 补充 `override` 关键字。 +- 移除未使用的全局变量 `g_hiddentTabIndex`。 +- `QTMTabPageContainer` 析构函数移除冗余的 `delete m_addTabButton`。 +- `arrangeTabPages` 中 `addButtonWidth` 语义修正:`height()` → `width()`。 + +**src/Plugins/Qt/qt_tm_widget.cpp** +- 标题栏高度统一为 `42 * scale`(macOS 原特殊值 20 移除)。 +- 系统按钮尺寸统一为 `60 * scale` 宽、`42 * scale` 高(移除 macOS 特殊逻辑)。 +- 图标基础尺寸统一为 `16 * scale`(macOS 原特殊值 20 移除)。 +- 工具栏高度统一为 `DpiUtils::scaled(32)`,tab row 高度统一为 `DpiUtils::scaled(38)`(移除 macOS 特殊值 30)。 +- 登录按钮图标尺寸统一为 `12`(macOS 原特殊值 20 移除)。 +- 登出按钮图标尺寸统一为 `20`(macOS 原特殊值 30 移除)。 + +**TeXmacs/misc/themes/liii.css / liii-night.css** +- `QTMTabPage` 移除硬编码 `padding`、`border-radius` 和 `border-bottom: none`,改为由 C++ 动态计算。 +- 关闭按钮和添加按钮选择器从 `QToolButton` 改为 `QPushButton`。 +- 移除全部 `[platform="mac"]` 规则。 +- 关闭按钮通过 `qproperty-iconNormal` / `qproperty-iconHovered` 设置图标(亮色:`close.svg` / `close-white.svg`;暗色:`close-white.svg`)。 +- 添加按钮通过 `qproperty-iconNormal` 设置图标(亮色:`add.svg`;暗色:`add-white.svg`)。 +- 移除关闭按钮的 `min-width`、`max-width`、`margin-left` 等硬编码尺寸。 +- 移除添加按钮的 `font-weight: bold`、`font-size`、`color` 等文字样式。 + +**TeXmacs/misc/images/images.qrc** +- 新增 4 个 SVG 资源文件:`tabpage/add.svg`、`tabpage/close.svg`、`tabpage/add-white.svg`、`tabpage/close-white.svg`。 + +**TeXmacs/misc/images/tabpage/*.svg** +- 新增 4 个 SVG 图标文件,基于 48×48 viewBox,提供亮色/暗色两版。 + +**TeXmacs/progs/texmacs/menus/tabpage-menu.scm** +- 关闭按钮文字从 `"✕"` 改为 `""`(空字符串),因为图标已由 CSS/C++ 接管。 + +### Why + +1. **跨平台统一**:旧代码中 macOS 拥有大量独立分支(标题栏高度、按钮尺寸、字体大小等),维护成本高且视觉不一致。统一后三平台代码完全一致。 +2. **图标化**:关闭按钮和添加按钮从纯文字(`✕`、`+`)升级为 SVG 图标,视觉更现代,且支持亮色/暗色主题自动切换。 +3. **样式解耦**:将 `padding`、`border-radius` 等从 CSS 硬编码移至 C++ 动态计算(通过 `DpiUtils::scaled()`),确保高 DPI 下尺寸正确。 +4. **交互优化**:关闭按钮仅在需要时显示(hover/选中),减少标签页视觉噪音,更接近现代浏览器标签页体验。 +5. **安全性**:`QPointer` 防护避免 action 生命周期问题;空指针检查使 `dummyTabPage` 不初始化关闭按钮的逻辑更安全。 + +### How + +- 引入 `QWK::WindowButton`(已存在于项目中,用于系统标题栏按钮)替代 `QToolButton`,复用其 `iconNormal` / `iconHovered` 属性支持。 +- 新增 `tabpage/` SVG 资源目录,通过 `.qrc` 编译进二进制。 +- CSS 中通过 `qproperty-*` 语法将图标路径与按钮绑定。 +- 全面替换 `int (base * getDPIScaleFactor())` 为 `DpiUtils::scaled(base)`,消除浮点截断误差。 +- 移除 `dummyTabPage` 的关闭按钮初始化,并在所有 `m_closeBtn` 访问点做空指针守卫。 diff --git a/src/Plugins/Qt/QTMTabPage.cpp b/src/Plugins/Qt/QTMTabPage.cpp index d28bb84730..1bf7bb39ce 100644 --- a/src/Plugins/Qt/QTMTabPage.cpp +++ b/src/Plugins/Qt/QTMTabPage.cpp @@ -3,6 +3,7 @@ * MODULE : QTMTabPage.cpp * DESCRIPTION: QT Texmacs tab page classes * COPYRIGHT : (C) 2024 Zhenjun Guo + * 2026 Yifan Lu ******************************************************************************* * This software falls under the GNU general public license version 3 or later. * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE @@ -17,9 +18,13 @@ #include // Base tab widths -constexpr int MAX_TAB_PAGE_WIDTH_BASE = 150; -constexpr int MIN_TAB_PAGE_WIDTH_BASE = 25; -constexpr int STARTUP_TAB_MAX_WIDTH_BASE= 100; +constexpr int MAX_TAB_PAGE_WIDTH_BASE= 150; +constexpr int MIN_TAB_PAGE_WIDTH_BASE= 25; +#ifdef IS_COMMUNITY +constexpr int STARTUP_TAB_MAX_WIDTH_BASE= 120; +#else +constexpr int STARTUP_TAB_MAX_WIDTH_BASE= 90; +#endif // The horizontal padding for tab container (in pixels). #ifdef Q_OS_MAC @@ -28,15 +33,11 @@ const int TAB_CONTAINER_PADDING= 75; const int TAB_CONTAINER_PADDING= 0; #endif -#ifdef Q_OS_MAC -constexpr int TAB_CONTENT_VERTICAL_OFFSET = 4.5; -constexpr int ADD_TAB_BUTTON_VERTICAL_OFFSET= 4; -constexpr int TAB_RIGHT_EXTRA_GAP = 0; -#else constexpr int TAB_CONTENT_VERTICAL_OFFSET = 0; constexpr int ADD_TAB_BUTTON_VERTICAL_OFFSET= 0; constexpr int TAB_RIGHT_EXTRA_GAP = 66; -#endif +constexpr int ADD_BUTTON_SIZE = 20; +constexpr int CLOSE_BUTTON_SIZE = 18; // DPI scaling utility functions (使用 DpiUtils) static double @@ -60,34 +61,13 @@ getScaledStartupTabMaxWidth () { } static int -getScaledSystemBarHeight () { -#ifdef Q_OS_MAC - constexpr int baseHeight= 22; -#else - constexpr int baseHeight= 36; -#endif - return int (baseHeight * getDPIScaleFactor ()); +getScaledAddButtonHeight () { + return DpiUtils::scaled (ADD_BUTTON_SIZE); } static int -getScaledSystemButtonHeight () { -#ifdef Q_OS_MAC - constexpr int baseHeight= 15; -#else - constexpr int baseHeight= 24; -#endif - return int (baseHeight * getDPIScaleFactor ()); -} - -static QSize -getScaledTabCloseButtonSize () { -#ifdef Q_OS_MAC - constexpr int baseSize= 12; -#else - constexpr int baseSize= 20; -#endif - int side= qMax (baseSize, int (baseSize * getDPIScaleFactor ())); - return QSize (side, side); +getScaledCloseButtonHeight () { + return DpiUtils::scaled (CLOSE_BUTTON_SIZE); } /** @@ -106,7 +86,6 @@ getScaledTabCloseButtonSize () { */ int g_tabWidth = -1; int g_pointingIndex = -1; -int g_hiddentTabIndex = -1; url g_mostRecentlyClosedTab = url_none (); url g_mostRecentlyDraggedTab= url_none (); QTMTabPageContainer* g_mostRecentlyDraggedBar= nullptr; @@ -142,29 +121,43 @@ QTMTabPage::QTMTabPage (url p_url, QAction* p_title, QAction* p_closeBtn, p_title->setChecked (p_isActive); setDefaultAction (p_title); setFocusPolicy (Qt::NoFocus); - initializeCloseButton (); - m_closeBtn->setDefaultAction (p_closeBtn); - connect (m_closeBtn, &QToolButton::clicked, this, - [=] () { g_mostRecentlyClosedTab= m_viewUrl; }); + initializeCloseButton (p_closeBtn); + int pad = DpiUtils::scaled (8); + int radius= DpiUtils::scaled (10); + setStyleSheet ( + QString ("padding: %1px; border-radius: %2px;").arg (pad).arg (radius)); + DpiUtils::applyScaledFont (this, 14); } QTMTabPage::QTMTabPage () : m_viewUrl (url_none ()) { setFocusPolicy (Qt::NoFocus); - initializeCloseButton (); + int pad = DpiUtils::scaled (8); + int radius= DpiUtils::scaled (10); + setStyleSheet ( + QString ("padding: %1px; border-radius: %2px;").arg (pad).arg (radius)); + DpiUtils::applyScaledFont (this, 14); } void -QTMTabPage::initializeCloseButton () { - m_closeBtn= new QToolButton (this); +QTMTabPage::initializeCloseButton (QAction* closeAction) { + m_closeBtn= new QWK::WindowButton (this); m_closeBtn->setObjectName ("tabpage-close-button"); m_closeBtn->setFocusPolicy (Qt::NoFocus); -#ifdef Q_OS_MAC - m_closeBtn->setProperty ("platform", "mac"); -#endif - const QSize closeBtnSize= getScaledTabCloseButtonSize (); - m_closeBtn->setFixedSize (closeBtnSize); - const int closeIconSide= qMax (closeBtnSize.width () - 4, 8); - m_closeBtn->setIconSize (QSize (closeIconSide, closeIconSide)); + int closeBtnSize= getScaledCloseButtonHeight (); + m_closeBtn->setMinimumSize (closeBtnSize, closeBtnSize); + m_closeBtn->setFixedSize (closeBtnSize, closeBtnSize); + m_closeBtn->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); + int closeBtnRadius= DpiUtils::scaled (6); + m_closeBtn->setStyleSheet ( + QString ("border-radius: %1px; padding: 0px;").arg (closeBtnRadius)); + if (closeAction) { + QPointer safeAction (closeAction); + connect (m_closeBtn, &QPushButton::clicked, this, [=] () { + if (!safeAction) return; + g_mostRecentlyClosedTab= m_viewUrl; + safeAction->trigger (); + }); + } updateCloseButtonVisibility (); } @@ -183,7 +176,7 @@ QTMTabPage::paintEvent (QPaintEvent*) { // 计算可用的文字绘制区域,需要排除关闭按钮的空间 int leftPadding = 10; - int rightPadding = m_closeBtn->isVisible () + int rightPadding = (m_closeBtn && m_closeBtn->isVisible ()) ? m_closeBtn->width () + 12 : 12; // 如果关闭按钮可见,留出更多空间 int availableWidth= width () - leftPadding - rightPadding; @@ -194,32 +187,28 @@ QTMTabPage::paintEvent (QPaintEvent*) { rightPadding = width () - leftPadding - availableWidth; } - int fontBoxH = fm.height (); - int centeredTop= (getScaledSystemBarHeight () - fontBoxH) / 2; - centeredTop+= TAB_CONTENT_VERTICAL_OFFSET; -#ifdef Q_OS_WIN - // Windows 上字体度量与控件背景的边距叠加,通常需要轻微上移 1px 以达到光学居中 - const int opticalAdjust= -1; -#else - const int opticalAdjust= 0; -#endif - centeredTop+= opticalAdjust; - - QRect textRect (leftPadding, qMax (0, centeredTop), availableWidth, fontBoxH); - // 使用省略号来处理过长的文字 QString elidedText= fm.elidedText (text (), Qt::ElideRight, availableWidth); - p.drawItemText (textRect, Qt::AlignLeft | Qt::AlignVCenter, palette (), + bool isStartup= is_startup_tab_view (m_viewUrl); + int textAlign= isStartup ? Qt::AlignCenter : Qt::AlignLeft; + + QRect textRect (leftPadding, 0, availableWidth, height ()); + if (isStartup) { + textRect= QRect (0, 0, width (), height ()); + } + + p.drawItemText (textRect, textAlign | Qt::AlignVCenter, palette (), isEnabled (), elidedText, QPalette::ButtonText); } void QTMTabPage::resizeEvent (QResizeEvent* e) { + if (!m_closeBtn) return; int w= m_closeBtn->width (); int h= m_closeBtn->height (); int x= e->size ().width () - w - 12; - int y= (getScaledSystemBarHeight () - h) / 2; + int y= (height () - h) / 2; y+= TAB_CONTENT_VERTICAL_OFFSET; m_closeBtn->setGeometry (x, y, w, h); @@ -297,7 +286,9 @@ QTMTabPage::leaveEvent (QEvent* e) { void QTMTabPage::updateCloseButtonVisibility () { - bool shouldShow= !is_startup_tab_view (m_viewUrl); + if (!m_closeBtn) return; + bool shouldShow= + !is_startup_tab_view (m_viewUrl) && (underMouse () || isChecked ()); bool wasVisible= m_closeBtn->isVisible (); m_closeBtn->setVisible (shouldShow); @@ -328,17 +319,16 @@ QTMTabPageContainer::QTMTabPageContainer (QWidget* p_parent) dummyTabPage->hide (); // 创建新增标签页按钮 - m_addTabButton= new QToolButton (this); + m_addTabButton= new QWK::WindowButton (this); m_addTabButton->setObjectName ("add-tab-button"); - m_addTabButton->setText ("+"); - int addButtonSide= getScaledSystemButtonHeight (); + int addButtonSide= getScaledAddButtonHeight (); m_addTabButton->setMinimumSize (addButtonSide, addButtonSide); m_addTabButton->setFixedSize (addButtonSide, addButtonSide); m_addTabButton->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); -#ifdef Q_OS_MAC - m_addTabButton->setProperty ("platform", "mac"); -#endif - connect (m_addTabButton, &QToolButton::clicked, this, + int addBtnRadius= DpiUtils::scaled (6); + m_addTabButton->setStyleSheet ( + QString ("border-radius: %1px; padding: 0px;").arg (addBtnRadius)); + connect (m_addTabButton, &QPushButton::clicked, this, &QTMTabPageContainer::onAddTabClicked); m_addTabButton->hide (); @@ -350,13 +340,7 @@ QTMTabPageContainer::QTMTabPageContainer (QWidget* p_parent) setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Preferred); } -QTMTabPageContainer::~QTMTabPageContainer () { - removeAllTabPages (); - if (m_addTabButton) { - delete m_addTabButton; - m_addTabButton= nullptr; - } -} +QTMTabPageContainer::~QTMTabPageContainer () { removeAllTabPages (); } void QTMTabPageContainer::replaceTabPages (QList* p_src) { @@ -412,7 +396,7 @@ QTMTabPageContainer::arrangeTabPages () { parentWidget () ? parentWidget ()->width () : this->width (); // 动态计算右侧预留空间,防止标签页覆盖系统按钮 double scale = getDPIScaleFactor (); - int buttonWidth= int (46 * scale); // 按钮宽度 + int buttonWidth= int (60 * scale); // 按钮宽度 int buttonCount= 5; // pin, min, max, close,login #ifdef Q_OS_MAC buttonCount= 1; // macOS 仅保留 login @@ -485,11 +469,11 @@ QTMTabPageContainer::arrangeTabPages () { // 设置新增标签页按钮的位置 if (m_addTabButton) { // 将按钮放在最后一个标签页的后面 - int addButtonWidth = m_addTabButton->height (); + int addButtonWidth = m_addTabButton->width (); int addButtonHeight= m_addTabButton->height (); int buttonX = accumWidth; // 调整按钮垂直位置,与系统按钮对齐 - int buttonY= (getScaledSystemBarHeight () - addButtonHeight) / 2; + int buttonY= (m_rowHeight - addButtonHeight) / 2; buttonY+= ADD_TAB_BUTTON_VERTICAL_OFFSET; m_addTabButton->setGeometry (buttonX, buttonY, addButtonWidth, addButtonHeight); @@ -503,7 +487,7 @@ QTMTabPageContainer::arrangeTabPages () { void QTMTabPageContainer::adjustHeight (int p_rowCount) { int h= m_rowHeight * (p_rowCount + 1); - setFixedHeight (h - 2); + setFixedHeight (h); } void @@ -704,7 +688,7 @@ QTMTabPageBar::resizeEvent (QResizeEvent* e) { // 确保容器使用全部可用宽度减去左边的留出的拖拽句柄空间 int availableWidth= size.width () - 7; if (availableWidth > 0 && m_container) { - m_container->setGeometry (7, 0, availableWidth, size.height () - 2); + m_container->setGeometry (7, 0, availableWidth, size.height ()); } } diff --git a/src/Plugins/Qt/QTMTabPage.hpp b/src/Plugins/Qt/QTMTabPage.hpp index 76c6f5186a..64a61c88cf 100644 --- a/src/Plugins/Qt/QTMTabPage.hpp +++ b/src/Plugins/Qt/QTMTabPage.hpp @@ -3,6 +3,7 @@ * MODULE : QTMTabPage.hpp * DESCRIPTION: QT Texmacs tab page classes * COPYRIGHT : (C) 2024 Zhenjun Guo + * 2026 Yifan Lu ******************************************************************************* * This software falls under the GNU general public license version 3 or later. * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE @@ -11,6 +12,7 @@ #ifndef QTMTABPAGE_HPP #define QTMTABPAGE_HPP +#include "windowbutton.hpp" #include #include #include @@ -29,8 +31,8 @@ */ class QTMTabPage : public QToolButton { Q_OBJECT - QToolButton* m_closeBtn; - QPoint m_dragStartPos; + QWK::WindowButton* m_closeBtn= nullptr; + QPoint m_dragStartPos; public: const url m_viewUrl; @@ -48,13 +50,12 @@ public slots: virtual void resizeEvent (QResizeEvent* e) override; virtual void mousePressEvent (QMouseEvent* e) override; virtual void mouseMoveEvent (QMouseEvent* e) override; - virtual void - enterEvent (QEnterEvent* e); // 为了防止和QEvent冲突,不要override + virtual void enterEvent (QEnterEvent* e) override; virtual void leaveEvent (QEvent* e) override; private: void updateCloseButtonVisibility (); - void initializeCloseButton (); + void initializeCloseButton (QAction* closeAction= nullptr); }; /*! QTMTabPageAction is used as a carrier of QTMTabPage widget. @@ -86,7 +87,7 @@ class QTMTabPageContainer : public QWidget { int m_width= 0; bool dragging; QPoint dragPosition; - QToolButton* m_addTabButton; + QWK::WindowButton* m_addTabButton; public: QTMTabPage* dummyTabPage; @@ -143,7 +144,6 @@ class QTMTabPageBar : public QToolBar { // Global variables for tab page management extern int g_tabWidth; extern int g_pointingIndex; -extern int g_hiddentTabIndex; extern url g_mostRecentlyClosedTab; extern url g_mostRecentlyDraggedTab; extern QTMTabPageContainer* g_mostRecentlyDraggedBar; diff --git a/src/Plugins/Qt/qt_tm_widget.cpp b/src/Plugins/Qt/qt_tm_widget.cpp index f2f8cfc559..395ce46f02 100644 --- a/src/Plugins/Qt/qt_tm_widget.cpp +++ b/src/Plugins/Qt/qt_tm_widget.cpp @@ -226,18 +226,17 @@ qt_tm_widget_rep::qt_tm_widget_rep (int mask, command _quit) }; double scale = DpiUtils::scaleFactor (); - int titleBarHeight= int (32 * scale); - int buttonWidth = int (46 * scale); - int buttonHeight = int (32 * scale); - int iconBaseSize = int (12 * scale); - int macosiconSize = int (20 * scale); + int titleBarHeight= int (42 * scale); + int buttonWidth = int (60 * scale); + int buttonHeight = int (42 * scale); + int iconBaseSize = int (16 * scale); #if defined(Q_OS_MAC) // 无边框布局(macOS)- 只显示登录按钮 Q_INIT_RESOURCE (styles); QWK::WindowBar* windowBar= nullptr; windowAgent = nullptr; - setupWindowBar (windowBar, windowAgent, /*minHeight*/ 20, + setupWindowBar (windowBar, windowAgent, /*minHeight*/ titleBarHeight, /*setSafeArea*/ true); #elif defined(Q_OS_WIN) || defined(Q_OS_LINUX) // 无边框布局(Windows / Linux),并使用 /styles 资源中的图标 @@ -348,11 +347,7 @@ qt_tm_widget_rep::qt_tm_widget_rep (int mask, command _quit) loginButton->setFocusPolicy (Qt::NoFocus); loginButton->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); loginButton->setFixedSize (buttonWidth, buttonHeight); -#if defined(Q_OS_MAC) - loginButton->setIconSize (QSize (macosiconSize, macosiconSize)); -#else loginButton->setIconSize (QSize (iconBaseSize, iconBaseSize)); -#endif loginButton->setIconNormal (QIcon (":/window-bar/login.svg")); loginButton->setObjectName ("login-button"); loginButton->setProperty ("system-button", true); @@ -590,12 +585,8 @@ qt_tm_widget_rep::qt_tm_widget_rep (int mask, command _quit) // NOTICE: setFixedHeight must be after setIconSize // TODO: the size of the toolbar should be calculated dynamically { - double scale = retina_scale; - int h = (int) floor (36 * scale + 0.5); - int tabRowHeight= h; -#ifdef Q_OS_MAC - tabRowHeight= (int) floor (30 * scale + 0.5); -#endif + int h = DpiUtils::scaled (32); + int tabRowHeight= DpiUtils::scaled (38); // 工具栏高度相等 mainToolBar->setFixedHeight (h); @@ -2045,13 +2036,8 @@ qt_tm_widget_rep::setupLoginDialog (QWK::LoginDialog* loginDialog) { infoLayout->setSpacing (4); // 登出按钮 - 登录成功后显示(使用图标) - const double logoutScale= DpiUtils::scaleFactor (); -#if defined(Q_OS_MAC) - const int logoutIconSize= int (30 * logoutScale); -#else - const int logoutIconSize= int (20 * logoutScale); -#endif - logoutButton= new QPushButton (); + const int logoutIconSize= DpiUtils::scaled (20); + logoutButton = new QPushButton (); logoutButton->setObjectName ("logout-button"); logoutButton->setIcon (QIcon (":/window-bar/logout.svg")); logoutButton->setToolTip (qt_translate ("Logout")); @@ -2491,13 +2477,8 @@ qt_tm_widget_rep::updateLoginButtonState (bool isLoggedIn, if (!isLoggedIn) { label= qt_translate ("Not logged in"); } -#if defined(Q_OS_MAC) - loginButton->setIconSize ( - QSize (DpiUtils::scaled (20), DpiUtils::scaled (20))); -#else loginButton->setIconSize ( QSize (DpiUtils::scaled (12), DpiUtils::scaled (12))); -#endif // 已登录时不设置文字,只显示图标 QFontMetrics metrics (loginButton->font ());