diff --git a/TeXmacs/misc/images/images.qrc b/TeXmacs/misc/images/images.qrc index adc2c63e44..a545655540 100644 --- a/TeXmacs/misc/images/images.qrc +++ b/TeXmacs/misc/images/images.qrc @@ -22,6 +22,7 @@ llm-chat/addchat.svg llm-chat/cancel.svg llm-chat/ellipsis.svg + llm-chat/search.svg ocr-button/left-align-white.svg diff --git a/TeXmacs/misc/images/llm-chat/search.svg b/TeXmacs/misc/images/llm-chat/search.svg new file mode 100644 index 0000000000..ac93962332 --- /dev/null +++ b/TeXmacs/misc/images/llm-chat/search.svg @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/TeXmacs/misc/themes/liii-night.css b/TeXmacs/misc/themes/liii-night.css index 13e714916c..35dc9364be 100644 --- a/TeXmacs/misc/themes/liii-night.css +++ b/TeXmacs/misc/themes/liii-night.css @@ -1335,9 +1335,17 @@ QLabel#chat-tab-nav-title { color: #ffffff; } +/* 搜索按钮 */ +QWidget#centralWidget QPushButton#chat-tab-search-btn { + background-color: transparent; +} +QWidget#centralWidget QPushButton#chat-tab-search-btn:hover { + background-color: #999999; +} + /* 收缩按钮 */ QWidget#centralWidget QPushButton#chat-tab-collapse-btn { - background-color: #bababa; + background-color: transparent; } QWidget#centralWidget QPushButton#chat-tab-collapse-btn:hover { background-color: #999999; @@ -1391,11 +1399,13 @@ QWidget#centralWidget QWidget#chat-tab-floating-container { /* 浮球按钮 */ QWidget#centralWidget QPushButton#chat-tab-floating-expand-btn, -QWidget#centralWidget QPushButton#chat-tab-floating-new-btn { +QWidget#centralWidget QPushButton#chat-tab-floating-new-btn, +QWidget#centralWidget QPushButton#chat-tab-floating-search-btn { background-color: transparent; } QWidget#centralWidget QPushButton#chat-tab-floating-expand-btn:hover, -QWidget#centralWidget QPushButton#chat-tab-floating-new-btn:hover { +QWidget#centralWidget QPushButton#chat-tab-floating-new-btn:hover, +QWidget#centralWidget QPushButton#chat-tab-floating-search-btn:hover { background-color: #999999; } diff --git a/TeXmacs/misc/themes/liii.css b/TeXmacs/misc/themes/liii.css index 9decb84548..aa17cc117b 100644 --- a/TeXmacs/misc/themes/liii.css +++ b/TeXmacs/misc/themes/liii.css @@ -1260,9 +1260,17 @@ QLabel#chat-tab-nav-title { color: #000000; } +/* 搜索按钮 */ +QPushButton#chat-tab-search-btn { + background-color: transparent; +} +QPushButton#chat-tab-search-btn:hover { + background-color: #d0d0d0; +} + /* 收缩按钮 */ QPushButton#chat-tab-collapse-btn { - background-color: #e8e8e8; + background-color: transparent; } QPushButton#chat-tab-collapse-btn:hover { background-color: #d0d0d0; @@ -1313,11 +1321,13 @@ QWidget#chat-tab-floating-container { /* 浮球按钮 */ QPushButton#chat-tab-floating-expand-btn, -QPushButton#chat-tab-floating-new-btn { +QPushButton#chat-tab-floating-new-btn, +QPushButton#chat-tab-floating-search-btn { background-color: transparent; } QPushButton#chat-tab-floating-expand-btn:hover, -QPushButton#chat-tab-floating-new-btn:hover { +QPushButton#chat-tab-floating-new-btn:hover, +QPushButton#chat-tab-floating-search-btn:hover { background-color: #d0d0d0; } diff --git a/devel/1040.md b/devel/1040.md new file mode 100644 index 0000000000..a788b317f5 --- /dev/null +++ b/devel/1040.md @@ -0,0 +1,54 @@ +# [1040] Chat 侧边栏搜索按钮 + +## 1 相关文档 +- [dddd.md](dddd.md) - 任务文档模板 + +## 2 任务相关的代码文件 +- src/Plugins/Qt/qt_chat_tab_widget.cpp - 搜索按钮创建、浮球搜索按钮、搜索框显隐逻辑 +- src/Plugins/Qt/qt_chat_tab_widget.hpp - ChatSidebar::focusSearch()、QTChatTabWidget 成员变量 +- TeXmacs/misc/images/llm-chat/search.svg - 搜索图标 +- TeXmacs/misc/images/images.qrc - 资源注册 +- TeXmacs/misc/themes/liii.css - 亮色主题样式 +- TeXmacs/misc/themes/liii-night.css - 暗色主题样式 + +## 3 如何测试 + +### 3.1 确定性测试(单元测试) +无单元测试。 + +### 3.2 非确定性测试(文档验证) +``` +xmake b stem +``` +手动验证: +1. 打开 Chat Tab,确认侧边栏标题栏折叠按钮左侧出现搜索按钮 +2. 点击搜索按钮,搜索框出现并获得焦点 +3. 输入文本进行搜索过滤 +4. 清空文本后点击其他区域,搜索框自动隐藏 +5. 折叠侧边栏,确认浮球区域中间出现搜索按钮 +6. 点击浮球搜索按钮,侧边栏展开并聚焦搜索框 + +## 4 如何提交 + +提交前执行以下最少步骤: + +```bash +xmake b stem +``` + +## 5 What +在 Chat 侧边栏添加搜索按钮,点击后显示搜索框,支持会话搜索过滤。 + +1. 侧边栏标题栏折叠按钮左侧添加搜索按钮,大小与折叠按钮一致 +2. 折叠后浮球容器中间添加搜索按钮(展开按钮和新建按钮之间) +3. 搜索框改为点击按钮才出现,失焦且内容为空时自动隐藏 +4. 添加 search.svg 图标及 CSS 样式(liii / liii-night 两套主题) + +## 6 Why +搜索框常驻占用侧边栏纵向空间,改为按钮触发显隐可以节省空间、简化视觉。 + +## 7 How +- 在 `setup_left_sidebar()` 中折叠按钮前创建搜索按钮,点击调用 `ChatSidebar::focusSearch()` +- 在 `setup_right_content()` 中浮球容器展开按钮后创建搜索按钮,点击先 `toggle_sidebar()` 展开侧边栏,再用 `QTimer::singleShot` 延迟聚焦搜索框 +- 搜索框默认 `hide()`,`focusSearch()` 中 `show()` 并聚焦 +- 在 `ChatSidebar::eventFilter` 中监听 `FocusOut` 事件,文本为空时隐藏搜索框 diff --git a/src/Plugins/Qt/qt_chat_tab_widget.cpp b/src/Plugins/Qt/qt_chat_tab_widget.cpp index 5e6ea06b00..4591e96b0c 100644 --- a/src/Plugins/Qt/qt_chat_tab_widget.cpp +++ b/src/Plugins/Qt/qt_chat_tab_widget.cpp @@ -61,6 +61,7 @@ constexpr int kFloatingBtnMarginX = 12; constexpr int kFloatingBtnMarginY = 12; constexpr int kFloatingContainerPad = 4; constexpr int kFloatingBtnSpacing = 4; +constexpr int kHeaderBtnSpacing = 4; constexpr int kNewChatIconSize = 18; constexpr int kNewChatButtonHeight = 36; constexpr int kNewChatButtonWidth = 140; @@ -448,6 +449,8 @@ ChatSidebar::ChatSidebar (const QList& sessions, .arg (DpiUtils::scaled (kCollapsePadX))); connect (searchEdit_, &QLineEdit::textChanged, this, [this] () { applySearchFilter (); }); + searchEdit_->hide (); + searchEdit_->installEventFilter (this); mainLayout->addWidget (searchEdit_); // 多选模式批量操作栏(默认隐藏) @@ -728,6 +731,15 @@ ChatSidebar::applySearchFilter () { updateCountLabels (); } +void +ChatSidebar::focusSearch () { + if (searchEdit_) { + searchEdit_->show (); + searchEdit_->setFocus (); + searchEdit_->selectAll (); + } +} + void ChatSidebar::updateCountLabels () { int activeCount = 0; @@ -946,7 +958,10 @@ ChatSidebar::activeSessionId () const { bool ChatSidebar::eventFilter (QObject* watched, QEvent* event) { - if (event->type () == QEvent::Resize) { + if (watched == searchEdit_ && event->type () == QEvent::FocusOut) { + if (searchEdit_->text ().isEmpty ()) searchEdit_->hide (); + } + else if (event->type () == QEvent::Resize) { for (auto it= items_.constBegin (); it != items_.constEnd (); ++it) { if (it->sidebarButton == watched && it->moreButton) { QRect cr= it->sidebarButton->contentsRect (); @@ -1103,6 +1118,25 @@ QTChatTabWidget::setup_left_sidebar (QVBoxLayout* sidebarLayout, headerLayout->addStretch (); + QPushButton* searchBtn= new QPushButton (headerWidget); + searchBtn->setObjectName ("chat-tab-search-btn"); + searchBtn->setFocusPolicy (Qt::NoFocus); + searchBtn->setCursor (Qt::PointingHandCursor); + searchBtn->setIcon (QIcon (":llm-chat/search.svg")); + searchBtn->setIconSize (QSize (DpiUtils::scaled (kToggleIconSize), + DpiUtils::scaled (kToggleIconSize))); + searchBtn->setFixedSize (DpiUtils::scaled (kToggleBtnSize), + DpiUtils::scaled (kToggleBtnSize)); + searchBtn->setStyleSheet ( + QString ("QPushButton { border: none; border-radius: %1px; }") + .arg (DpiUtils::scaled (kToggleBtnSize / 2))); + connect (searchBtn, &QPushButton::clicked, this, + [this] () { sidebar_->focusSearch (); }); + searchButton_= searchBtn; + headerLayout->addWidget (searchBtn); + + headerLayout->addSpacing (DpiUtils::scaled (kHeaderBtnSpacing)); + QPushButton* collapseBtn= new QPushButton (headerWidget); collapseBtn->setObjectName ("chat-tab-collapse-btn"); collapseBtn->setFocusPolicy (Qt::NoFocus); @@ -1214,6 +1248,16 @@ QTChatTabWidget::setup_right_content (QHBoxLayout* mainLayout) { floatingLayout->addWidget (floatingBtn); floatingExpandBtn_= floatingBtn; + QPushButton* floatingSearchBtn= + make_floating_btn (floatingContainer, "chat-tab-floating-search-btn", + ":llm-chat/search.svg"); + connect (floatingSearchBtn, &QPushButton::clicked, this, [this] () { + toggle_sidebar (); + QTimer::singleShot (0, this, [this] () { sidebar_->focusSearch (); }); + }); + floatingSearchBtn_= floatingSearchBtn; + floatingLayout->addWidget (floatingSearchBtn); + QPushButton* floatingNewBtn= make_floating_btn ( floatingContainer, "chat-tab-floating-new-btn", ":llm-chat/addchat.svg"); floatingNewChatBtn_= floatingNewBtn; diff --git a/src/Plugins/Qt/qt_chat_tab_widget.hpp b/src/Plugins/Qt/qt_chat_tab_widget.hpp index 03df26d855..f92eb3c80e 100644 --- a/src/Plugins/Qt/qt_chat_tab_widget.hpp +++ b/src/Plugins/Qt/qt_chat_tab_widget.hpp @@ -187,6 +187,11 @@ class ChatSidebar : public QWidget { */ void applySearchFilter (); + /** + * @brief 聚焦搜索框。 + */ + void focusSearch (); + // ---- 其他公共方法 ---- /** @@ -333,7 +338,9 @@ class QTChatTabWidget : public QWidget { QWidget* sidebarWidget_ = nullptr; ///< 侧边栏容器 QWidget* contentWidget_ = nullptr; ///< 右侧内容区容器 QPushButton* collapseButton_ = nullptr; ///< 折叠按钮 + QPushButton* searchButton_ = nullptr; ///< 搜索按钮 QPushButton* floatingExpandBtn_ = nullptr; ///< 浮动展开按钮 + QPushButton* floatingSearchBtn_ = nullptr; ///< 浮动搜索按钮 QPushButton* floatingNewChatBtn_ = nullptr; ///< 浮动新建按钮 QWidget* floatingBtnContainer_= nullptr; ///< 浮动按钮容器 QPushButton* newChatButton_ = nullptr; ///< 侧边栏新建按钮