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 ());