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]>
102 lines
3.0 KiB
Python
102 lines
3.0 KiB
Python
"""Provider editor dialog."""
|
|
|
|
from PySide6.QtWidgets import (
|
|
QDialog, QVBoxLayout, QFormLayout, QLineEdit,
|
|
QPushButton, QHBoxLayout, QLabel
|
|
)
|
|
|
|
from ...providers import Provider, add_provider
|
|
|
|
|
|
class ProviderDialog(QDialog):
|
|
"""Dialog for adding/editing providers."""
|
|
|
|
def __init__(self, parent, name: str = None, provider: Provider = None):
|
|
super().__init__(parent)
|
|
self.setWindowTitle("Edit Provider" if provider else "Add Provider")
|
|
self.setMinimumWidth(450)
|
|
self._editing = provider is not None
|
|
self._original_name = name
|
|
self._setup_ui()
|
|
|
|
if provider:
|
|
self._load_provider(name, provider)
|
|
|
|
def _setup_ui(self):
|
|
"""Set up the UI."""
|
|
layout = QVBoxLayout(self)
|
|
layout.setSpacing(16)
|
|
|
|
# Form
|
|
form = QFormLayout()
|
|
form.setSpacing(12)
|
|
|
|
self.name_input = QLineEdit()
|
|
self.name_input.setPlaceholderText("claude")
|
|
form.addRow("Name:", self.name_input)
|
|
|
|
self.cmd_input = QLineEdit()
|
|
self.cmd_input.setPlaceholderText("claude-cli")
|
|
form.addRow("Command:", self.cmd_input)
|
|
|
|
self.desc_input = QLineEdit()
|
|
self.desc_input.setPlaceholderText("Claude AI via claude-cli")
|
|
form.addRow("Description:", self.desc_input)
|
|
|
|
layout.addLayout(form)
|
|
|
|
# Help text
|
|
help_text = QLabel(
|
|
"The command should accept input on stdin and output to stdout.\n"
|
|
"Example commands: claude-cli, sgpt, llm, mods"
|
|
)
|
|
help_text.setStyleSheet("color: #718096; font-size: 11px;")
|
|
help_text.setWordWrap(True)
|
|
layout.addWidget(help_text)
|
|
|
|
layout.addStretch()
|
|
|
|
# Buttons
|
|
buttons = QHBoxLayout()
|
|
buttons.addStretch()
|
|
|
|
self.btn_cancel = QPushButton("Cancel")
|
|
self.btn_cancel.setObjectName("secondary")
|
|
self.btn_cancel.clicked.connect(self.reject)
|
|
buttons.addWidget(self.btn_cancel)
|
|
|
|
self.btn_ok = QPushButton("Save")
|
|
self.btn_ok.clicked.connect(self._save)
|
|
buttons.addWidget(self.btn_ok)
|
|
|
|
layout.addLayout(buttons)
|
|
|
|
def _load_provider(self, name: str, provider: Provider):
|
|
"""Load provider data into form."""
|
|
self.name_input.setText(name)
|
|
self.name_input.setEnabled(False) # Can't rename
|
|
self.cmd_input.setText(provider.command)
|
|
self.desc_input.setText(provider.description or "")
|
|
|
|
def _save(self):
|
|
"""Save the provider."""
|
|
name = self.name_input.text().strip()
|
|
command = self.cmd_input.text().strip()
|
|
|
|
if not name:
|
|
self.name_input.setFocus()
|
|
return
|
|
|
|
if not command:
|
|
self.cmd_input.setFocus()
|
|
return
|
|
|
|
description = self.desc_input.text().strip() or None
|
|
|
|
try:
|
|
add_provider(name, command, description)
|
|
self.accept()
|
|
except Exception as e:
|
|
from PySide6.QtWidgets import QMessageBox
|
|
QMessageBox.critical(self, "Error", f"Failed to save provider:\n{e}")
|