Merge master: the downloadable builds

Three files disagreed. The test workflow gained a job on either side, so
both stay: the Mac now parses the release and packaging scripts as well,
and Windows keeps its own job below.

`restart` and `launch_gui` both start Dikte again, and master moved that
argv into `ipc.launcher()` because a packaged build has no `__main__.py`
to name. Windows still cannot use execv there, so the detached start it
needs now takes what the launcher hands it rather than spelling the
interpreter and the script itself.

The test counts in CONTRIBUTING are the suite as it stands after the
merge: 1104 of 1147 run anywhere, and the 43 left are the Linux ones.
This commit is contained in:
2026-08-16 15:44:40 +03:00
19 changed files with 1650 additions and 14 deletions
+9 -2
View File
@@ -45,6 +45,7 @@ from . import config as cfg # noqa: E402
from . import ggml # noqa: E402
from . import hotkey # noqa: E402
from . import i18n # noqa: E402
from . import integrate # noqa: E402
from . import ipc # noqa: E402
from . import meeting # noqa: E402
from . import trayicon # noqa: E402
@@ -980,18 +981,19 @@ class Dikte:
if self.server is not None:
self.server.close()
QLocalServer.removeServer(SERVER_NAME)
args = ipc.launcher() + ["--gui"]
if sys.platform == "win32":
# execv on Windows mangles arguments with spaces and leaves the two
# processes sharing a console; a detached start does neither.
subprocess.Popen(
[sys.executable, ipc.script_path(), "--gui"],
args,
creationflags=(subprocess.DETACHED_PROCESS
| subprocess.CREATE_NEW_PROCESS_GROUP),
close_fds=True,
)
QApplication.instance().quit()
return
os.execv(sys.executable, [sys.executable, ipc.script_path(), "--gui"])
os.execv(args[0], args)
def shutdown(self):
self._quitting = True
@@ -1131,6 +1133,11 @@ def run_app(args):
app.setWindowIcon(trayicon.app_icon())
app.setQuitOnLastWindowClosed(False)
_stay_out_of_the_dock()
# A downloaded build ran no installer, so it writes its own menu entry,
# login item and icon. Here rather than in main() because drawing that icon
# needs the QApplication above, and quiet because there is nothing to say
# on every start after the first.
integrate.ensure()
# Before Dikte is built, because building it is what may start a server, and
# a signal arriving in the middle of that would otherwise take the default
# action and leave the server behind. A signal this early lands in the