diff --git a/app.py b/app.py index 620d856..9360703 100644 --- a/app.py +++ b/app.py @@ -285,6 +285,12 @@ class MainWindow(QMainWindow): self.nav_recents = self._new_nav_tree("navRecents") self.nav_recents.itemClicked.connect(self._on_rail_recent) sv.addWidget(self.nav_recents, 1) + # Collapsing hides RECENTS, and with it the only item carrying a stretch + # factor. A box layout with nothing left to expand centres what remains, + # so the destinations dropped ~300px down the rail — "thu gọn menu lại + # ra giữa". This spacer takes the slack instead, and takes none of it + # while RECENTS is visible (stretch 0 against its 1). + sv.addStretch(0) self._nav_scroll.setWidget(scroll_body) nvl.addWidget(self._nav_scroll, 1) # Bottom-pinned group: the places you visit occasionally, kept out of the diff --git a/tools/check_rail_align.py b/tools/check_rail_align.py index 8000e3f..ca19f13 100644 --- a/tools/check_rail_align.py +++ b/tools/check_rail_align.py @@ -140,6 +140,7 @@ def main() -> int: app.processEvents() fails += compare(theme_name, rail, opened, closed) fails += column_widths_do_not_move_icons(win, app, theme_name) + fails += rows_stay_under_the_header(win, app, theme_name) print() for f in fails: @@ -150,6 +151,35 @@ def main() -> int: os._exit(1 if fails else 0) +def rows_stay_under_the_header(win, app, theme_name): + """The destinations start just below the + button in both states. + + Collapsing hides RECENTS, the one item in the scroll body with a stretch + factor. With nothing left to expand, a box layout centres what remains, and + the whole group slid ~300px down the rail. + """ + from PySide6.QtCore import QPoint + + rail = win._nav_wrap + gaps = {} + for state in ("open", "collapsed"): + if (state == "collapsed") != win._nav_collapsed: + win._toggle_nav() + app.processEvents() + btn = win.nav_new_chat + below = btn.mapTo(rail, QPoint(0, btn.height())).y() + top = win.nav.mapTo(rail, QPoint(0, 0)).y() + win.nav.visualItemRect(win.nav.topLevelItem(0)).top() + gaps[state] = top - below + if win._nav_collapsed: + win._toggle_nav() + app.processEvents() + print(f" gap under +: open={gaps['open']}px collapsed={gaps['collapsed']}px") + if abs(gaps["collapsed"] - gaps["open"]) > 4: + return [f"{theme_name}: the destinations sit {gaps['collapsed']}px below " + f"the + button when collapsed but {gaps['open']}px when open"] + return [] + + def column_widths_do_not_move_icons(win, app, theme_name): """The icon must not care how wide the column is.