Feature/fsg gamma team ui fix #3

Merged
gitea-admin merged 41 commits from feature/FSG_GammaTeam_UI_Fix into main 2026-08-20 12:12:59 +00:00
2 changed files with 118 additions and 3 deletions
Showing only changes of commit d1e3be0feb - Show all commits
+112
View File
@@ -0,0 +1,112 @@
"""GraphRAG rebuilds when it is opened, not every time a project is picked.
Switching project used to rescan the folder, redo the force layout and setHtml
the whole D3 page immediately — for a tab usually not on screen. With the rail's
picker one click away from anywhere, that fired constantly, and the rebuild you
did see on opening GraphRAG read as the page reloading itself.
"""
from __future__ import annotations
import os
import sys
import time
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 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(1600, 950)
win.show()
app.processEvents()
st, w = win.structure, win.workspace
fails = []
# first visit builds the view and scans once
win._goto(win._ROW_WORKSPACE, w._graphrag_tab_idx)
deadline = time.monotonic() + 30
while st._graph is None and time.monotonic() < deadline:
app.processEvents()
time.sleep(0.02)
if st._graph is None:
print("FAIL lan dau khong dung duoc do thi")
sys.stdout.flush()
os._exit(1)
calls = {"scan": 0, "html": 0}
real_scan, real_html = st._scan, st._render_d3
st._scan = lambda: (calls.__setitem__("scan", calls["scan"] + 1), real_scan())[1]
st._render_d3 = lambda: (calls.__setitem__("html", calls["html"] + 1), real_html())[1]
# re-entering an unchanged graph must not rebuild anything
for _ in range(3):
win._goto(win._ROW_WORKSPACE, w._project_tab_idx)
app.processEvents()
win._goto(win._ROW_WORKSPACE, w._graphrag_tab_idx)
app.processEvents()
print(f"vao lai 3 lan (khong doi gi): _scan={calls['scan']} setHtml={calls['html']}")
if calls["scan"] or calls["html"]:
fails.append("vao lai GraphRAG van quet/reload du khong co gi doi")
# switching project off-screen defers the work
win._goto(win._ROW_WORKSPACE, w._cowork_tab_idx)
app.processEvents()
ids = [pid for _n, pid in w.project_choices()]
for pid in ids[1:3]:
w.choose_project(pid)
app.processEvents()
print(f"doi {len(ids[1:3])} project khi dang o Cowork: _scan={calls['scan']} "
f"setHtml={calls['html']} | can quet lan toi={st._needs_scan}")
if calls["scan"]:
fails.append("doi project van quet ngay du GraphRAG khong tren man")
if len(ids) > 1 and not st._needs_scan:
fails.append("doi project ma khong danh dau can quet lai")
# ...and opening it does the work once
win._goto(win._ROW_WORKSPACE, w._graphrag_tab_idx)
app.processEvents()
print(f"mo GraphRAG: _scan={calls['scan']}")
if len(ids) > 1 and calls["scan"] != 1:
fails.append(f"mo GraphRAG phai quet dung 1 lan, dang {calls['scan']}")
print()
for f in fails:
print("FAIL " + f)
print("PASS GraphRAG chi dung lai do thi khi can" 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())
+6 -3
View File
@@ -404,10 +404,13 @@ class StructureGraphView(QWidget):
if project is not None:
self.path_edit.setText(str(project.workspace_dir()))
if project_changed:
# Mark it and scan on the next visit rather than now. The rail's
# project picker made switching a one-click thing from any screen,
# and each switch rebuilt this graph — a folder walk plus a force
# layout plus a full setHtml of the D3 page — for a tab that was
# usually not even on screen. auto_scan_and_fit() picks the flag up
# when GraphRAG is actually opened.
self._needs_scan = True
if self.web is not None:
self._needs_scan = False
self._scan()
# ---- helpers -----------------------------------------------------
def _pick(self) -> None: