Files
PortProtonQt/portprotonqt/app.py
Boris Yumankulov 29d25cec01
All checks were successful
Code check / Check code (push) Successful in 1m13s
Build AppImage, Arch and Fedora Packages / Build AppImage (push) Successful in 2m50s
Build AppImage, Arch and Fedora Packages / Build Arch Package (push) Successful in 1m42s
Build AppImage, Arch and Fedora Packages / Build Fedora RPM (41) (push) Successful in 59s
Build AppImage, Arch and Fedora Packages / Build Fedora RPM (42) (push) Successful in 1m1s
Build AppImage, Arch and Fedora Packages / Build Fedora RPM (43) (push) Successful in 54s
Build AppImage, Arch and Fedora Packages / Build Fedora RPM (rawhide) (push) Successful in 58s
Build AppImage, Arch and Fedora Packages / Create and Publish Release (push) Successful in 35s
chore: bump ver to 0.1.9
Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
2025-12-01 20:29:45 +05:00

178 lines
6.1 KiB
Python

import sys
import os
import subprocess
from PySide6.QtCore import QLocale, QTranslator, QLibraryInfo, QTimer, Qt
from PySide6.QtWidgets import QApplication
from PySide6.QtGui import QIcon
from PySide6.QtNetwork import QLocalServer, QLocalSocket
from portprotonqt.main_window import MainWindow
from portprotonqt.config_utils import (
save_fullscreen_config,
read_fullscreen_config,
get_portproton_start_command
)
from portprotonqt.logger import get_logger, setup_logger
from portprotonqt.cli import parse_args
__app_id__ = "ru.linux_gaming.PortProtonQt"
__app_name__ = "PortProtonQt"
__app_version__ = "0.1.9"
def get_version():
try:
commit = subprocess.check_output(
["git", "rev-parse", "--short", "HEAD"],
stderr=subprocess.DEVNULL,
).decode("utf-8").strip()
return f"{__app_version__} ({commit})"
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
return __app_version__
def main():
os.environ["PW_CLI"] = "1"
os.environ["PROCESS_LOG"] = "1"
os.environ["START_FROM_STEAM"] = "1"
# Get the PortProton start command
start_sh = get_portproton_start_command()
if start_sh is None:
return
app = QApplication(sys.argv)
app.setWindowIcon(QIcon.fromTheme(__app_id__))
app.setDesktopFileName(__app_id__)
app.setApplicationName(__app_name__)
app.setApplicationVersion(__app_version__)
args = parse_args()
setup_logger(args.debug_level)
logger = get_logger(__name__)
# --- Single-instance logic ---
server_name = __app_id__
socket = QLocalSocket()
socket.connectToServer(server_name)
if socket.waitForConnected(200):
# Второй экземпляр — передаём команду первому
fullscreen = args.fullscreen or read_fullscreen_config()
msg = b"show:fullscreen" if fullscreen else b"show"
socket.write(msg)
socket.flush()
socket.waitForBytesWritten(500)
socket.disconnectFromServer()
logger.info("Restored existing instance from tray")
return
# Если старый сокет остался — удалить
QLocalServer.removeServer(server_name)
local_server = QLocalServer()
if not local_server.listen(server_name):
logger.warning(f"Failed to start local server: {local_server.errorString()}")
return
# --- Qt translations ---
system_locale = QLocale.system()
qt_translator = QTranslator()
translations_path = QLibraryInfo.path(QLibraryInfo.LibraryPath.TranslationsPath)
if qt_translator.load(system_locale, "qtbase", "_", translations_path):
app.installTranslator(qt_translator)
else:
logger.warning(
f"Qt translations for {system_locale.name()} not found in {translations_path}, using English"
)
# --- Main Window ---
version = get_version()
window = MainWindow(app_name=__app_name__, version=version)
# --- Handle incoming connections ---
def handle_new_connection():
conn = local_server.nextPendingConnection()
if not conn:
return
if conn.waitForReadyRead(1000):
data = conn.readAll().data()
msg = bytes(data).decode("utf-8", errors="ignore")
logger.info(f"IPC message received: {msg}")
def restore_window():
try:
if msg.startswith("show"):
# Ensure the window is visible and not minimized
window.setWindowState(window.windowState() & ~Qt.WindowState.WindowMinimized)
window.show()
window.raise_()
window.activateWindow()
# Ensure window is in active state for systems with strict focus policies
window.setWindowState(window.windowState() | Qt.WindowState.WindowActive)
if ":fullscreen" in msg:
logger.info("Switching to fullscreen via IPC")
save_fullscreen_config(True)
window.showFullScreen()
else:
logger.info("Switching to normal window via IPC")
save_fullscreen_config(False)
window.showNormal()
except Exception as e:
logger.warning(f"Failed to restore window: {e}")
# Выполняем в основном потоке
QTimer.singleShot(0, restore_window)
conn.disconnectFromServer()
local_server.newConnection.connect(handle_new_connection)
# --- Initial fullscreen state ---
launch_fullscreen = args.fullscreen or read_fullscreen_config()
if launch_fullscreen:
logger.info(
f"Launching in fullscreen mode ({'--fullscreen' if args.fullscreen else 'config'})"
)
save_fullscreen_config(True)
window.showFullScreen()
else:
logger.info("Launching in normal mode")
save_fullscreen_config(False)
window.showNormal()
# Execute the initial PortProton command after the UI is set up
def run_initial_command():
nonlocal start_sh
if start_sh:
try:
subprocess.run(start_sh + ["cli", "--initial"], timeout=10)
except subprocess.TimeoutExpired:
logger.warning("Initial PortProton command timed out")
except Exception as e:
logger.error(f"Error running initial PortProton command: {e}")
else:
logger.warning("PortProton start command not available, skipping initial command")
# Run the initial command after the UI is displayed
QTimer.singleShot(100, run_initial_command)
# --- Cleanup ---
def cleanup_on_exit():
try:
local_server.close()
QLocalServer.removeServer(server_name)
if window:
window.close()
except Exception as e:
logger.warning(f"Cleanup error: {e}")
app.aboutToQuit.connect(cleanup_on_exit)
sys.exit(app.exec())
if __name__ == "__main__":
main()