Keep the project picker reachable while the rail is collapsed
The picker was hidden outright at 54px, on the grounds that a combo box there could only show a stub of a name. True, but it left the collapsed rail with no way to change project at all — and the audit page's own inventory of the 11 collapsible controls says the rail's fold "giữ nguyên toàn bộ". A folder QToolButton stands in for it: same items, and choosing one moves the combo, so _on_rail_project_pick stays the single code path. Its tooltip carries the current project name, which the combo could not have shown anyway. It matches the + button's width and drops its menu arrow — at 42px the arrow would take a third of the row to say nothing. check_nav now collapses the rail and requires a reachable picker whose menu matches the combo item for item, then picks a row and asserts the project actually changed. Hiding the button fails it. 15/15 checkers pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ac29f519cc
commit
bcdfe43c7c
@@ -247,10 +247,23 @@ class MainWindow(QMainWindow):
|
||||
self.nav_new_chat.setIcon(_icon("plus"))
|
||||
self.nav_new_chat.setCursor(Qt.PointingHandCursor)
|
||||
self.nav_new_chat.clicked.connect(self._on_rail_new_chat)
|
||||
# At 54px the picker cannot show a name, but dropping it altogether left
|
||||
# the collapsed rail with no way to change project at all. This stands in
|
||||
# for it: same list, same handler, just the folder icon and a tooltip.
|
||||
self.nav_project_btn = QToolButton()
|
||||
self.nav_project_btn.setObjectName("navProjectPickMini")
|
||||
self.nav_project_btn.setIcon(_icon("folder"))
|
||||
self.nav_project_btn.setCursor(Qt.PointingHandCursor)
|
||||
self.nav_project_btn.setPopupMode(QToolButton.InstantPopup)
|
||||
self.nav_project_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||
self.nav_project_btn.setMenu(QMenu(self.nav_project_btn))
|
||||
self.nav_project_btn.menu().aboutToShow.connect(self._fill_rail_project_menu)
|
||||
self.nav_project_btn.setVisible(False)
|
||||
head = QVBoxLayout()
|
||||
head.setContentsMargins(6, 0, 6, 6)
|
||||
head.setSpacing(6)
|
||||
head.addWidget(self.nav_project)
|
||||
head.addWidget(self.nav_project_btn)
|
||||
head.addWidget(self.nav_new_chat)
|
||||
nvl.addLayout(head)
|
||||
self.workspace.project_selected.connect(self._sync_rail_project)
|
||||
@@ -621,12 +634,28 @@ class MainWindow(QMainWindow):
|
||||
self.nav_project.setCurrentIndex(idx)
|
||||
has = bool(choices)
|
||||
self.nav_project.setEnabled(has)
|
||||
self.nav_project_btn.setEnabled(has)
|
||||
self.nav_project_btn.setToolTip(
|
||||
self.nav_project.currentText().replace("📁 ", "")
|
||||
if has else tr("app.nav.create_project_first"))
|
||||
self.nav_new_chat.setEnabled(has)
|
||||
self.nav_new_chat.setToolTip(
|
||||
"" if has else tr("app.nav.create_project_first"))
|
||||
finally:
|
||||
self._syncing_rail_project = False
|
||||
|
||||
def _fill_rail_project_menu(self) -> None:
|
||||
"""Mirror the picker's items. Choosing one moves the picker, which runs
|
||||
_on_rail_project_pick — the collapsed rail adds no second code path."""
|
||||
menu = self.nav_project_btn.menu()
|
||||
menu.clear()
|
||||
for i in range(self.nav_project.count()):
|
||||
act = menu.addAction(self.nav_project.itemText(i))
|
||||
act.setCheckable(True)
|
||||
act.setChecked(i == self.nav_project.currentIndex())
|
||||
act.triggered.connect(
|
||||
lambda _checked=False, row=i: self.nav_project.setCurrentIndex(row))
|
||||
|
||||
def _on_rail_project_pick(self, _idx: int) -> None:
|
||||
if self._syncing_rail_project:
|
||||
return
|
||||
@@ -701,6 +730,7 @@ class MainWindow(QMainWindow):
|
||||
# picker would be a stub of a name, so it steps aside entirely and the
|
||||
# button keeps just its + icon.
|
||||
self.nav_project.setVisible(not self._nav_collapsed)
|
||||
self.nav_project_btn.setVisible(self._nav_collapsed)
|
||||
self._refresh_rail_recents()
|
||||
# Collapsed to 54px only the theme toggle still fits; the rest of the
|
||||
# account row would be clipped, so it steps aside (Settings, which opens
|
||||
|
||||
@@ -469,6 +469,16 @@ QComboBox#navProjectPick {
|
||||
background: $surface_raised; border: 1px solid $nav_border; color: $text;
|
||||
padding: 4px 8px; border-radius: ${radius}px;
|
||||
}
|
||||
/* Stand-in for the picker while the rail is 54px wide: icon only, no arrow —
|
||||
the arrow would eat a third of the width for no information. */
|
||||
QToolButton#navProjectPickMini {
|
||||
background: $surface_raised; border: 1px solid $nav_border; border-radius: ${radius}px;
|
||||
padding: 4px; qproperty-iconSize: 16px 16px;
|
||||
}
|
||||
QToolButton#navProjectPickMini:hover { background: $nav_hover; }
|
||||
QToolButton#navProjectPickMini:disabled { background: transparent; border-color: $border; }
|
||||
QToolButton#navProjectPickMini::menu-indicator { image: none; width: 0; }
|
||||
|
||||
QPushButton#navSettingsBtn {
|
||||
background: transparent; border: none; color: $text_muted;
|
||||
padding: 6px 8px 6px 4px; text-align: left; border-radius: ${radius}px;
|
||||
|
||||
@@ -289,6 +289,37 @@ def main() -> int:
|
||||
print(f"provider dang chon : {win.provider_combo.currentText()!r}")
|
||||
print(f"tai khoan : {win.account_lbl.text()!r}")
|
||||
|
||||
# Collapsing the rail must not take the project picker away with it: at
|
||||
# 54px the combo cannot show a name, so a folder button stands in for it.
|
||||
if not win._nav_collapsed:
|
||||
win._toggle_nav()
|
||||
app.processEvents()
|
||||
mini = getattr(win, "nav_project_btn", None)
|
||||
if mini is None or mini.isHidden():
|
||||
fails.append("thu gon rail xong khong con cach nao doi project")
|
||||
else:
|
||||
mini.menu().aboutToShow.emit()
|
||||
app.processEvents()
|
||||
menu_items = [a.text() for a in mini.menu().actions()]
|
||||
combo_items = [win.nav_project.itemText(i)
|
||||
for i in range(win.nav_project.count())]
|
||||
if menu_items != combo_items:
|
||||
fails.append(f"menu project khi thu gon lech voi combo: "
|
||||
f"{menu_items} vs {combo_items}")
|
||||
elif len(menu_items) > 1:
|
||||
before = win.workspace.selected_project_id()
|
||||
# Any row but the one already selected, or nothing would change.
|
||||
row = (win.nav_project.currentIndex() + 1) % len(menu_items)
|
||||
mini.menu().actions()[row].trigger()
|
||||
app.processEvents()
|
||||
after = win.workspace.selected_project_id()
|
||||
if after == before:
|
||||
fails.append("chon project tu menu thu gon khong doi project")
|
||||
else:
|
||||
print(f"doi project khi thu gon: {before} -> {after}")
|
||||
win._toggle_nav()
|
||||
app.processEvents()
|
||||
|
||||
print()
|
||||
print(f"tong dong dieu huong: {n_total} + nut Cai dat")
|
||||
if fails:
|
||||
|
||||
Reference in New Issue
Block a user