Convert TUI to PySide6 desktop GUI
Major UI overhaul replacing the urwid-based Terminal UI with a modern PySide6 desktop application. New GUI features: - Sidebar navigation (My Tools, Registry, Providers) - Tool Builder with visual form for creating/editing tools - Registry browser with search and one-click install - Provider management page - Connect dialog for account pairing - Publish dialog for sharing tools - Keyboard shortcuts (Ctrl+N, Ctrl+S, Ctrl+R, Ctrl+1/2/3, Escape, Ctrl+Q) - Window geometry persistence (remembers size/position) - Modern clean stylesheet Removed: - ui.py, ui_snack.py, ui_registry.py, ui_urwid.py - ui_urwid/ directory (urwid TUI implementation) Updated: - pyproject.toml: PySide6 now required, removed urwid - CLI entry points to launch GUI - All documentation (README, CLAUDE.md, AGENTS.md, wiki) Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,379 @@
|
||||
"""Modern stylesheet for CmdForge GUI."""
|
||||
|
||||
STYLESHEET = """
|
||||
/* Main Window */
|
||||
QMainWindow {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* Sidebar */
|
||||
#sidebar {
|
||||
background-color: #2d3748;
|
||||
border: none;
|
||||
min-width: 180px;
|
||||
max-width: 180px;
|
||||
}
|
||||
|
||||
#sidebar::item {
|
||||
color: #e2e8f0;
|
||||
padding: 12px 16px;
|
||||
border: none;
|
||||
border-left: 3px solid transparent;
|
||||
}
|
||||
|
||||
#sidebar::item:selected {
|
||||
background-color: #4a5568;
|
||||
border-left: 3px solid #667eea;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#sidebar::item:hover:!selected {
|
||||
background-color: #3d4a5c;
|
||||
}
|
||||
|
||||
/* Content area */
|
||||
QWidget#content_area {
|
||||
background-color: #f7fafc;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
QPushButton {
|
||||
background-color: #667eea;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
padding: 8px 16px;
|
||||
font-weight: 500;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
QPushButton:hover {
|
||||
background-color: #5a67d8;
|
||||
}
|
||||
|
||||
QPushButton:pressed {
|
||||
background-color: #4c51bf;
|
||||
}
|
||||
|
||||
QPushButton:disabled {
|
||||
background-color: #a0aec0;
|
||||
}
|
||||
|
||||
QPushButton#secondary {
|
||||
background-color: #e2e8f0;
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
QPushButton#secondary:hover {
|
||||
background-color: #cbd5e0;
|
||||
}
|
||||
|
||||
QPushButton#danger {
|
||||
background-color: #e53e3e;
|
||||
}
|
||||
|
||||
QPushButton#danger:hover {
|
||||
background-color: #c53030;
|
||||
}
|
||||
|
||||
/* Input fields */
|
||||
QLineEdit, QTextEdit, QPlainTextEdit {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
padding: 8px 12px;
|
||||
background-color: white;
|
||||
selection-background-color: #667eea;
|
||||
}
|
||||
|
||||
QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus {
|
||||
border-color: #667eea;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Combo boxes */
|
||||
QComboBox {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
padding: 8px 12px;
|
||||
background-color: white;
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
QComboBox:focus {
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
QComboBox::drop-down {
|
||||
border: none;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
QComboBox::down-arrow {
|
||||
image: none;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
border-top: 6px solid #718096;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
QComboBox QAbstractItemView {
|
||||
border: 1px solid #e2e8f0;
|
||||
background-color: white;
|
||||
selection-background-color: #667eea;
|
||||
}
|
||||
|
||||
/* Lists and Trees */
|
||||
QListWidget, QTreeWidget, QTableWidget {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
background-color: white;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
QListWidget::item, QTreeWidget::item {
|
||||
padding: 8px 12px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
QListWidget::item:selected, QTreeWidget::item:selected {
|
||||
background-color: #667eea;
|
||||
color: white;
|
||||
}
|
||||
|
||||
QListWidget::item:hover:!selected, QTreeWidget::item:hover:!selected {
|
||||
background-color: #edf2f7;
|
||||
}
|
||||
|
||||
/* Table Widget */
|
||||
QTableWidget {
|
||||
gridline-color: #e2e8f0;
|
||||
}
|
||||
|
||||
QTableWidget::item {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
QTableWidget::item:selected {
|
||||
background-color: #667eea;
|
||||
color: white;
|
||||
}
|
||||
|
||||
QHeaderView::section {
|
||||
background-color: #f7fafc;
|
||||
padding: 8px 12px;
|
||||
border: none;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
font-weight: 600;
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
/* Group boxes */
|
||||
QGroupBox {
|
||||
font-weight: 600;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
margin-top: 12px;
|
||||
padding-top: 12px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
subcontrol-position: top left;
|
||||
left: 12px;
|
||||
padding: 0 8px;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
/* Labels */
|
||||
QLabel {
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
QLabel#heading {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #1a202c;
|
||||
}
|
||||
|
||||
QLabel#subheading {
|
||||
font-size: 14px;
|
||||
color: #718096;
|
||||
}
|
||||
|
||||
QLabel#label {
|
||||
font-weight: 500;
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
/* Scrollbars */
|
||||
QScrollBar:vertical {
|
||||
background-color: #f7fafc;
|
||||
width: 12px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical {
|
||||
background-color: #cbd5e0;
|
||||
border-radius: 6px;
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical:hover {
|
||||
background-color: #a0aec0;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
QScrollBar:horizontal {
|
||||
background-color: #f7fafc;
|
||||
height: 12px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:horizontal {
|
||||
background-color: #cbd5e0;
|
||||
border-radius: 6px;
|
||||
min-width: 30px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:horizontal:hover {
|
||||
background-color: #a0aec0;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
/* Status bar */
|
||||
QStatusBar {
|
||||
background-color: #f7fafc;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
color: #718096;
|
||||
}
|
||||
|
||||
/* Splitter */
|
||||
QSplitter::handle {
|
||||
background-color: #e2e8f0;
|
||||
}
|
||||
|
||||
QSplitter::handle:horizontal {
|
||||
width: 2px;
|
||||
}
|
||||
|
||||
QSplitter::handle:vertical {
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
/* Tabs */
|
||||
QTabWidget::pane {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
QTabBar::tab {
|
||||
background-color: #edf2f7;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-bottom: none;
|
||||
padding: 8px 16px;
|
||||
margin-right: 2px;
|
||||
border-top-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
}
|
||||
|
||||
QTabBar::tab:selected {
|
||||
background-color: white;
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
|
||||
QTabBar::tab:hover:!selected {
|
||||
background-color: #e2e8f0;
|
||||
}
|
||||
|
||||
/* Dialogs */
|
||||
QDialog {
|
||||
background-color: #f7fafc;
|
||||
}
|
||||
|
||||
/* Message boxes */
|
||||
QMessageBox {
|
||||
background-color: #f7fafc;
|
||||
}
|
||||
|
||||
QMessageBox QPushButton {
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
/* Tool tips */
|
||||
QToolTip {
|
||||
background-color: #2d3748;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 6px 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* Progress bar */
|
||||
QProgressBar {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
background-color: #edf2f7;
|
||||
text-align: center;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
QProgressBar::chunk {
|
||||
background-color: #667eea;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/* Spin boxes */
|
||||
QSpinBox, QDoubleSpinBox {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
padding: 8px 12px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
QSpinBox:focus, QDoubleSpinBox:focus {
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
/* Check boxes and radio buttons */
|
||||
QCheckBox, QRadioButton {
|
||||
spacing: 8px;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
QCheckBox::indicator, QRadioButton::indicator {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
QCheckBox::indicator:unchecked {
|
||||
border: 2px solid #cbd5e0;
|
||||
border-radius: 4px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
QCheckBox::indicator:checked {
|
||||
border: 2px solid #667eea;
|
||||
border-radius: 4px;
|
||||
background-color: #667eea;
|
||||
}
|
||||
|
||||
QRadioButton::indicator:unchecked {
|
||||
border: 2px solid #cbd5e0;
|
||||
border-radius: 9px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
QRadioButton::indicator:checked {
|
||||
border: 2px solid #667eea;
|
||||
border-radius: 9px;
|
||||
background-color: #667eea;
|
||||
}
|
||||
"""
|
||||
Reference in New Issue
Block a user