Repository navigation
Expand file tree
/
Copy pathmain.py
More file actions
109 lines (82 loc) · 3.17 KB
/
Copy pathmain.py
File metadata and controls
109 lines (82 loc) · 3.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
"""Entry point for Poltergeist."""
from __future__ import annotations
import sys
from PySide6.QtCore import QCoreApplication, Qt
from PySide6.QtWidgets import QApplication, QMessageBox
from services import edition as edition_svc
APP_USER_MODEL_ID_BASE = "Poltergeist.SnippetManager"
def _app_user_model_id() -> str:
"""Admin and user editions get distinct IDs so Windows treats them as
separate apps in the taskbar / start menu when both are installed."""
if edition_svc.is_admin():
return f"{APP_USER_MODEL_ID_BASE}.Admin"
return APP_USER_MODEL_ID_BASE
def _single_instance_mutex_name() -> str:
"""Parallel to ``_app_user_model_id`` - the two editions run side by
side so they must not share the single-instance mutex."""
if edition_svc.is_admin():
return "Global\\PoltergeistSnippetManager.Admin"
return "Global\\PoltergeistSnippetManager"
def _set_app_user_model_id() -> None:
"""Tell Windows this is its own app so the taskbar shows our icon.
Without this, a process launched via ``python.exe`` is grouped under the
Python interpreter and the taskbar keeps the Python icon. A custom
AppUserModelID detaches us into our own group and lets Qt's window icon
show up in the taskbar as well.
"""
try:
import ctypes
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
_app_user_model_id()
)
except Exception:
pass
def _acquire_single_instance():
"""Return a handle that keeps the process as the only running instance.
Uses a named Windows mutex. If another instance already holds it, this
function shows a message and terminates the process.
"""
try:
import win32api
import win32event
import winerror
except Exception:
return None
handle = win32event.CreateMutex(None, False, _single_instance_mutex_name())
if win32api.GetLastError() == winerror.ERROR_ALREADY_EXISTS:
QApplication.instance() or QApplication(sys.argv)
QMessageBox.information(
None,
QCoreApplication.translate("Main", "Poltergeist"),
QCoreApplication.translate(
"Main",
"Poltergeist is already running.\n"
"Look for the icon in the system tray.",
),
)
sys.exit(0)
return handle
def main() -> int:
_set_app_user_model_id()
QApplication.setAttribute(Qt.ApplicationAttribute.AA_DontCreateNativeWidgetSiblings)
app = QApplication(sys.argv)
app.setApplicationName("Poltergeist")
app.setOrganizationName("Poltergeist")
app.setQuitOnLastWindowClosed(False)
import config
from models.tree import Settings
from services import i18n
data = config.load()
_startup_settings = Settings.from_dict(data.get("settings") or {})
i18n.install(app, _startup_settings.language)
_handle = _acquire_single_instance()
from app import Poltergeist
from services import icons as icons_svc
app.setWindowIcon(icons_svc.app_icon())
controller = Poltergeist(app)
try:
return app.exec()
finally:
controller.shutdown()
if __name__ == "__main__":
sys.exit(main())