From 1946632990b43c6c2726b0001eb47a059485e6ce Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Thu, 22 Jan 2026 14:36:45 +0800
Subject: [PATCH 01/27] =?UTF-8?q?=E7=AA=97=E5=8F=A3=E6=82=AC=E6=B5=AE?=
=?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
TeXmacs/misc/images/images.qrc | 22 ++
.../text-toolbar/align-center-white.svg | 8 +
.../misc/images/text-toolbar/align-center.svg | 8 +
.../text-toolbar/align-justify-white.svg | 8 +
.../images/text-toolbar/align-justify.svg | 8 +
.../images/text-toolbar/align-left-white.svg | 8 +
.../misc/images/text-toolbar/align-left.svg | 8 +
.../images/text-toolbar/align-right-white.svg | 8 +
.../misc/images/text-toolbar/align-right.svg | 8 +
.../misc/images/text-toolbar/bold-white.svg | 4 +
TeXmacs/misc/images/text-toolbar/bold.svg | 4 +
.../misc/images/text-toolbar/color-white.svg | 5 +
TeXmacs/misc/images/text-toolbar/color.svg | 5 +
.../images/text-toolbar/highlight-white.svg | 5 +
.../misc/images/text-toolbar/highlight.svg | 5 +
.../misc/images/text-toolbar/italic-white.svg | 4 +
TeXmacs/misc/images/text-toolbar/italic.svg | 4 +
.../images/text-toolbar/underline-white.svg | 4 +
.../misc/images/text-toolbar/underline.svg | 4 +
TeXmacs/misc/themes/liii-night.css | 62 ++++
TeXmacs/misc/themes/liii.css | 64 ++++
src/Edit/Interface/edit_interface.hpp | 6 +
src/Edit/Interface/edit_mouse.cpp | 60 ++++
src/Plugins/Qt/QTMTextToolbar.cpp | 282 ++++++++++++++++++
src/Plugins/Qt/QTMTextToolbar.hpp | 71 +++++
src/Plugins/Qt/qt_simple_widget.cpp | 46 +++
src/Plugins/Qt/qt_simple_widget.hpp | 10 +
27 files changed, 731 insertions(+)
create mode 100644 TeXmacs/misc/images/text-toolbar/align-center-white.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/align-center.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/align-justify-white.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/align-justify.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/align-left-white.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/align-left.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/align-right-white.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/align-right.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/bold-white.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/bold.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/color-white.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/color.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/highlight-white.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/highlight.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/italic-white.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/italic.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/underline-white.svg
create mode 100644 TeXmacs/misc/images/text-toolbar/underline.svg
create mode 100644 src/Plugins/Qt/QTMTextToolbar.cpp
create mode 100644 src/Plugins/Qt/QTMTextToolbar.hpp
diff --git a/TeXmacs/misc/images/images.qrc b/TeXmacs/misc/images/images.qrc
index eab0c22212..2c9d4e5d07 100644
--- a/TeXmacs/misc/images/images.qrc
+++ b/TeXmacs/misc/images/images.qrc
@@ -11,5 +11,27 @@
ocr-button/middle-align-white.svg
ocr-button/right-align-white.svg
ocr-button/ocr-white.svg
+
+
+ text-toolbar/bold.svg
+ text-toolbar/italic.svg
+ text-toolbar/underline.svg
+ text-toolbar/highlight.svg
+ text-toolbar/color.svg
+ text-toolbar/align-left.svg
+ text-toolbar/align-center.svg
+ text-toolbar/align-right.svg
+ text-toolbar/align-justify.svg
+
+
+ text-toolbar/bold-white.svg
+ text-toolbar/italic-white.svg
+ text-toolbar/underline-white.svg
+ text-toolbar/highlight-white.svg
+ text-toolbar/color-white.svg
+ text-toolbar/align-left-white.svg
+ text-toolbar/align-center-white.svg
+ text-toolbar/align-right-white.svg
+ text-toolbar/align-justify-white.svg
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-center-white.svg b/TeXmacs/misc/images/text-toolbar/align-center-white.svg
new file mode 100644
index 0000000000..7c55d0603b
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/align-center-white.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-center.svg b/TeXmacs/misc/images/text-toolbar/align-center.svg
new file mode 100644
index 0000000000..1ffc2c05b6
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/align-center.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-justify-white.svg b/TeXmacs/misc/images/text-toolbar/align-justify-white.svg
new file mode 100644
index 0000000000..923a9ab5c0
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/align-justify-white.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-justify.svg b/TeXmacs/misc/images/text-toolbar/align-justify.svg
new file mode 100644
index 0000000000..220a697ffe
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/align-justify.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-left-white.svg b/TeXmacs/misc/images/text-toolbar/align-left-white.svg
new file mode 100644
index 0000000000..002d21b022
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/align-left-white.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-left.svg b/TeXmacs/misc/images/text-toolbar/align-left.svg
new file mode 100644
index 0000000000..e63297a38a
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/align-left.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-right-white.svg b/TeXmacs/misc/images/text-toolbar/align-right-white.svg
new file mode 100644
index 0000000000..a06c661af7
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/align-right-white.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-right.svg b/TeXmacs/misc/images/text-toolbar/align-right.svg
new file mode 100644
index 0000000000..4cf62a85d8
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/align-right.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/bold-white.svg b/TeXmacs/misc/images/text-toolbar/bold-white.svg
new file mode 100644
index 0000000000..e360c7a44c
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/bold-white.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/bold.svg b/TeXmacs/misc/images/text-toolbar/bold.svg
new file mode 100644
index 0000000000..8b01b4dc33
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/bold.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/color-white.svg b/TeXmacs/misc/images/text-toolbar/color-white.svg
new file mode 100644
index 0000000000..73c1f5621d
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/color-white.svg
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/color.svg b/TeXmacs/misc/images/text-toolbar/color.svg
new file mode 100644
index 0000000000..c20d08816d
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/color.svg
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/highlight-white.svg b/TeXmacs/misc/images/text-toolbar/highlight-white.svg
new file mode 100644
index 0000000000..6d257a72ba
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/highlight-white.svg
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/highlight.svg b/TeXmacs/misc/images/text-toolbar/highlight.svg
new file mode 100644
index 0000000000..309d263c0d
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/highlight.svg
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/italic-white.svg b/TeXmacs/misc/images/text-toolbar/italic-white.svg
new file mode 100644
index 0000000000..73f816eb30
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/italic-white.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/italic.svg b/TeXmacs/misc/images/text-toolbar/italic.svg
new file mode 100644
index 0000000000..e2835547c6
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/italic.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/underline-white.svg b/TeXmacs/misc/images/text-toolbar/underline-white.svg
new file mode 100644
index 0000000000..6e987ff225
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/underline-white.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/underline.svg b/TeXmacs/misc/images/text-toolbar/underline.svg
new file mode 100644
index 0000000000..4dab8fa2eb
--- /dev/null
+++ b/TeXmacs/misc/images/text-toolbar/underline.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/themes/liii-night.css b/TeXmacs/misc/themes/liii-night.css
index 5f41f33eec..47c9cc988e 100644
--- a/TeXmacs/misc/themes/liii-night.css
+++ b/TeXmacs/misc/themes/liii-night.css
@@ -873,3 +873,65 @@ QWidget#centralWidget QWidget {
background: #202020;
color: #ffffff;
}
+
+/*文本工具栏窗口样式*/
+QWidget#text_toolbar {
+ background: #333333;
+ border: none;
+ border-radius: 8px;
+}
+
+/*文本工具栏按钮图标*/
+QToolButton#text-toolbar-button[icon-name="bold"] {
+ qproperty-icon: url(":/text-toolbar/bold-white.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="italic"] {
+ qproperty-icon: url(":/text-toolbar/italic-white.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="underline"] {
+ qproperty-icon: url(":/text-toolbar/underline-white.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="highlight"] {
+ qproperty-icon: url(":/text-toolbar/highlight-white.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="color"] {
+ qproperty-icon: url(":/text-toolbar/color-white.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="align-left"] {
+ qproperty-icon: url(":/text-toolbar/align-left-white.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="align-center"] {
+ qproperty-icon: url(":/text-toolbar/align-center-white.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="align-right"] {
+ qproperty-icon: url(":/text-toolbar/align-right-white.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="align-justify"] {
+ qproperty-icon: url(":/text-toolbar/align-justify-white.svg");
+}
+
+/*文本工具栏按钮样式*/
+QToolButton#text-toolbar-button {
+ background-color: transparent;
+ border: none;
+}
+
+/*文本工具栏按钮悬停样式*/
+QToolButton#text-toolbar-button:hover {
+ background-color: rgba(255, 255, 255, 0.1);
+ border: none;
+}
+
+/*文本工具栏按钮按下样式*/
+QToolButton#text-toolbar-button:pressed {
+ background-color: rgba(255, 255, 255, 0.2);
+ border: none;
+}
diff --git a/TeXmacs/misc/themes/liii.css b/TeXmacs/misc/themes/liii.css
index 823770835e..a39010f472 100644
--- a/TeXmacs/misc/themes/liii.css
+++ b/TeXmacs/misc/themes/liii.css
@@ -850,3 +850,67 @@ QWidget#auxiliary_container {
#guestNotificationCloseButton:pressed {
background-color: rgba(0, 0, 0, 0.2);
}
+
+/*文本工具栏窗口样式*/
+
+/*文本工具栏窗口样式*/
+QWidget#text_toolbar {
+ background: #ffffff;
+ border: none;
+ border-radius: 8px;
+}
+
+/*文本工具栏按钮图标*/
+QToolButton#text-toolbar-button[icon-name="bold"] {
+ qproperty-icon: url(":/text-toolbar/bold.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="italic"] {
+ qproperty-icon: url(":/text-toolbar/italic.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="underline"] {
+ qproperty-icon: url(":/text-toolbar/underline.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="highlight"] {
+ qproperty-icon: url(":/text-toolbar/highlight.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="color"] {
+ qproperty-icon: url(":/text-toolbar/color.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="align-left"] {
+ qproperty-icon: url(":/text-toolbar/align-left.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="align-center"] {
+ qproperty-icon: url(":/text-toolbar/align-center.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="align-right"] {
+ qproperty-icon: url(":/text-toolbar/align-right.svg");
+}
+
+QToolButton#text-toolbar-button[icon-name="align-justify"] {
+ qproperty-icon: url(":/text-toolbar/align-justify.svg");
+}
+
+/*文本工具栏按钮样式*/
+QToolButton#text-toolbar-button {
+ background-color: transparent;
+ border: none;
+}
+
+/*文本工具栏按钮悬停样式*/
+QToolButton#text-toolbar-button:hover {
+ background-color: rgba(128, 128, 128, 0.3);
+ border: none;
+}
+
+/*文本工具栏按钮按下样式*/
+QToolButton#text-toolbar-button:pressed {
+ background-color: rgba(128, 128, 128, 0.5);
+ border: none;
+}
diff --git a/src/Edit/Interface/edit_interface.hpp b/src/Edit/Interface/edit_interface.hpp
index 2f99a1ee0d..6491f89a01 100644
--- a/src/Edit/Interface/edit_interface.hpp
+++ b/src/Edit/Interface/edit_interface.hpp
@@ -237,6 +237,12 @@ class edit_interface_rep : virtual public editor_rep {
void update_mouse_loci ();
void update_focus_loci ();
bool should_show_image_popup (tree t);
+ bool should_show_text_toolbar ();
+ rectangle get_text_selection_rect ();
+ void show_text_toolbar (rectangle selr, double magf,
+ int scroll_x, int scroll_y, int canvas_x,
+ int canvas_y);
+ void hide_text_toolbar ();
/* the footer */
tree compute_text_footer (tree st);
diff --git a/src/Edit/Interface/edit_mouse.cpp b/src/Edit/Interface/edit_mouse.cpp
index 7f9b9feefa..293e43b6b5 100644
--- a/src/Edit/Interface/edit_mouse.cpp
+++ b/src/Edit/Interface/edit_mouse.cpp
@@ -25,6 +25,7 @@
#include "sys_utils.hpp"
#include "tm_buffer.hpp"
#include "tm_timer.hpp"
+#include "qt_simple_widget.hpp"
#include
#include
@@ -780,10 +781,23 @@ edit_interface_rep::mouse_any (string type, SI x, SI y, int mods, time_t t,
show_image_popup (tree_of_image_parent, selr, magf, get_scroll_x (),
get_scroll_y (), get_canvas_x (), get_canvas_y ());
}
+ hide_text_toolbar ();
}
else {
set_cursor_style ("normal");
hide_image_popup ();
+
+ // 检查是否应该显示文本工具栏
+ if (should_show_text_toolbar ()) {
+ rectangle text_selr= get_text_selection_rect ();
+ // 检查矩形是否有效(非零面积)
+ if (text_selr->x1 < text_selr->x2 && text_selr->y1 < text_selr->y2) {
+ show_text_toolbar (text_selr, magf, get_scroll_x (),
+ get_scroll_y (), get_canvas_x (), get_canvas_y ());
+ }
+ } else {
+ hide_text_toolbar ();
+ }
}
if (type == "move") mouse_message ("move", x, y);
@@ -1014,3 +1028,49 @@ edit_interface_rep::handle_mouse (string kind, SI x, SI y, int m, time_t t,
}
handle_exceptions ();
}
+
+/******************************************************************************
+ * Text toolbar support
+ ******************************************************************************/
+
+bool
+edit_interface_rep::should_show_text_toolbar () {
+ // 检查是否有活动的文本选区
+ if (!selection_active_any ()) return false;
+
+ // 检查选区是否非空
+ tree sel_tree= selection_get ();
+ if (is_atomic (sel_tree) && as_string (sel_tree) == "") return false;
+
+ return true;
+}
+
+rectangle
+edit_interface_rep::get_text_selection_rect () {
+ rectangle sel_rect;
+
+ if (selection_active_any () && !is_nil (selection_rects)) {
+ // 使用现有的选区矩形
+ sel_rect= least_upper_bound (selection_rects);
+ }
+
+ return sel_rect;
+}
+
+void
+edit_interface_rep::show_text_toolbar (rectangle selr, double magf,
+ int scroll_x, int scroll_y, int canvas_x,
+ int canvas_y) {
+ // 通过qt_simple_widget显示文本工具栏
+ // this指针实际上是edit_interface_rep,它继承自editor_rep,而editor_rep继承自simple_widget_rep
+ // 在Qt环境下,simple_widget_rep实际上是qt_simple_widget_rep
+ qt_simple_widget_rep* qsw= static_cast (this);
+ qsw->show_text_toolbar (selr, magf, scroll_x, scroll_y, canvas_x, canvas_y);
+}
+
+void
+edit_interface_rep::hide_text_toolbar () {
+ // 通过qt_simple_widget隐藏文本工具栏
+ qt_simple_widget_rep* qsw= static_cast (this);
+ qsw->hide_text_toolbar ();
+}
diff --git a/src/Plugins/Qt/QTMTextToolbar.cpp b/src/Plugins/Qt/QTMTextToolbar.cpp
new file mode 100644
index 0000000000..2c1e90565f
--- /dev/null
+++ b/src/Plugins/Qt/QTMTextToolbar.cpp
@@ -0,0 +1,282 @@
+/******************************************************************************
+ * MODULE : QTMTextToolbar.cpp
+ * DESCRIPTION: Text selection toolbar popup widget implementation
+ * COPYRIGHT : (C) 2025
+ *******************************************************************************
+ * 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
+ * in the root directory or .
+ ******************************************************************************/
+
+#include "QTMTextToolbar.hpp"
+#include "bitmap_font.hpp"
+#include "qbuttongroup.h"
+#include "qt_renderer.hpp"
+#include "qt_utilities.hpp"
+#include "scheme.hpp"
+#include "server.hpp"
+#include "tm_ostream.hpp"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// 悬浮工具栏创建函数
+QTMTextToolbar::QTMTextToolbar (QWidget* parent, qt_simple_widget_rep* owner)
+ : QWidget (parent), owner (owner), layout (nullptr), cached_selection_mid_x (0),
+ cached_selection_mid_y (0), cached_scroll_x (0), cached_scroll_y (0),
+ cached_canvas_x (0), cached_canvas_y (0), cached_magf (0.0),
+ painted (false), painted_count (0) {
+ Q_INIT_RESOURCE (images);
+ setObjectName ("text_toolbar");
+ setWindowFlags (Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
+ setAttribute (Qt::WA_ShowWithoutActivating);
+ setMouseTracking (true);
+ setFocusPolicy (Qt::NoFocus);
+ layout= new QHBoxLayout (this);
+ layout->setContentsMargins (0, 0, 0, 0);
+ layout->setSizeConstraint (QLayout::SetMinimumSize);
+ layout->setSpacing (1);
+ setLayout (layout);
+
+ // 添加阴影效果
+ QGraphicsDropShadowEffect* effect= new QGraphicsDropShadowEffect (this);
+ effect->setBlurRadius (40);
+ effect->setOffset (0, 4);
+ effect->setColor (QColor (0, 0, 0, 120));
+ this->setGraphicsEffect (effect);
+
+ // 创建按钮
+ boldBtn= new QToolButton ();
+ boldBtn->setObjectName ("text-toolbar-button");
+ boldBtn->setProperty ("icon-name", "bold");
+ boldBtn->setCheckable (true);
+ boldBtn->setToolTip (qt_translate ("Bold"));
+
+ italicBtn= new QToolButton ();
+ italicBtn->setObjectName ("text-toolbar-button");
+ italicBtn->setProperty ("icon-name", "italic");
+ italicBtn->setCheckable (true);
+ italicBtn->setToolTip (qt_translate ("Italic"));
+
+ underlineBtn= new QToolButton ();
+ underlineBtn->setObjectName ("text-toolbar-button");
+ underlineBtn->setProperty ("icon-name", "underline");
+ underlineBtn->setCheckable (true);
+ underlineBtn->setToolTip (qt_translate ("Underline"));
+
+ highlightBtn= new QToolButton ();
+ highlightBtn->setObjectName ("text-toolbar-button");
+ highlightBtn->setProperty ("icon-name", "highlight");
+ highlightBtn->setCheckable (true);
+ highlightBtn->setToolTip (qt_translate ("Highlight"));
+
+ colorBtn= new QToolButton ();
+ colorBtn->setObjectName ("text-toolbar-button");
+ colorBtn->setProperty ("icon-name", "color");
+ colorBtn->setCheckable (false);
+ colorBtn->setToolTip (qt_translate ("Text color"));
+
+ alignLeftBtn= new QToolButton ();
+ alignLeftBtn->setObjectName ("text-toolbar-button");
+ alignLeftBtn->setProperty ("icon-name", "align-left");
+ alignLeftBtn->setCheckable (true);
+ alignLeftBtn->setToolTip (qt_translate ("Align left"));
+
+ alignCenterBtn= new QToolButton ();
+ alignCenterBtn->setObjectName ("text-toolbar-button");
+ alignCenterBtn->setProperty ("icon-name", "align-center");
+ alignCenterBtn->setCheckable (true);
+ alignCenterBtn->setToolTip (qt_translate ("Align center"));
+
+ alignRightBtn= new QToolButton ();
+ alignRightBtn->setObjectName ("text-toolbar-button");
+ alignRightBtn->setProperty ("icon-name", "align-right");
+ alignRightBtn->setCheckable (true);
+ alignRightBtn->setToolTip (qt_translate ("Align right"));
+
+ alignJustifyBtn= new QToolButton ();
+ alignJustifyBtn->setObjectName ("text-toolbar-button");
+ alignJustifyBtn->setProperty ("icon-name", "align-justify");
+ alignJustifyBtn->setCheckable (true);
+ alignJustifyBtn->setToolTip (qt_translate ("Justify"));
+
+ // 添加按钮到布局
+ layout->addWidget (boldBtn);
+ layout->addWidget (italicBtn);
+ layout->addWidget (underlineBtn);
+ layout->addWidget (highlightBtn);
+ layout->addWidget (colorBtn);
+ layout->addWidget (alignLeftBtn);
+ layout->addWidget (alignCenterBtn);
+ layout->addWidget (alignRightBtn);
+ layout->addWidget (alignJustifyBtn);
+
+ // 连接按钮点击事件(暂时只显示,不实现功能)
+ connect (boldBtn, &QToolButton::clicked, this, []() {
+ // TODO: 实现加粗功能
+ });
+ connect (italicBtn, &QToolButton::clicked, this, []() {
+ // TODO: 实现斜体功能
+ });
+ connect (underlineBtn, &QToolButton::clicked, this, []() {
+ // TODO: 实现下划线功能
+ });
+ connect (highlightBtn, &QToolButton::clicked, this, []() {
+ // TODO: 实现高亮功能
+ });
+ connect (colorBtn, &QToolButton::clicked, this, []() {
+ // TODO: 实现文字颜色功能
+ });
+
+ // 对齐按钮分组
+ QButtonGroup* alignGroup= new QButtonGroup (this);
+ alignGroup->addButton (alignLeftBtn);
+ alignGroup->addButton (alignCenterBtn);
+ alignGroup->addButton (alignRightBtn);
+ alignGroup->addButton (alignJustifyBtn);
+ alignGroup->setExclusive (true);
+
+ connect (alignGroup,
+ QOverload::of (&QButtonGroup::buttonClicked), this,
+ [=] (QAbstractButton* button) {
+ // TODO: 实现对齐功能
+ });
+
+ autoSize ();
+}
+
+QTMTextToolbar::~QTMTextToolbar () {}
+
+void
+QTMTextToolbar::showTextToolbar (qt_renderer_rep* ren, rectangle selr, double magf,
+ int scroll_x, int scroll_y, int canvas_x, int canvas_y) {
+ cachePosition (selr, magf, scroll_x, scroll_y, canvas_x, canvas_y);
+ updatePosition (ren);
+ show ();
+ raise ();
+}
+
+void
+QTMTextToolbar::updatePosition (qt_renderer_rep* ren) {
+ int x, y;
+ getCachedPosition (ren, x, y);
+ move (x, y);
+}
+
+void
+QTMTextToolbar::scrollBy (int x, int y) {
+ cached_scroll_x+= x;
+ cached_scroll_y+= y;
+}
+
+void
+QTMTextToolbar::cachePosition (rectangle selr, double magf, int scroll_x, int scroll_y,
+ int canvas_x, int canvas_y) {
+ cached_rect = selr;
+ cached_magf = magf;
+ cached_scroll_x = scroll_x;
+ cached_scroll_y = scroll_y;
+ cached_canvas_x = canvas_x;
+ cached_canvas_y = canvas_y;
+
+ // 计算选区中心位置
+ cached_selection_mid_x= (selr->x1 + selr->x2) * 0.5;
+ cached_selection_mid_y= selr->y2; // 使用选区底部位置,使工具栏显示在选中文字正上方
+}
+
+void
+QTMTextToolbar::getCachedPosition (qt_renderer_rep* ren, int& x, int& y) {
+ rectangle selr = cached_rect;
+ double inv_unit = 1.0 / 256.0;
+ double cx_logic = (selr->x1 + selr->x2) * 0.5;
+ double top_logic= selr->y2; // 使用选区底部位置,使工具栏显示在选中文字正上方
+
+ // 使用公式计算QT坐标
+ double cx_px=
+ ((cx_logic - cached_scroll_x) * cached_magf + cached_canvas_x) * inv_unit;
+ double top_px= -(top_logic - cached_scroll_y) * cached_magf * inv_unit;
+
+ // 修正:视口 > 表面:存在空白顶部
+ double blank_top= 0.0;
+ if (owner && owner->scrollarea () && owner->scrollarea ()->viewport () &&
+ owner->scrollarea ()->surface ()) {
+ int vp_h = owner->scrollarea ()->viewport ()->height ();
+ int surf_h= owner->scrollarea ()->surface ()->height ();
+ if (vp_h > surf_h) blank_top= (vp_h - surf_h) * 0.5;
+ }
+ top_px+= blank_top;
+
+ x= int (std::round (cx_px - cached_width * 0.5));
+ y= int (std::round (top_px - cached_height)); // 在选区底部上方显示,与图片悬浮窗口一致
+
+ // 确保工具栏在视口内
+ if (x < 0) x= 0;
+ if (y < 0) y= int (std::round (top_px + 10)); // 如果上面空间不够,显示在选区下方
+ if (owner && owner->scrollarea () && owner->scrollarea ()->viewport ()) {
+ int vp_w= owner->scrollarea ()->viewport ()->width ();
+ int vp_h= owner->scrollarea ()->viewport ()->height ();
+ if (x + cached_width > vp_w) x= vp_w - cached_width;
+ if (y + cached_height > vp_h) y= vp_h - cached_height;
+ }
+}
+
+void
+QTMTextToolbar::autoSize () {
+ // 根据DPI和缩放因子自动调整大小
+ QScreen* Screen = QGuiApplication::primaryScreen ();
+ const double Dpi = Screen ? Screen->logicalDotsPerInch () : 96.0;
+ const double Scale = Dpi / 96.0;
+ const double totalScale= Scale * cached_magf * 3.0;
+ int btn_size;
+
+#if defined(Q_OS_MAC)
+ btn_size= int (50 * totalScale);
+#else
+ btn_size= int (40 * totalScale);
+#endif
+
+ if (cached_magf <= 0.16) {
+ btn_size= 25;
+ }
+
+ // 设置按钮大小
+ QSize icon_size (btn_size, btn_size);
+ boldBtn->setIconSize (icon_size);
+ italicBtn->setIconSize (icon_size);
+ underlineBtn->setIconSize (icon_size);
+ highlightBtn->setIconSize (icon_size);
+ colorBtn->setIconSize (icon_size);
+ alignLeftBtn->setIconSize (icon_size);
+ alignCenterBtn->setIconSize (icon_size);
+ alignRightBtn->setIconSize (icon_size);
+ alignJustifyBtn->setIconSize (icon_size);
+
+ // 设置按钮固定大小
+ QSize fixed_size (btn_size + 8, btn_size + 8);
+ boldBtn->setFixedSize (fixed_size);
+ italicBtn->setFixedSize (fixed_size);
+ underlineBtn->setFixedSize (fixed_size);
+ highlightBtn->setFixedSize (fixed_size);
+ colorBtn->setFixedSize (fixed_size);
+ alignLeftBtn->setFixedSize (fixed_size);
+ alignCenterBtn->setFixedSize (fixed_size);
+ alignRightBtn->setFixedSize (fixed_size);
+ alignJustifyBtn->setFixedSize (fixed_size);
+
+ // 调整窗口大小
+ adjustSize ();
+ cached_width = width ();
+ cached_height= height ();
+}
+
+bool
+QTMTextToolbar::eventFilter (QObject* obj, QEvent* event) {
+ // 处理事件过滤
+ return QWidget::eventFilter (obj, event);
+}
\ No newline at end of file
diff --git a/src/Plugins/Qt/QTMTextToolbar.hpp b/src/Plugins/Qt/QTMTextToolbar.hpp
new file mode 100644
index 0000000000..16795cb797
--- /dev/null
+++ b/src/Plugins/Qt/QTMTextToolbar.hpp
@@ -0,0 +1,71 @@
+/******************************************************************************
+ * MODULE : QTMTextToolbar.hpp
+ * DESCRIPTION: Text selection toolbar popup widget
+ * COPYRIGHT : (C) 2025
+ *******************************************************************************
+ * 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
+ * in the root directory or .
+ ******************************************************************************/
+
+#ifndef QT_TEXT_TOOLBAR_HPP
+#define QT_TEXT_TOOLBAR_HPP
+
+#include "qt_simple_widget.hpp"
+#include "rectangles.hpp"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+class QTMTextToolbar : public QWidget {
+protected:
+ qt_simple_widget_rep* owner;
+ QHBoxLayout* layout;
+ QGraphicsDropShadowEffect* effect;
+ int cached_selection_mid_x;
+ int cached_selection_mid_y;
+ rectangle cached_rect;
+ int cached_scroll_x; // 页面滚动位置x
+ int cached_scroll_y; // 页面滚动位置y
+ int cached_canvas_x;
+ int cached_canvas_y;
+ int cached_width;
+ int cached_height;
+ double cached_magf; // 缩放因子
+ bool painted;
+ int painted_count;
+
+ // 工具栏按钮
+ QToolButton* boldBtn;
+ QToolButton* italicBtn;
+ QToolButton* underlineBtn;
+ QToolButton* highlightBtn;
+ QToolButton* colorBtn;
+ QToolButton* alignLeftBtn;
+ QToolButton* alignCenterBtn;
+ QToolButton* alignRightBtn;
+ QToolButton* alignJustifyBtn;
+ QString btn_style;
+
+public:
+ QTMTextToolbar (QWidget* parent, qt_simple_widget_rep* owner);
+ ~QTMTextToolbar ();
+
+ void showTextToolbar (qt_renderer_rep* ren, rectangle selr, double magf,
+ int scroll_x, int scroll_y, int canvas_x, int canvas_y);
+ void updatePosition (qt_renderer_rep* ren);
+ void scrollBy (int x, int y);
+ void autoSize ();
+
+protected:
+ void cachePosition (rectangle selr, double magf, int scroll_x, int scroll_y,
+ int canvas_x, int canvas_y);
+ void getCachedPosition (qt_renderer_rep* ren, int& x, int& y);
+ bool eventFilter (QObject* obj, QEvent* event) override;
+};
+
+#endif // QT_TEXT_TOOLBAR_HPP
\ No newline at end of file
diff --git a/src/Plugins/Qt/qt_simple_widget.cpp b/src/Plugins/Qt/qt_simple_widget.cpp
index 3774278a9e..5ef19df5cd 100644
--- a/src/Plugins/Qt/qt_simple_widget.cpp
+++ b/src/Plugins/Qt/qt_simple_widget.cpp
@@ -19,6 +19,7 @@
#include "QTMCompletionPopup.hpp"
#include "QTMImagePopup.hpp"
#include "QTMMathCompletionPopup.hpp"
+#include "QTMTextToolbar.hpp"
#include "QTMMenuHelper.hpp"
#include "QTMStyle.hpp"
#include "QTMWidget.hpp"
@@ -789,4 +790,49 @@ qt_simple_widget_rep::scroll_image_popup_by (SI x, SI y) {
qt_renderer_rep* ren= the_qt_renderer ();
imagePopUp->updatePosition (ren);
}
+}
+
+/******************************************************************************
+ * Text toolbar support
+ ******************************************************************************/
+
+void
+qt_simple_widget_rep::ensure_text_toolbar () {
+ if (!textToolbar && canvas ()) {
+ textToolbar= new QTMTextToolbar (canvas (), this);
+ if (is_empty (tm_style_sheet)) {
+ textToolbar->setStyle (qtmstyle ());
+ }
+ }
+}
+
+void
+qt_simple_widget_rep::show_text_toolbar (rectangle selr, double magf,
+ int scroll_x, int scroll_y, int canvas_x,
+ int canvas_y) {
+ ensure_text_toolbar ();
+ qt_renderer_rep* ren= the_qt_renderer ();
+ textToolbar->showTextToolbar (ren, selr, magf, scroll_x, scroll_y, canvas_x,
+ canvas_y);
+}
+
+void
+qt_simple_widget_rep::hide_text_toolbar () {
+ if (textToolbar) {
+ textToolbar->hide ();
+ textToolbar->setParent (nullptr);
+ textToolbar->deleteLater ();
+ textToolbar= nullptr;
+ }
+}
+
+void
+qt_simple_widget_rep::scroll_text_toolbar_by (SI x, SI y) {
+ if (textToolbar) {
+ QPoint qp (x, y);
+ coord2 p= from_qpoint (qp);
+ textToolbar->scrollBy (p.x1, p.x2);
+ qt_renderer_rep* ren= the_qt_renderer ();
+ textToolbar->updatePosition (ren);
+ }
}
\ No newline at end of file
diff --git a/src/Plugins/Qt/qt_simple_widget.hpp b/src/Plugins/Qt/qt_simple_widget.hpp
index 99fb02d199..0b2ce236e3 100644
--- a/src/Plugins/Qt/qt_simple_widget.hpp
+++ b/src/Plugins/Qt/qt_simple_widget.hpp
@@ -24,6 +24,7 @@
class QTMCompletionPopup;
class QTMMathCompletionPopup;
class QTMImagePopup;
+class QTMTextToolbar;
/*! A widget containing a TeXmacs canvas.
@@ -121,6 +122,14 @@ class qt_simple_widget_rep : public qt_widget_rep {
void hide_image_popup ();
void scroll_image_popup_by (SI x, SI y);
+ ////////////////////// Text toolbar support
+ void ensure_text_toolbar ();
+ void show_text_toolbar (rectangle selr, double magf,
+ int scroll_x, int scroll_y, int canvas_x,
+ int canvas_y);
+ void hide_text_toolbar ();
+ void scroll_text_toolbar_by (SI x, SI y);
+
////////////////////// backing store management
static void repaint_all (); // called by qt_gui_rep::update()
@@ -131,6 +140,7 @@ class qt_simple_widget_rep : public qt_widget_rep {
QPointer completionPopUp;
QPointer mathCompletionPopUp;
QPointer imagePopUp;
+ QPointer textToolbar;
#ifdef USE_MUPDF_RENDERER
double bs_zoomf;
picture backing_store;
From be002cab734f77ff1e6951d2d328d79868ef4f51 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Thu, 22 Jan 2026 22:15:04 +0800
Subject: [PATCH 02/27] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=AE=9E=E7=8E=B0,?=
=?UTF-8?q?=E5=9B=BE=E6=A0=87=E9=9C=80=E8=A6=81=E6=9B=B4=E6=8D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
TeXmacs/misc/images/images.qrc | 16 +++----
TeXmacs/misc/themes/liii-night.css | 12 ++---
TeXmacs/misc/themes/liii.css | 12 ++---
src/Edit/Interface/edit_interface.cpp | 7 +++
src/Edit/Interface/edit_interface.hpp | 2 +
src/Edit/Interface/edit_keyboard.cpp | 2 +
src/Edit/Interface/edit_mouse.cpp | 63 ++++++++++++++++++++-----
src/Plugins/Qt/QTMTextToolbar.cpp | 67 ++++++++++++++++-----------
src/Plugins/Qt/QTMTextToolbar.hpp | 1 -
src/Plugins/Qt/qt_simple_widget.cpp | 16 +++++++
src/Plugins/Qt/qt_simple_widget.hpp | 1 +
11 files changed, 139 insertions(+), 60 deletions(-)
diff --git a/TeXmacs/misc/images/images.qrc b/TeXmacs/misc/images/images.qrc
index 2c9d4e5d07..6e5691b8b1 100644
--- a/TeXmacs/misc/images/images.qrc
+++ b/TeXmacs/misc/images/images.qrc
@@ -18,10 +18,10 @@
text-toolbar/underline.svg
text-toolbar/highlight.svg
text-toolbar/color.svg
- text-toolbar/align-left.svg
- text-toolbar/align-center.svg
- text-toolbar/align-right.svg
- text-toolbar/align-justify.svg
+ ocr-button/left-align.svg
+ ocr-button/middle-align.svg
+ ocr-button/right-align.svg
+
text-toolbar/bold-white.svg
@@ -29,9 +29,9 @@
text-toolbar/underline-white.svg
text-toolbar/highlight-white.svg
text-toolbar/color-white.svg
- text-toolbar/align-left-white.svg
- text-toolbar/align-center-white.svg
- text-toolbar/align-right-white.svg
- text-toolbar/align-justify-white.svg
+ ocr-button/left-align-white.svg
+ ocr-button/middle-align-white.svg
+ ocr-button/right-align-white.svg
+
\ No newline at end of file
diff --git a/TeXmacs/misc/themes/liii-night.css b/TeXmacs/misc/themes/liii-night.css
index 47c9cc988e..e7b63d2c17 100644
--- a/TeXmacs/misc/themes/liii-night.css
+++ b/TeXmacs/misc/themes/liii-night.css
@@ -902,16 +902,16 @@ QToolButton#text-toolbar-button[icon-name="color"] {
qproperty-icon: url(":/text-toolbar/color-white.svg");
}
-QToolButton#text-toolbar-button[icon-name="align-left"] {
- qproperty-icon: url(":/text-toolbar/align-left-white.svg");
+QToolButton#text-toolbar-button[icon-name="left-align"] {
+ qproperty-icon: url(":/ocr-button/left-align-white.svg");
}
-QToolButton#text-toolbar-button[icon-name="align-center"] {
- qproperty-icon: url(":/text-toolbar/align-center-white.svg");
+QToolButton#text-toolbar-button[icon-name="middle-align"] {
+ qproperty-icon: url(":/ocr-button/middle-align-white.svg");
}
-QToolButton#text-toolbar-button[icon-name="align-right"] {
- qproperty-icon: url(":/text-toolbar/align-right-white.svg");
+QToolButton#text-toolbar-button[icon-name="right-align"] {
+ qproperty-icon: url(":/ocr-button/right-align-white.svg");
}
QToolButton#text-toolbar-button[icon-name="align-justify"] {
diff --git a/TeXmacs/misc/themes/liii.css b/TeXmacs/misc/themes/liii.css
index a39010f472..53cb4a2250 100644
--- a/TeXmacs/misc/themes/liii.css
+++ b/TeXmacs/misc/themes/liii.css
@@ -881,16 +881,16 @@ QToolButton#text-toolbar-button[icon-name="color"] {
qproperty-icon: url(":/text-toolbar/color.svg");
}
-QToolButton#text-toolbar-button[icon-name="align-left"] {
- qproperty-icon: url(":/text-toolbar/align-left.svg");
+QToolButton#text-toolbar-button[icon-name="left-align"] {
+ qproperty-icon: url(":/ocr-button/left-align.svg");
}
-QToolButton#text-toolbar-button[icon-name="align-center"] {
- qproperty-icon: url(":/text-toolbar/align-center.svg");
+QToolButton#text-toolbar-button[icon-name="middle-align"] {
+ qproperty-icon: url(":/ocr-button/middle-align.svg");
}
-QToolButton#text-toolbar-button[icon-name="align-right"] {
- qproperty-icon: url(":/text-toolbar/align-right.svg");
+QToolButton#text-toolbar-button[icon-name="right-align"] {
+ qproperty-icon: url(":/ocr-button/right-align.svg");
}
QToolButton#text-toolbar-button[icon-name="align-justify"] {
diff --git a/src/Edit/Interface/edit_interface.cpp b/src/Edit/Interface/edit_interface.cpp
index 019c84c6e2..bd47322357 100644
--- a/src/Edit/Interface/edit_interface.cpp
+++ b/src/Edit/Interface/edit_interface.cpp
@@ -648,6 +648,11 @@ edit_interface_rep::notify_change (int change) {
needs_update ();
if ((change & (THE_TREE | THE_SELECTION | THE_CURSOR)) != 0)
manual_focus_set (path (), (change & THE_TREE) != 0);
+
+ // 当选区改变时,更新文本工具栏
+ if ((change & THE_SELECTION) != 0) {
+ update_text_toolbar ();
+ }
}
bool
@@ -990,6 +995,8 @@ edit_interface_rep::apply_changes () {
selection_rects= rs;
invalidate (selection_rects);
}
+ // 选区改变后更新文本工具栏
+ update_text_toolbar ();
}
// cout << "Handling alternative selection\n";
diff --git a/src/Edit/Interface/edit_interface.hpp b/src/Edit/Interface/edit_interface.hpp
index 6491f89a01..5f6cc73dcb 100644
--- a/src/Edit/Interface/edit_interface.hpp
+++ b/src/Edit/Interface/edit_interface.hpp
@@ -243,6 +243,8 @@ class edit_interface_rep : virtual public editor_rep {
int scroll_x, int scroll_y, int canvas_x,
int canvas_y);
void hide_text_toolbar ();
+ bool is_point_in_text_toolbar (SI x, SI y);
+ void update_text_toolbar ();
/* the footer */
tree compute_text_footer (tree st);
diff --git a/src/Edit/Interface/edit_keyboard.cpp b/src/Edit/Interface/edit_keyboard.cpp
index 7997903d43..7bad5e2b22 100644
--- a/src/Edit/Interface/edit_keyboard.cpp
+++ b/src/Edit/Interface/edit_keyboard.cpp
@@ -487,6 +487,8 @@ edit_interface_rep::handle_keypress (string key_u8, time_t t) {
if (!is_nil (focus_ids) && got_focus)
call ("link-follow-ids", object (focus_ids), object ("focus"));
notify_change (THE_DECORATIONS);
+ // 键盘事件后更新文本工具栏显示状态
+ update_text_toolbar ();
end_editing ();
// time_t t2= texmacs_time ();
// if (t2 - t1 >= 10) cout << "handle_keypress took " << t2-t1 << "ms\n";
diff --git a/src/Edit/Interface/edit_mouse.cpp b/src/Edit/Interface/edit_mouse.cpp
index 293e43b6b5..6548b95a6b 100644
--- a/src/Edit/Interface/edit_mouse.cpp
+++ b/src/Edit/Interface/edit_mouse.cpp
@@ -788,16 +788,7 @@ edit_interface_rep::mouse_any (string type, SI x, SI y, int mods, time_t t,
hide_image_popup ();
// 检查是否应该显示文本工具栏
- if (should_show_text_toolbar ()) {
- rectangle text_selr= get_text_selection_rect ();
- // 检查矩形是否有效(非零面积)
- if (text_selr->x1 < text_selr->x2 && text_selr->y1 < text_selr->y2) {
- show_text_toolbar (text_selr, magf, get_scroll_x (),
- get_scroll_y (), get_canvas_x (), get_canvas_y ());
- }
- } else {
- hide_text_toolbar ();
- }
+ update_text_toolbar ();
}
if (type == "move") mouse_message ("move", x, y);
@@ -895,8 +886,13 @@ edit_interface_rep::mouse_any (string type, SI x, SI y, int mods, time_t t,
if ((type == "press-left") || (type == "release-left") ||
(type == "end-drag-left") || (type == "press-middle") ||
- (type == "press-right"))
+ (type == "press-right")) {
+ // 当用户点击其他地方(不在文本工具栏内)时,隐藏文本工具栏
+ if (!is_point_in_text_toolbar (x, y)) {
+ hide_text_toolbar ();
+ }
notify_change (THE_DECORATIONS);
+ }
if (type == "wheel" && N (data) == 2)
eval ("(wheel-event " * as_string (data[0]) * " " * as_string (data[1]) *
@@ -1053,6 +1049,23 @@ edit_interface_rep::get_text_selection_rect () {
// 使用现有的选区矩形
sel_rect= least_upper_bound (selection_rects);
}
+ else if (selection_active_any ()) {
+ // 如果没有选区矩形,但选区存在,计算一个默认矩形
+ path p1, p2;
+ selection_get (p1, p2);
+ if (p1 != p2) {
+ selection sel= search_selection (p1, p2);
+ if (!is_nil (sel->rs)) {
+ sel_rect= least_upper_bound (sel->rs);
+ }
+ else {
+ // 如果选区矩形为空,使用光标位置创建一个最小矩形
+ cursor cu= get_cursor ();
+ sel_rect= rectangle (cu->ox - 10 * pixel, cu->oy - 5 * pixel,
+ cu->ox + 10 * pixel, cu->oy + 5 * pixel);
+ }
+ }
+ }
return sel_rect;
}
@@ -1074,3 +1087,31 @@ edit_interface_rep::hide_text_toolbar () {
qt_simple_widget_rep* qsw= static_cast (this);
qsw->hide_text_toolbar ();
}
+
+bool
+edit_interface_rep::is_point_in_text_toolbar (SI x, SI y) {
+ // 通过qt_simple_widget检查点是否在文本工具栏内
+ qt_simple_widget_rep* qsw= static_cast (this);
+ return qsw->is_point_in_text_toolbar (x, y);
+}
+
+void
+edit_interface_rep::update_text_toolbar () {
+ // 检查是否应该显示文本工具栏
+ if (should_show_text_toolbar ()) {
+ rectangle text_selr= get_text_selection_rect ();
+ // 检查矩形是否有效(非零面积)
+ // 注意:rectangle 不是 list 类型,不能使用 is_nil
+ // 我们检查矩形坐标是否有效
+ if (text_selr->x1 < text_selr->x2 && text_selr->y1 < text_selr->y2) {
+ show_text_toolbar (text_selr, magf, get_scroll_x (),
+ get_scroll_y (), get_canvas_x (), get_canvas_y ());
+ }
+ else {
+ // 即使矩形无效,也尝试显示工具栏(例如单个字符选区)
+ hide_text_toolbar ();
+ }
+ } else {
+ hide_text_toolbar ();
+ }
+}
diff --git a/src/Plugins/Qt/QTMTextToolbar.cpp b/src/Plugins/Qt/QTMTextToolbar.cpp
index 2c1e90565f..1aae630bf3 100644
--- a/src/Plugins/Qt/QTMTextToolbar.cpp
+++ b/src/Plugins/Qt/QTMTextToolbar.cpp
@@ -16,6 +16,7 @@
#include "scheme.hpp"
#include "server.hpp"
#include "tm_ostream.hpp"
+#include "moebius/data/scheme.hpp"
#include
#include
@@ -84,28 +85,22 @@ QTMTextToolbar::QTMTextToolbar (QWidget* parent, qt_simple_widget_rep* owner)
alignLeftBtn= new QToolButton ();
alignLeftBtn->setObjectName ("text-toolbar-button");
- alignLeftBtn->setProperty ("icon-name", "align-left");
+ alignLeftBtn->setProperty ("icon-name", "left-align");
alignLeftBtn->setCheckable (true);
alignLeftBtn->setToolTip (qt_translate ("Align left"));
alignCenterBtn= new QToolButton ();
alignCenterBtn->setObjectName ("text-toolbar-button");
- alignCenterBtn->setProperty ("icon-name", "align-center");
+ alignCenterBtn->setProperty ("icon-name", "middle-align");
alignCenterBtn->setCheckable (true);
alignCenterBtn->setToolTip (qt_translate ("Align center"));
alignRightBtn= new QToolButton ();
alignRightBtn->setObjectName ("text-toolbar-button");
- alignRightBtn->setProperty ("icon-name", "align-right");
+ alignRightBtn->setProperty ("icon-name", "right-align");
alignRightBtn->setCheckable (true);
alignRightBtn->setToolTip (qt_translate ("Align right"));
- alignJustifyBtn= new QToolButton ();
- alignJustifyBtn->setObjectName ("text-toolbar-button");
- alignJustifyBtn->setProperty ("icon-name", "align-justify");
- alignJustifyBtn->setCheckable (true);
- alignJustifyBtn->setToolTip (qt_translate ("Justify"));
-
// 添加按钮到布局
layout->addWidget (boldBtn);
layout->addWidget (italicBtn);
@@ -115,23 +110,34 @@ QTMTextToolbar::QTMTextToolbar (QWidget* parent, qt_simple_widget_rep* owner)
layout->addWidget (alignLeftBtn);
layout->addWidget (alignCenterBtn);
layout->addWidget (alignRightBtn);
- layout->addWidget (alignJustifyBtn);
- // 连接按钮点击事件(暂时只显示,不实现功能)
- connect (boldBtn, &QToolButton::clicked, this, []() {
- // TODO: 实现加粗功能
+ // 连接按钮点击事件
+ connect (boldBtn, &QToolButton::clicked, this, [this]() {
+ if (this->owner) {
+ call ("toggle-bold");
+ }
});
- connect (italicBtn, &QToolButton::clicked, this, []() {
- // TODO: 实现斜体功能
+ connect (italicBtn, &QToolButton::clicked, this, [this]() {
+ if (this->owner) {
+ call ("toggle-italic");
+ }
});
- connect (underlineBtn, &QToolButton::clicked, this, []() {
- // TODO: 实现下划线功能
+ connect (underlineBtn, &QToolButton::clicked, this, [this]() {
+ if (this->owner) {
+ call ("toggle-underlined");
+ }
});
- connect (highlightBtn, &QToolButton::clicked, this, []() {
- // TODO: 实现高亮功能
+ connect (highlightBtn, &QToolButton::clicked, this, [this]() {
+ if (this->owner) {
+ // 高亮功能
+ call ("mark-text");
+ }
});
- connect (colorBtn, &QToolButton::clicked, this, []() {
- // TODO: 实现文字颜色功能
+ connect (colorBtn, &QToolButton::clicked, this, [this]() {
+ if (this->owner) {
+ // 文字颜色功能 - 打开颜色选择器
+ call ("interactive", object ("open-color-selector"));
+ }
});
// 对齐按钮分组
@@ -139,13 +145,20 @@ QTMTextToolbar::QTMTextToolbar (QWidget* parent, qt_simple_widget_rep* owner)
alignGroup->addButton (alignLeftBtn);
alignGroup->addButton (alignCenterBtn);
alignGroup->addButton (alignRightBtn);
- alignGroup->addButton (alignJustifyBtn);
alignGroup->setExclusive (true);
connect (alignGroup,
QOverload::of (&QButtonGroup::buttonClicked), this,
[=] (QAbstractButton* button) {
- // TODO: 实现对齐功能
+ if (this->owner) {
+ if (button == alignLeftBtn) {
+ call ("make-line-with", object ("par-mode"), object ("left"));
+ } else if (button == alignCenterBtn) {
+ call ("make-line-with", object ("par-mode"), object ("center"));
+ } else if (button == alignRightBtn) {
+ call ("make-line-with", object ("par-mode"), object ("right"));
+ }
+ }
});
autoSize ();
@@ -232,7 +245,7 @@ QTMTextToolbar::autoSize () {
QScreen* Screen = QGuiApplication::primaryScreen ();
const double Dpi = Screen ? Screen->logicalDotsPerInch () : 96.0;
const double Scale = Dpi / 96.0;
- const double totalScale= Scale * cached_magf * 3.0;
+ const double totalScale= Scale * cached_magf * 12.0; // 原始3.0倍,扩大4倍后为12.0倍
int btn_size;
#if defined(Q_OS_MAC)
@@ -255,10 +268,9 @@ QTMTextToolbar::autoSize () {
alignLeftBtn->setIconSize (icon_size);
alignCenterBtn->setIconSize (icon_size);
alignRightBtn->setIconSize (icon_size);
- alignJustifyBtn->setIconSize (icon_size);
// 设置按钮固定大小
- QSize fixed_size (btn_size + 8, btn_size + 8);
+ QSize fixed_size (btn_size + 32, btn_size + 32); // 内边距也扩大4倍 (8 * 4.0 = 32)
boldBtn->setFixedSize (fixed_size);
italicBtn->setFixedSize (fixed_size);
underlineBtn->setFixedSize (fixed_size);
@@ -267,7 +279,6 @@ QTMTextToolbar::autoSize () {
alignLeftBtn->setFixedSize (fixed_size);
alignCenterBtn->setFixedSize (fixed_size);
alignRightBtn->setFixedSize (fixed_size);
- alignJustifyBtn->setFixedSize (fixed_size);
// 调整窗口大小
adjustSize ();
@@ -279,4 +290,4 @@ bool
QTMTextToolbar::eventFilter (QObject* obj, QEvent* event) {
// 处理事件过滤
return QWidget::eventFilter (obj, event);
-}
\ No newline at end of file
+}
diff --git a/src/Plugins/Qt/QTMTextToolbar.hpp b/src/Plugins/Qt/QTMTextToolbar.hpp
index 16795cb797..6b1c12bb13 100644
--- a/src/Plugins/Qt/QTMTextToolbar.hpp
+++ b/src/Plugins/Qt/QTMTextToolbar.hpp
@@ -48,7 +48,6 @@ class QTMTextToolbar : public QWidget {
QToolButton* alignLeftBtn;
QToolButton* alignCenterBtn;
QToolButton* alignRightBtn;
- QToolButton* alignJustifyBtn;
QString btn_style;
public:
diff --git a/src/Plugins/Qt/qt_simple_widget.cpp b/src/Plugins/Qt/qt_simple_widget.cpp
index 5ef19df5cd..14e02108da 100644
--- a/src/Plugins/Qt/qt_simple_widget.cpp
+++ b/src/Plugins/Qt/qt_simple_widget.cpp
@@ -835,4 +835,20 @@ qt_simple_widget_rep::scroll_text_toolbar_by (SI x, SI y) {
qt_renderer_rep* ren= the_qt_renderer ();
textToolbar->updatePosition (ren);
}
+}
+
+bool
+qt_simple_widget_rep::is_point_in_text_toolbar (SI x, SI y) {
+ if (!textToolbar) return false;
+
+ // 将逻辑坐标转换为像素坐标
+ double inv_unit = 1.0 / 256.0;
+ int px = int (std::round (x * inv_unit));
+ int py = int (std::round (y * inv_unit));
+
+ // 获取工具栏的几何位置
+ QRect toolbarRect = textToolbar->geometry();
+
+ // 检查点是否在工具栏内
+ return toolbarRect.contains (px, py);
}
\ No newline at end of file
diff --git a/src/Plugins/Qt/qt_simple_widget.hpp b/src/Plugins/Qt/qt_simple_widget.hpp
index 0b2ce236e3..5bc1278792 100644
--- a/src/Plugins/Qt/qt_simple_widget.hpp
+++ b/src/Plugins/Qt/qt_simple_widget.hpp
@@ -129,6 +129,7 @@ class qt_simple_widget_rep : public qt_widget_rep {
int canvas_y);
void hide_text_toolbar ();
void scroll_text_toolbar_by (SI x, SI y);
+ bool is_point_in_text_toolbar (SI x, SI y);
////////////////////// backing store management
From d98f4109c4af224ae114ea12d7e0e0de890269e7 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Fri, 23 Jan 2026 17:11:05 +0800
Subject: [PATCH 03/27] =?UTF-8?q?=E5=9B=BE=E6=A0=87=E6=9B=B4=E6=8D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
TeXmacs/misc/images/images.qrc | 16 ++++++++++++++++
TeXmacs/misc/themes/liii-night.css | 8 ++++----
TeXmacs/misc/themes/liii.css | 8 ++++----
3 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/TeXmacs/misc/images/images.qrc b/TeXmacs/misc/images/images.qrc
index 6e5691b8b1..1d657bd94f 100644
--- a/TeXmacs/misc/images/images.qrc
+++ b/TeXmacs/misc/images/images.qrc
@@ -22,6 +22,14 @@
ocr-button/middle-align.svg
ocr-button/right-align.svg
+
+ ../pixmaps/liii/20x20/mode/tm_bold.svg
+ ../pixmaps/liii/20x20/mode/tm_italic.svg
+ ../pixmaps/liii/20x20/mode/tm_underline.svg
+ ../pixmaps/liii/20x20/mode/tm_marked.svg
+
+
+
text-toolbar/bold-white.svg
@@ -32,6 +40,14 @@
ocr-button/left-align-white.svg
ocr-button/middle-align-white.svg
ocr-button/right-align-white.svg
+
+
+ ../pixmaps/liii-night/20x20/mode/tm_bold.svg
+ ../pixmaps/liii-night/20x20/mode/tm_italic.svg
+ ../pixmaps/liii-night/20x20/mode/tm_underline.svg
+ ../pixmaps/liii-night/20x20/mode/tm_marked.svg
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/themes/liii-night.css b/TeXmacs/misc/themes/liii-night.css
index e7b63d2c17..a71fc78574 100644
--- a/TeXmacs/misc/themes/liii-night.css
+++ b/TeXmacs/misc/themes/liii-night.css
@@ -883,19 +883,19 @@ QWidget#text_toolbar {
/*文本工具栏按钮图标*/
QToolButton#text-toolbar-button[icon-name="bold"] {
- qproperty-icon: url(":/text-toolbar/bold-white.svg");
+ qproperty-icon: url(":/mode-toolbar/bold-white.svg");
}
QToolButton#text-toolbar-button[icon-name="italic"] {
- qproperty-icon: url(":/text-toolbar/italic-white.svg");
+ qproperty-icon: url(":/mode-toolbar/italic-white.svg");
}
QToolButton#text-toolbar-button[icon-name="underline"] {
- qproperty-icon: url(":/text-toolbar/underline-white.svg");
+ qproperty-icon: url(":/mode-toolbar/underline-white.svg");
}
QToolButton#text-toolbar-button[icon-name="highlight"] {
- qproperty-icon: url(":/text-toolbar/highlight-white.svg");
+ qproperty-icon: url(":/mode-toolbar/highlight-white.svg");
}
QToolButton#text-toolbar-button[icon-name="color"] {
diff --git a/TeXmacs/misc/themes/liii.css b/TeXmacs/misc/themes/liii.css
index 53cb4a2250..24c1d2ac9c 100644
--- a/TeXmacs/misc/themes/liii.css
+++ b/TeXmacs/misc/themes/liii.css
@@ -862,19 +862,19 @@ QWidget#text_toolbar {
/*文本工具栏按钮图标*/
QToolButton#text-toolbar-button[icon-name="bold"] {
- qproperty-icon: url(":/text-toolbar/bold.svg");
+ qproperty-icon: url(":/mode-toolbar/bold.svg");
}
QToolButton#text-toolbar-button[icon-name="italic"] {
- qproperty-icon: url(":/text-toolbar/italic.svg");
+ qproperty-icon: url(":/mode-toolbar/italic.svg");
}
QToolButton#text-toolbar-button[icon-name="underline"] {
- qproperty-icon: url(":/text-toolbar/underline.svg");
+ qproperty-icon: url(":/mode-toolbar/underline.svg");
}
QToolButton#text-toolbar-button[icon-name="highlight"] {
- qproperty-icon: url(":/text-toolbar/highlight.svg");
+ qproperty-icon: url(":/mode-toolbar/highlight.svg");
}
QToolButton#text-toolbar-button[icon-name="color"] {
From 027b9f39e7122a52c3fcfeecbc40553f21475144 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Fri, 23 Jan 2026 17:29:08 +0800
Subject: [PATCH 04/27] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99?=
=?UTF-8?q?=E5=9B=BE=E6=A0=87?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
TeXmacs/misc/images/images.qrc | 32 +++++++------------
.../text-toolbar/align-center-white.svg | 8 -----
.../misc/images/text-toolbar/align-center.svg | 8 -----
.../text-toolbar/align-justify-white.svg | 8 -----
.../images/text-toolbar/align-justify.svg | 8 -----
.../images/text-toolbar/align-left-white.svg | 8 -----
.../misc/images/text-toolbar/align-left.svg | 8 -----
.../images/text-toolbar/align-right-white.svg | 8 -----
.../misc/images/text-toolbar/align-right.svg | 8 -----
.../misc/images/text-toolbar/bold-white.svg | 4 ---
TeXmacs/misc/images/text-toolbar/bold.svg | 4 ---
.../misc/images/text-toolbar/color-white.svg | 5 ---
TeXmacs/misc/images/text-toolbar/color.svg | 5 ---
.../images/text-toolbar/highlight-white.svg | 5 ---
.../misc/images/text-toolbar/highlight.svg | 5 ---
.../misc/images/text-toolbar/italic-white.svg | 4 ---
TeXmacs/misc/images/text-toolbar/italic.svg | 4 ---
.../images/text-toolbar/underline-white.svg | 4 ---
.../misc/images/text-toolbar/underline.svg | 4 ---
TeXmacs/misc/themes/liii-night.css | 10 +++---
TeXmacs/misc/themes/liii.css | 10 +++---
21 files changed, 22 insertions(+), 138 deletions(-)
delete mode 100644 TeXmacs/misc/images/text-toolbar/align-center-white.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/align-center.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/align-justify-white.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/align-justify.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/align-left-white.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/align-left.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/align-right-white.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/align-right.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/bold-white.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/bold.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/color-white.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/color.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/highlight-white.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/highlight.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/italic-white.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/italic.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/underline-white.svg
delete mode 100644 TeXmacs/misc/images/text-toolbar/underline.svg
diff --git a/TeXmacs/misc/images/images.qrc b/TeXmacs/misc/images/images.qrc
index 1d657bd94f..25b92dc7a4 100644
--- a/TeXmacs/misc/images/images.qrc
+++ b/TeXmacs/misc/images/images.qrc
@@ -13,39 +13,31 @@
ocr-button/ocr-white.svg
- text-toolbar/bold.svg
- text-toolbar/italic.svg
- text-toolbar/underline.svg
- text-toolbar/highlight.svg
- text-toolbar/color.svg
+ ../pixmaps/liii/20x20/mode/tm_bold.svg
+ ../pixmaps/liii/20x20/mode/tm_italic.svg
+ ../pixmaps/liii/20x20/mode/tm_underline.svg
+ ../pixmaps/liii/20x20/mode/tm_marked.svg
+ ../pixmaps/liii/20x20/mode/tm_color.svg
ocr-button/left-align.svg
ocr-button/middle-align.svg
ocr-button/right-align.svg
-
- ../pixmaps/liii/20x20/mode/tm_bold.svg
- ../pixmaps/liii/20x20/mode/tm_italic.svg
- ../pixmaps/liii/20x20/mode/tm_underline.svg
- ../pixmaps/liii/20x20/mode/tm_marked.svg
+
- text-toolbar/bold-white.svg
- text-toolbar/italic-white.svg
- text-toolbar/underline-white.svg
- text-toolbar/highlight-white.svg
- text-toolbar/color-white.svg
+ ../pixmaps/liii-night/20x20/mode/tm_bold.svg
+ ../pixmaps/liii-night/20x20/mode/tm_italic.svg
+ ../pixmaps/liii-night/20x20/mode/tm_underline.svg
+ ../pixmaps/liii-night/20x20/mode/tm_marked.svg
+ ../pixmaps/liii-night/20x20/mode/tm_color.svg
ocr-button/left-align-white.svg
ocr-button/middle-align-white.svg
ocr-button/right-align-white.svg
-
- ../pixmaps/liii-night/20x20/mode/tm_bold.svg
- ../pixmaps/liii-night/20x20/mode/tm_italic.svg
- ../pixmaps/liii-night/20x20/mode/tm_underline.svg
- ../pixmaps/liii-night/20x20/mode/tm_marked.svg
+
diff --git a/TeXmacs/misc/images/text-toolbar/align-center-white.svg b/TeXmacs/misc/images/text-toolbar/align-center-white.svg
deleted file mode 100644
index 7c55d0603b..0000000000
--- a/TeXmacs/misc/images/text-toolbar/align-center-white.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-center.svg b/TeXmacs/misc/images/text-toolbar/align-center.svg
deleted file mode 100644
index 1ffc2c05b6..0000000000
--- a/TeXmacs/misc/images/text-toolbar/align-center.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-justify-white.svg b/TeXmacs/misc/images/text-toolbar/align-justify-white.svg
deleted file mode 100644
index 923a9ab5c0..0000000000
--- a/TeXmacs/misc/images/text-toolbar/align-justify-white.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-justify.svg b/TeXmacs/misc/images/text-toolbar/align-justify.svg
deleted file mode 100644
index 220a697ffe..0000000000
--- a/TeXmacs/misc/images/text-toolbar/align-justify.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-left-white.svg b/TeXmacs/misc/images/text-toolbar/align-left-white.svg
deleted file mode 100644
index 002d21b022..0000000000
--- a/TeXmacs/misc/images/text-toolbar/align-left-white.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-left.svg b/TeXmacs/misc/images/text-toolbar/align-left.svg
deleted file mode 100644
index e63297a38a..0000000000
--- a/TeXmacs/misc/images/text-toolbar/align-left.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-right-white.svg b/TeXmacs/misc/images/text-toolbar/align-right-white.svg
deleted file mode 100644
index a06c661af7..0000000000
--- a/TeXmacs/misc/images/text-toolbar/align-right-white.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/align-right.svg b/TeXmacs/misc/images/text-toolbar/align-right.svg
deleted file mode 100644
index 4cf62a85d8..0000000000
--- a/TeXmacs/misc/images/text-toolbar/align-right.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/bold-white.svg b/TeXmacs/misc/images/text-toolbar/bold-white.svg
deleted file mode 100644
index e360c7a44c..0000000000
--- a/TeXmacs/misc/images/text-toolbar/bold-white.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/bold.svg b/TeXmacs/misc/images/text-toolbar/bold.svg
deleted file mode 100644
index 8b01b4dc33..0000000000
--- a/TeXmacs/misc/images/text-toolbar/bold.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/color-white.svg b/TeXmacs/misc/images/text-toolbar/color-white.svg
deleted file mode 100644
index 73c1f5621d..0000000000
--- a/TeXmacs/misc/images/text-toolbar/color-white.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/color.svg b/TeXmacs/misc/images/text-toolbar/color.svg
deleted file mode 100644
index c20d08816d..0000000000
--- a/TeXmacs/misc/images/text-toolbar/color.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/highlight-white.svg b/TeXmacs/misc/images/text-toolbar/highlight-white.svg
deleted file mode 100644
index 6d257a72ba..0000000000
--- a/TeXmacs/misc/images/text-toolbar/highlight-white.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/highlight.svg b/TeXmacs/misc/images/text-toolbar/highlight.svg
deleted file mode 100644
index 309d263c0d..0000000000
--- a/TeXmacs/misc/images/text-toolbar/highlight.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/italic-white.svg b/TeXmacs/misc/images/text-toolbar/italic-white.svg
deleted file mode 100644
index 73f816eb30..0000000000
--- a/TeXmacs/misc/images/text-toolbar/italic-white.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/italic.svg b/TeXmacs/misc/images/text-toolbar/italic.svg
deleted file mode 100644
index e2835547c6..0000000000
--- a/TeXmacs/misc/images/text-toolbar/italic.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/underline-white.svg b/TeXmacs/misc/images/text-toolbar/underline-white.svg
deleted file mode 100644
index 6e987ff225..0000000000
--- a/TeXmacs/misc/images/text-toolbar/underline-white.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/images/text-toolbar/underline.svg b/TeXmacs/misc/images/text-toolbar/underline.svg
deleted file mode 100644
index 4dab8fa2eb..0000000000
--- a/TeXmacs/misc/images/text-toolbar/underline.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
\ No newline at end of file
diff --git a/TeXmacs/misc/themes/liii-night.css b/TeXmacs/misc/themes/liii-night.css
index a71fc78574..21c50cd88d 100644
--- a/TeXmacs/misc/themes/liii-night.css
+++ b/TeXmacs/misc/themes/liii-night.css
@@ -883,23 +883,23 @@ QWidget#text_toolbar {
/*文本工具栏按钮图标*/
QToolButton#text-toolbar-button[icon-name="bold"] {
- qproperty-icon: url(":/mode-toolbar/bold-white.svg");
+ qproperty-icon: url(":/pixmaps/liii-night/20x20/mode/tm_bold.svg");
}
QToolButton#text-toolbar-button[icon-name="italic"] {
- qproperty-icon: url(":/mode-toolbar/italic-white.svg");
+ qproperty-icon: url(":/pixmaps/liii-night/20x20/mode/tm_italic.svg");
}
QToolButton#text-toolbar-button[icon-name="underline"] {
- qproperty-icon: url(":/mode-toolbar/underline-white.svg");
+ qproperty-icon: url(":/pixmaps/liii-night/20x20/mode/tm_underline.svg");
}
QToolButton#text-toolbar-button[icon-name="highlight"] {
- qproperty-icon: url(":/mode-toolbar/highlight-white.svg");
+ qproperty-icon: url(":/pixmaps/liii-night/20x20/mode/tm_marked.svg");
}
QToolButton#text-toolbar-button[icon-name="color"] {
- qproperty-icon: url(":/text-toolbar/color-white.svg");
+ qproperty-icon: url(":/pixmaps/liii-night/20x20/mode/tm_color.svg");
}
QToolButton#text-toolbar-button[icon-name="left-align"] {
diff --git a/TeXmacs/misc/themes/liii.css b/TeXmacs/misc/themes/liii.css
index 24c1d2ac9c..967fa36e57 100644
--- a/TeXmacs/misc/themes/liii.css
+++ b/TeXmacs/misc/themes/liii.css
@@ -862,23 +862,23 @@ QWidget#text_toolbar {
/*文本工具栏按钮图标*/
QToolButton#text-toolbar-button[icon-name="bold"] {
- qproperty-icon: url(":/mode-toolbar/bold.svg");
+ qproperty-icon: url(":/pixmaps/liii/20x20/mode/tm_bold.svg");
}
QToolButton#text-toolbar-button[icon-name="italic"] {
- qproperty-icon: url(":/mode-toolbar/italic.svg");
+ qproperty-icon: url(":/pixmaps/liii/20x20/mode/tm_italic.svg");
}
QToolButton#text-toolbar-button[icon-name="underline"] {
- qproperty-icon: url(":/mode-toolbar/underline.svg");
+ qproperty-icon: url(":/pixmaps/liii/20x20/mode/tm_underline.svg");
}
QToolButton#text-toolbar-button[icon-name="highlight"] {
- qproperty-icon: url(":/mode-toolbar/highlight.svg");
+ qproperty-icon: url(":/pixmaps/liii/20x20/mode/tm_marked.svg");
}
QToolButton#text-toolbar-button[icon-name="color"] {
- qproperty-icon: url(":/text-toolbar/color.svg");
+ qproperty-icon: url(":/pixmaps/liii/20x20/mode/tm_color.svg");
}
QToolButton#text-toolbar-button[icon-name="left-align"] {
From a07c9583bffd968a9ac60917f54a4473c70c9661 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Fri, 23 Jan 2026 17:33:33 +0800
Subject: [PATCH 05/27] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=A0=BC=E5=BC=8F?=
=?UTF-8?q?=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Edit/Interface/edit_interface.hpp | 5 +-
src/Edit/Interface/edit_mouse.cpp | 17 +++---
src/Plugins/Qt/QTMTextToolbar.cpp | 82 +++++++++++++++------------
src/Plugins/Qt/QTMTextToolbar.hpp | 20 +++----
src/Plugins/Qt/qt_simple_widget.cpp | 16 +++---
src/Plugins/Qt/qt_simple_widget.hpp | 5 +-
6 files changed, 77 insertions(+), 68 deletions(-)
diff --git a/src/Edit/Interface/edit_interface.hpp b/src/Edit/Interface/edit_interface.hpp
index 5f6cc73dcb..f9e6524f19 100644
--- a/src/Edit/Interface/edit_interface.hpp
+++ b/src/Edit/Interface/edit_interface.hpp
@@ -239,9 +239,8 @@ class edit_interface_rep : virtual public editor_rep {
bool should_show_image_popup (tree t);
bool should_show_text_toolbar ();
rectangle get_text_selection_rect ();
- void show_text_toolbar (rectangle selr, double magf,
- int scroll_x, int scroll_y, int canvas_x,
- int canvas_y);
+ void show_text_toolbar (rectangle selr, double magf, int scroll_x,
+ int scroll_y, int canvas_x, int canvas_y);
void hide_text_toolbar ();
bool is_point_in_text_toolbar (SI x, SI y);
void update_text_toolbar ();
diff --git a/src/Edit/Interface/edit_mouse.cpp b/src/Edit/Interface/edit_mouse.cpp
index 6548b95a6b..d40e93e500 100644
--- a/src/Edit/Interface/edit_mouse.cpp
+++ b/src/Edit/Interface/edit_mouse.cpp
@@ -21,11 +21,11 @@
#include "path.hpp"
#include "qapplication.h"
#include "qnamespace.h"
+#include "qt_simple_widget.hpp"
#include "scheme.hpp"
#include "sys_utils.hpp"
#include "tm_buffer.hpp"
#include "tm_timer.hpp"
-#include "qt_simple_widget.hpp"
#include
#include
@@ -1061,8 +1061,8 @@ edit_interface_rep::get_text_selection_rect () {
else {
// 如果选区矩形为空,使用光标位置创建一个最小矩形
cursor cu= get_cursor ();
- sel_rect= rectangle (cu->ox - 10 * pixel, cu->oy - 5 * pixel,
- cu->ox + 10 * pixel, cu->oy + 5 * pixel);
+ sel_rect = rectangle (cu->ox - 10 * pixel, cu->oy - 5 * pixel,
+ cu->ox + 10 * pixel, cu->oy + 5 * pixel);
}
}
}
@@ -1072,8 +1072,8 @@ edit_interface_rep::get_text_selection_rect () {
void
edit_interface_rep::show_text_toolbar (rectangle selr, double magf,
- int scroll_x, int scroll_y, int canvas_x,
- int canvas_y) {
+ int scroll_x, int scroll_y, int canvas_x,
+ int canvas_y) {
// 通过qt_simple_widget显示文本工具栏
// this指针实际上是edit_interface_rep,它继承自editor_rep,而editor_rep继承自simple_widget_rep
// 在Qt环境下,simple_widget_rep实际上是qt_simple_widget_rep
@@ -1104,14 +1104,15 @@ edit_interface_rep::update_text_toolbar () {
// 注意:rectangle 不是 list 类型,不能使用 is_nil
// 我们检查矩形坐标是否有效
if (text_selr->x1 < text_selr->x2 && text_selr->y1 < text_selr->y2) {
- show_text_toolbar (text_selr, magf, get_scroll_x (),
- get_scroll_y (), get_canvas_x (), get_canvas_y ());
+ show_text_toolbar (text_selr, magf, get_scroll_x (), get_scroll_y (),
+ get_canvas_x (), get_canvas_y ());
}
else {
// 即使矩形无效,也尝试显示工具栏(例如单个字符选区)
hide_text_toolbar ();
}
- } else {
+ }
+ else {
hide_text_toolbar ();
}
}
diff --git a/src/Plugins/Qt/QTMTextToolbar.cpp b/src/Plugins/Qt/QTMTextToolbar.cpp
index 1aae630bf3..d20d3b81dd 100644
--- a/src/Plugins/Qt/QTMTextToolbar.cpp
+++ b/src/Plugins/Qt/QTMTextToolbar.cpp
@@ -10,13 +10,13 @@
#include "QTMTextToolbar.hpp"
#include "bitmap_font.hpp"
+#include "moebius/data/scheme.hpp"
#include "qbuttongroup.h"
#include "qt_renderer.hpp"
#include "qt_utilities.hpp"
#include "scheme.hpp"
#include "server.hpp"
#include "tm_ostream.hpp"
-#include "moebius/data/scheme.hpp"
#include
#include
@@ -29,10 +29,11 @@
// 悬浮工具栏创建函数
QTMTextToolbar::QTMTextToolbar (QWidget* parent, qt_simple_widget_rep* owner)
- : QWidget (parent), owner (owner), layout (nullptr), cached_selection_mid_x (0),
- cached_selection_mid_y (0), cached_scroll_x (0), cached_scroll_y (0),
- cached_canvas_x (0), cached_canvas_y (0), cached_magf (0.0),
- painted (false), painted_count (0) {
+ : QWidget (parent), owner (owner), layout (nullptr),
+ cached_selection_mid_x (0), cached_selection_mid_y (0),
+ cached_scroll_x (0), cached_scroll_y (0), cached_canvas_x (0),
+ cached_canvas_y (0), cached_magf (0.0), painted (false),
+ painted_count (0) {
Q_INIT_RESOURCE (images);
setObjectName ("text_toolbar");
setWindowFlags (Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
@@ -112,28 +113,28 @@ QTMTextToolbar::QTMTextToolbar (QWidget* parent, qt_simple_widget_rep* owner)
layout->addWidget (alignRightBtn);
// 连接按钮点击事件
- connect (boldBtn, &QToolButton::clicked, this, [this]() {
+ connect (boldBtn, &QToolButton::clicked, this, [this] () {
if (this->owner) {
call ("toggle-bold");
}
});
- connect (italicBtn, &QToolButton::clicked, this, [this]() {
+ connect (italicBtn, &QToolButton::clicked, this, [this] () {
if (this->owner) {
call ("toggle-italic");
}
});
- connect (underlineBtn, &QToolButton::clicked, this, [this]() {
+ connect (underlineBtn, &QToolButton::clicked, this, [this] () {
if (this->owner) {
call ("toggle-underlined");
}
});
- connect (highlightBtn, &QToolButton::clicked, this, [this]() {
+ connect (highlightBtn, &QToolButton::clicked, this, [this] () {
if (this->owner) {
// 高亮功能
call ("mark-text");
}
});
- connect (colorBtn, &QToolButton::clicked, this, [this]() {
+ connect (colorBtn, &QToolButton::clicked, this, [this] () {
if (this->owner) {
// 文字颜色功能 - 打开颜色选择器
call ("interactive", object ("open-color-selector"));
@@ -153,9 +154,12 @@ QTMTextToolbar::QTMTextToolbar (QWidget* parent, qt_simple_widget_rep* owner)
if (this->owner) {
if (button == alignLeftBtn) {
call ("make-line-with", object ("par-mode"), object ("left"));
- } else if (button == alignCenterBtn) {
- call ("make-line-with", object ("par-mode"), object ("center"));
- } else if (button == alignRightBtn) {
+ }
+ else if (button == alignCenterBtn) {
+ call ("make-line-with", object ("par-mode"),
+ object ("center"));
+ }
+ else if (button == alignRightBtn) {
call ("make-line-with", object ("par-mode"), object ("right"));
}
}
@@ -167,8 +171,9 @@ QTMTextToolbar::QTMTextToolbar (QWidget* parent, qt_simple_widget_rep* owner)
QTMTextToolbar::~QTMTextToolbar () {}
void
-QTMTextToolbar::showTextToolbar (qt_renderer_rep* ren, rectangle selr, double magf,
- int scroll_x, int scroll_y, int canvas_x, int canvas_y) {
+QTMTextToolbar::showTextToolbar (qt_renderer_rep* ren, rectangle selr,
+ double magf, int scroll_x, int scroll_y,
+ int canvas_x, int canvas_y) {
cachePosition (selr, magf, scroll_x, scroll_y, canvas_x, canvas_y);
updatePosition (ren);
show ();
@@ -189,26 +194,27 @@ QTMTextToolbar::scrollBy (int x, int y) {
}
void
-QTMTextToolbar::cachePosition (rectangle selr, double magf, int scroll_x, int scroll_y,
- int canvas_x, int canvas_y) {
- cached_rect = selr;
- cached_magf = magf;
- cached_scroll_x = scroll_x;
- cached_scroll_y = scroll_y;
- cached_canvas_x = canvas_x;
- cached_canvas_y = canvas_y;
+QTMTextToolbar::cachePosition (rectangle selr, double magf, int scroll_x,
+ int scroll_y, int canvas_x, int canvas_y) {
+ cached_rect = selr;
+ cached_magf = magf;
+ cached_scroll_x= scroll_x;
+ cached_scroll_y= scroll_y;
+ cached_canvas_x= canvas_x;
+ cached_canvas_y= canvas_y;
// 计算选区中心位置
cached_selection_mid_x= (selr->x1 + selr->x2) * 0.5;
- cached_selection_mid_y= selr->y2; // 使用选区底部位置,使工具栏显示在选中文字正上方
+ cached_selection_mid_y=
+ selr->y2; // 使用选区底部位置,使工具栏显示在选中文字正上方
}
void
QTMTextToolbar::getCachedPosition (qt_renderer_rep* ren, int& x, int& y) {
- rectangle selr = cached_rect;
- double inv_unit = 1.0 / 256.0;
- double cx_logic = (selr->x1 + selr->x2) * 0.5;
- double top_logic= selr->y2; // 使用选区底部位置,使工具栏显示在选中文字正上方
+ rectangle selr = cached_rect;
+ double inv_unit= 1.0 / 256.0;
+ double cx_logic= (selr->x1 + selr->x2) * 0.5;
+ double top_logic= selr->y2; // 使用选区底部位置,使工具栏显示在选中文字正上方
// 使用公式计算QT坐标
double cx_px=
@@ -226,11 +232,13 @@ QTMTextToolbar::getCachedPosition (qt_renderer_rep* ren, int& x, int& y) {
top_px+= blank_top;
x= int (std::round (cx_px - cached_width * 0.5));
- y= int (std::round (top_px - cached_height)); // 在选区底部上方显示,与图片悬浮窗口一致
+ y= int (std::round (top_px -
+ cached_height)); // 在选区底部上方显示,与图片悬浮窗口一致
// 确保工具栏在视口内
if (x < 0) x= 0;
- if (y < 0) y= int (std::round (top_px + 10)); // 如果上面空间不够,显示在选区下方
+ if (y < 0)
+ y= int (std::round (top_px + 10)); // 如果上面空间不够,显示在选区下方
if (owner && owner->scrollarea () && owner->scrollarea ()->viewport ()) {
int vp_w= owner->scrollarea ()->viewport ()->width ();
int vp_h= owner->scrollarea ()->viewport ()->height ();
@@ -242,11 +250,12 @@ QTMTextToolbar::getCachedPosition (qt_renderer_rep* ren, int& x, int& y) {
void
QTMTextToolbar::autoSize () {
// 根据DPI和缩放因子自动调整大小
- QScreen* Screen = QGuiApplication::primaryScreen ();
- const double Dpi = Screen ? Screen->logicalDotsPerInch () : 96.0;
- const double Scale = Dpi / 96.0;
- const double totalScale= Scale * cached_magf * 12.0; // 原始3.0倍,扩大4倍后为12.0倍
- int btn_size;
+ QScreen* Screen= QGuiApplication::primaryScreen ();
+ const double Dpi = Screen ? Screen->logicalDotsPerInch () : 96.0;
+ const double Scale = Dpi / 96.0;
+ const double totalScale=
+ Scale * cached_magf * 12.0; // 原始3.0倍,扩大4倍后为12.0倍
+ int btn_size;
#if defined(Q_OS_MAC)
btn_size= int (50 * totalScale);
@@ -270,7 +279,8 @@ QTMTextToolbar::autoSize () {
alignRightBtn->setIconSize (icon_size);
// 设置按钮固定大小
- QSize fixed_size (btn_size + 32, btn_size + 32); // 内边距也扩大4倍 (8 * 4.0 = 32)
+ QSize fixed_size (btn_size + 32,
+ btn_size + 32); // 内边距也扩大4倍 (8 * 4.0 = 32)
boldBtn->setFixedSize (fixed_size);
italicBtn->setFixedSize (fixed_size);
underlineBtn->setFixedSize (fixed_size);
diff --git a/src/Plugins/Qt/QTMTextToolbar.hpp b/src/Plugins/Qt/QTMTextToolbar.hpp
index 6b1c12bb13..8b53c44792 100644
--- a/src/Plugins/Qt/QTMTextToolbar.hpp
+++ b/src/Plugins/Qt/QTMTextToolbar.hpp
@@ -40,22 +40,22 @@ class QTMTextToolbar : public QWidget {
int painted_count;
// 工具栏按钮
- QToolButton* boldBtn;
- QToolButton* italicBtn;
- QToolButton* underlineBtn;
- QToolButton* highlightBtn;
- QToolButton* colorBtn;
- QToolButton* alignLeftBtn;
- QToolButton* alignCenterBtn;
- QToolButton* alignRightBtn;
- QString btn_style;
+ QToolButton* boldBtn;
+ QToolButton* italicBtn;
+ QToolButton* underlineBtn;
+ QToolButton* highlightBtn;
+ QToolButton* colorBtn;
+ QToolButton* alignLeftBtn;
+ QToolButton* alignCenterBtn;
+ QToolButton* alignRightBtn;
+ QString btn_style;
public:
QTMTextToolbar (QWidget* parent, qt_simple_widget_rep* owner);
~QTMTextToolbar ();
void showTextToolbar (qt_renderer_rep* ren, rectangle selr, double magf,
- int scroll_x, int scroll_y, int canvas_x, int canvas_y);
+ int scroll_x, int scroll_y, int canvas_x, int canvas_y);
void updatePosition (qt_renderer_rep* ren);
void scrollBy (int x, int y);
void autoSize ();
diff --git a/src/Plugins/Qt/qt_simple_widget.cpp b/src/Plugins/Qt/qt_simple_widget.cpp
index 14e02108da..49a91eb023 100644
--- a/src/Plugins/Qt/qt_simple_widget.cpp
+++ b/src/Plugins/Qt/qt_simple_widget.cpp
@@ -19,9 +19,9 @@
#include "QTMCompletionPopup.hpp"
#include "QTMImagePopup.hpp"
#include "QTMMathCompletionPopup.hpp"
-#include "QTMTextToolbar.hpp"
#include "QTMMenuHelper.hpp"
#include "QTMStyle.hpp"
+#include "QTMTextToolbar.hpp"
#include "QTMWidget.hpp"
#include
#include
@@ -808,12 +808,12 @@ qt_simple_widget_rep::ensure_text_toolbar () {
void
qt_simple_widget_rep::show_text_toolbar (rectangle selr, double magf,
- int scroll_x, int scroll_y, int canvas_x,
- int canvas_y) {
+ int scroll_x, int scroll_y,
+ int canvas_x, int canvas_y) {
ensure_text_toolbar ();
qt_renderer_rep* ren= the_qt_renderer ();
textToolbar->showTextToolbar (ren, selr, magf, scroll_x, scroll_y, canvas_x,
- canvas_y);
+ canvas_y);
}
void
@@ -842,12 +842,12 @@ qt_simple_widget_rep::is_point_in_text_toolbar (SI x, SI y) {
if (!textToolbar) return false;
// 将逻辑坐标转换为像素坐标
- double inv_unit = 1.0 / 256.0;
- int px = int (std::round (x * inv_unit));
- int py = int (std::round (y * inv_unit));
+ double inv_unit= 1.0 / 256.0;
+ int px = int (std::round (x * inv_unit));
+ int py = int (std::round (y * inv_unit));
// 获取工具栏的几何位置
- QRect toolbarRect = textToolbar->geometry();
+ QRect toolbarRect= textToolbar->geometry ();
// 检查点是否在工具栏内
return toolbarRect.contains (px, py);
diff --git a/src/Plugins/Qt/qt_simple_widget.hpp b/src/Plugins/Qt/qt_simple_widget.hpp
index 5bc1278792..55c217229f 100644
--- a/src/Plugins/Qt/qt_simple_widget.hpp
+++ b/src/Plugins/Qt/qt_simple_widget.hpp
@@ -124,9 +124,8 @@ class qt_simple_widget_rep : public qt_widget_rep {
////////////////////// Text toolbar support
void ensure_text_toolbar ();
- void show_text_toolbar (rectangle selr, double magf,
- int scroll_x, int scroll_y, int canvas_x,
- int canvas_y);
+ void show_text_toolbar (rectangle selr, double magf, int scroll_x,
+ int scroll_y, int canvas_x, int canvas_y);
void hide_text_toolbar ();
void scroll_text_toolbar_by (SI x, SI y);
bool is_point_in_text_toolbar (SI x, SI y);
From be4ebe159f33ea1b34b7912d9ef5cf9cc90565df Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Fri, 23 Jan 2026 17:38:32 +0800
Subject: [PATCH 06/27] =?UTF-8?q?=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
devel/201_63.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 devel/201_63.md
diff --git a/devel/201_63.md b/devel/201_63.md
new file mode 100644
index 0000000000..4270ba0783
--- /dev/null
+++ b/devel/201_63.md
@@ -0,0 +1,5 @@
+# [201_63] 文字选中悬浮窗口初步实现
+
+## 如何测试
+1. 输入一段文字通过键盘或鼠标选中,会出现悬浮窗口
+2. 点击悬浮窗口按钮,实现的功能和模式工具栏一致,第五个按钮暂未实现
From e9964b73a9102eedd7f0520de2629c395240bd15 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Fri, 23 Jan 2026 17:40:36 +0800
Subject: [PATCH 07/27] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
TeXmacs/misc/images/images.qrc | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/TeXmacs/misc/images/images.qrc b/TeXmacs/misc/images/images.qrc
index 25b92dc7a4..c2f7023c74 100644
--- a/TeXmacs/misc/images/images.qrc
+++ b/TeXmacs/misc/images/images.qrc
@@ -22,11 +22,6 @@
ocr-button/middle-align.svg
ocr-button/right-align.svg
-
-
-
-
-
../pixmaps/liii-night/20x20/mode/tm_bold.svg
../pixmaps/liii-night/20x20/mode/tm_italic.svg
@@ -36,10 +31,6 @@
ocr-button/left-align-white.svg
ocr-button/middle-align-white.svg
ocr-button/right-align-white.svg
-
-
-
-
\ No newline at end of file
From 3206c1b7b3081afa86363763565c3e56b426215f Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Fri, 23 Jan 2026 19:51:27 +0800
Subject: [PATCH 08/27] =?UTF-8?q?=E6=9B=B4=E9=9A=8F=E7=A7=BB=E5=8A=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Plugins/Qt/QTMTextToolbar.cpp | 4 ++--
src/Plugins/Qt/QTMWidget.cpp | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/Plugins/Qt/QTMTextToolbar.cpp b/src/Plugins/Qt/QTMTextToolbar.cpp
index d20d3b81dd..849040eab3 100644
--- a/src/Plugins/Qt/QTMTextToolbar.cpp
+++ b/src/Plugins/Qt/QTMTextToolbar.cpp
@@ -189,8 +189,8 @@ QTMTextToolbar::updatePosition (qt_renderer_rep* ren) {
void
QTMTextToolbar::scrollBy (int x, int y) {
- cached_scroll_x+= x;
- cached_scroll_y+= y;
+ cached_scroll_x-= (int) (x / cached_magf);
+ cached_scroll_y-= (int) (y / cached_magf);
}
void
diff --git a/src/Plugins/Qt/QTMWidget.cpp b/src/Plugins/Qt/QTMWidget.cpp
index 78580a9568..1640c3ec2a 100644
--- a/src/Plugins/Qt/QTMWidget.cpp
+++ b/src/Plugins/Qt/QTMWidget.cpp
@@ -156,6 +156,7 @@ QTMWidget::scrollContentsBy (int dx, int dy) {
tm_widget ()->scroll_completion_popup_by (dx, dy);
tm_widget ()->scroll_math_completion_popup_by (dx, dy);
tm_widget ()->scroll_image_popup_by (dx, dy);
+ tm_widget ()->scroll_text_toolbar_by (dx, dy);
}
void
From a0461ab0c4f05b1e7ca451ddd4e2fcfdfbd31d25 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Fri, 30 Jan 2026 09:07:32 +0800
Subject: [PATCH 09/27] link color menu
---
src/Plugins/Qt/QTMTextToolbar.cpp | 30 +++++-
src/Plugins/Qt/color.md | 156 ++++++++++++++++++++++++++++++
2 files changed, 184 insertions(+), 2 deletions(-)
create mode 100644 src/Plugins/Qt/color.md
diff --git a/src/Plugins/Qt/QTMTextToolbar.cpp b/src/Plugins/Qt/QTMTextToolbar.cpp
index 849040eab3..94a7901e4c 100644
--- a/src/Plugins/Qt/QTMTextToolbar.cpp
+++ b/src/Plugins/Qt/QTMTextToolbar.cpp
@@ -136,8 +136,34 @@ QTMTextToolbar::QTMTextToolbar (QWidget* parent, qt_simple_widget_rep* owner)
});
connect (colorBtn, &QToolButton::clicked, this, [this] () {
if (this->owner) {
- // 文字颜色功能 - 打开颜色选择器
- call ("interactive", object ("open-color-selector"));
+ debug_std << "点击颜色按钮\n";
+
+ // 方案1:call("interactive", object("color-menu"))
+ // 编译通过,但可能不工作,因为 interactive 期望命令而不是菜单
+ //debug_std << "尝试方案1: call(\"interactive\", object(\"color-menu\"))\n";
+ //call ("interactive", object ("color-menu"));
+
+ // 方案2:eval("(interactive color-menu)")
+ // 编译通过,但可能同样的问题
+ // debug_std << "尝试方案2: eval(\"(interactive color-menu)\")\n";
+ // eval ("(interactive color-menu)");
+
+ // 方案3:eval("(menu-popup (lambda () (link color-menu)) (gui-position))")
+ // 编译通过,尝试使用 menu-popup 函数
+ // debug_std << "尝试方案3: menu-popup\n";
+ //eval ("(menu-popup (lambda () (link color-menu)) (gui-position))");
+
+ // 方案4:eval("(show-context-menu (lambda () (link color-menu)) (gui-position))")
+ // 编译通过,尝试使用 show-context-menu 函数
+ // debug_std << "尝试方案4: show-context-menu\n";
+ // eval ("(show-context-menu (lambda () (link color-menu)) (gui-position))");
+
+ // 方案5:call("interactive-color", ...)
+ // 编译通过,提供基本的颜色选择功能
+ // debug_std << "尝试方案5: interactive-color\n";
+ // call ("interactive-color",
+ // object ("(lambda (col) (make-with \"color\" col))"),
+ // object ("()"));
}
});
diff --git a/src/Plugins/Qt/color.md b/src/Plugins/Qt/color.md
new file mode 100644
index 0000000000..a8806d3df3
--- /dev/null
+++ b/src/Plugins/Qt/color.md
@@ -0,0 +1,156 @@
+文本模式工具栏中的选择前景色功能分析
+
+ 基于您提供的 color-menu 代码片段和我的分析,以下是文本模式工具栏中选择前景色功能的完整实现机制:
+
+ 1. 调用链分析
+
+ 从工具栏按钮到颜色选择器的完整调用路径:
+
+ 文本模式工具栏颜色按钮点击
+ ↓
+ text-format-icons 中的颜色按钮定义 (TeXmacs/progs/text/text-menu.scm:633-634)
+ ↓
+ (=> (balloon (icon "tm_color.xpm") "Select a foreground color") (link color-menu))
+ ↓
+ color-menu 定义 (TeXmacs/progs/generic/format-menu.scm:73-82)
+ ↓
+ (with setter (lambda (col) (make-with "color" col)) …)
+ ↓
+ ("Palette" (interactive-color setter '()))
+ ↓
+ interactive-color 函数 (TeXmacs/progs/kernel/gui/menu-widget.scm:1243-1250)
+ ↓
+ widget-color-picker Scheme 函数
+ ↓
+ color_picker_widget C++ 函数 (src/Plugins/Qt/qt_widget.cpp:594-597)
+ ↓
+ qt_color_picker_widget_rep C++ 类 (src/Plugins/Qt/qt_color_picker_widget.cpp)
+ ↓
+ QColorDialog::getColor() Qt 原生颜色选择器
+
+ 2. color-menu 功能详解
+
+ 您提供的 color-menu 代码片段包含以下选项:
+
+ (menu-bind color-menu
+ (with setter (lambda (col) (make-with "color" col))
+ (if (allow-pattern-colors?)
+ (pick-background "" (setter answer)))
+ (if (not (allow-pattern-colors?))
+ (pick-color (setter answer)))
+ ("Palette" (interactive-color setter '()))
+ (if (allow-pattern-colors?)
+ ("Pattern" (open-pattern-selector setter "1cm")))
+ ("Other" (make-interactive-with "color"))))
+
+ 各选项功能:
+
+ 1. pick-background / pick-color - 快速颜色选择(预定义颜色网格)
+ 2. "Palette" - 打开完整的颜色选择器对话框
+ 3. "Pattern" - 打开图案选择器(如果允许图案颜色)
+ 4. "Other" - 交互式颜色输入对话框
+
+ 3. 核心函数分析
+
+ make-with 函数 (src/Edit/Modify/edit_dynamic.cpp:414-421)
+
+ void edit_dynamic_rep::make_with (string var, string val) {
+ if (selection_active_normal ()) {
+ tree t = remove_changes_in (selection_get (), var);
+ selection_cut ();
+ insert_tree (tree (WITH, var, val, t), path (2, end (t)));
+ }
+ else insert_tree (tree (WITH, var, val, ""), path (2, 0));
+ }
+ 功能:创建 with 环境来设置文本属性
+ - var = "color"(颜色属性)
+ - val = 颜色值(如 "#ff0000"、"red" 等)
+ - 如果有选区,将选区内容包装在 with 环境中
+ - 如果没有选区,在当前光标位置插入 with 环境
+
+ interactive-color 函数 (TeXmacs/progs/kernel/gui/menu-widget.scm:1243-1250)
+
+ (tm-define (interactive-color cmd proposals)
+ (:interactive #t)
+ (set! proposals (map tm->tree proposals))
+ (if (not (qt-gui?))
+ (interactive-rgb-picker cmd proposals)
+ (with p (lambda (com) (widget-color-picker com #f proposals))
+ (with cmd* (lambda (t) (when t (cmd (tm->stree t))))
+ (interactive-window p cmd* "Choose color")))))
+ 功能:创建交互式颜色选择器
+ - 如果是 Qt GUI,使用 widget-color-picker
+ - 否则使用 interactive-rgb-picker
+ - cmd 参数是回调函数(即 setter = (lambda (col) (make-with "color" col)))
+
+ color_picker_widget 函数 (src/Plugins/Qt/qt_widget.cpp:594-597)
+
+ widget color_picker_widget (command call_back, bool bg, array proposals) {
+ if (headless_mode) return headless_widget ();
+ return tm_new (call_back, bg, proposals);
+ }
+
+ Qt 颜色选择器实现 (src/Plugins/Qt/qt_color_picker_widget.cpp:66-80)
+
+ void qt_color_picker_widget_rep::showDialog () {
+ // …
+ QColor _sel = QColorDialog::getColor(Qt::white);
+ if (_sel.isValid ()) {
+ _commandAfterExecution (list_object (object (tree (from_qcolor (_sel)))));
+ }
+ }
+ 功能:调用 Qt 原生颜色选择对话框,将选择的颜色传递给回调函数
+
+ 4. 数据结构转换
+
+ 颜色数据的转换流程:
+ QColor (Qt 颜色对象)
+ ↓ from_qcolor()
+ string (颜色字符串,如 "#ff0000")
+ ↓ tree()
+ tree (TeXmacs 树结构)
+ ↓ object()
+ object (Scheme 对象)
+ ↓ list_object()
+ list_object (Scheme 列表对象)
+ ↓ _commandAfterExecution()
+ 执行回调函数 setter
+ ↓ (lambda (col) (make-with "color" col))
+ make-with "color" col
+ ↓ 创建 with 环境设置文本颜色
+
+ 5. 在文本模式工具栏中的位置
+
+ 调用层级:
+ texmacs-mode-icons (主模式图标)
+ ↓ (if (in-text?) (link text-icons))
+ text-icons (文本模式图标)
+ ↓ (link text-inline-icons)
+ text-inline-icons
+ ↓ (link text-format-icons)
+ text-format-icons (文本格式图标)
+ ↓ (=> (balloon (icon "tm_color.xpm") "Select a foreground color") (link color-menu))
+ color-menu (颜色菜单)
+
+ 6. 关键文件位置
+
+ 1. 颜色菜单定义:TeXmacs/progs/generic/format-menu.scm:73-82
+ 2. 文本模式颜色按钮:TeXmacs/progs/text/text-menu.scm:633-634
+ 3. 交互式颜色选择器:TeXmacs/progs/kernel/gui/menu-widget.scm:1243-1250
+ 4. C++ make_with 实现:src/Edit/Modify/edit_dynamic.cpp:414-421
+ 5. Qt 颜色选择器:src/Plugins/Qt/qt_color_picker_widget.cpp:66-80
+ 6. 颜色选择器工厂函数:src/Plugins/Qt/qt_widget.cpp:594-597
+
+ 7. 工作流程总结
+
+ 1. 用户点击:在文本模式下点击工具栏中的颜色按钮(tm_color.xpm 图标)
+ 2. 菜单展开:显示 color-menu 子菜单
+ 3. 选择"Palette":用户点击"Palette"选项
+ 4. 打开颜色选择器:调用 interactive-color → widget-color-picker → color_picker_widget
+ 5. Qt 对话框:显示 Qt 原生颜色选择对话框 QColorDialog::getColor()
+ 6. 颜色选择:用户选择颜色并确认
+ 7. 回调执行:颜色值通过回调链传递回 setter 函数
+ 8. 应用颜色:make-with "color" col 创建 with 环境设置文本颜色
+ 9. 文档更新:选中的文本或当前光标位置应用新的前景色
+
+ 这个机制展示了 TeXmacs 如何将 Scheme 配置、C++ 核心功能和 Qt GUI 组件紧密结合,提供了完整的颜色选择功能。
\ No newline at end of file
From 4691fb554ad6d8790cbe7d5e7c07b210596cf977 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 11:17:52 +0800
Subject: [PATCH 10/27] =?UTF-8?q?scheme=E5=AE=9E=E7=8E=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
TeXmacs/progs/generic/text-toolbar.scm | 34 ++++
src/Plugins/Qt/QTMTextToolbar.cpp | 231 +++++++++----------------
src/Plugins/Qt/QTMTextToolbar.hpp | 17 +-
3 files changed, 116 insertions(+), 166 deletions(-)
create mode 100644 TeXmacs/progs/generic/text-toolbar.scm
diff --git a/TeXmacs/progs/generic/text-toolbar.scm b/TeXmacs/progs/generic/text-toolbar.scm
new file mode 100644
index 0000000000..1da5a1545a
--- /dev/null
+++ b/TeXmacs/progs/generic/text-toolbar.scm
@@ -0,0 +1,34 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; MODULE : text-toolbar.scm
+;; DESCRIPTION : text selection toolbar icons
+;; COPYRIGHT : (C) 2026
+;;
+;; 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
+;; in the root directory or .
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(texmacs-module (generic text-toolbar)
+ (:use (generic format-edit)
+ (generic format-menu)
+ (generic generic-edit)))
+
+(menu-bind text-toolbar-icons
+ ((balloon (icon "tm_bold.xpm") "Write bold text")
+ (toggle-bold))
+ ((balloon (icon "tm_italic.xpm") "Write italic text")
+ (toggle-italic))
+ ((balloon (icon "tm_underline.xpm") "Write underline")
+ (toggle-underlined))
+ ((balloon (icon "tm_marked.svg") "Marked text")
+ (mark-text))
+ (=> (balloon (icon "tm_color.xpm") "Select a foreground color")
+ (link color-menu))
+ ((balloon (icon "tm_align_left.xpm") "Align text to the left")
+ (make-line-with "par-mode" "left"))
+ ((balloon (icon "tm_align_center.xpm") "Center text")
+ (make-line-with "par-mode" "center"))
+ ((balloon (icon "tm_align_right.xpm") "Align text to the right")
+ (make-line-with "par-mode" "right")))
diff --git a/src/Plugins/Qt/QTMTextToolbar.cpp b/src/Plugins/Qt/QTMTextToolbar.cpp
index 94a7901e4c..0364a79d6e 100644
--- a/src/Plugins/Qt/QTMTextToolbar.cpp
+++ b/src/Plugins/Qt/QTMTextToolbar.cpp
@@ -9,9 +9,10 @@
******************************************************************************/
#include "QTMTextToolbar.hpp"
+#include "QTMStyle.hpp"
#include "bitmap_font.hpp"
#include "moebius/data/scheme.hpp"
-#include "qbuttongroup.h"
+#include "object_l5.hpp"
#include "qt_renderer.hpp"
#include "qt_utilities.hpp"
#include "scheme.hpp"
@@ -19,12 +20,17 @@
#include "tm_ostream.hpp"
#include
+#include
#include
#include
+#include
#include
#include
#include
+#include
+#include
#include
+#include
#include
// 悬浮工具栏创建函数
@@ -53,149 +59,77 @@ QTMTextToolbar::QTMTextToolbar (QWidget* parent, qt_simple_widget_rep* owner)
effect->setColor (QColor (0, 0, 0, 120));
this->setGraphicsEffect (effect);
- // 创建按钮
- boldBtn= new QToolButton ();
- boldBtn->setObjectName ("text-toolbar-button");
- boldBtn->setProperty ("icon-name", "bold");
- boldBtn->setCheckable (true);
- boldBtn->setToolTip (qt_translate ("Bold"));
-
- italicBtn= new QToolButton ();
- italicBtn->setObjectName ("text-toolbar-button");
- italicBtn->setProperty ("icon-name", "italic");
- italicBtn->setCheckable (true);
- italicBtn->setToolTip (qt_translate ("Italic"));
-
- underlineBtn= new QToolButton ();
- underlineBtn->setObjectName ("text-toolbar-button");
- underlineBtn->setProperty ("icon-name", "underline");
- underlineBtn->setCheckable (true);
- underlineBtn->setToolTip (qt_translate ("Underline"));
-
- highlightBtn= new QToolButton ();
- highlightBtn->setObjectName ("text-toolbar-button");
- highlightBtn->setProperty ("icon-name", "highlight");
- highlightBtn->setCheckable (true);
- highlightBtn->setToolTip (qt_translate ("Highlight"));
-
- colorBtn= new QToolButton ();
- colorBtn->setObjectName ("text-toolbar-button");
- colorBtn->setProperty ("icon-name", "color");
- colorBtn->setCheckable (false);
- colorBtn->setToolTip (qt_translate ("Text color"));
-
- alignLeftBtn= new QToolButton ();
- alignLeftBtn->setObjectName ("text-toolbar-button");
- alignLeftBtn->setProperty ("icon-name", "left-align");
- alignLeftBtn->setCheckable (true);
- alignLeftBtn->setToolTip (qt_translate ("Align left"));
-
- alignCenterBtn= new QToolButton ();
- alignCenterBtn->setObjectName ("text-toolbar-button");
- alignCenterBtn->setProperty ("icon-name", "middle-align");
- alignCenterBtn->setCheckable (true);
- alignCenterBtn->setToolTip (qt_translate ("Align center"));
-
- alignRightBtn= new QToolButton ();
- alignRightBtn->setObjectName ("text-toolbar-button");
- alignRightBtn->setProperty ("icon-name", "right-align");
- alignRightBtn->setCheckable (true);
- alignRightBtn->setToolTip (qt_translate ("Align right"));
-
- // 添加按钮到布局
- layout->addWidget (boldBtn);
- layout->addWidget (italicBtn);
- layout->addWidget (underlineBtn);
- layout->addWidget (highlightBtn);
- layout->addWidget (colorBtn);
- layout->addWidget (alignLeftBtn);
- layout->addWidget (alignCenterBtn);
- layout->addWidget (alignRightBtn);
-
- // 连接按钮点击事件
- connect (boldBtn, &QToolButton::clicked, this, [this] () {
- if (this->owner) {
- call ("toggle-bold");
+ rebuildButtonsFromScheme ();
+}
+
+QTMTextToolbar::~QTMTextToolbar () {}
+
+void
+QTMTextToolbar::clearButtons () {
+ if (!layout) return;
+ QLayoutItem* item= nullptr;
+ while ((item= layout->takeAt (0)) != nullptr) {
+ if (QWidget* w= item->widget ()) {
+ w->setParent (nullptr);
+ delete w;
}
- });
- connect (italicBtn, &QToolButton::clicked, this, [this] () {
- if (this->owner) {
- call ("toggle-italic");
+ else if (QLayout* l= item->layout ()) {
+ delete l;
}
- });
- connect (underlineBtn, &QToolButton::clicked, this, [this] () {
- if (this->owner) {
- call ("toggle-underlined");
+ delete item;
+ }
+}
+
+void
+QTMTextToolbar::rebuildButtonsFromScheme () {
+ eval ("(use-modules (generic text-toolbar))");
+ object menu= eval ("'(horizontal (link text-toolbar-icons))");
+ object obj = call ("make-menu-widget", menu, 0);
+ if (!is_widget (obj)) return;
+
+ text_toolbar_widget= concrete (as_widget (obj));
+ QList* list= text_toolbar_widget->get_qactionlist ();
+ if (!list) return;
+
+ clearButtons ();
+
+ for (int i= 0; i < list->count (); ++i) {
+ QAction* action= list->at (i);
+ if (!action) continue;
+
+ if (action->isSeparator ()) {
+ QFrame* sep= new QFrame (this);
+ sep->setFrameShape (QFrame::VLine);
+ sep->setFrameShadow (QFrame::Plain);
+ sep->setFixedWidth (1);
+ sep->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Expanding);
+ layout->addWidget (sep);
+ continue;
}
- });
- connect (highlightBtn, &QToolButton::clicked, this, [this] () {
- if (this->owner) {
- // 高亮功能
- call ("mark-text");
+
+ if (action->text ().isNull () && action->icon ().isNull ()) {
+ layout->addSpacing (8);
+ continue;
}
- });
- connect (colorBtn, &QToolButton::clicked, this, [this] () {
- if (this->owner) {
- debug_std << "点击颜色按钮\n";
-
- // 方案1:call("interactive", object("color-menu"))
- // 编译通过,但可能不工作,因为 interactive 期望命令而不是菜单
- //debug_std << "尝试方案1: call(\"interactive\", object(\"color-menu\"))\n";
- //call ("interactive", object ("color-menu"));
-
- // 方案2:eval("(interactive color-menu)")
- // 编译通过,但可能同样的问题
- // debug_std << "尝试方案2: eval(\"(interactive color-menu)\")\n";
- // eval ("(interactive color-menu)");
-
- // 方案3:eval("(menu-popup (lambda () (link color-menu)) (gui-position))")
- // 编译通过,尝试使用 menu-popup 函数
- // debug_std << "尝试方案3: menu-popup\n";
- //eval ("(menu-popup (lambda () (link color-menu)) (gui-position))");
-
- // 方案4:eval("(show-context-menu (lambda () (link color-menu)) (gui-position))")
- // 编译通过,尝试使用 show-context-menu 函数
- // debug_std << "尝试方案4: show-context-menu\n";
- // eval ("(show-context-menu (lambda () (link color-menu)) (gui-position))");
-
- // 方案5:call("interactive-color", ...)
- // 编译通过,提供基本的颜色选择功能
- // debug_std << "尝试方案5: interactive-color\n";
- // call ("interactive-color",
- // object ("(lambda (col) (make-with \"color\" col))"),
- // object ("()"));
+
+ if (QWidgetAction* wa= qobject_cast (action)) {
+ QWidget* w= wa->requestWidget (this);
+ if (w) layout->addWidget (w);
+ continue;
}
- });
-
- // 对齐按钮分组
- QButtonGroup* alignGroup= new QButtonGroup (this);
- alignGroup->addButton (alignLeftBtn);
- alignGroup->addButton (alignCenterBtn);
- alignGroup->addButton (alignRightBtn);
- alignGroup->setExclusive (true);
-
- connect (alignGroup,
- QOverload::of (&QButtonGroup::buttonClicked), this,
- [=] (QAbstractButton* button) {
- if (this->owner) {
- if (button == alignLeftBtn) {
- call ("make-line-with", object ("par-mode"), object ("left"));
- }
- else if (button == alignCenterBtn) {
- call ("make-line-with", object ("par-mode"),
- object ("center"));
- }
- else if (button == alignRightBtn) {
- call ("make-line-with", object ("par-mode"), object ("right"));
- }
- }
- });
+
+ QToolButton* button= new QToolButton (this);
+ button->setObjectName ("text-toolbar-button");
+ button->setAutoRaise (true);
+ button->setDefaultAction (action);
+ button->setPopupMode (QToolButton::InstantPopup);
+ if (tm_style_sheet == "") button->setStyle (qtmstyle ());
+ layout->addWidget (button);
+ }
autoSize ();
}
-QTMTextToolbar::~QTMTextToolbar () {}
-
void
QTMTextToolbar::showTextToolbar (qt_renderer_rep* ren, rectangle selr,
double magf, int scroll_x, int scroll_y,
@@ -295,26 +229,17 @@ QTMTextToolbar::autoSize () {
// 设置按钮大小
QSize icon_size (btn_size, btn_size);
- boldBtn->setIconSize (icon_size);
- italicBtn->setIconSize (icon_size);
- underlineBtn->setIconSize (icon_size);
- highlightBtn->setIconSize (icon_size);
- colorBtn->setIconSize (icon_size);
- alignLeftBtn->setIconSize (icon_size);
- alignCenterBtn->setIconSize (icon_size);
- alignRightBtn->setIconSize (icon_size);
-
- // 设置按钮固定大小
QSize fixed_size (btn_size + 32,
btn_size + 32); // 内边距也扩大4倍 (8 * 4.0 = 32)
- boldBtn->setFixedSize (fixed_size);
- italicBtn->setFixedSize (fixed_size);
- underlineBtn->setFixedSize (fixed_size);
- highlightBtn->setFixedSize (fixed_size);
- colorBtn->setFixedSize (fixed_size);
- alignLeftBtn->setFixedSize (fixed_size);
- alignCenterBtn->setFixedSize (fixed_size);
- alignRightBtn->setFixedSize (fixed_size);
+ const QList buttons=
+ findChildren (QString (), Qt::FindChildrenRecursively);
+ for (QToolButton* button : buttons) {
+ if (!button) continue;
+ if (button->objectName ().isEmpty ())
+ button->setObjectName ("text-toolbar-button");
+ button->setIconSize (icon_size);
+ button->setFixedSize (fixed_size);
+ }
// 调整窗口大小
adjustSize ();
diff --git a/src/Plugins/Qt/QTMTextToolbar.hpp b/src/Plugins/Qt/QTMTextToolbar.hpp
index 8b53c44792..622664abd4 100644
--- a/src/Plugins/Qt/QTMTextToolbar.hpp
+++ b/src/Plugins/Qt/QTMTextToolbar.hpp
@@ -18,7 +18,6 @@
#include
#include
#include
-#include
#include
class QTMTextToolbar : public QWidget {
@@ -38,17 +37,7 @@ class QTMTextToolbar : public QWidget {
double cached_magf; // 缩放因子
bool painted;
int painted_count;
-
- // 工具栏按钮
- QToolButton* boldBtn;
- QToolButton* italicBtn;
- QToolButton* underlineBtn;
- QToolButton* highlightBtn;
- QToolButton* colorBtn;
- QToolButton* alignLeftBtn;
- QToolButton* alignCenterBtn;
- QToolButton* alignRightBtn;
- QString btn_style;
+ qt_widget text_toolbar_widget;
public:
QTMTextToolbar (QWidget* parent, qt_simple_widget_rep* owner);
@@ -64,7 +53,9 @@ class QTMTextToolbar : public QWidget {
void cachePosition (rectangle selr, double magf, int scroll_x, int scroll_y,
int canvas_x, int canvas_y);
void getCachedPosition (qt_renderer_rep* ren, int& x, int& y);
+ void rebuildButtonsFromScheme ();
+ void clearButtons ();
bool eventFilter (QObject* obj, QEvent* event) override;
};
-#endif // QT_TEXT_TOOLBAR_HPP
\ No newline at end of file
+#endif // QT_TEXT_TOOLBAR_HPP
From 25fc892df9673824ed49af4682727361b1cc8ec4 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 11:56:25 +0800
Subject: [PATCH 11/27] =?UTF-8?q?=E5=9B=BE=E6=A0=87=E6=9B=B4=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../liii-night/20x20/mode/left-align.svg | 8 ++++
.../liii-night/20x20/mode/middle-align.svg | 8 ++++
.../liii-night/20x20/mode/right-align.svg | 8 ++++
.../pixmaps/liii/20x20/mode/left-align.svg | 8 ++++
.../pixmaps/liii/20x20/mode/middle-align.svg | 8 ++++
.../pixmaps/liii/20x20/mode/right-align.svg | 8 ++++
TeXmacs/misc/themes/liii-night.css | 37 ------------------
TeXmacs/misc/themes/liii.css | 38 -------------------
TeXmacs/progs/generic/text-toolbar.scm | 6 +--
9 files changed, 51 insertions(+), 78 deletions(-)
create mode 100644 TeXmacs/misc/pixmaps/liii-night/20x20/mode/left-align.svg
create mode 100644 TeXmacs/misc/pixmaps/liii-night/20x20/mode/middle-align.svg
create mode 100644 TeXmacs/misc/pixmaps/liii-night/20x20/mode/right-align.svg
create mode 100644 TeXmacs/misc/pixmaps/liii/20x20/mode/left-align.svg
create mode 100644 TeXmacs/misc/pixmaps/liii/20x20/mode/middle-align.svg
create mode 100644 TeXmacs/misc/pixmaps/liii/20x20/mode/right-align.svg
diff --git a/TeXmacs/misc/pixmaps/liii-night/20x20/mode/left-align.svg b/TeXmacs/misc/pixmaps/liii-night/20x20/mode/left-align.svg
new file mode 100644
index 0000000000..002d21b022
--- /dev/null
+++ b/TeXmacs/misc/pixmaps/liii-night/20x20/mode/left-align.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/pixmaps/liii-night/20x20/mode/middle-align.svg b/TeXmacs/misc/pixmaps/liii-night/20x20/mode/middle-align.svg
new file mode 100644
index 0000000000..7c55d0603b
--- /dev/null
+++ b/TeXmacs/misc/pixmaps/liii-night/20x20/mode/middle-align.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/pixmaps/liii-night/20x20/mode/right-align.svg b/TeXmacs/misc/pixmaps/liii-night/20x20/mode/right-align.svg
new file mode 100644
index 0000000000..a06c661af7
--- /dev/null
+++ b/TeXmacs/misc/pixmaps/liii-night/20x20/mode/right-align.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/pixmaps/liii/20x20/mode/left-align.svg b/TeXmacs/misc/pixmaps/liii/20x20/mode/left-align.svg
new file mode 100644
index 0000000000..e63297a38a
--- /dev/null
+++ b/TeXmacs/misc/pixmaps/liii/20x20/mode/left-align.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/pixmaps/liii/20x20/mode/middle-align.svg b/TeXmacs/misc/pixmaps/liii/20x20/mode/middle-align.svg
new file mode 100644
index 0000000000..1ffc2c05b6
--- /dev/null
+++ b/TeXmacs/misc/pixmaps/liii/20x20/mode/middle-align.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/pixmaps/liii/20x20/mode/right-align.svg b/TeXmacs/misc/pixmaps/liii/20x20/mode/right-align.svg
new file mode 100644
index 0000000000..4cf62a85d8
--- /dev/null
+++ b/TeXmacs/misc/pixmaps/liii/20x20/mode/right-align.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/TeXmacs/misc/themes/liii-night.css b/TeXmacs/misc/themes/liii-night.css
index 21c50cd88d..abb2220ff7 100644
--- a/TeXmacs/misc/themes/liii-night.css
+++ b/TeXmacs/misc/themes/liii-night.css
@@ -881,43 +881,6 @@ QWidget#text_toolbar {
border-radius: 8px;
}
-/*文本工具栏按钮图标*/
-QToolButton#text-toolbar-button[icon-name="bold"] {
- qproperty-icon: url(":/pixmaps/liii-night/20x20/mode/tm_bold.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="italic"] {
- qproperty-icon: url(":/pixmaps/liii-night/20x20/mode/tm_italic.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="underline"] {
- qproperty-icon: url(":/pixmaps/liii-night/20x20/mode/tm_underline.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="highlight"] {
- qproperty-icon: url(":/pixmaps/liii-night/20x20/mode/tm_marked.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="color"] {
- qproperty-icon: url(":/pixmaps/liii-night/20x20/mode/tm_color.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="left-align"] {
- qproperty-icon: url(":/ocr-button/left-align-white.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="middle-align"] {
- qproperty-icon: url(":/ocr-button/middle-align-white.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="right-align"] {
- qproperty-icon: url(":/ocr-button/right-align-white.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="align-justify"] {
- qproperty-icon: url(":/text-toolbar/align-justify-white.svg");
-}
-
/*文本工具栏按钮样式*/
QToolButton#text-toolbar-button {
background-color: transparent;
diff --git a/TeXmacs/misc/themes/liii.css b/TeXmacs/misc/themes/liii.css
index 967fa36e57..9df2c74d0d 100644
--- a/TeXmacs/misc/themes/liii.css
+++ b/TeXmacs/misc/themes/liii.css
@@ -852,7 +852,6 @@ QWidget#auxiliary_container {
}
/*文本工具栏窗口样式*/
-
/*文本工具栏窗口样式*/
QWidget#text_toolbar {
background: #ffffff;
@@ -860,43 +859,6 @@ QWidget#text_toolbar {
border-radius: 8px;
}
-/*文本工具栏按钮图标*/
-QToolButton#text-toolbar-button[icon-name="bold"] {
- qproperty-icon: url(":/pixmaps/liii/20x20/mode/tm_bold.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="italic"] {
- qproperty-icon: url(":/pixmaps/liii/20x20/mode/tm_italic.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="underline"] {
- qproperty-icon: url(":/pixmaps/liii/20x20/mode/tm_underline.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="highlight"] {
- qproperty-icon: url(":/pixmaps/liii/20x20/mode/tm_marked.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="color"] {
- qproperty-icon: url(":/pixmaps/liii/20x20/mode/tm_color.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="left-align"] {
- qproperty-icon: url(":/ocr-button/left-align.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="middle-align"] {
- qproperty-icon: url(":/ocr-button/middle-align.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="right-align"] {
- qproperty-icon: url(":/ocr-button/right-align.svg");
-}
-
-QToolButton#text-toolbar-button[icon-name="align-justify"] {
- qproperty-icon: url(":/text-toolbar/align-justify.svg");
-}
-
/*文本工具栏按钮样式*/
QToolButton#text-toolbar-button {
background-color: transparent;
diff --git a/TeXmacs/progs/generic/text-toolbar.scm b/TeXmacs/progs/generic/text-toolbar.scm
index 1da5a1545a..99770ba5cf 100644
--- a/TeXmacs/progs/generic/text-toolbar.scm
+++ b/TeXmacs/progs/generic/text-toolbar.scm
@@ -26,9 +26,9 @@
(mark-text))
(=> (balloon (icon "tm_color.xpm") "Select a foreground color")
(link color-menu))
- ((balloon (icon "tm_align_left.xpm") "Align text to the left")
+ ((balloon (icon "left-align.xpm") "left")
(make-line-with "par-mode" "left"))
- ((balloon (icon "tm_align_center.xpm") "Center text")
+ ((balloon (icon "middle-align.xpm") "center")
(make-line-with "par-mode" "center"))
- ((balloon (icon "tm_align_right.xpm") "Align text to the right")
+ ((balloon (icon "right-align.xpm") "right")
(make-line-with "par-mode" "right")))
From 440c206bb2e7a5de83af4938e6a3a4b9a153f04d Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 13:22:02 +0800
Subject: [PATCH 12/27] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99?=
=?UTF-8?q?=E5=86=85=E5=AE=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
TeXmacs/misc/images/images.qrc | 20 ----
TeXmacs/misc/themes/liii.css | 1 -
devel/201_63.md | 2 +-
src/Plugins/Qt/QTMTextToolbar.cpp | 10 +-
src/Plugins/Qt/color.md | 156 ------------------------------
5 files changed, 6 insertions(+), 183 deletions(-)
delete mode 100644 src/Plugins/Qt/color.md
diff --git a/TeXmacs/misc/images/images.qrc b/TeXmacs/misc/images/images.qrc
index c2f7023c74..3609a6851d 100644
--- a/TeXmacs/misc/images/images.qrc
+++ b/TeXmacs/misc/images/images.qrc
@@ -11,26 +11,6 @@
ocr-button/middle-align-white.svg
ocr-button/right-align-white.svg
ocr-button/ocr-white.svg
-
-
- ../pixmaps/liii/20x20/mode/tm_bold.svg
- ../pixmaps/liii/20x20/mode/tm_italic.svg
- ../pixmaps/liii/20x20/mode/tm_underline.svg
- ../pixmaps/liii/20x20/mode/tm_marked.svg
- ../pixmaps/liii/20x20/mode/tm_color.svg
- ocr-button/left-align.svg
- ocr-button/middle-align.svg
- ocr-button/right-align.svg
-
-
- ../pixmaps/liii-night/20x20/mode/tm_bold.svg
- ../pixmaps/liii-night/20x20/mode/tm_italic.svg
- ../pixmaps/liii-night/20x20/mode/tm_underline.svg
- ../pixmaps/liii-night/20x20/mode/tm_marked.svg
- ../pixmaps/liii-night/20x20/mode/tm_color.svg
- ocr-button/left-align-white.svg
- ocr-button/middle-align-white.svg
- ocr-button/right-align-white.svg
\ No newline at end of file
diff --git a/TeXmacs/misc/themes/liii.css b/TeXmacs/misc/themes/liii.css
index 9df2c74d0d..109400fb2d 100644
--- a/TeXmacs/misc/themes/liii.css
+++ b/TeXmacs/misc/themes/liii.css
@@ -851,7 +851,6 @@ QWidget#auxiliary_container {
background-color: rgba(0, 0, 0, 0.2);
}
-/*文本工具栏窗口样式*/
/*文本工具栏窗口样式*/
QWidget#text_toolbar {
background: #ffffff;
diff --git a/devel/201_63.md b/devel/201_63.md
index 4270ba0783..a4e697cec3 100644
--- a/devel/201_63.md
+++ b/devel/201_63.md
@@ -2,4 +2,4 @@
## 如何测试
1. 输入一段文字通过键盘或鼠标选中,会出现悬浮窗口
-2. 点击悬浮窗口按钮,实现的功能和模式工具栏一致,第五个按钮暂未实现
+2. 依次点击悬浮窗口按钮,实现的功能和模式工具栏一致
diff --git a/src/Plugins/Qt/QTMTextToolbar.cpp b/src/Plugins/Qt/QTMTextToolbar.cpp
index 0364a79d6e..dc67eeeecf 100644
--- a/src/Plugins/Qt/QTMTextToolbar.cpp
+++ b/src/Plugins/Qt/QTMTextToolbar.cpp
@@ -19,8 +19,8 @@
#include "server.hpp"
#include "tm_ostream.hpp"
-#include
#include
+#include
#include
#include
#include
@@ -87,7 +87,7 @@ QTMTextToolbar::rebuildButtonsFromScheme () {
object obj = call ("make-menu-widget", menu, 0);
if (!is_widget (obj)) return;
- text_toolbar_widget= concrete (as_widget (obj));
+ text_toolbar_widget = concrete (as_widget (obj));
QList* list= text_toolbar_widget->get_qactionlist ();
if (!list) return;
@@ -228,9 +228,9 @@ QTMTextToolbar::autoSize () {
}
// 设置按钮大小
- QSize icon_size (btn_size, btn_size);
- QSize fixed_size (btn_size + 32,
- btn_size + 32); // 内边距也扩大4倍 (8 * 4.0 = 32)
+ QSize icon_size (btn_size, btn_size);
+ QSize fixed_size (btn_size + 32,
+ btn_size + 32); // 内边距也扩大4倍 (8 * 4.0 = 32)
const QList buttons=
findChildren (QString (), Qt::FindChildrenRecursively);
for (QToolButton* button : buttons) {
diff --git a/src/Plugins/Qt/color.md b/src/Plugins/Qt/color.md
deleted file mode 100644
index a8806d3df3..0000000000
--- a/src/Plugins/Qt/color.md
+++ /dev/null
@@ -1,156 +0,0 @@
-文本模式工具栏中的选择前景色功能分析
-
- 基于您提供的 color-menu 代码片段和我的分析,以下是文本模式工具栏中选择前景色功能的完整实现机制:
-
- 1. 调用链分析
-
- 从工具栏按钮到颜色选择器的完整调用路径:
-
- 文本模式工具栏颜色按钮点击
- ↓
- text-format-icons 中的颜色按钮定义 (TeXmacs/progs/text/text-menu.scm:633-634)
- ↓
- (=> (balloon (icon "tm_color.xpm") "Select a foreground color") (link color-menu))
- ↓
- color-menu 定义 (TeXmacs/progs/generic/format-menu.scm:73-82)
- ↓
- (with setter (lambda (col) (make-with "color" col)) …)
- ↓
- ("Palette" (interactive-color setter '()))
- ↓
- interactive-color 函数 (TeXmacs/progs/kernel/gui/menu-widget.scm:1243-1250)
- ↓
- widget-color-picker Scheme 函数
- ↓
- color_picker_widget C++ 函数 (src/Plugins/Qt/qt_widget.cpp:594-597)
- ↓
- qt_color_picker_widget_rep C++ 类 (src/Plugins/Qt/qt_color_picker_widget.cpp)
- ↓
- QColorDialog::getColor() Qt 原生颜色选择器
-
- 2. color-menu 功能详解
-
- 您提供的 color-menu 代码片段包含以下选项:
-
- (menu-bind color-menu
- (with setter (lambda (col) (make-with "color" col))
- (if (allow-pattern-colors?)
- (pick-background "" (setter answer)))
- (if (not (allow-pattern-colors?))
- (pick-color (setter answer)))
- ("Palette" (interactive-color setter '()))
- (if (allow-pattern-colors?)
- ("Pattern" (open-pattern-selector setter "1cm")))
- ("Other" (make-interactive-with "color"))))
-
- 各选项功能:
-
- 1. pick-background / pick-color - 快速颜色选择(预定义颜色网格)
- 2. "Palette" - 打开完整的颜色选择器对话框
- 3. "Pattern" - 打开图案选择器(如果允许图案颜色)
- 4. "Other" - 交互式颜色输入对话框
-
- 3. 核心函数分析
-
- make-with 函数 (src/Edit/Modify/edit_dynamic.cpp:414-421)
-
- void edit_dynamic_rep::make_with (string var, string val) {
- if (selection_active_normal ()) {
- tree t = remove_changes_in (selection_get (), var);
- selection_cut ();
- insert_tree (tree (WITH, var, val, t), path (2, end (t)));
- }
- else insert_tree (tree (WITH, var, val, ""), path (2, 0));
- }
- 功能:创建 with 环境来设置文本属性
- - var = "color"(颜色属性)
- - val = 颜色值(如 "#ff0000"、"red" 等)
- - 如果有选区,将选区内容包装在 with 环境中
- - 如果没有选区,在当前光标位置插入 with 环境
-
- interactive-color 函数 (TeXmacs/progs/kernel/gui/menu-widget.scm:1243-1250)
-
- (tm-define (interactive-color cmd proposals)
- (:interactive #t)
- (set! proposals (map tm->tree proposals))
- (if (not (qt-gui?))
- (interactive-rgb-picker cmd proposals)
- (with p (lambda (com) (widget-color-picker com #f proposals))
- (with cmd* (lambda (t) (when t (cmd (tm->stree t))))
- (interactive-window p cmd* "Choose color")))))
- 功能:创建交互式颜色选择器
- - 如果是 Qt GUI,使用 widget-color-picker
- - 否则使用 interactive-rgb-picker
- - cmd 参数是回调函数(即 setter = (lambda (col) (make-with "color" col)))
-
- color_picker_widget 函数 (src/Plugins/Qt/qt_widget.cpp:594-597)
-
- widget color_picker_widget (command call_back, bool bg, array proposals) {
- if (headless_mode) return headless_widget ();
- return tm_new (call_back, bg, proposals);
- }
-
- Qt 颜色选择器实现 (src/Plugins/Qt/qt_color_picker_widget.cpp:66-80)
-
- void qt_color_picker_widget_rep::showDialog () {
- // …
- QColor _sel = QColorDialog::getColor(Qt::white);
- if (_sel.isValid ()) {
- _commandAfterExecution (list_object (object (tree (from_qcolor (_sel)))));
- }
- }
- 功能:调用 Qt 原生颜色选择对话框,将选择的颜色传递给回调函数
-
- 4. 数据结构转换
-
- 颜色数据的转换流程:
- QColor (Qt 颜色对象)
- ↓ from_qcolor()
- string (颜色字符串,如 "#ff0000")
- ↓ tree()
- tree (TeXmacs 树结构)
- ↓ object()
- object (Scheme 对象)
- ↓ list_object()
- list_object (Scheme 列表对象)
- ↓ _commandAfterExecution()
- 执行回调函数 setter
- ↓ (lambda (col) (make-with "color" col))
- make-with "color" col
- ↓ 创建 with 环境设置文本颜色
-
- 5. 在文本模式工具栏中的位置
-
- 调用层级:
- texmacs-mode-icons (主模式图标)
- ↓ (if (in-text?) (link text-icons))
- text-icons (文本模式图标)
- ↓ (link text-inline-icons)
- text-inline-icons
- ↓ (link text-format-icons)
- text-format-icons (文本格式图标)
- ↓ (=> (balloon (icon "tm_color.xpm") "Select a foreground color") (link color-menu))
- color-menu (颜色菜单)
-
- 6. 关键文件位置
-
- 1. 颜色菜单定义:TeXmacs/progs/generic/format-menu.scm:73-82
- 2. 文本模式颜色按钮:TeXmacs/progs/text/text-menu.scm:633-634
- 3. 交互式颜色选择器:TeXmacs/progs/kernel/gui/menu-widget.scm:1243-1250
- 4. C++ make_with 实现:src/Edit/Modify/edit_dynamic.cpp:414-421
- 5. Qt 颜色选择器:src/Plugins/Qt/qt_color_picker_widget.cpp:66-80
- 6. 颜色选择器工厂函数:src/Plugins/Qt/qt_widget.cpp:594-597
-
- 7. 工作流程总结
-
- 1. 用户点击:在文本模式下点击工具栏中的颜色按钮(tm_color.xpm 图标)
- 2. 菜单展开:显示 color-menu 子菜单
- 3. 选择"Palette":用户点击"Palette"选项
- 4. 打开颜色选择器:调用 interactive-color → widget-color-picker → color_picker_widget
- 5. Qt 对话框:显示 Qt 原生颜色选择对话框 QColorDialog::getColor()
- 6. 颜色选择:用户选择颜色并确认
- 7. 回调执行:颜色值通过回调链传递回 setter 函数
- 8. 应用颜色:make-with "color" col 创建 with 环境设置文本颜色
- 9. 文档更新:选中的文本或当前光标位置应用新的前景色
-
- 这个机制展示了 TeXmacs 如何将 Scheme 配置、C++ 核心功能和 Qt GUI 组件紧密结合,提供了完整的颜色选择功能。
\ No newline at end of file
From b6ba8f9cecb8de79888e03c3f732258c9eae74f5 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 13:23:13 +0800
Subject: [PATCH 13/27] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99?=
=?UTF-8?q?=E5=86=85=E5=AE=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
TeXmacs/misc/images/images.qrc | 1 -
1 file changed, 1 deletion(-)
diff --git a/TeXmacs/misc/images/images.qrc b/TeXmacs/misc/images/images.qrc
index 3609a6851d..eab0c22212 100644
--- a/TeXmacs/misc/images/images.qrc
+++ b/TeXmacs/misc/images/images.qrc
@@ -11,6 +11,5 @@
ocr-button/middle-align-white.svg
ocr-button/right-align-white.svg
ocr-button/ocr-white.svg
-
\ No newline at end of file
From 42de5b09573cf4b055a9e2acf4e0a3b3239eb6f9 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 14:24:28 +0800
Subject: [PATCH 14/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=BF=BB=E8=AF=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
TeXmacs/progs/generic/text-toolbar.scm | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/TeXmacs/progs/generic/text-toolbar.scm b/TeXmacs/progs/generic/text-toolbar.scm
index 99770ba5cf..6df32c1c4f 100644
--- a/TeXmacs/progs/generic/text-toolbar.scm
+++ b/TeXmacs/progs/generic/text-toolbar.scm
@@ -26,9 +26,9 @@
(mark-text))
(=> (balloon (icon "tm_color.xpm") "Select a foreground color")
(link color-menu))
- ((balloon (icon "left-align.xpm") "left")
+ ((balloon (icon "left-align.xpm") "left aligned")
(make-line-with "par-mode" "left"))
((balloon (icon "middle-align.xpm") "center")
(make-line-with "par-mode" "center"))
- ((balloon (icon "right-align.xpm") "right")
+ ((balloon (icon "right-align.xpm") "right aligned")
(make-line-with "par-mode" "right")))
From 9c63a7b29b1ea02154a19ba04416dadfa485ba24 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 17:14:34 +0800
Subject: [PATCH 15/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Edit/Interface/edit_interface.cpp | 5 -----
src/Edit/Interface/edit_mouse.cpp | 7 +++++--
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/src/Edit/Interface/edit_interface.cpp b/src/Edit/Interface/edit_interface.cpp
index bd47322357..afb6eb3d45 100644
--- a/src/Edit/Interface/edit_interface.cpp
+++ b/src/Edit/Interface/edit_interface.cpp
@@ -648,11 +648,6 @@ edit_interface_rep::notify_change (int change) {
needs_update ();
if ((change & (THE_TREE | THE_SELECTION | THE_CURSOR)) != 0)
manual_focus_set (path (), (change & THE_TREE) != 0);
-
- // 当选区改变时,更新文本工具栏
- if ((change & THE_SELECTION) != 0) {
- update_text_toolbar ();
- }
}
bool
diff --git a/src/Edit/Interface/edit_mouse.cpp b/src/Edit/Interface/edit_mouse.cpp
index d40e93e500..bd856f43fe 100644
--- a/src/Edit/Interface/edit_mouse.cpp
+++ b/src/Edit/Interface/edit_mouse.cpp
@@ -884,8 +884,7 @@ edit_interface_rep::mouse_any (string type, SI x, SI y, int mods, time_t t,
if (type == "press-up") mouse_scroll (x, y, true);
if (type == "press-down") mouse_scroll (x, y, false);
- if ((type == "press-left") || (type == "release-left") ||
- (type == "end-drag-left") || (type == "press-middle") ||
+ if ((type == "press-left") || (type == "press-middle") ||
(type == "press-right")) {
// 当用户点击其他地方(不在文本工具栏内)时,隐藏文本工具栏
if (!is_point_in_text_toolbar (x, y)) {
@@ -1097,6 +1096,10 @@ edit_interface_rep::is_point_in_text_toolbar (SI x, SI y) {
void
edit_interface_rep::update_text_toolbar () {
+ if (left_dragging) {
+ hide_text_toolbar ();
+ return;
+ }
// 检查是否应该显示文本工具栏
if (should_show_text_toolbar ()) {
rectangle text_selr= get_text_selection_rect ();
From 082549a860c5b7bc258353036c7cb4ea2d8b0b3c Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 17:25:28 +0800
Subject: [PATCH 16/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Plugins/Qt/qt_simple_widget.cpp | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/Plugins/Qt/qt_simple_widget.cpp b/src/Plugins/Qt/qt_simple_widget.cpp
index 49a91eb023..f9d322030d 100644
--- a/src/Plugins/Qt/qt_simple_widget.cpp
+++ b/src/Plugins/Qt/qt_simple_widget.cpp
@@ -47,6 +47,7 @@ qt_simple_widget_rep::~qt_simple_widget_rep () {
if (backingPixmap != NULL) delete backingPixmap;
#endif
if (completionPopUp != nullptr) delete completionPopUp;
+ if (textToolbar != nullptr) delete textToolbar;
}
QWidget*
@@ -820,9 +821,6 @@ void
qt_simple_widget_rep::hide_text_toolbar () {
if (textToolbar) {
textToolbar->hide ();
- textToolbar->setParent (nullptr);
- textToolbar->deleteLater ();
- textToolbar= nullptr;
}
}
@@ -851,4 +849,4 @@ qt_simple_widget_rep::is_point_in_text_toolbar (SI x, SI y) {
// 检查点是否在工具栏内
return toolbarRect.contains (px, py);
-}
\ No newline at end of file
+}
From dd0fae72fad90ff6d6edea77de2a5fa2a4f9e81b Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 17:51:14 +0800
Subject: [PATCH 17/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9hide=5Ftext=5Ftoolbar?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Plugins/Qt/qt_simple_widget.cpp | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/src/Plugins/Qt/qt_simple_widget.cpp b/src/Plugins/Qt/qt_simple_widget.cpp
index f9d322030d..585f491777 100644
--- a/src/Plugins/Qt/qt_simple_widget.cpp
+++ b/src/Plugins/Qt/qt_simple_widget.cpp
@@ -799,11 +799,16 @@ qt_simple_widget_rep::scroll_image_popup_by (SI x, SI y) {
void
qt_simple_widget_rep::ensure_text_toolbar () {
- if (!textToolbar && canvas ()) {
- textToolbar= new QTMTextToolbar (canvas (), this);
- if (is_empty (tm_style_sheet)) {
- textToolbar->setStyle (qtmstyle ());
+ if (!canvas ()) return;
+ if (textToolbar) {
+ if (textToolbar->parent () != canvas ()) {
+ textToolbar->setParent (canvas ());
}
+ return;
+ }
+ textToolbar= new QTMTextToolbar (canvas (), this);
+ if (is_empty (tm_style_sheet)) {
+ textToolbar->setStyle (qtmstyle ());
}
}
@@ -821,6 +826,9 @@ void
qt_simple_widget_rep::hide_text_toolbar () {
if (textToolbar) {
textToolbar->hide ();
+ //textToolbar->setParent (nullptr);
+ textToolbar->deleteLater ();
+ textToolbar= nullptr;
}
}
From 5a0eedf1ee68ab4e966c4ff6d5d7aeba549eafc1 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 18:05:48 +0800
Subject: [PATCH 18/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9hide=5Ftext=5Ftoolbar?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Plugins/Qt/qt_simple_widget.cpp | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/src/Plugins/Qt/qt_simple_widget.cpp b/src/Plugins/Qt/qt_simple_widget.cpp
index 585f491777..61df5eb859 100644
--- a/src/Plugins/Qt/qt_simple_widget.cpp
+++ b/src/Plugins/Qt/qt_simple_widget.cpp
@@ -799,16 +799,11 @@ qt_simple_widget_rep::scroll_image_popup_by (SI x, SI y) {
void
qt_simple_widget_rep::ensure_text_toolbar () {
- if (!canvas ()) return;
- if (textToolbar) {
- if (textToolbar->parent () != canvas ()) {
- textToolbar->setParent (canvas ());
+ if (!textToolbar && canvas ()) {
+ textToolbar= new QTMTextToolbar (canvas (), this);
+ if (is_empty (tm_style_sheet)) {
+ textToolbar->setStyle (qtmstyle ());
}
- return;
- }
- textToolbar= new QTMTextToolbar (canvas (), this);
- if (is_empty (tm_style_sheet)) {
- textToolbar->setStyle (qtmstyle ());
}
}
From 0f7afe9380a8b223733701f120152923489586b6 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 18:16:15 +0800
Subject: [PATCH 19/27] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Plugins/Qt/qt_simple_widget.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Plugins/Qt/qt_simple_widget.cpp b/src/Plugins/Qt/qt_simple_widget.cpp
index 61df5eb859..af0604deed 100644
--- a/src/Plugins/Qt/qt_simple_widget.cpp
+++ b/src/Plugins/Qt/qt_simple_widget.cpp
@@ -821,7 +821,7 @@ void
qt_simple_widget_rep::hide_text_toolbar () {
if (textToolbar) {
textToolbar->hide ();
- //textToolbar->setParent (nullptr);
+ // textToolbar->setParent (nullptr);
textToolbar->deleteLater ();
textToolbar= nullptr;
}
From b2266def675e79242c88a14214cfa98b8dead985 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 18:36:38 +0800
Subject: [PATCH 20/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9ensure=5Ftext=5Ftoolbar?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Plugins/Qt/qt_simple_widget.cpp | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/src/Plugins/Qt/qt_simple_widget.cpp b/src/Plugins/Qt/qt_simple_widget.cpp
index af0604deed..1c90e6cb48 100644
--- a/src/Plugins/Qt/qt_simple_widget.cpp
+++ b/src/Plugins/Qt/qt_simple_widget.cpp
@@ -799,11 +799,16 @@ qt_simple_widget_rep::scroll_image_popup_by (SI x, SI y) {
void
qt_simple_widget_rep::ensure_text_toolbar () {
- if (!textToolbar && canvas ()) {
- textToolbar= new QTMTextToolbar (canvas (), this);
- if (is_empty (tm_style_sheet)) {
- textToolbar->setStyle (qtmstyle ());
+ if (!canvas ()) return;
+ if (textToolbar) {
+ if (textToolbar->parent () != canvas ()) {
+ textToolbar->setParent (canvas ());
}
+ return;
+ }
+ textToolbar= new QTMTextToolbar (canvas (), this);
+ if (is_empty (tm_style_sheet)) {
+ textToolbar->setStyle (qtmstyle ());
}
}
@@ -821,9 +826,6 @@ void
qt_simple_widget_rep::hide_text_toolbar () {
if (textToolbar) {
textToolbar->hide ();
- // textToolbar->setParent (nullptr);
- textToolbar->deleteLater ();
- textToolbar= nullptr;
}
}
From 3c23f04d953cb8f623439f24f19bfb6e2479be4a Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 20:19:54 +0800
Subject: [PATCH 21/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BD=8D=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Edit/Interface/edit_mouse.cpp | 11 +++++
src/Plugins/Qt/QTMTextToolbar.cpp | 81 ++++++++++++++++++++++++++++---
src/Plugins/Qt/QTMTextToolbar.hpp | 1 +
src/Plugins/Qt/QTMWidget.cpp | 5 ++
4 files changed, 90 insertions(+), 8 deletions(-)
diff --git a/src/Edit/Interface/edit_mouse.cpp b/src/Edit/Interface/edit_mouse.cpp
index bd856f43fe..d647a8ae72 100644
--- a/src/Edit/Interface/edit_mouse.cpp
+++ b/src/Edit/Interface/edit_mouse.cpp
@@ -1107,6 +1107,17 @@ edit_interface_rep::update_text_toolbar () {
// 注意:rectangle 不是 list 类型,不能使用 is_nil
// 我们检查矩形坐标是否有效
if (text_selr->x1 < text_selr->x2 && text_selr->y1 < text_selr->y2) {
+ update_visible ();
+ SI sel_x1= min (text_selr->x1, text_selr->x2);
+ SI sel_x2= max (text_selr->x1, text_selr->x2);
+ SI sel_y1= min (text_selr->y1, text_selr->y2);
+ SI sel_y2= max (text_selr->y1, text_selr->y2);
+ bool sel_in_view=
+ !(sel_x2 < vx1 || sel_x1 > vx2 || sel_y2 < vy1 || sel_y1 > vy2);
+ if (!sel_in_view) {
+ hide_text_toolbar ();
+ return;
+ }
show_text_toolbar (text_selr, magf, get_scroll_x (), get_scroll_y (),
get_canvas_x (), get_canvas_y ());
}
diff --git a/src/Plugins/Qt/QTMTextToolbar.cpp b/src/Plugins/Qt/QTMTextToolbar.cpp
index dc67eeeecf..5f4c994cf4 100644
--- a/src/Plugins/Qt/QTMTextToolbar.cpp
+++ b/src/Plugins/Qt/QTMTextToolbar.cpp
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
#include
// 悬浮工具栏创建函数
@@ -135,6 +136,10 @@ QTMTextToolbar::showTextToolbar (qt_renderer_rep* ren, rectangle selr,
double magf, int scroll_x, int scroll_y,
int canvas_x, int canvas_y) {
cachePosition (selr, magf, scroll_x, scroll_y, canvas_x, canvas_y);
+ if (!selectionInView ()) {
+ hide ();
+ return;
+ }
updatePosition (ren);
show ();
raise ();
@@ -142,6 +147,10 @@ QTMTextToolbar::showTextToolbar (qt_renderer_rep* ren, rectangle selr,
void
QTMTextToolbar::updatePosition (qt_renderer_rep* ren) {
+ if (!selectionInView ()) {
+ hide ();
+ return;
+ }
int x, y;
getCachedPosition (ren, x, y);
move (x, y);
@@ -173,13 +182,17 @@ void
QTMTextToolbar::getCachedPosition (qt_renderer_rep* ren, int& x, int& y) {
rectangle selr = cached_rect;
double inv_unit= 1.0 / 256.0;
- double cx_logic= (selr->x1 + selr->x2) * 0.5;
- double top_logic= selr->y2; // 使用选区底部位置,使工具栏显示在选中文字正上方
+ double cx_logic = (selr->x1 + selr->x2) * 0.5;
+ double sel_top_logic = (selr->y1 > selr->y2) ? selr->y1 : selr->y2;
+ double sel_bottom_logic= (selr->y1 > selr->y2) ? selr->y2 : selr->y1;
// 使用公式计算QT坐标
double cx_px=
((cx_logic - cached_scroll_x) * cached_magf + cached_canvas_x) * inv_unit;
- double top_px= -(top_logic - cached_scroll_y) * cached_magf * inv_unit;
+ double top_px=
+ -(sel_top_logic - cached_scroll_y) * cached_magf * inv_unit;
+ double bottom_px=
+ -(sel_bottom_logic - cached_scroll_y) * cached_magf * inv_unit;
// 修正:视口 > 表面:存在空白顶部
double blank_top= 0.0;
@@ -190,21 +203,73 @@ QTMTextToolbar::getCachedPosition (qt_renderer_rep* ren, int& x, int& y) {
if (vp_h > surf_h) blank_top= (vp_h - surf_h) * 0.5;
}
top_px+= blank_top;
+ bottom_px+= blank_top;
+
+ const int above_y=
+ int (std::round (top_px -
+ cached_height-10)); // 在选区顶部上方显示
+ const int below_y=
+ int (std::round (bottom_px + 10)); // 如果上面空间不够,显示在选区下方
x= int (std::round (cx_px - cached_width * 0.5));
- y= int (std::round (top_px -
- cached_height)); // 在选区底部上方显示,与图片悬浮窗口一致
+ y= above_y;
// 确保工具栏在视口内
- if (x < 0) x= 0;
- if (y < 0)
- y= int (std::round (top_px + 10)); // 如果上面空间不够,显示在选区下方
if (owner && owner->scrollarea () && owner->scrollarea ()->viewport ()) {
int vp_w= owner->scrollarea ()->viewport ()->width ();
int vp_h= owner->scrollarea ()->viewport ()->height ();
+
+ const bool above_fits=
+ (above_y >= 0) && (above_y + cached_height <= vp_h);
+ if (!above_fits) y= below_y;
+
+ if (x < 0) x= 0;
if (x + cached_width > vp_w) x= vp_w - cached_width;
+ if (y < 0) y= 0;
if (y + cached_height > vp_h) y= vp_h - cached_height;
}
+ else {
+ if (y < 0) y= below_y;
+ }
+}
+
+bool
+QTMTextToolbar::selectionInView () const {
+ if (!owner || !owner->scrollarea () || !owner->scrollarea ()->viewport ())
+ return true;
+
+ rectangle selr = cached_rect;
+ double inv_unit= 1.0 / 256.0;
+
+ double x1_px=
+ ((selr->x1 - cached_scroll_x) * cached_magf + cached_canvas_x) * inv_unit;
+ double x2_px=
+ ((selr->x2 - cached_scroll_x) * cached_magf + cached_canvas_x) * inv_unit;
+ double y1_px=
+ -(selr->y1 - cached_scroll_y) * cached_magf * inv_unit;
+ double y2_px=
+ -(selr->y2 - cached_scroll_y) * cached_magf * inv_unit;
+
+ double blank_top= 0.0;
+ if (owner->scrollarea ()->surface ()) {
+ int vp_h = owner->scrollarea ()->viewport ()->height ();
+ int surf_h= owner->scrollarea ()->surface ()->height ();
+ if (vp_h > surf_h) blank_top= (vp_h - surf_h) * 0.5;
+ }
+ y1_px+= blank_top;
+ y2_px+= blank_top;
+
+ double left = std::min (x1_px, x2_px);
+ double right = std::max (x1_px, x2_px);
+ double top = std::min (y1_px, y2_px);
+ double bottom= std::max (y1_px, y2_px);
+
+ int vp_w= owner->scrollarea ()->viewport ()->width ();
+ int vp_h= owner->scrollarea ()->viewport ()->height ();
+
+ if (right < 0.0 || left > vp_w) return false;
+ if (bottom < 0.0 || top > vp_h) return false;
+ return true;
}
void
diff --git a/src/Plugins/Qt/QTMTextToolbar.hpp b/src/Plugins/Qt/QTMTextToolbar.hpp
index 622664abd4..d60e76c1ba 100644
--- a/src/Plugins/Qt/QTMTextToolbar.hpp
+++ b/src/Plugins/Qt/QTMTextToolbar.hpp
@@ -53,6 +53,7 @@ class QTMTextToolbar : public QWidget {
void cachePosition (rectangle selr, double magf, int scroll_x, int scroll_y,
int canvas_x, int canvas_y);
void getCachedPosition (qt_renderer_rep* ren, int& x, int& y);
+ bool selectionInView () const;
void rebuildButtonsFromScheme ();
void clearButtons ();
bool eventFilter (QObject* obj, QEvent* event) override;
diff --git a/src/Plugins/Qt/QTMWidget.cpp b/src/Plugins/Qt/QTMWidget.cpp
index 1640c3ec2a..7b8e0cb861 100644
--- a/src/Plugins/Qt/QTMWidget.cpp
+++ b/src/Plugins/Qt/QTMWidget.cpp
@@ -19,6 +19,7 @@
#include "qt_gui.hpp"
#include "qt_simple_widget.hpp"
#include "qt_utilities.hpp"
+#include "edit_interface.hpp"
#include "scheme.hpp"
#include "sys_utils.hpp"
#ifdef USE_MUPDF_RENDERER
@@ -157,6 +158,10 @@ QTMWidget::scrollContentsBy (int dx, int dy) {
tm_widget ()->scroll_math_completion_popup_by (dx, dy);
tm_widget ()->scroll_image_popup_by (dx, dy);
tm_widget ()->scroll_text_toolbar_by (dx, dy);
+ if (edit_interface_rep* ed=
+ dynamic_cast (tm_widget ())) {
+ ed->update_text_toolbar ();
+ }
}
void
From bcd15911ce5fd9ec93b6a3446132af5dd51124af Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 20:39:25 +0800
Subject: [PATCH 22/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BD=8D=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Edit/Interface/edit_mouse.cpp | 8 ++++----
src/Plugins/Qt/QTMTextToolbar.cpp | 34 ++++++++++++++++---------------
src/Plugins/Qt/QTMWidget.cpp | 2 +-
3 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/src/Edit/Interface/edit_mouse.cpp b/src/Edit/Interface/edit_mouse.cpp
index d647a8ae72..03277fda74 100644
--- a/src/Edit/Interface/edit_mouse.cpp
+++ b/src/Edit/Interface/edit_mouse.cpp
@@ -1108,10 +1108,10 @@ edit_interface_rep::update_text_toolbar () {
// 我们检查矩形坐标是否有效
if (text_selr->x1 < text_selr->x2 && text_selr->y1 < text_selr->y2) {
update_visible ();
- SI sel_x1= min (text_selr->x1, text_selr->x2);
- SI sel_x2= max (text_selr->x1, text_selr->x2);
- SI sel_y1= min (text_selr->y1, text_selr->y2);
- SI sel_y2= max (text_selr->y1, text_selr->y2);
+ SI sel_x1= min (text_selr->x1, text_selr->x2);
+ SI sel_x2= max (text_selr->x1, text_selr->x2);
+ SI sel_y1= min (text_selr->y1, text_selr->y2);
+ SI sel_y2= max (text_selr->y1, text_selr->y2);
bool sel_in_view=
!(sel_x2 < vx1 || sel_x1 > vx2 || sel_y2 < vy1 || sel_y1 > vy2);
if (!sel_in_view) {
diff --git a/src/Plugins/Qt/QTMTextToolbar.cpp b/src/Plugins/Qt/QTMTextToolbar.cpp
index 5f4c994cf4..18f2242c4b 100644
--- a/src/Plugins/Qt/QTMTextToolbar.cpp
+++ b/src/Plugins/Qt/QTMTextToolbar.cpp
@@ -180,17 +180,16 @@ QTMTextToolbar::cachePosition (rectangle selr, double magf, int scroll_x,
void
QTMTextToolbar::getCachedPosition (qt_renderer_rep* ren, int& x, int& y) {
- rectangle selr = cached_rect;
- double inv_unit= 1.0 / 256.0;
- double cx_logic = (selr->x1 + selr->x2) * 0.5;
- double sel_top_logic = (selr->y1 > selr->y2) ? selr->y1 : selr->y2;
- double sel_bottom_logic= (selr->y1 > selr->y2) ? selr->y2 : selr->y1;
+ rectangle selr = cached_rect;
+ double inv_unit = 1.0 / 256.0;
+ double cx_logic = (selr->x1 + selr->x2) * 0.5;
+ double sel_top_logic = (selr->y1 > selr->y2) ? selr->y1 : selr->y2;
+ double sel_bottom_logic= (selr->y1 > selr->y2) ? selr->y2 : selr->y1;
// 使用公式计算QT坐标
double cx_px=
((cx_logic - cached_scroll_x) * cached_magf + cached_canvas_x) * inv_unit;
- double top_px=
- -(sel_top_logic - cached_scroll_y) * cached_magf * inv_unit;
+ double top_px= -(sel_top_logic - cached_scroll_y) * cached_magf * inv_unit;
double bottom_px=
-(sel_bottom_logic - cached_scroll_y) * cached_magf * inv_unit;
@@ -206,8 +205,7 @@ QTMTextToolbar::getCachedPosition (qt_renderer_rep* ren, int& x, int& y) {
bottom_px+= blank_top;
const int above_y=
- int (std::round (top_px -
- cached_height-10)); // 在选区顶部上方显示
+ int (std::round (top_px - cached_height - 10)); // 在选区顶部上方显示
const int below_y=
int (std::round (bottom_px + 10)); // 如果上面空间不够,显示在选区下方
@@ -219,9 +217,15 @@ QTMTextToolbar::getCachedPosition (qt_renderer_rep* ren, int& x, int& y) {
int vp_w= owner->scrollarea ()->viewport ()->width ();
int vp_h= owner->scrollarea ()->viewport ()->height ();
- const bool above_fits=
- (above_y >= 0) && (above_y + cached_height <= vp_h);
- if (!above_fits) y= below_y;
+ const bool above_fits= (above_y >= 0) && (above_y + cached_height <= vp_h);
+ const bool below_fits= (below_y >= 0) && (below_y + cached_height <= vp_h);
+
+ if (above_fits) y= above_y;
+ else if (below_fits) y= below_y;
+ else {
+ x= std::max (0, (vp_w - cached_width) / 2);
+ y= std::max (0, (vp_h - cached_height) / 2);
+ }
if (x < 0) x= 0;
if (x + cached_width > vp_w) x= vp_w - cached_width;
@@ -245,10 +249,8 @@ QTMTextToolbar::selectionInView () const {
((selr->x1 - cached_scroll_x) * cached_magf + cached_canvas_x) * inv_unit;
double x2_px=
((selr->x2 - cached_scroll_x) * cached_magf + cached_canvas_x) * inv_unit;
- double y1_px=
- -(selr->y1 - cached_scroll_y) * cached_magf * inv_unit;
- double y2_px=
- -(selr->y2 - cached_scroll_y) * cached_magf * inv_unit;
+ double y1_px= -(selr->y1 - cached_scroll_y) * cached_magf * inv_unit;
+ double y2_px= -(selr->y2 - cached_scroll_y) * cached_magf * inv_unit;
double blank_top= 0.0;
if (owner->scrollarea ()->surface ()) {
diff --git a/src/Plugins/Qt/QTMWidget.cpp b/src/Plugins/Qt/QTMWidget.cpp
index 7b8e0cb861..65bf212611 100644
--- a/src/Plugins/Qt/QTMWidget.cpp
+++ b/src/Plugins/Qt/QTMWidget.cpp
@@ -14,12 +14,12 @@
#include "array.hpp"
#include "boot.hpp"
#include "converter.hpp"
+#include "edit_interface.hpp"
#include "object_l5.hpp"
#include "preferences.hpp"
#include "qt_gui.hpp"
#include "qt_simple_widget.hpp"
#include "qt_utilities.hpp"
-#include "edit_interface.hpp"
#include "scheme.hpp"
#include "sys_utils.hpp"
#ifdef USE_MUPDF_RENDERER
From fada47d9630cceeef52daabad9d0fc85cf1f162e Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 21:05:20 +0800
Subject: [PATCH 23/27] =?UTF-8?q?=E5=8D=95=E7=8B=AC=E9=80=89=E4=B8=AD?=
=?UTF-8?q?=E5=85=AC=E5=BC=8F=E4=B8=8D=E6=98=BE=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Edit/Interface/edit_mouse.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Edit/Interface/edit_mouse.cpp b/src/Edit/Interface/edit_mouse.cpp
index 03277fda74..446a298b1a 100644
--- a/src/Edit/Interface/edit_mouse.cpp
+++ b/src/Edit/Interface/edit_mouse.cpp
@@ -1030,6 +1030,7 @@ edit_interface_rep::handle_mouse (string kind, SI x, SI y, int m, time_t t,
bool
edit_interface_rep::should_show_text_toolbar () {
+ if (as_bool (call ("in-math?"))) return false;
// 检查是否有活动的文本选区
if (!selection_active_any ()) return false;
From 26e2dd59da54e54bedf20aa6c72416ef523fd1a5 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Wed, 4 Feb 2026 21:13:00 +0800
Subject: [PATCH 24/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
devel/201_63.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/devel/201_63.md b/devel/201_63.md
index a4e697cec3..f4147d353a 100644
--- a/devel/201_63.md
+++ b/devel/201_63.md
@@ -3,3 +3,6 @@
## 如何测试
1. 输入一段文字通过键盘或鼠标选中,会出现悬浮窗口
2. 依次点击悬浮窗口按钮,实现的功能和模式工具栏一致
+3. 窗口位置的优先级应该是选区顶部>选区底部>窗口中央
+4. 切换标签页不会导致原标签页的文本选中窗口失效
+5. 单独选中任意数学公式环境该悬浮窗口都不出现,选中公式文本混合内容悬浮窗口出现
From fa33eedd8386cd9d7441060e76a6620d51b0f1af Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Fri, 6 Feb 2026 10:42:23 +0800
Subject: [PATCH 25/27] =?UTF-8?q?=E9=80=89=E4=B8=AD=E6=96=87=E6=9C=AC?=
=?UTF-8?q?=E6=89=8D=E6=98=BE=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Edit/Interface/edit_mouse.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/Edit/Interface/edit_mouse.cpp b/src/Edit/Interface/edit_mouse.cpp
index 446a298b1a..25008be80e 100644
--- a/src/Edit/Interface/edit_mouse.cpp
+++ b/src/Edit/Interface/edit_mouse.cpp
@@ -1030,7 +1030,9 @@ edit_interface_rep::handle_mouse (string kind, SI x, SI y, int m, time_t t,
bool
edit_interface_rep::should_show_text_toolbar () {
- if (as_bool (call ("in-math?"))) return false;
+ if (as_bool (call ("in-math?")) || as_bool (call ("in-prog?")) ||
+ as_bool (call ("in-code?")) || as_bool (call ("in-verbatim?")))
+ return false;
// 检查是否有活动的文本选区
if (!selection_active_any ()) return false;
From fa989138e9d423935702abdfdb44103c2a041ee2 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Fri, 6 Feb 2026 12:31:19 +0800
Subject: [PATCH 26/27] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=AB=A0=E8=8A=82?=
=?UTF-8?q?=E5=92=8C=E8=AF=AD=E4=B9=89=E5=9D=97=E7=9A=84=E6=8C=89=E9=92=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
TeXmacs/progs/generic/text-toolbar.scm | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/TeXmacs/progs/generic/text-toolbar.scm b/TeXmacs/progs/generic/text-toolbar.scm
index 6df32c1c4f..fedb99b259 100644
--- a/TeXmacs/progs/generic/text-toolbar.scm
+++ b/TeXmacs/progs/generic/text-toolbar.scm
@@ -26,6 +26,10 @@
(mark-text))
(=> (balloon (icon "tm_color.xpm") "Select a foreground color")
(link color-menu))
+ (=> (balloon (icon "tm_chapter.xpm") "chapter::menu")
+ (link chapter-menu))
+ (=> (balloon (icon "tm_theorem.xpm") "enunciation")
+ (link enunciation-menu))
((balloon (icon "left-align.xpm") "left aligned")
(make-line-with "par-mode" "left"))
((balloon (icon "middle-align.xpm") "center")
From 25d175b8cc2df6a7a97ca7049001841bc5f43e81 Mon Sep 17 00:00:00 2001
From: JackChen <17683835261@163.com>
Date: Fri, 6 Feb 2026 12:46:20 +0800
Subject: [PATCH 27/27] =?UTF-8?q?=E6=9B=B4=E6=8D=A2=E5=9B=BE=E6=A0=87?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
TeXmacs/progs/generic/text-toolbar.scm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/TeXmacs/progs/generic/text-toolbar.scm b/TeXmacs/progs/generic/text-toolbar.scm
index fedb99b259..38bc329bb0 100644
--- a/TeXmacs/progs/generic/text-toolbar.scm
+++ b/TeXmacs/progs/generic/text-toolbar.scm
@@ -26,7 +26,7 @@
(mark-text))
(=> (balloon (icon "tm_color.xpm") "Select a foreground color")
(link color-menu))
- (=> (balloon (icon "tm_chapter.xpm") "chapter::menu")
+ (=> (balloon (icon "tm_section.xpm") "chapter::menu")
(link chapter-menu))
(=> (balloon (icon "tm_theorem.xpm") "enunciation")
(link enunciation-menu))