feat: add '复制标签' option to terminal tab right-click menu

User asked: '标签使用鼠标右键应该有复制标签的功能'

In ui/terminal_tab_widget.py _on_tab_context_menu:
- Added '📋 复制标签' action between '重命名' and '关闭标签'
- New method _duplicate_tab(idx): creates a new terminal tab for
  the same host (reuses SSH connection, opens independent shell
  channel via paramiko invoke_shell)
- New tab title = '<src_title> (副本)' with  state dot
- If host not connected: duplicate creates a placeholder tab
- If host connected: duplicate immediately opens a new shell

Verified: 3 tabs after duplicating 'test-server' (欢迎 +  test-server
+  test-server (副本))

All tests still pass.
This commit is contained in:
Hermes
2026-07-29 07:12:52 +08:00
parent 2c6f06e392
commit a98f22202d
+26
View File
@@ -231,6 +231,7 @@ class TerminalTabWidget(QWidget):
menu = QMenu(self) menu = QMenu(self)
panel = self._panel_at(idx) panel = self._panel_at(idx)
a_rename = menu.addAction("重命名") a_rename = menu.addAction("重命名")
a_duplicate = menu.addAction("📋 复制标签")
a_close = menu.addAction("关闭标签") a_close = menu.addAction("关闭标签")
a_close_others = menu.addAction("关闭其他") a_close_others = menu.addAction("关闭其他")
if panel and panel._connected: if panel and panel._connected:
@@ -242,6 +243,8 @@ class TerminalTabWidget(QWidget):
chosen = menu.exec_(self.tabs.tabBar().mapToGlobal(pos)) chosen = menu.exec_(self.tabs.tabBar().mapToGlobal(pos))
if chosen == a_rename: if chosen == a_rename:
self._on_tab_double_clicked(idx) self._on_tab_double_clicked(idx)
elif chosen == a_duplicate:
self._duplicate_tab(idx)
elif chosen == a_close: elif chosen == a_close:
self._close_tab(idx) self._close_tab(idx)
elif chosen == a_close_others: elif chosen == a_close_others:
@@ -250,6 +253,29 @@ class TerminalTabWidget(QWidget):
if panel and panel.conn: if panel and panel.conn:
panel._reopen_shell() panel._reopen_shell()
def _duplicate_tab(self, idx: int):
"""复制标签:新建一个同主机的终端标签(独立 shell 通道)"""
src_panel = self._panel_at(idx)
if src_panel is None:
return
host_id = self._host_id_for_panel(src_panel)
# 决定新标签的初始连接
conn = self.manager.get_connection(host_id) if host_id else None
# 新建标签(open_terminal 会 attach conn
new_idx = self.open_terminal(host_id or "", conn=conn)
# 用源标签的当前标题做新标签名(去掉状态点前缀)
src_title = self.tabs.tabText(idx)
for prefix in ("", "🟢 ", "🔴 ", "🟡 "):
if src_title.startswith(prefix):
src_title = src_title[len(prefix):]
break
# 加 " (副本)" 后缀
self.tabs.setTabText(new_idx, f"{src_title} (副本)")
self.tabs.setCurrentIndex(new_idx)
# 如果已连接,给用户一个小提示:每个副本是独立 shell
if conn:
self.statusBar_msg = f"已创建副本(独立 shell" if hasattr(self, "statusBar_msg") else None
def _close_tab(self, idx: int): def _close_tab(self, idx: int):
panel = self._panel_at(idx) panel = self._panel_at(idx)
if panel and panel._connected: if panel and panel._connected: