diff --git a/TeXmacs/misc/images/images.qrc b/TeXmacs/misc/images/images.qrc
index 207d1c955c..ba5c8e5eca 100644
--- a/TeXmacs/misc/images/images.qrc
+++ b/TeXmacs/misc/images/images.qrc
@@ -19,6 +19,7 @@
llm-chat/send.svg
llm-chat/sidebar.svg
+ llm-chat/addchat.svg
ocr-button/left-align-white.svg
diff --git a/TeXmacs/misc/images/llm-chat/addchat.svg b/TeXmacs/misc/images/llm-chat/addchat.svg
new file mode 100644
index 0000000000..50ceb0d611
--- /dev/null
+++ b/TeXmacs/misc/images/llm-chat/addchat.svg
@@ -0,0 +1,478 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/plugins/lang/dic/en_US/zh_CN.scm b/TeXmacs/plugins/lang/dic/en_US/zh_CN.scm
index ece576238c..53aee08dc4 100644
--- a/TeXmacs/plugins/lang/dic/en_US/zh_CN.scm
+++ b/TeXmacs/plugins/lang/dic/en_US/zh_CN.scm
@@ -1550,6 +1550,7 @@
("new account" "新建账号")
("New Blank Document" "新建空白文档")
("new buffer" "")
+("New chat" "开启新对话")
("new column" "添加一行")
("new document" "新建文档")
("new double page before" "新起双页(在前面)")
diff --git a/devel/1019.md b/devel/1019.md
new file mode 100644
index 0000000000..5d13b88287
--- /dev/null
+++ b/devel/1019.md
@@ -0,0 +1,114 @@
+# [1019] 优化 New chat 按钮及浮球按钮 UI
+
+## 1 相关文档
+- [dddd.md](dddd.md) - 任务文档模板
+- [1018.md](1018.md) - 优化 LLM Chat 侧边栏开关按钮 UI
+
+## 2 任务相关的代码文件
+- `src/Plugins/Qt/qt_chat_tab_widget.cpp`
+- `src/Plugins/Qt/qt_chat_tab_widget.hpp`
+- `TeXmacs/misc/images/llm-chat/addchat.svg`
+- `TeXmacs/misc/images/images.qrc`
+
+## 3 如何测试
+
+### 3.1 确定性测试(单元测试)
+```bash
+xmake b qt_chat_tab_widget_test
+xmake r qt_chat_tab_widget_test
+```
+
+### 3.2 非确定性测试(文档验证)
+```bash
+xmake b stem
+```
+运行后打开 LLM Chat 标签页,验证:
+
+1. **New chat 按钮样式**:
+ - 文本左侧有 addchat.svg 图标(18px)
+ - 按钮居中显示在侧边栏
+ - 固定尺寸 140x36px,pill 形状(圆角 18px)
+ - 无边框,白色背景,无 hover 背景色变化
+ - 有柔和阴影(blur=3, alpha=25, offset=1px)
+ - 鼠标悬停时阴影加深(blur=6, alpha=50, offset=2px)
+
+2. **收起态浮球按钮**:
+ - 点击收缩按钮后侧边栏隐藏
+ - 内容区左上角出现胶囊形容器,包含两个圆球按钮:
+ - 左侧:展开按钮(sidebar.svg)
+ - 右侧:新建聊天按钮(addchat.svg)
+ - 胶囊容器有 4px 内边距和圆角背景
+ - 点击新建聊天按钮可创建新会话
+
+3. **常量提取**:文件顶部所有魔法数字均已提取为 `constexpr` 常量
+
+## 4 如何提交
+
+提交前执行以下最少步骤:
+
+```bash
+xmake b qt_chat_tab_widget_test
+xmake r qt_chat_tab_widget_test
+xmake b stem
+```
+
+## 5 What
+
+优化 LLM Chat 标签页的 New chat 按钮及收起态浮球按钮 UI。
+
+1. **New chat 按钮视觉升级**:
+ - 添加 addchat.svg 图标到文本左侧
+ - 固定尺寸 140x36px,pill 圆角(高度的一半)
+ - 去掉边框和 hover 背景色
+ - 添加 `QGraphicsDropShadowEffect` 阴影效果
+ - 悬停时通过 eventFilter 动态加深阴影(替代背景色变化)
+ - 按钮在侧边栏水平居中
+
+2. **收起态添加浮球新建聊天按钮**:
+ - 在内容区左上角添加圆球新建聊天按钮(与展开按钮并排)
+ - 两个浮球按钮放入统一的胶囊形容器中
+ - 容器有灰色背景、4px 内边距、4px 按钮间距和圆角
+
+3. **提取魔法数字为常量**:
+ - 新增 17 个 `constexpr` 常量:按钮尺寸、阴影参数、间距、圆角等
+ - 删除 7 个不再使用的无用常量
+ - 所有 `DpiUtils::scaled()` 调用均使用命名常量
+
+## 6 Why
+
+1. New chat 按钮原为纯文本且无样式,视觉上不够突出,缺乏现代感
+2. 收起态只有展开按钮,用户需要展开侧边栏才能新建聊天,操作路径长
+3. 代码中存在大量裸魔法数字,不利于维护和 DPI 适配
+
+## 7 How
+
+### 7.1 New chat 按钮
+在 `setup_left_sidebar()` 中:
+- `setIcon(QIcon(":llm-chat/addchat.svg"))` 添加图标
+- `setFixedSize(QSize(140, 36))` 固定尺寸
+- QSS 中 `border: none` 去掉边框,`border-radius: 18px` 形成 pill 形状
+- 去掉 `QPushButton:hover` 背景色规则
+- 创建 `QGraphicsDropShadowEffect`,设置 blur=3、alpha=25、offset_y=1
+- `installEventFilter` 监听 `HoverEnter`/`HoverLeave`,动态调整阴影参数
+- `normalLayout->addWidget(newChatButton_, 0, Qt::AlignHCenter)` 居中
+
+### 7.2 浮球胶囊容器
+在 `setup_right_content()` 中:
+- 创建 `QWidget` 作为容器,使用 `QHBoxLayout` 水平排列两个按钮
+- 容器设置 `#e8e8e8` 背景色和圆角(按钮半径 + 内边距)
+- 两个按钮通过 `setup_floating_button()` 统一创建(透明背景,由容器提供底色)
+- 容器统一显示/隐藏,通过 `move()` 定位到内容区左上角
+
+### 7.3 常量提取
+新增常量示例:
+- `kNewChatButtonHeight = 36`, `kNewChatButtonWidth = 140`
+- `kNewChatShadowBlur = 3`, `kNewChatShadowAlpha = 25`
+- `kNewChatHoverShadowBlur = 6`, `kNewChatHoverShadowAlpha = 50`
+- `kSendButtonSize = 36`, `kSendButtonRadius = 18`
+- `kConversationBtnRadius = 6`, `kModelLabelMinHeight = 20`
+- 等 17 个常量
+
+删除无用常量:
+- `kSendButtonPadY`, `kSendButtonPadX`, `kSendButtonFontPx`
+- `kContentMarginX`, `kTopPanelMaxWidth`, `kInputFrameBorder`
+- `kFloatingNewChatBtnMarginX`
diff --git a/src/Plugins/Qt/qt_chat_tab_widget.cpp b/src/Plugins/Qt/qt_chat_tab_widget.cpp
index 3aec0d0969..0ef1918c8a 100644
--- a/src/Plugins/Qt/qt_chat_tab_widget.cpp
+++ b/src/Plugins/Qt/qt_chat_tab_widget.cpp
@@ -28,6 +28,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -137,14 +138,6 @@ constexpr int kInputLineHeight= 22;
constexpr int kInputDefaultLines= 3;
/// 输入编辑器最大行数。
constexpr int kInputMaxLines= 10;
-/// 发送按钮垂直内边距。
-constexpr int kSendButtonPadY= 6;
-/// 发送按钮水平内边距。
-constexpr int kSendButtonPadX= 16;
-/// 发送按钮字体大小(像素)。
-constexpr int kSendButtonFontPx= 13;
-/// 内容区水平边距。
-constexpr int kContentMarginX= 24;
/// 内容区垂直边距。
constexpr int kContentMarginY= 24;
/// 内容区元素间距。
@@ -153,12 +146,8 @@ constexpr int kContentSpacing= 16;
constexpr int kWelcomeTopOffsetY= 240;
/// 会话模式下顶部占位高度(像素)。
constexpr int kConversationTopOffsetY= 24;
-/// 顶部面板最大宽度(像素)。
-constexpr int kTopPanelMaxWidth= 680;
/// 输入/消息框圆角半径。
constexpr int kInputFrameRadius= 8;
-/// 输入/消息框边框宽度(像素)。
-constexpr int kInputFrameBorder= 1;
/// 输入/消息框内边距。
constexpr int kInputFramePad= 8;
/// 消息展示区最小高度(像素)。
@@ -173,6 +162,71 @@ constexpr int kToggleIconSize= 20;
constexpr int kFloatingBtnMarginX= 12;
/// 浮球展开按钮垂直边距(像素)。
constexpr int kFloatingBtnMarginY= 130;
+/// 浮球容器内边距(像素)。
+constexpr int kFloatingContainerPad= 4;
+/// 浮球按钮间距(像素)。
+constexpr int kFloatingBtnSpacing= 4;
+/// New chat 按钮图标尺寸(像素)。
+constexpr int kNewChatIconSize= 18;
+/// New chat 按钮固定高度(像素)。
+constexpr int kNewChatButtonHeight= 36;
+/// New chat 按钮固定宽度(像素)。
+constexpr int kNewChatButtonWidth= 140;
+/// New chat 按钮阴影模糊半径(像素)。
+constexpr int kNewChatShadowBlur= 3;
+/// New chat 按钮阴影不透明度(0-255)。
+constexpr int kNewChatShadowAlpha= 25;
+/// New chat 按钮阴影垂直偏移(像素)。
+constexpr int kNewChatShadowOffsetY= 1;
+/// New chat 按钮悬停阴影模糊半径(像素)。
+constexpr int kNewChatHoverShadowBlur= 6;
+/// New chat 按钮悬停阴影不透明度(0-255)。
+constexpr int kNewChatHoverShadowAlpha= 50;
+/// New chat 按钮悬停阴影垂直偏移(像素)。
+constexpr int kNewChatHoverShadowOffsetY= 2;
+/// 多选操作栏元素间距(像素)。
+constexpr int kMultiSelectSpacing= 4;
+/// 会话项布局间距(像素)。
+constexpr int kSessionItemSpacing= 4;
+/// 模型标签最小高度(像素)。
+constexpr int kModelLabelMinHeight= 20;
+/// 模型标签圆角半径(像素)。
+constexpr int kModelLabelRadius= 4;
+/// 发送按钮图标尺寸(像素)。
+constexpr int kSendIconSize= 24;
+/// 发送按钮尺寸(像素)。
+constexpr int kSendButtonSize= 36;
+/// 发送按钮圆角半径(像素)。
+constexpr int kSendButtonRadius= 18;
+/// 会话按钮圆角半径(像素)。
+constexpr int kConversationBtnRadius= 6;
+/// 输入框高度检查间隔(毫秒)。
+constexpr int kInputHeightCheckIntervalMs= 100;
+/// 菜单栏固定高度(像素)。
+constexpr int kMenuBarHeight= 108;
+
+/**
+ * @brief 创建统一风格的浮球按钮(圆形、无边框、灰色背景)。
+ */
+QPushButton*
+setup_floating_button (QWidget* parent, const QString& objectName,
+ const QString& iconPath) {
+ QPushButton* btn= new QPushButton (parent);
+ btn->setObjectName (objectName);
+ btn->setFocusPolicy (Qt::NoFocus);
+ btn->setCursor (Qt::PointingHandCursor);
+ btn->setIcon (QIcon (iconPath));
+ btn->setIconSize (QSize (DpiUtils::scaled (kToggleIconSize),
+ DpiUtils::scaled (kToggleIconSize)));
+ btn->setFixedSize (DpiUtils::scaled (kToggleBtnSize),
+ DpiUtils::scaled (kToggleBtnSize));
+ btn->setStyleSheet (
+ QString ("QPushButton { border: none; border-radius: %1px; "
+ "background-color: transparent; } "
+ "QPushButton:hover { background-color: #d0d0d0; }")
+ .arg (DpiUtils::scaled (kToggleBtnSize / 2)));
+ return btn;
+}
} // namespace
@@ -220,6 +274,7 @@ QTChatTabWidget::QTChatTabWidget (QWidget* parent)
archiveListWidget_ (nullptr), archiveListLayout_ (nullptr),
archiveCollapsed_ (true), newChatButton_ (nullptr),
collapseButton_ (nullptr), floatingExpandBtn_ (nullptr),
+ floatingNewChatBtn_ (nullptr), floatingBtnContainer_ (nullptr),
sidebarNormalContent_ (nullptr), conversationStack_ (nullptr),
activeConversation_ (nullptr), sidebarCollapsed_ (false),
sidebarExpandedWidth_ (0), chatMenuToolBar_ (nullptr),
@@ -325,20 +380,40 @@ QTChatTabWidget::setup_left_sidebar (QVBoxLayout* sidebarLayout) {
normalLayout->addWidget (headerWidget);
// New chat 按钮
- newChatButton_= new QPushButton ("New chat", normalContent);
+ newChatButton_= new QPushButton (qt_translate ("New chat"), normalContent);
newChatButton_->setObjectName ("chat-tab-new-btn");
newChatButton_->setFocusPolicy (Qt::NoFocus);
newChatButton_->setCursor (Qt::PointingHandCursor);
DpiUtils::applyScaledFont (newChatButton_, kNavButtonFontPx);
- newChatButton_->setStyleSheet (QString ("padding: %1px %2px;")
- .arg (DpiUtils::scaled (kNavButtonPadY))
- .arg (DpiUtils::scaled (kNavButtonPadX)));
+ newChatButton_->setIcon (QIcon (":llm-chat/addchat.svg"));
+ newChatButton_->setIconSize (QSize (DpiUtils::scaled (kNewChatIconSize),
+ DpiUtils::scaled (kNewChatIconSize)));
+ newChatButton_->setFixedSize (
+ QSize (DpiUtils::scaled (kNewChatButtonWidth),
+ DpiUtils::scaled (kNewChatButtonHeight)));
+ newChatButton_->setStyleSheet (
+ QString ("QPushButton { text-align: center; border: none; "
+ "border-radius: %1px; padding: %2px %3px; "
+ "background-color: #ffffff; color: #333333; }")
+ .arg (DpiUtils::scaled (kNewChatButtonHeight / 2))
+ .arg (DpiUtils::scaled (kNavButtonPadY))
+ .arg (DpiUtils::scaled (kNavButtonPadX)));
+
+ QGraphicsDropShadowEffect* newChatShadow=
+ new QGraphicsDropShadowEffect (newChatButton_);
+ newChatShadow->setBlurRadius (DpiUtils::scaled (kNewChatShadowBlur));
+ newChatShadow->setColor (QColor (0, 0, 0, kNewChatShadowAlpha));
+ newChatShadow->setOffset (0, DpiUtils::scaled (kNewChatShadowOffsetY));
+ newChatButton_->setGraphicsEffect (newChatShadow);
+
+ newChatButton_->setAttribute (Qt::WA_Hover);
+ newChatButton_->installEventFilter (this);
connect (newChatButton_, &QPushButton::clicked, this, [this] () {
string model=
as_string (call ("chat-tab-session-select-model", string ("")));
create_new_conversation_with_model (model);
});
- normalLayout->addWidget (newChatButton_);
+ normalLayout->addWidget (newChatButton_, 0, Qt::AlignHCenter);
conversationCountLabel_= new QLabel ("Conversations (0)", normalContent);
conversationCountLabel_->setObjectName ("chat-tab-conversation-count");
@@ -369,7 +444,7 @@ QTChatTabWidget::setup_left_sidebar (QVBoxLayout* sidebarLayout) {
multiSelectBar_->setObjectName ("chat-tab-multi-select-bar");
QHBoxLayout* multiSelectLayout= new QHBoxLayout (multiSelectBar_);
multiSelectLayout->setContentsMargins (0, 0, 0, 0);
- multiSelectLayout->setSpacing (DpiUtils::scaled (4));
+ multiSelectLayout->setSpacing (DpiUtils::scaled (kMultiSelectSpacing));
QPushButton* cancelSelectBtn= new QPushButton ("取消", multiSelectBar_);
cancelSelectBtn->setObjectName ("chat-tab-cancel-select-btn");
@@ -547,27 +622,43 @@ QTChatTabWidget::setup_right_content (QHBoxLayout* mainLayout) {
mainLayout->addWidget (content, 1);
- // 浮球展开按钮(侧边栏收起时显示在内容区左上角)
- QPushButton* floatingBtn= new QPushButton (this);
- floatingBtn->setObjectName ("chat-tab-floating-expand-btn");
- floatingBtn->setFocusPolicy (Qt::NoFocus);
- floatingBtn->setCursor (Qt::PointingHandCursor);
- floatingBtn->setIcon (QIcon (":llm-chat/sidebar.svg"));
- floatingBtn->setIconSize (QSize (DpiUtils::scaled (kToggleIconSize),
- DpiUtils::scaled (kToggleIconSize)));
- floatingBtn->setFixedSize (DpiUtils::scaled (kToggleBtnSize),
- DpiUtils::scaled (kToggleBtnSize));
- floatingBtn->setStyleSheet (
- QString ("QPushButton { border: none; border-radius: %1px; "
- "background-color: #e8e8e8; } "
- "QPushButton:hover { background-color: #d0d0d0; }")
- .arg (DpiUtils::scaled (kToggleBtnSize / 2)));
+ // 浮球按钮容器(侧边栏收起时显示在内容区左上角)
+ QWidget* floatingContainer= new QWidget (this);
+ floatingContainer->setObjectName ("chat-tab-floating-container");
+ QHBoxLayout* floatingLayout= new QHBoxLayout (floatingContainer);
+ floatingLayout->setContentsMargins (DpiUtils::scaled (kFloatingContainerPad),
+ DpiUtils::scaled (kFloatingContainerPad),
+ DpiUtils::scaled (kFloatingContainerPad),
+ DpiUtils::scaled (kFloatingContainerPad));
+ floatingLayout->setSpacing (DpiUtils::scaled (kFloatingBtnSpacing));
+ floatingContainer->setStyleSheet (
+ QString ("QWidget#chat-tab-floating-container { "
+ "background-color: #e8e8e8; border-radius: %1px; }")
+ .arg (DpiUtils::scaled (kToggleBtnSize / 2 + kFloatingContainerPad)));
+
+ QPushButton* floatingBtn=
+ setup_floating_button (floatingContainer, "chat-tab-floating-expand-btn",
+ ":llm-chat/sidebar.svg");
connect (floatingBtn, &QPushButton::clicked, this,
[this] () { toggle_sidebar (); });
- floatingBtn->move (DpiUtils::scaled (kFloatingBtnMarginX),
- DpiUtils::scaled (kFloatingBtnMarginY));
- floatingBtn->hide ();
+ floatingLayout->addWidget (floatingBtn);
floatingExpandBtn_= floatingBtn;
+
+ QPushButton* floatingNewBtn= setup_floating_button (
+ floatingContainer, "chat-tab-floating-new-btn", ":llm-chat/addchat.svg");
+ connect (floatingNewBtn, &QPushButton::clicked, this, [this] () {
+ string model=
+ as_string (call ("chat-tab-session-select-model", string ("")));
+ create_new_conversation_with_model (model);
+ });
+ floatingLayout->addWidget (floatingNewBtn);
+ floatingNewChatBtn_= floatingNewBtn;
+
+ floatingContainer->adjustSize ();
+ floatingContainer->move (DpiUtils::scaled (kFloatingBtnMarginX),
+ DpiUtils::scaled (kFloatingBtnMarginY));
+ floatingContainer->hide ();
+ floatingBtnContainer_= floatingContainer;
}
/**
@@ -616,9 +707,11 @@ QTChatTabWidget::create_conversation (const QString& title) {
panel->modelLabel->setAlignment (Qt::AlignCenter);
DpiUtils::applyScaledFont (panel->modelLabel, kNavTitleFontPx);
panel->modelLabel->setStyleSheet (
- "color: #888888; padding: 2px 8px; background-color: #f0f0f0; "
- "border-radius: 4px;");
- panel->modelLabel->setMinimumHeight (DpiUtils::scaled (20));
+ QString ("color: #888888; padding: 2px %1px; background-color: #f0f0f0; "
+ "border-radius: %2px;")
+ .arg (DpiUtils::scaled (kNavButtonPadX))
+ .arg (DpiUtils::scaled (kModelLabelRadius)));
+ panel->modelLabel->setMinimumHeight (DpiUtils::scaled (kModelLabelMinHeight));
topLayout->addWidget (panel->modelLabel, 0, Qt::AlignHCenter);
panel->messageWidget= texmacs_input_widget (
@@ -703,16 +796,16 @@ QTChatTabWidget::create_conversation (const QString& title) {
panel->sendButton->setFocusPolicy (Qt::NoFocus);
panel->sendButton->setCursor (Qt::PointingHandCursor);
panel->sendButton->setIcon (QIcon (":llm-chat/send.svg"));
- int sendIconSize= DpiUtils::scaled (24);
+ int sendIconSize= DpiUtils::scaled (kSendIconSize);
panel->sendButton->setIconSize (QSize (sendIconSize, sendIconSize));
- panel->sendButton->setFixedSize (DpiUtils::scaled (36),
- DpiUtils::scaled (36));
+ panel->sendButton->setFixedSize (DpiUtils::scaled (kSendButtonSize),
+ DpiUtils::scaled (kSendButtonSize));
panel->sendButton->setStyleSheet (
QString ("QPushButton { border: none; border-radius: %1px; "
" background-color: transparent; }"
"QPushButton:hover { background-color: #f0f0f0; }"
"QPushButton:pressed { background-color: #e0e0e0; }")
- .arg (DpiUtils::scaled (18)));
+ .arg (DpiUtils::scaled (kSendButtonRadius)));
connect (panel->sendButton, &QPushButton::clicked, this,
[this, panel] () { handle_send (panel); });
btnLayout->addWidget (panel->sendButton);
@@ -721,7 +814,7 @@ QTChatTabWidget::create_conversation (const QString& title) {
inputAreaLayout->addWidget (inputFrame, 0);
QTimer* inputHeightTimer= new QTimer (inputFrame);
- inputHeightTimer->setInterval (100);
+ inputHeightTimer->setInterval (kInputHeightCheckIntervalMs);
connect (inputHeightTimer, &QTimer::timeout, this,
[this, panel] () { adjust_input_height (panel); });
inputHeightTimer->start ();
@@ -739,7 +832,7 @@ QTChatTabWidget::create_conversation (const QString& title) {
panel->itemWidget->setObjectName ("chat-tab-session-item");
QHBoxLayout* itemLayout= new QHBoxLayout (panel->itemWidget);
itemLayout->setContentsMargins (0, 0, 0, 0);
- itemLayout->setSpacing (DpiUtils::scaled (4));
+ itemLayout->setSpacing (DpiUtils::scaled (kSessionItemSpacing));
panel->selectCheckBox= new QCheckBox (panel->itemWidget);
panel->selectCheckBox->setObjectName ("chat-tab-select-checkbox");
@@ -766,7 +859,7 @@ QTChatTabWidget::create_conversation (const QString& title) {
"#ffffff; } "
"QPushButton:checked { background-color: #e8eefc; "
"border-color: #9bb3ff; font-weight: 600; }")
- .arg (DpiUtils::scaled (6))
+ .arg (DpiUtils::scaled (kConversationBtnRadius))
.arg (DpiUtils::scaled (kNavButtonPadY))
.arg (DpiUtils::scaled (kNavButtonPadX)));
connect (panel->sidebarButton, &QPushButton::clicked, this,
@@ -1201,16 +1294,16 @@ QTChatTabWidget::toggle_sidebar () {
if (!sidebarWidget_) return;
if (sidebarCollapsed_) {
- if (floatingExpandBtn_) floatingExpandBtn_->hide ();
+ if (floatingBtnContainer_) floatingBtnContainer_->hide ();
sidebarWidget_->show ();
sidebarCollapsed_= false;
}
else {
sidebarWidget_->hide ();
- if (floatingExpandBtn_) {
- floatingExpandBtn_->move (DpiUtils::scaled (kFloatingBtnMarginX),
- DpiUtils::scaled (kFloatingBtnMarginY));
- floatingExpandBtn_->show ();
+ if (floatingBtnContainer_) {
+ floatingBtnContainer_->move (DpiUtils::scaled (kFloatingBtnMarginX),
+ DpiUtils::scaled (kFloatingBtnMarginY));
+ floatingBtnContainer_->show ();
}
sidebarCollapsed_= true;
}
@@ -1476,6 +1569,26 @@ QTChatTabWidget::eventFilter (QObject* watched, QEvent* event) {
}
}
}
+ if (watched == newChatButton_) {
+ if (event->type () == QEvent::HoverEnter) {
+ if (QGraphicsDropShadowEffect* effect=
+ qobject_cast (
+ newChatButton_->graphicsEffect ())) {
+ effect->setBlurRadius (DpiUtils::scaled (kNewChatHoverShadowBlur));
+ effect->setColor (QColor (0, 0, 0, kNewChatHoverShadowAlpha));
+ effect->setOffset (0, DpiUtils::scaled (kNewChatHoverShadowOffsetY));
+ }
+ }
+ else if (event->type () == QEvent::HoverLeave) {
+ if (QGraphicsDropShadowEffect* effect=
+ qobject_cast (
+ newChatButton_->graphicsEffect ())) {
+ effect->setBlurRadius (DpiUtils::scaled (kNewChatShadowBlur));
+ effect->setColor (QColor (0, 0, 0, kNewChatShadowAlpha));
+ effect->setOffset (0, DpiUtils::scaled (kNewChatShadowOffsetY));
+ }
+ }
+ }
return QWidget::eventFilter (watched, event);
}
@@ -1487,7 +1600,7 @@ QTChatTabWidget::install_chat_menu_bar (widget menuWidget) {
QMenuBar* dest = new QMenuBar ();
double scale= DpiUtils::scaleFactor ();
- int h = DpiUtils::scaled (108);
+ int h = DpiUtils::scaled (kMenuBarHeight);
dest->setFixedHeight (h);
if (tm_style_sheet == "") dest->setStyle (qtmstyle ());
dest->setNativeMenuBar (false);
@@ -1793,9 +1906,11 @@ QTChatTabWidget::restore_conversation (const string& sessionId,
panel->modelLabel->setAlignment (Qt::AlignCenter);
DpiUtils::applyScaledFont (panel->modelLabel, kNavTitleFontPx);
panel->modelLabel->setStyleSheet (
- "color: #888888; padding: 2px 8px; background-color: #f0f0f0; "
- "border-radius: 4px;");
- panel->modelLabel->setMinimumHeight (DpiUtils::scaled (20));
+ QString ("color: #888888; padding: 2px %1px; background-color: #f0f0f0; "
+ "border-radius: %2px;")
+ .arg (DpiUtils::scaled (kNavButtonPadX))
+ .arg (DpiUtils::scaled (kModelLabelRadius)));
+ panel->modelLabel->setMinimumHeight (DpiUtils::scaled (kModelLabelMinHeight));
topLayout->addWidget (panel->modelLabel, 0, Qt::AlignHCenter);
// 恢复会话时,buffer 中已有 Scheme 加载的消息内容,需使用 buffer 内容而非空
@@ -1884,16 +1999,16 @@ QTChatTabWidget::restore_conversation (const string& sessionId,
panel->sendButton->setFocusPolicy (Qt::NoFocus);
panel->sendButton->setCursor (Qt::PointingHandCursor);
panel->sendButton->setIcon (QIcon (":llm-chat/send.svg"));
- int sendIconSize= DpiUtils::scaled (24);
+ int sendIconSize= DpiUtils::scaled (kSendIconSize);
panel->sendButton->setIconSize (QSize (sendIconSize, sendIconSize));
- panel->sendButton->setFixedSize (DpiUtils::scaled (36),
- DpiUtils::scaled (36));
+ panel->sendButton->setFixedSize (DpiUtils::scaled (kSendButtonSize),
+ DpiUtils::scaled (kSendButtonSize));
panel->sendButton->setStyleSheet (
QString ("QPushButton { border: none; border-radius: %1px; "
" background-color: transparent; }"
"QPushButton:hover { background-color: #f0f0f0; }"
"QPushButton:pressed { background-color: #e0e0e0; }")
- .arg (DpiUtils::scaled (18)));
+ .arg (DpiUtils::scaled (kSendButtonRadius)));
connect (panel->sendButton, &QPushButton::clicked, this,
[this, panel] () { handle_send (panel); });
btnLayout->addWidget (panel->sendButton);
@@ -1902,7 +2017,7 @@ QTChatTabWidget::restore_conversation (const string& sessionId,
inputAreaLayout->addWidget (inputFrame, 0);
QTimer* inputHeightTimer= new QTimer (inputFrame);
- inputHeightTimer->setInterval (100);
+ inputHeightTimer->setInterval (kInputHeightCheckIntervalMs);
connect (inputHeightTimer, &QTimer::timeout, this,
[this, panel] () { adjust_input_height (panel); });
inputHeightTimer->start ();
@@ -1920,7 +2035,7 @@ QTChatTabWidget::restore_conversation (const string& sessionId,
panel->itemWidget->setObjectName ("chat-tab-session-item");
QHBoxLayout* itemLayout= new QHBoxLayout (panel->itemWidget);
itemLayout->setContentsMargins (0, 0, 0, 0);
- itemLayout->setSpacing (DpiUtils::scaled (4));
+ itemLayout->setSpacing (DpiUtils::scaled (kSessionItemSpacing));
panel->selectCheckBox= new QCheckBox (panel->itemWidget);
panel->selectCheckBox->setObjectName ("chat-tab-select-checkbox");
@@ -1947,7 +2062,7 @@ QTChatTabWidget::restore_conversation (const string& sessionId,
"#ffffff; } "
"QPushButton:checked { background-color: #e8eefc; "
"border-color: #9bb3ff; font-weight: 600; }")
- .arg (DpiUtils::scaled (6))
+ .arg (DpiUtils::scaled (kConversationBtnRadius))
.arg (DpiUtils::scaled (kNavButtonPadY))
.arg (DpiUtils::scaled (kNavButtonPadX)));
connect (panel->sidebarButton, &QPushButton::clicked, this,
diff --git a/src/Plugins/Qt/qt_chat_tab_widget.hpp b/src/Plugins/Qt/qt_chat_tab_widget.hpp
index e94902e0f6..2558073e14 100644
--- a/src/Plugins/Qt/qt_chat_tab_widget.hpp
+++ b/src/Plugins/Qt/qt_chat_tab_widget.hpp
@@ -376,6 +376,8 @@ class QTChatTabWidget : public QWidget {
bool archiveCollapsed_; ///< 归档区当前是否折叠。
QPushButton* collapseButton_; ///< 侧边栏内的收缩按钮。
QPushButton* floatingExpandBtn_; ///< 内容区左上角的浮球展开按钮。
+ QPushButton* floatingNewChatBtn_; ///< 内容区左上角的新建聊天浮球按钮。
+ QWidget* floatingBtnContainer_; ///< 浮球按钮的胶囊形容器。
QPushButton* newChatButton_; ///< 新建会话按钮。
QWidget* sidebarNormalContent_; ///< 侧边栏展开时的内容容器。
QStackedWidget* conversationStack_; ///< 会话页面的堆叠控件。