feat: dark theme toggle + CPU/memory sparkline trend charts

- ui/theme.py: light/dark QSS stylesheets, persisted to ~/.sshclient/settings.json
- main_window.py: View menu with dark theme checkbox, applies on startup
- ui/widgets.py: SparklineChart widget for mini trend visualization
- MonitorPanel: CPU and memory sparkline charts showing last 60 samples
- Charts cleared on stop/switch host
This commit is contained in:
Your Name
2026-07-28 23:00:50 +08:00
parent 5d83348db3
commit 57092cad03
3 changed files with 240 additions and 0 deletions
+20
View File
@@ -22,6 +22,7 @@ from .workers import ConnectWorker
from .widgets import FileBrowser, MonitorPanel, AIChatPanel
from .config_dialog import AIConfigDialog
from .terminal_panel import TerminalPanel
from .theme import get_qss, get_theme, set_theme
APP_NAME = "SSHClient"
@@ -43,6 +44,7 @@ class MainWindow(QMainWindow):
self._build_ui()
self._build_menu()
self._build_statusbar()
self._apply_theme()
self._load_hosts_to_list()
# ============================================================
@@ -144,6 +146,12 @@ class MainWindow(QMainWindow):
act_clear = QAction("清空 AI 对话", self)
act_clear.triggered.connect(lambda: self.ai_panel._clear())
m_ai.addAction(act_clear)
# 视图
m_view = menubar.addMenu("视图(&V)")
self.act_dark = QAction("🌙 暗色主题", self, checkable=True)
self.act_dark.setChecked(get_theme() == "dark")
self.act_dark.triggered.connect(self._toggle_theme)
m_view.addAction(self.act_dark)
# 帮助
m_help = menubar.addMenu("帮助(&H)")
act_about = QAction("关于", self)
@@ -301,6 +309,18 @@ class MainWindow(QMainWindow):
# ============================================================
# AI / 关于
# ============================================================
def _apply_theme(self):
theme = get_theme()
qss = get_qss(theme)
QApplication.instance().setStyleSheet(qss)
def _toggle_theme(self):
new_theme = "dark" if self.act_dark.isChecked() else "light"
set_theme(new_theme)
self._apply_theme()
label = "暗色" if new_theme == "dark" else "亮色"
self.statusBar().showMessage(f"已切换到{label}主题", 3000)
def _show_ai_config(self):
dlg = AIConfigDialog(self.agent, self)
if dlg.exec_():