## Summary epic r04 - begin refactor ## Change Type - [x] Cowork feature - [ ] Bug fix - [ ] 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: Anh Tran Nguyen Minh <anhtnm1@fpt.com> Co-authored-by: Huong Le Thi Thien <huongltt35@fpt.com> Co-authored-by: Nam Pham Dinh Thanh <nampdt@fpt.com> Co-authored-by: Vu Dam Tuan <vudt15@fpt.com> Co-authored-by: Hiep Ha Van <hiephv3@fpt.com> Co-authored-by: Lam Hoang Van <lamhv7@fpt.com> Reviewed-on: #7 Co-authored-by: Duy Le Huu <duylh19@fpt.com>
This commit was merged in pull request #7.
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
"""Xuất khung đồ thị đang xem ra file PNG — tách khỏi ``graph_renderer.py``.
|
||||
|
||||
GraphRAG có hai khung xem: cảnh Qt 2D và trang D3 chạy trong WebEngine. Hai
|
||||
khung ấy chụp ảnh theo hai cách hoàn toàn khác nhau (``QWidget.grab()`` so
|
||||
với một lượt gọi JavaScript trả về data URL), nên chỗ này gom cả hai lại sau
|
||||
một hàm duy nhất và tự chọn đường đi.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
from typing import Callable, Optional
|
||||
|
||||
from PySide6.QtWidgets import QFileDialog, QWidget
|
||||
|
||||
from cowork_local.i18n import tr
|
||||
|
||||
#: Bên gọi truyền vào để hiện kết quả trên thanh trạng thái.
|
||||
StatusFn = Callable[[str], None]
|
||||
|
||||
|
||||
def ask_export_path(parent: QWidget) -> str:
|
||||
"""Hỏi người dùng nơi lưu ảnh; trả về '' nếu họ bấm Huỷ."""
|
||||
path, _ = QFileDialog.getSaveFileName(
|
||||
parent, tr("structure.export_title"), "structure-graph.png", "PNG (*.png)")
|
||||
return path or ""
|
||||
|
||||
|
||||
def export_widget_grab(widget: QWidget, path: str, status: StatusFn) -> None:
|
||||
"""Chụp thẳng widget đang hiện ra PNG.
|
||||
|
||||
Đây cũng là đường lui khi xuất từ D3 thất bại: chụp widget luôn cho ra
|
||||
một tấm ảnh, dù không sắc nét bằng bản vẽ vector của D3.
|
||||
"""
|
||||
if widget.grab().save(path, "PNG"):
|
||||
status(tr("structure.export_done", path=path))
|
||||
else:
|
||||
status(tr("structure.export_failed", err="grab() returned no image"))
|
||||
|
||||
|
||||
def export_d3_png(web, path: str, fallback: QWidget, status: StatusFn) -> None:
|
||||
"""Xuất PNG từ trang D3 bằng cách nhờ chính trang đó vẽ ra data URL.
|
||||
|
||||
``runJavaScript`` chạy bất đồng bộ nên kết quả về trong hàm gọi lại. Mọi
|
||||
đường hỏng — trang chưa nạp xong, ``window.exportPng`` không tồn tại,
|
||||
chuỗi trả về không phải data URL — đều quay sang chụp widget, để người
|
||||
dùng bấm Xuất vẫn luôn nhận được một file thay vì im lặng không có gì.
|
||||
"""
|
||||
def on_result(data_url) -> None:
|
||||
"""Nhận data URL từ trang D3 và ghi ra file; hỏng ở bất cứ đâu thì quay sang
|
||||
chụp widget.
|
||||
"""
|
||||
if not isinstance(data_url, str) or "," not in data_url:
|
||||
export_widget_grab(fallback, path, status)
|
||||
return
|
||||
try:
|
||||
with open(path, "wb") as f:
|
||||
f.write(base64.b64decode(data_url.split(",", 1)[1]))
|
||||
status(tr("structure.export_done", path=path))
|
||||
except (OSError, ValueError) as exc:
|
||||
status(tr("structure.export_failed", err=str(exc)))
|
||||
|
||||
web.page().runJavaScript("window.exportPng ? window.exportPng() : ''", on_result)
|
||||
|
||||
|
||||
def export_png(parent: QWidget, showing: QWidget, web: Optional[object],
|
||||
is_web_visible: bool, status: StatusFn) -> None:
|
||||
"""Hỏi đường dẫn rồi xuất khung ĐANG hiện — D3 hay cảnh Qt tuỳ tab đang mở.
|
||||
|
||||
Chỉ dùng đường D3 khi trang D3 thật sự đang hiển thị; đang xem cảnh Qt mà
|
||||
lại chụp D3 thì ảnh ra không khớp với thứ người dùng nhìn thấy.
|
||||
"""
|
||||
path = ask_export_path(parent)
|
||||
if not path:
|
||||
return
|
||||
if web is not None and is_web_visible:
|
||||
export_d3_png(web, path, showing, status)
|
||||
else:
|
||||
export_widget_grab(showing, path, status)
|
||||
|
||||
|
||||
__all__ = ["export_png", "export_d3_png", "export_widget_grab", "ask_export_path"]
|
||||
Reference in New Issue
Block a user