## Summary What changed and why? ## Change Type - [ ] Cowork feature - [ ] Bug fix - [x] Core AI contribution - [ ] Test / hardening - [ ] Performance - [ ] Documentation ## Related Work Cowork Task: Core Repo: http://34.143.229.138/gitea-admin/fsg-ai-core-assets Core AI Issue: Core Task: Related PR: ## Scope What is intentionally included? What is intentionally NOT included? ## Validation - [ ] Unit tests - [ ] Integration tests - [ ] Manual verification - [ ] Regression check Commands / evidence: ## Security Impact Permission / credential / network / customer data impact: ## Compatibility - [ ] No breaking change - [ ] Breaking change documented ## Reviewer Notes Anything Cowork reviewers should pay attention to. --------- Co-authored-by: Hiep Ha Van <hiephv3@fpt.com> Co-authored-by: Nam Pham Dinh Thanh <nampdt@fpt.com> Co-authored-by: Lam Hoang Van <lamhv7@fpt.com> Co-authored-by: NamPDT <minhanhpkpro@gmail.com> Reviewed-on: #3
This commit was merged in pull request #3.
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
"""Measure what actually breaks on a small screen, screen by screen.
|
||||
|
||||
A pane is "clipped" when the width it is given is smaller than the width it says
|
||||
it needs (minimumSizeHint): Qt then cuts content off instead of shrinking it,
|
||||
which is what shows up as half-drawn buttons and cut-off labels.
|
||||
|
||||
Reports per destination, at a few window sizes, and lists the widest offenders
|
||||
so a fix can be aimed at the right widget instead of guessed at.
|
||||
|
||||
Run: python tools/check_responsive.py [width height ...]
|
||||
"""
|
||||
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 _freeze_schedulers, _isolate_home, _load_fonts # noqa: E402
|
||||
|
||||
SIZES = [(1920, 1080), (1366, 768), (1280, 720)]
|
||||
|
||||
|
||||
def panes(widget):
|
||||
"""Direct children worth measuring: splitter panes and page-level boxes."""
|
||||
from PySide6.QtWidgets import QSplitter
|
||||
out = []
|
||||
for sp in widget.findChildren(QSplitter):
|
||||
for i in range(sp.count()):
|
||||
w = sp.widget(i)
|
||||
if w is not None and not w.isHidden():
|
||||
out.append((f"{sp.objectName() or 'splitter'}[{i}] {type(w).__name__}", w))
|
||||
return out
|
||||
|
||||
|
||||
def main(argv) -> int:
|
||||
sizes = SIZES
|
||||
if len(argv) >= 2:
|
||||
sizes = [(int(argv[i]), int(argv[i + 1])) for i in range(0, len(argv) - 1, 2)]
|
||||
|
||||
sandbox = _isolate_home()
|
||||
from PySide6.QtWidgets import QApplication
|
||||
|
||||
app = QApplication([])
|
||||
_load_fonts()
|
||||
_freeze_schedulers()
|
||||
|
||||
from cowork_local.config import AppConfig, 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 MainWindow
|
||||
from cowork_local.i18n import set_language
|
||||
from cowork_local.state import AppContext
|
||||
from cowork_local.theme import set_active_theme, stylesheet
|
||||
|
||||
set_language("vi")
|
||||
cfg = AppConfig.load()
|
||||
set_active_theme(cfg.theme)
|
||||
app.setStyleSheet(stylesheet(cfg.theme))
|
||||
win = MainWindow(AppContext(cfg), user_name="local")
|
||||
win.show()
|
||||
for _ in range(6):
|
||||
app.processEvents()
|
||||
|
||||
dests = [("Project", win._ROW_WORKSPACE, win.workspace._project_tab_idx),
|
||||
("Cowork", win._ROW_WORKSPACE, win.workspace._cowork_tab_idx),
|
||||
("Co4E", win._ROW_WORKSPACE, win.workspace._co4e_tab_idx),
|
||||
("Folder", win._ROW_WORKSPACE, win.workspace._folder_tab_idx),
|
||||
("GraphRAG", win._ROW_WORKSPACE, win.workspace._graphrag_tab_idx),
|
||||
("Schedule", win._ROW_SCHEDULE, None),
|
||||
("Dashboard", win._ROW_DASHBOARD, None),
|
||||
("Monitoring", win._ROW_MONITORING, None)]
|
||||
|
||||
print(f"cua so: minimumSizeHint = {win.minimumSizeHint().width()}"
|
||||
f"x{win.minimumSizeHint().height()}px")
|
||||
print()
|
||||
worst: dict[str, int] = {}
|
||||
for w, h in sizes:
|
||||
win.resize(w, h)
|
||||
for _ in range(4):
|
||||
app.processEvents()
|
||||
print(f"=== {w}x{h} ===")
|
||||
for name, page, sub in dests:
|
||||
win._goto(page, sub)
|
||||
for _ in range(4):
|
||||
app.processEvents()
|
||||
widget = win._page_widgets[page]
|
||||
need = widget.minimumSizeHint().width()
|
||||
have = widget.width()
|
||||
tight = [(n, p.minimumSizeHint().width(), p.width())
|
||||
for n, p in panes(widget)
|
||||
if p.minimumSizeHint().width() > p.width() + 1]
|
||||
flag = "" if need <= have else f" <-- THIEU {need - have}px"
|
||||
print(f" {name:11} can {need:5}px · duoc {have:5}px{flag}")
|
||||
for n, nd, hv in tight:
|
||||
print(f" · {n:34} can {nd:4} duoc {hv:4}")
|
||||
worst[f"{name}/{n}"] = max(worst.get(f"{name}/{n}", 0), nd - hv)
|
||||
print()
|
||||
|
||||
if worst:
|
||||
print("BO BO NHIEU NHAT:")
|
||||
for k, v in sorted(worst.items(), key=lambda kv: -kv[1])[:12]:
|
||||
print(f" {v:5}px {k}")
|
||||
else:
|
||||
print("KET QUA: khong pane nao bi bo o cac co da thu")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main(sys.argv[1:]))
|
||||
Reference in New Issue
Block a user