Add Help menu and contextual tooltips to GUI
- Add Help menu with quick guides: Getting Started, Create Tool, Install Tools, Publish Tools, Keyboard Shortcuts, About - F1 shortcut opens Getting Started guide - Add tooltips to Tool Builder section headings (Arguments, Steps, Output Template) that appear on hover over the label text - Add tooltips to Registry page controls (search, filters, pagination) - Enhance sidebar tooltips with keyboard shortcuts Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
@@ -129,6 +129,7 @@ class RegistryPage(QWidget):
|
||||
|
||||
# Browse all button
|
||||
self.btn_browse = QPushButton("Browse All")
|
||||
self.btn_browse.setToolTip("Clear filters and show all available tools")
|
||||
self.btn_browse.clicked.connect(self._browse_all)
|
||||
header.addWidget(self.btn_browse)
|
||||
|
||||
@@ -143,6 +144,7 @@ class RegistryPage(QWidget):
|
||||
# Search input
|
||||
self.search_input = QLineEdit()
|
||||
self.search_input.setPlaceholderText("Search tools...")
|
||||
self.search_input.setToolTip("Search by name, description, or keywords (press Enter)")
|
||||
self.search_input.returnPressed.connect(self._do_search)
|
||||
filters_layout.addWidget(self.search_input, 2)
|
||||
|
||||
@@ -152,6 +154,7 @@ class RegistryPage(QWidget):
|
||||
self.category_combo = QComboBox()
|
||||
self.category_combo.addItems(["All", "Text", "Developer", "Data", "Other"])
|
||||
self.category_combo.setMinimumWidth(100)
|
||||
self.category_combo.setToolTip("Filter by tool category")
|
||||
self.category_combo.currentTextChanged.connect(self._on_filter_changed)
|
||||
filters_layout.addWidget(self.category_combo)
|
||||
|
||||
@@ -163,11 +166,13 @@ class RegistryPage(QWidget):
|
||||
self.sort_combo.addItem("Newest", "published_at")
|
||||
self.sort_combo.addItem("Name (A-Z)", "name")
|
||||
self.sort_combo.setMinimumWidth(120)
|
||||
self.sort_combo.setToolTip("Change sort order of results")
|
||||
self.sort_combo.currentIndexChanged.connect(self._on_filter_changed)
|
||||
filters_layout.addWidget(self.sort_combo)
|
||||
|
||||
# Search button
|
||||
self.btn_search = QPushButton("Search")
|
||||
self.btn_search.setToolTip("Search with current filters")
|
||||
self.btn_search.clicked.connect(self._do_search)
|
||||
filters_layout.addWidget(self.btn_search)
|
||||
|
||||
@@ -196,6 +201,7 @@ class RegistryPage(QWidget):
|
||||
self.results_table = QTableWidget()
|
||||
self.results_table.setColumnCount(6)
|
||||
self.results_table.setHorizontalHeaderLabels(["", "Name", "Owner", "Rating", "Downloads", "Version"])
|
||||
self.results_table.setToolTip("Click a tool to see details. ✓ = installed, ↑ = update available")
|
||||
self.results_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Fixed)
|
||||
self.results_table.setColumnWidth(0, 30) # Installed indicator
|
||||
self.results_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
|
||||
@@ -215,6 +221,7 @@ class RegistryPage(QWidget):
|
||||
pag_layout.setContentsMargins(0, 8, 0, 0)
|
||||
|
||||
self.btn_prev = QPushButton("← Previous")
|
||||
self.btn_prev.setToolTip("Go to previous page of results")
|
||||
self.btn_prev.clicked.connect(self._prev_page)
|
||||
self.btn_prev.setEnabled(False)
|
||||
pag_layout.addWidget(self.btn_prev)
|
||||
@@ -228,6 +235,7 @@ class RegistryPage(QWidget):
|
||||
pag_layout.addStretch()
|
||||
|
||||
self.btn_next = QPushButton("Next →")
|
||||
self.btn_next.setToolTip("Go to next page of results")
|
||||
self.btn_next.clicked.connect(self._next_page)
|
||||
self.btn_next.setEnabled(False)
|
||||
pag_layout.addWidget(self.btn_next)
|
||||
@@ -263,6 +271,7 @@ class RegistryPage(QWidget):
|
||||
self.version_combo.setMinimumWidth(120)
|
||||
self.version_combo.addItem("Latest", None)
|
||||
self.version_combo.setEnabled(False)
|
||||
self.version_combo.setToolTip("Select which version to install")
|
||||
version_row.addWidget(self.version_combo)
|
||||
|
||||
version_row.addStretch()
|
||||
@@ -272,11 +281,13 @@ class RegistryPage(QWidget):
|
||||
actions = QHBoxLayout()
|
||||
|
||||
self.btn_install = QPushButton("Install")
|
||||
self.btn_install.setToolTip("Download and install this tool locally")
|
||||
self.btn_install.clicked.connect(self._install_tool)
|
||||
self.btn_install.setEnabled(False)
|
||||
actions.addWidget(self.btn_install)
|
||||
|
||||
self.btn_update = QPushButton("Update Available")
|
||||
self.btn_update.setToolTip("Update to the latest version from the registry")
|
||||
self.btn_update.clicked.connect(self._install_tool)
|
||||
self.btn_update.setEnabled(False)
|
||||
self.btn_update.setStyleSheet("background-color: #48bb78; color: white;")
|
||||
|
||||
@@ -51,10 +51,12 @@ class ToolBuilderPage(QWidget):
|
||||
|
||||
self.btn_cancel = QPushButton("Cancel")
|
||||
self.btn_cancel.setObjectName("secondary")
|
||||
self.btn_cancel.setToolTip("Cancel and return to tools page (Escape)")
|
||||
self.btn_cancel.clicked.connect(self._cancel)
|
||||
header_layout.addWidget(self.btn_cancel)
|
||||
|
||||
self.btn_save = QPushButton("Save")
|
||||
self.btn_save.setToolTip("Save this tool (Ctrl+S)")
|
||||
self.btn_save.clicked.connect(self._save)
|
||||
header_layout.addWidget(self.btn_save)
|
||||
|
||||
@@ -76,14 +78,17 @@ class ToolBuilderPage(QWidget):
|
||||
|
||||
self.name_input = QLineEdit()
|
||||
self.name_input.setPlaceholderText("my-tool")
|
||||
self.name_input.setToolTip("Unique tool name using lowercase letters, numbers, and hyphens")
|
||||
info_layout.addRow("Name:", self.name_input)
|
||||
|
||||
self.desc_input = QLineEdit()
|
||||
self.desc_input.setPlaceholderText("A brief description of what this tool does")
|
||||
self.desc_input.setToolTip("Brief description shown in tool listings and help text")
|
||||
info_layout.addRow("Description:", self.desc_input)
|
||||
|
||||
self.category_combo = QComboBox()
|
||||
self.category_combo.setEditable(True)
|
||||
self.category_combo.setToolTip("Category for organizing tools (select or type custom)")
|
||||
for cat in DEFAULT_CATEGORIES:
|
||||
self.category_combo.addItem(cat)
|
||||
info_layout.addRow("Category:", self.category_combo)
|
||||
@@ -91,9 +96,19 @@ class ToolBuilderPage(QWidget):
|
||||
left_layout.addWidget(info_box)
|
||||
|
||||
# Arguments group
|
||||
args_box = QGroupBox("Arguments")
|
||||
args_box = QGroupBox()
|
||||
args_layout = QVBoxLayout(args_box)
|
||||
|
||||
args_label = QLabel("Arguments")
|
||||
args_label.setObjectName("sectionHeading")
|
||||
args_label.setToolTip(
|
||||
"<p>Arguments are command-line flags users can pass to your tool.</p>"
|
||||
"<p>Example: Adding --max with variable 'max' lets users run:<br>"
|
||||
"<code>my-tool --max 100 < input.txt</code></p>"
|
||||
"<p>Use {max} in your prompts to reference the value.</p>"
|
||||
)
|
||||
args_layout.addWidget(args_label)
|
||||
|
||||
self.args_list = QListWidget()
|
||||
self.args_list.itemDoubleClicked.connect(self._edit_argument)
|
||||
args_layout.addWidget(self.args_list)
|
||||
@@ -127,21 +142,37 @@ class ToolBuilderPage(QWidget):
|
||||
right_layout.setSpacing(16)
|
||||
|
||||
# Steps group with view toggle
|
||||
steps_box = QGroupBox("Steps")
|
||||
steps_box = QGroupBox()
|
||||
steps_layout = QVBoxLayout(steps_box)
|
||||
|
||||
# View toggle header
|
||||
view_header = QHBoxLayout()
|
||||
# Steps header with label and view toggle
|
||||
steps_header = QHBoxLayout()
|
||||
steps_label = QLabel("Steps")
|
||||
steps_label.setObjectName("sectionHeading")
|
||||
steps_label.setToolTip(
|
||||
"<p>Steps define what your tool does, executed in order.</p>"
|
||||
"<p><b>Step types:</b><br>"
|
||||
"- Prompt: Call an AI provider with a template<br>"
|
||||
"- Code: Run Python code to process data<br>"
|
||||
"- Tool: Call another CmdForge tool</p>"
|
||||
"<p>Use {variable} syntax to pass data between steps.<br>"
|
||||
"Built-in: {input} contains stdin content.</p>"
|
||||
)
|
||||
steps_header.addWidget(steps_label)
|
||||
steps_header.addStretch()
|
||||
|
||||
# View toggle buttons
|
||||
self.btn_list_view = QPushButton("List")
|
||||
self.btn_list_view.setCheckable(True)
|
||||
self.btn_list_view.setChecked(True)
|
||||
self.btn_list_view.setObjectName("viewToggle")
|
||||
self.btn_list_view.setToolTip("View steps as a list (drag to reorder)")
|
||||
self.btn_list_view.clicked.connect(lambda: self._set_view_mode(0))
|
||||
|
||||
self.btn_flow_view = QPushButton("Flow")
|
||||
self.btn_flow_view.setCheckable(True)
|
||||
self.btn_flow_view.setObjectName("viewToggle")
|
||||
self.btn_flow_view.setToolTip("View steps as a visual flow graph")
|
||||
self.btn_flow_view.clicked.connect(lambda: self._set_view_mode(1))
|
||||
|
||||
# Button group for mutual exclusivity
|
||||
@@ -149,10 +180,9 @@ class ToolBuilderPage(QWidget):
|
||||
self.view_group.addButton(self.btn_list_view, 0)
|
||||
self.view_group.addButton(self.btn_flow_view, 1)
|
||||
|
||||
view_header.addWidget(self.btn_list_view)
|
||||
view_header.addWidget(self.btn_flow_view)
|
||||
view_header.addStretch()
|
||||
steps_layout.addLayout(view_header)
|
||||
steps_header.addWidget(self.btn_list_view)
|
||||
steps_header.addWidget(self.btn_flow_view)
|
||||
steps_layout.addLayout(steps_header)
|
||||
|
||||
# Stacked widget for list/flow views
|
||||
self.steps_stack = QStackedWidget()
|
||||
@@ -183,24 +213,29 @@ class ToolBuilderPage(QWidget):
|
||||
# Step action buttons
|
||||
steps_btns = QHBoxLayout()
|
||||
self.btn_add_prompt = QPushButton("Add Prompt")
|
||||
self.btn_add_prompt.setToolTip("Add an AI prompt step - calls your provider with a template")
|
||||
self.btn_add_prompt.clicked.connect(self._add_prompt_step)
|
||||
steps_btns.addWidget(self.btn_add_prompt)
|
||||
|
||||
self.btn_add_code = QPushButton("Add Code")
|
||||
self.btn_add_code.setToolTip("Add a Python code step - process or transform data")
|
||||
self.btn_add_code.clicked.connect(self._add_code_step)
|
||||
steps_btns.addWidget(self.btn_add_code)
|
||||
|
||||
self.btn_add_tool = QPushButton("Add Tool")
|
||||
self.btn_add_tool.setToolTip("Add a tool step - chain another CmdForge tool")
|
||||
self.btn_add_tool.clicked.connect(self._add_tool_step)
|
||||
steps_btns.addWidget(self.btn_add_tool)
|
||||
|
||||
self.btn_edit_step = QPushButton("Edit")
|
||||
self.btn_edit_step.setObjectName("secondary")
|
||||
self.btn_edit_step.setToolTip("Edit the selected step (or double-click)")
|
||||
self.btn_edit_step.clicked.connect(self._edit_step)
|
||||
steps_btns.addWidget(self.btn_edit_step)
|
||||
|
||||
self.btn_del_step = QPushButton("Delete")
|
||||
self.btn_del_step.setObjectName("danger")
|
||||
self.btn_del_step.setToolTip("Delete the selected step")
|
||||
self.btn_del_step.clicked.connect(self._delete_step)
|
||||
steps_btns.addWidget(self.btn_del_step)
|
||||
|
||||
@@ -210,9 +245,21 @@ class ToolBuilderPage(QWidget):
|
||||
right_layout.addWidget(steps_box, 1) # Steps box gets stretch priority
|
||||
|
||||
# Output group
|
||||
output_box = QGroupBox("Output Template")
|
||||
output_box = QGroupBox()
|
||||
output_layout = QVBoxLayout(output_box)
|
||||
|
||||
output_label = QLabel("Output Template")
|
||||
output_label.setObjectName("sectionHeading")
|
||||
output_label.setToolTip(
|
||||
"<p>The output template defines what your tool prints.</p>"
|
||||
"<p><b>Use {variable} to include step outputs:</b><br>"
|
||||
"- {response} - typical AI response variable<br>"
|
||||
"- {result} - common code step output<br>"
|
||||
"- Any output_var you defined in steps</p>"
|
||||
"<p>Example: <code>{response}</code> prints just the AI response.</p>"
|
||||
)
|
||||
output_layout.addWidget(output_label)
|
||||
|
||||
self.output_input = QTextEdit()
|
||||
self.output_input.setPlaceholderText("Use {variable} to reference step outputs, e.g. {response}")
|
||||
self.output_input.setPlainText("{response}") # Default value
|
||||
|
||||
Reference in New Issue
Block a user