From aeecdf5da0a5a27017e5318a1dd99da4aeb2c081 Mon Sep 17 00:00:00 2001 From: Anh Tran Nguyen Minh Date: Tue, 8 Sep 2026 21:27:28 +0900 Subject: [PATCH] =?UTF-8?q?fix(ui):=20t=C3=A1ch=20h=C3=A0ng=20C=C3=A0i=20?= =?UTF-8?q?=C4=91=E1=BA=B7t=20kh=E1=BB=8Fi=20nh=C3=B3m=20menu=20ngay=20tr?= =?UTF-8?q?=C3=AAn=20n=C3=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanh rail đặt setSpacing(0) nên nút Cài đặt dán sát Dashboard/Giám sát, ba dòng đọc thành một khối. Thêm hằng _NAV_SETTINGS_GAP trong rail_metrics và xin khe bằng nvl.addSpacing() — margin trong QSS vẽ BÊN TRONG hộp widget, mà nút này bị _rebuild_nav ghim đúng chiều cao một dòng menu nên margin không mua được pixel nào. Rút gọn lại comment ở _rebuild_nav cho khớp. Co-Authored-By: Claude Opus 5 (1M context) --- presentation/shell/nav_rail.py | 19 ++++++------------- presentation/shell/rail_metrics.py | 5 +++++ presentation/shell/top_bar.py | 8 +++++++- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/presentation/shell/nav_rail.py b/presentation/shell/nav_rail.py index 13a7f9c..32fdfb8 100644 --- a/presentation/shell/nav_rail.py +++ b/presentation/shell/nav_rail.py @@ -251,24 +251,17 @@ class NavRailMixin: blocked = tree.blockSignals(True) tree.addTopLevelItem(it) tree.blockSignals(blocked) - # Both destination lists are exactly as tall as their rows; the - # stretch in between belongs to RECENTS. - # - # The frame, and nothing else. A flat ``+ 8`` here used to leave 6px - # of dead space under the last row of each list, and because the - # Settings button sits DIRECTLY under nav_bottom (nvl has no - # spacing), that space landed between Giám sát and Settings only — - # so three rows that read as one list were spaced 18/26px. Padding - # a row is the item delegate's job; this is the frame's. + # Rows plus frame, nothing else: the flat ``+ 8`` this replaces + # left 6px of dead space under the last row, and since Settings + # sits directly under nav_bottom it fell between Giám sát and + # Settings alone — 18/26px for rows that read as one list. row_h = 0 for tree in (self.nav, self.nav_bottom): n = tree.topLevelItemCount() row_h = tree.sizeHintForRow(0) if n else row_h tree.setFixedHeight(n * row_h + 2 * tree.frameWidth()) - # Settings is one more row of the same list, so it gets the rows' - # own height rather than a second set of paddings guessed to match - # it — the only way the three stay evenly spaced when the font (and - # with it ``sizeHintForRow``) is not the one this was tuned on. + # Settings is one more row of the list, so it takes the rows' own + # height instead of paddings guessed to match it. if row_h and hasattr(self, "_nav_settings_btn"): self._nav_settings_btn.setFixedHeight(row_h) if keep: diff --git a/presentation/shell/rail_metrics.py b/presentation/shell/rail_metrics.py index 116869a..3732c7e 100644 --- a/presentation/shell/rail_metrics.py +++ b/presentation/shell/rail_metrics.py @@ -15,6 +15,11 @@ _NAV_EXPANDED_WIDTH = 232 _NAV_COLLAPSED_WIDTH = 54 _NAV_ROW_INSET = 8 _NAV_ROW_GAP = 6 +# Khe TRÊN nút Cài đặt, tính bằng khoảng trống thật trong layout của rail. +# Không đặt bằng ``margin`` trong QSS: margin của stylesheet được vẽ BÊN TRONG +# hộp của widget, mà nút này lại bị ``_rebuild_nav`` ghim đúng chiều cao một +# dòng menu — nên margin không mua được một pixel khoảng cách nào. +_NAV_SETTINGS_GAP = 10 # 132 -> 232: o 132px nhan "Cuoc tro chuyen moi" bi cat mat chu. San phai du # rong cho nhan DAI NHAT tren thanh, khong phai cho nhan trung binh. _NAV_MIN_WIDTH = 232 diff --git a/presentation/shell/top_bar.py b/presentation/shell/top_bar.py index 472bad3..0fbcecc 100644 --- a/presentation/shell/top_bar.py +++ b/presentation/shell/top_bar.py @@ -35,7 +35,7 @@ class TopBarMixin: from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton from ...i18n import tr from ...ui.icons import icon as _icon - from .rail_metrics import _NAV_ROW_GAP, _NAV_ROW_INSET + from .rail_metrics import _NAV_ROW_GAP, _NAV_ROW_INSET, _NAV_SETTINGS_GAP # Bottom-pinned group: the places you visit occasionally, kept out of the # way of the ones you live in. A hairline (styled via #navrailBottom in @@ -71,6 +71,12 @@ class TopBarMixin: # The first _rebuild_nav() ran before this button existed (it is what # fills the list this row belongs under), so take the height here too. self._nav_settings_btn.setFixedHeight(self.nav_bottom.sizeHintForRow(0)) + # Khe TRÊN hàng Cài đặt, xin thẳng từ layout — thanh rail đặt + # ``setSpacing(0)`` nên không có khoảng nào sẵn, và margin trong QSS thì + # không mua được pixel nào (xem ``_NAV_SETTINGS_GAP``). Cài đặt là việc + # khác với nhóm Dashboard/Giám sát ngay trên nó; dán sát vào thì hai thứ + # đọc thành một khối. + nvl.addSpacing(_NAV_SETTINGS_GAP) nvl.addWidget(self._nav_settings_btn) self._account_row = self._build_account_row()