Files
cowork-local/tools/check_no_hscroll.py
T
NamPDTandClaude Opus 5 cb68f87b35 feat(ui): close the last gaps against the audit design (31/31)
check_design_parity.py reads its checklist from the audit page's own
proposals; it now reports every one of the 31 as implemented, with no
deliberate divergences left.

  * Schedule: the Kanban/Calendar drop-list became a pair of tabs, and the
    Running lane is outlined while it holds anything — dropping a card there
    starts the task for real, so it should not look like the other six.
  * Cowork: agent / routing / usage / folder moved out of the typing box into
    their own status strip beneath it, styled as status rather than a second
    toolbar. All of them stay interactive; the design's read-only strip would
    have cost features.
  * Folder: the path is written as the screen's title instead of sitting in a
    read-only text box that looked editable and cost a row.
  * GraphRAG: the second toolbar row is gone (Export joined the first), and
    the one button that relabelled itself became Đồ thị | Tin nhắn tabs, so
    the view you are NOT in is named too.
  * Settings gained the theme picker, so language / provider / theme are all
    reachable there as well as on the rail's account row.
  * Task editor: the five group boxes are grouped into three step tabs
    (Nội dung → Lịch chạy → Liên kết). All 22 fields verified present after
    the move; only the old section index is gone, replaced by the tabs.
  * The assistant dot now clears a screen's own bottom bar (Cowork's
    composer), measured from the composer's top edge in window coordinates.

Also adds .gitattributes: without it a Windows checkout records CRLF and
every file reads as fully rewritten to a Linux CI runner.

Verification: 7 check_*.py suites green, no screen clipped at 1920/1366/1280,
and no dialog scrolls sideways at 9/11/14pt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 12:25:25 +09:00

114 lines
3.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""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
tabs = getattr(dlg, "step_tabs", None)
if tabs is not None:
keep = tabs.currentIndex()
for i in range(tabs.count()):
tabs.setCurrentIndex(i)
for _ in range(3):
app.processEvents()
sa = tabs.widget(i)
if sa.widget().sizeHint().width() > sa.viewport().width():
over_area = True
tabs.setCurrentIndex(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())