modlink_studio.app

 1from __future__ import annotations
 2
 3import argparse
 4import logging
 5import sys
 6from collections.abc import Sequence
 7from pathlib import Path
 8
 9from PyQt6.QtWidgets import QApplication, QMessageBox
10
11from modlink_core import configure_host_logging
12
13from .startup import (
14    load_app_icon,
15    load_runtime_deps,
16    set_windows_app_user_model_id,
17    show_splash_screen,
18)
19
20logger = logging.getLogger(__name__)
21
22
23def _shutdown_bridge_with_prompt(bridge: object) -> None:
24    try:
25        bridge.shutdown()
26    except Exception as exc:
27        QMessageBox.critical(None, "ModLink Studio", f"关闭后台资源时发生错误。\n\n{exc}")
28
29
30def _run_app(argv: Sequence[str] | None, *, debug: bool, prog: str) -> None:
31    parser = argparse.ArgumentParser(
32        prog=prog,
33        description="Start the ModLink Studio desktop host.",
34    )
35    parser.add_argument(
36        "--log-path",
37        type=Path,
38        help="write the rotating desktop log to a specific file",
39    )
40    raw_args = list(argv) if argv is not None else list(sys.argv[1:])
41    options, qt_args = parser.parse_known_args(raw_args)
42
43    log_path = configure_host_logging(
44        log_path=options.log_path,
45        log_filename="modlink-studio.log",
46        debug=debug,
47    )
48    logger.info("Starting ModLink Studio (logs at %s)", log_path)
49
50    set_windows_app_user_model_id()
51    app = QApplication([prog, *qt_args])
52    app.setApplicationName("ModLink Studio")
53    app.setOrganizationName("ModLink")
54    icon = load_app_icon()
55    app.setWindowIcon(icon)
56
57    # Splash first, then heavy imports under it. Reordering here trades
58    # 1.5 s of cold-start blank screen for a brand splash within ~280 ms,
59    # and avoids a first-frame stall when the user opens a signal preview.
60    splash = show_splash_screen(icon)
61    ModLinkEngine, QtModLinkBridge, MainWindow = load_runtime_deps()
62
63    runtime = ModLinkEngine(parent=app)
64    bridge = QtModLinkBridge(runtime, parent=app)
65    app.aboutToQuit.connect(lambda: _shutdown_bridge_with_prompt(bridge))
66
67    window = MainWindow(engine=bridge)
68    window.setWindowIcon(icon)
69    window.show()
70    splash.finish()
71    raise SystemExit(app.exec())
72
73
74def main(argv: Sequence[str] | None = None) -> None:
75    """Single supported non-debug startup entry for ModLink Studio."""
76    _run_app(argv, debug=False, prog="modlink-studio")
77
78
79def debug_main(argv: Sequence[str] | None = None) -> None:
80    """Console-backed debug startup entry for ModLink Studio."""
81    _run_app(argv, debug=True, prog="modlink-studio-debug")
logger = <Logger modlink_studio.app (WARNING)>
def main(argv: Sequence[str] | None = None) -> None:
75def main(argv: Sequence[str] | None = None) -> None:
76    """Single supported non-debug startup entry for ModLink Studio."""
77    _run_app(argv, debug=False, prog="modlink-studio")

Single supported non-debug startup entry for ModLink Studio.

def debug_main(argv: Sequence[str] | None = None) -> None:
80def debug_main(argv: Sequence[str] | None = None) -> None:
81    """Console-backed debug startup entry for ModLink Studio."""
82    _run_app(argv, debug=True, prog="modlink-studio-debug")

Console-backed debug startup entry for ModLink Studio.