Renommage des onglets

Double-clic sur un onglet pour le renommer, ou clic droit pour le menu. Le menu
contextuel permet aussi de fermer l'onglet vise ou tous les autres.

Le nom saisi est conserve tel quel : un onglet renomme "Serveur prod" ne
retrouve pas son libelle d'origine, y compris apres une reconnexion.

Un nom vide ou uniquement compose d'espaces est refuse, et annuler la saisie
laisse le nom inchange.

La fermeture des autres onglets parcourt la liste a l'envers : retirer un
onglet decale l'index des suivants, un parcours en avant en sauterait.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
snoopy
2026-09-04 12:17:34 +02:00
parent 1760dc39ac
commit c4afc31e34
2 changed files with 42 additions and 1 deletions

View File

@@ -11,6 +11,8 @@ Client SSH/SFTP personnel (type MobaXterm/Termius/Bitvise), 100% local, sans com
- Confort d'affichage : zoom `Ctrl+molette` ou `Ctrl+ +/-` (`Ctrl+0` remet a zero, la taille est
memorisee), barre de defilement de l'historique, `Maj+PagePrec/Suiv`, `Ctrl+Fin` pour revenir
en direct, et recherche dans l'historique avec `Ctrl+F`
- Onglets renommables (double-clic sur l'onglet, ou clic droit) et deplaçables ;
le clic droit permet aussi de fermer les autres onglets
- Panneau des sessions redimensionnable en attrapant le separateur, et masquable entierement
(`F9`, menu Affichage, ou la croix du panneau) pour donner tout l'ecran au terminal
- **Tunnels SSH** (redirection de ports) : bouton "Tunnels" dans la barre d'un onglet SSH.

View File

@@ -12,7 +12,7 @@ from PySide6.QtGui import QAction, QActionGroup, QKeySequence, QShortcut
from PySide6.QtWidgets import (
QMainWindow, QDockWidget, QTreeWidget, QTreeWidgetItem, QTabWidget, QWidget,
QVBoxLayout, QHBoxLayout, QToolButton, QLabel, QMenu, QMessageBox, QSplitter,
QStatusBar, QFrame, QApplication, QLineEdit, QFileDialog,
QStatusBar, QFrame, QApplication, QLineEdit, QFileDialog, QInputDialog,
)
from app.session_manager import SessionStore, Session, AUTH_KEY, AUTH_PASSWORD
@@ -661,6 +661,10 @@ class MainWindow(QMainWindow):
self.tabs = QTabWidget()
self.tabs.setTabsClosable(True)
self.tabs.setMovable(True)
# double-clic sur un onglet pour le renommer, clic droit pour le menu
self.tabs.tabBarDoubleClicked.connect(self.rename_tab)
self.tabs.tabBar().setContextMenuPolicy(Qt.CustomContextMenu)
self.tabs.tabBar().customContextMenuRequested.connect(self._on_tab_context_menu)
self.tabs.tabCloseRequested.connect(self._on_tab_close)
self.setCentralWidget(self.tabs)
@@ -896,6 +900,41 @@ class MainWindow(QMainWindow):
def _register_broadcast(self, tab) -> None:
tab.terminal.data_to_send.connect(lambda data, t=tab: self._broadcast(data, t))
# ---------- renommage des onglets ----------
def rename_tab(self, index: int) -> None:
if index < 0:
return
actuel = self.tabs.tabText(index)
nouveau, ok = QInputDialog.getText(
self, "Renommer l'onglet", "Nom de l'onglet :", text=actuel
)
if ok and nouveau.strip():
self.tabs.setTabText(index, nouveau.strip())
def _on_tab_context_menu(self, pos) -> None:
bar = self.tabs.tabBar()
index = bar.tabAt(pos)
if index < 0:
return
menu = QMenu(self)
act_rename = menu.addAction("Renommer... (double-clic)")
menu.addSeparator()
act_close = menu.addAction("Fermer cet onglet")
act_close_others = menu.addAction("Fermer les autres onglets")
act_close_others.setEnabled(self.tabs.count() > 1)
action = menu.exec(bar.mapToGlobal(pos))
if action == act_rename:
self.rename_tab(index)
elif action == act_close:
self._on_tab_close(index)
elif action == act_close_others:
# on ferme par la fin : retirer un onglet decale les suivants
cible = self.tabs.widget(index)
for other in range(self.tabs.count() - 1, -1, -1):
if self.tabs.widget(other) is not cible:
self._on_tab_close(other)
def _on_tab_close(self, index: int) -> None:
widget = self.tabs.widget(index)
if isinstance(widget, (BaseTerminalTab, SFTPTabWidget)):