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; ///< 侧边栏新建按钮