"""Prove the long dialogs never scroll sideways — including at large fonts. The report that started this came from a display at 125–150% scaling, where every label is wider than on a 100% screen. Rather than trusting one font size, this runs each dialog at several point sizes and several widths and fails if any horizontal scrollbar turns up, in the scroll area or in the section index. Run: python tools/check_no_hscroll.py """ from __future__ import annotations import os import sys from pathlib import Path REPO = Path(__file__).resolve().parent.parent sys.path.insert(0, str(REPO.parent)) sys.path.insert(0, str(Path(__file__).resolve().parent)) os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") from capture_screens import _isolate_home, _load_fonts # noqa: E402 WIDTHS = (1100, 964, 820, 700) POINTS = (9, 11, 14) # ~100%, ~125%, ~150% display scaling def hscroll(dlg, app): """(scroll-area overflow, index overflow) — each True means content is wider than the space it is given. A dialog built from step tabs has one scroll area per page, and a page that is not current has stale geometry — so each tab is brought to the front before its page is measured. """ from PySide6.QtWidgets import QListWidget, QScrollArea over_area = False stack = getattr(dlg, "section_stack", None) if stack is not None: # One scroll area per section; a page that is not current has stale # geometry, so bring each to the front before measuring it. idx = dlg.section_list keep = idx.currentRow() for i in range(stack.count()): idx.setCurrentRow(i) for _ in range(3): app.processEvents() sa = stack.widget(i) if sa.widget().sizeHint().width() > sa.viewport().width(): over_area = True idx.setCurrentRow(keep) else: sa = dlg.findChildren(QScrollArea)[0] over_area = sa.widget().sizeHint().width() > sa.viewport().width() idx = dlg.findChild(QListWidget, "sectionIndex") over_idx = False if idx is not None: over_idx = idx.sizeHintForColumn(0) > idx.viewport().width() return over_area, over_idx def main() -> int: sandbox = _isolate_home() from PySide6.QtGui import QFont from PySide6.QtWidgets import QApplication app = QApplication([]) _load_fonts() from cowork_local.config import AppConfig, CONFIG_DIR assert str(sandbox) in str(CONFIG_DIR), f"isolation failed: {CONFIG_DIR}" from cowork_local.i18n import set_language from cowork_local.state import AppContext from cowork_local.ui.settings_dialog import SettingsDialog from cowork_local.ui.task_editor_dialog import TaskEditorDialog set_language("vi") ctx = AppContext(AppConfig.load()) fails: list[str] = [] for pt in POINTS: f = QFont(app.font()) f.setPointSize(pt) app.setFont(f) for name, make in (("Cai dat", lambda: SettingsDialog(ctx)), ("Task editor", lambda: TaskEditorDialog(ctx=ctx))): dlg = make() dlg.show() row = [] for w in WIDTHS: dlg.resize(w, 900) for _ in range(4): app.processEvents() over_area, over_idx = hscroll(dlg, app) row.append(f"{w}:{'A' if over_area else '.'}{'I' if over_idx else '.'}") if over_area: fails.append(f"{name} @ {pt}pt {w}px — vung cuon tran ngang") if over_idx: fails.append(f"{name} @ {pt}pt {w}px — muc luc tran ngang") print(f" {pt:>2}pt {name:12} {' '.join(row)}") dlg.close() print() print("A = vung cuon tran · I = muc luc tran · . = khong tran") print() if fails: print("*** LOI ***") for x in fails: print(" " + x) return 1 print("KET QUA: khong hop thoai nao cuon ngang, o moi co chu va be rong da thu") return 0 if __name__ == "__main__": raise SystemExit(main())