"""Kích thước và cách vẽ một hàng trên thanh rail — R08-T10. Chỉ số và cách vẽ, không có hành vi. Tách riêng vì ``theme.py`` cũng phải biết mấy con số này (nó style ``#navrailBottom`` theo cùng lề), và vì thứ hay phải tra lại nhất khi chỉnh giao diện là chúng — không nên nằm lẫn trong 400 dòng dựng widget. """ from __future__ import annotations from PySide6.QtCore import Qt from PySide6.QtWidgets import QStyledItemDelegate # ---- kích thước --------------------------------------------------------- _NAV_EXPANDED_WIDTH = 150 _NAV_COLLAPSED_WIDTH = 54 _NAV_ROW_INSET = 4 _NAV_ROW_GAP = 6 _NAV_MIN_WIDTH = 132 _NAV_MAX_SHARE = 0.22 _NAV_MAX_CEILING = 360 class _NavItemDelegate(QStyledItemDelegate): """Keep a rail row's icon on the left edge, whatever the column is doing. QStyledItemDelegate hands the style decorationAlignment = AlignHCenter, so a row with no label — every row once the rail collapses to 54px — has its icon centred inside whatever box the column happens to give it. That box tracks the column width, which is not stable: stretched to the viewport the icons land in the middle of the rail, while a column left wider than the view leaves them at the left. Same code, two different pictures, which is why a test render disagreed with the running app. """ def initStyleOption(self, option, index): super().initStyleOption(option, index) option.decorationAlignment = Qt.AlignLeft | Qt.AlignVCenter