Let the splitter handle beside the rail actually resize it

The rail was setFixedWidth, so the handle QSplitter draws between it and the
content was inert — it looked draggable and did nothing when dragged.

The expanded rail is now a range (132–360px) instead of one number, so the
handle has something to give. Collapsing still pins it at 54px exactly, and a
width dragged to is remembered across the fold rather than snapping back to the
150px default. Long project names and RECENTS threads are what a wider rail
buys.

check_rail_resize drives the splitter the way the handle does and asserts the
rail follows, clamps at both ends, folds to 54px and comes back to the chosen
width. Restoring setFixedWidth fails it — the first attempt at that mutation
passed, because setMaximumWidth on the next line quietly undid it.

16/16 checkers pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nam Pham Dinh Thanh
2026-08-18 11:55:35 +09:00
co-authored by Claude Opus 5
parent bcdfe43c7c
commit d37a0c1578
2 changed files with 139 additions and 3 deletions
+110
View File
@@ -0,0 +1,110 @@
"""The splitter handle beside the rail has to actually move the rail.
setFixedWidth left it drawn but inert: it looked draggable and did nothing.
Also checks that a width the user drags to survives a collapse/expand, and
that collapsing still pins the rail at 54px.
"""
from __future__ import annotations
import os
import sys
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
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 ( # noqa: E402
_apply_theme, _freeze_schedulers, _isolate_home, _load_fonts)
def main() -> int:
sandbox = _isolate_home()
from PySide6.QtWidgets import QApplication
app = QApplication([])
_load_fonts()
_freeze_schedulers()
_apply_theme(app)
from cowork_local.config import CONFIG_DIR
assert str(sandbox) in str(CONFIG_DIR), f"isolation failed: {CONFIG_DIR}"
from seed_demo_data import seed
seed()
from cowork_local.app import (
_NAV_COLLAPSED_WIDTH, _NAV_MAX_WIDTH, _NAV_MIN_WIDTH, MainWindow)
from cowork_local.config import AppConfig
from cowork_local.i18n import set_language
from cowork_local.state import AppContext
set_language("vi")
win = MainWindow(AppContext(AppConfig.load()), user_name="local")
win.resize(1400, 900)
win.show()
app.processEvents()
fails = []
rail, split = win._nav_wrap, win.split
def drag_to(px):
"""What the splitter does when the handle is dragged."""
total = sum(split.sizes())
split.setSizes([px, max(1, total - px)])
app.processEvents()
win._on_split_moved(px, 1)
app.processEvents()
return rail.width()
start = rail.width()
wide = drag_to(300)
print(f"keo rong : {start} -> {wide}px")
if wide <= start:
fails.append(f"keo tay nam ra 300px ma rail van {wide}px")
narrow = drag_to(_NAV_MIN_WIDTH)
print(f"keo hep : {wide} -> {narrow}px")
if narrow >= wide:
fails.append(f"keo hep lai khong an: {narrow}px")
over = drag_to(_NAV_MAX_WIDTH + 200)
print(f"keo qua max: {over}px (tran {_NAV_MAX_WIDTH})")
if over > _NAV_MAX_WIDTH:
fails.append(f"rail vuot tran: {over} > {_NAV_MAX_WIDTH}")
under = drag_to(20)
print(f"keo duoi min: {under}px (san {_NAV_MIN_WIDTH})")
if under < _NAV_MIN_WIDTH:
fails.append(f"rail thap hon san: {under} < {_NAV_MIN_WIDTH}")
# a dragged width has to come back after a fold
chosen = drag_to(280)
win._toggle_nav()
app.processEvents()
folded = rail.width()
print(f"thu gon : {folded}px")
if folded != _NAV_COLLAPSED_WIDTH:
fails.append(f"thu gon phai la {_NAV_COLLAPSED_WIDTH}px, dang {folded}px")
win._toggle_nav()
app.processEvents()
back = rail.width()
print(f"mo lai : {back}px (da chon {chosen}px)")
if abs(back - chosen) > 4:
fails.append(f"mo lai quen be rong da keo: {back} thay vi {chosen}")
print()
for f in fails:
print("FAIL " + f)
print("PASS tay nam keo duoc, nho be rong qua lan gap" if not fails
else f"{len(fails)} problem(s)")
sys.stdout.flush()
os._exit(1 if fails else 0)
if __name__ == "__main__":
raise SystemExit(main())