feat(ui): close the last gaps against the audit design (31/31)
check_design_parity.py reads its checklist from the audit page's own
proposals; it now reports every one of the 31 as implemented, with no
deliberate divergences left.
* Schedule: the Kanban/Calendar drop-list became a pair of tabs, and the
Running lane is outlined while it holds anything — dropping a card there
starts the task for real, so it should not look like the other six.
* Cowork: agent / routing / usage / folder moved out of the typing box into
their own status strip beneath it, styled as status rather than a second
toolbar. All of them stay interactive; the design's read-only strip would
have cost features.
* Folder: the path is written as the screen's title instead of sitting in a
read-only text box that looked editable and cost a row.
* GraphRAG: the second toolbar row is gone (Export joined the first), and
the one button that relabelled itself became Đồ thị | Tin nhắn tabs, so
the view you are NOT in is named too.
* Settings gained the theme picker, so language / provider / theme are all
reachable there as well as on the rail's account row.
* Task editor: the five group boxes are grouped into three step tabs
(Nội dung → Lịch chạy → Liên kết). All 22 fields verified present after
the move; only the old section index is gone, replaced by the tabs.
* The assistant dot now clears a screen's own bottom bar (Cowork's
composer), measured from the composer's top edge in window coordinates.
Also adds .gitattributes: without it a Windows checkout records CRLF and
every file reads as fully rewritten to a Linux CI runner.
Verification: 7 check_*.py suites green, no screen clipped at 1920/1366/1280,
and no dialog scrolls sideways at 9/11/14pt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+43
-26
@@ -19,7 +19,7 @@ from PySide6.QtWidgets import (
|
||||
QCheckBox, QComboBox, QDateTimeEdit, QDialog, QDialogButtonBox, QFileDialog,
|
||||
QFormLayout, QGroupBox, QHBoxLayout, QInputDialog, QLabel, QLineEdit,
|
||||
QListWidget, QListWidgetItem, QMessageBox, QPlainTextEdit, QPushButton,
|
||||
QScrollArea, QSpinBox, QVBoxLayout, QWidget,
|
||||
QScrollArea, QSpinBox, QTabWidget, QVBoxLayout, QWidget,
|
||||
)
|
||||
|
||||
from ..config import PROVIDER_LABELS
|
||||
@@ -93,12 +93,11 @@ class TaskEditorDialog(QDialog):
|
||||
root = QVBoxLayout(content)
|
||||
|
||||
# ---- basics ----------------------------------------------------
|
||||
# Zero-height anchor: this block is a bare form, so the index needs
|
||||
# something to scroll to.
|
||||
self._anchor_basic = QWidget()
|
||||
self._anchor_basic.setFixedHeight(0)
|
||||
root.addWidget(self._anchor_basic)
|
||||
form = QFormLayout()
|
||||
# Held in its own widget so the whole block can be moved into a step
|
||||
# tab below; it is a bare form, not a group box.
|
||||
self._basic_box = QWidget()
|
||||
form = QFormLayout(self._basic_box)
|
||||
form.setContentsMargins(0, 0, 0, 0)
|
||||
self.title_edit = QLineEdit(self.task.get("title", ""))
|
||||
# Description is the source of truth. Its ✨ button GENERATES the Prompt
|
||||
# (Input) FROM the description — the title is just the task's label and
|
||||
@@ -211,7 +210,7 @@ class TaskEditorDialog(QDialog):
|
||||
form.addRow(tr("schedtask.f_skill"), self.skill_combo)
|
||||
form.addRow(tr("schedtask.f_priority"), self.priority_combo)
|
||||
form.addRow(tr("schedtask.f_status"), self.status_combo)
|
||||
root.addLayout(form)
|
||||
root.addWidget(self._basic_box)
|
||||
self._main_form = form
|
||||
self._model_box = model_box
|
||||
self._on_run_kind_changed() # apply agent/flow row visibility
|
||||
@@ -433,25 +432,38 @@ class TaskEditorDialog(QDialog):
|
||||
eform.addRow("", self.approval_chk)
|
||||
root.addWidget(eg)
|
||||
|
||||
# Five groups in one long scroll — same problem, same fix as Settings.
|
||||
from .widgets import section_index
|
||||
self.section_list = section_index(scroll, [
|
||||
(tr("schedtask.g_basic"), self._anchor_basic),
|
||||
(tr("schedtask.g_schedule"), sg),
|
||||
(tr("schedtask.g_input"), ig),
|
||||
(tr("schedtask.g_dependency"), dg),
|
||||
(tr("schedtask.g_execution"), eg),
|
||||
])
|
||||
# Three steps, as tabs: Nội dung → Lịch chạy → Liên kết. The five group
|
||||
# boxes are re-parented into three pages — none is dropped, they are
|
||||
# grouped by the question being answered rather than stacked in one
|
||||
# scroll where the later ones are out of sight.
|
||||
self.step_tabs = QTabWidget()
|
||||
self.step_tabs.setObjectName("taskSteps")
|
||||
pages = [
|
||||
("schedtask.step_content", [self._basic_box, ig]),
|
||||
("schedtask.step_schedule", [sg]),
|
||||
("schedtask.step_link", [dg, eg]),
|
||||
]
|
||||
self._step_keys = [key for key, _ in pages]
|
||||
for _key, groups in pages:
|
||||
page = QWidget()
|
||||
pv = QVBoxLayout(page)
|
||||
pv.setContentsMargins(4, 8, 4, 4)
|
||||
for g in groups:
|
||||
root.removeWidget(g)
|
||||
pv.addWidget(g)
|
||||
pv.addStretch(1)
|
||||
wrap = QScrollArea()
|
||||
wrap.setWidgetResizable(True)
|
||||
wrap.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
wrap.setWidget(page)
|
||||
self.step_tabs.addTab(wrap, "")
|
||||
outer.removeWidget(scroll)
|
||||
body = QHBoxLayout()
|
||||
body.setSpacing(10)
|
||||
body.addWidget(self.section_list)
|
||||
body.addWidget(scroll, 1)
|
||||
outer.insertLayout(0, body, 1)
|
||||
# Same floor as Settings: the dialog may not be narrower than its own
|
||||
# content at the font in use, so nothing is ever cut off sideways.
|
||||
self.setMinimumWidth(self.section_list.width()
|
||||
+ content.sizeHint().width() + 60)
|
||||
scroll.setParent(None)
|
||||
outer.insertWidget(0, self.step_tabs, 1)
|
||||
self._retranslate_steps()
|
||||
# Floor the width at what the widest page needs, at the font in use.
|
||||
self.setMinimumWidth(max(p.widget().sizeHint().width()
|
||||
for p in self.step_tabs.findChildren(QScrollArea)) + 60)
|
||||
|
||||
buttons = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Cancel)
|
||||
buttons.button(QDialogButtonBox.Save).setIcon(icon("save"))
|
||||
@@ -465,6 +477,11 @@ class TaskEditorDialog(QDialog):
|
||||
from .widgets import guard_wheel
|
||||
guard_wheel(self)
|
||||
|
||||
def _retranslate_steps(self) -> None:
|
||||
"""Name the three step tabs for the current language."""
|
||||
for i, key in enumerate(self._step_keys):
|
||||
self.step_tabs.setTabText(i, f"{i + 1}. {tr(key)}")
|
||||
|
||||
def _apply_hints(self) -> None:
|
||||
"""Tooltip hints on every non-obvious control, so each option explains
|
||||
itself on hover."""
|
||||
|
||||
Reference in New Issue
Block a user