Files
SoftwareManager/src/main.py
T

161 lines
5.3 KiB
Python

from network.libtorrent_misc import send_notification, update_log, check_deleted_files
from utils.logging.loghandler import split_data, check_completed, check_downloads
from network.interface import list_interfaces, init_interfaces
from PySide6.QtNetwork import QLocalServer, QLocalSocket
from utils.logging.logs import get_download_logs
from utils.logging.logs import set_main_window
from network.libtorrent_int import check_space
from utils.general.shutdown import closehelper
from utils.general.wrappers import run_thread
from interface.assets.base64_icons import logo_base64
from PySide6.QtWidgets import QSystemTrayIcon, QMenu
from utils.general.shutdown import force_exit
from utils.config.config import read_config
from PySide6.QtGui import QAction, QPixmap
from utils.logging.logs import consoleLog
from interface.gui import MainWindow
from PySide6.QtCore import Qt, QObject
from utils.data.state import state
from PySide6 import QtWidgets
import qdarktheme
import threading
import platform
import base64
import signal
import time
import sys
SERVER_NAME = "SoftwareManager_KeksPirates"
class SingleInstance(QObject):
def __init__(self):
super().__init__()
self.server = QLocalServer()
socket = QLocalSocket()
socket.connectToServer(SERVER_NAME)
if socket.waitForConnected(100):
socket.write(b"raise")
socket.flush()
socket.waitForBytesWritten(100)
self.is_running = True
else:
QLocalServer.removeServer(SERVER_NAME)
self.server.listen(SERVER_NAME)
self.server.newConnection.connect(self.handle_connection)
self.is_running = False
self.is_running = False
def handle_connection(self):
socket = self.server.nextPendingConnection()
socket.readyRead.connect(lambda: self.read_socket(socket))
def read_socket(self, socket):
msg = socket.readAll().data()
if msg == b"raise":
self.on_raise()
def on_raise(self):
pass
def check_running(app):
single = SingleInstance()
if single.is_running:
print("Another instance is already running. Exiting this instance.")
closehelper()
force_exit()
app._single_instance = single
def run_gui(app):
single = app._single_instance
custom_colors = {}
if state.accent_color:
custom_colors["primary"] = state.accent_color
qdarktheme.setup_theme("auto", custom_colors=custom_colors if custom_colors else None)
widget = MainWindow()
# Check OS for window transparency compatibility and apply
if state.window_transparency and platform.system() != "Windows":
widget.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
transparent_colors = {"background": "#00000000", **custom_colors}
qdarktheme.setup_theme("auto", custom_colors=transparent_colors)
pixmap = QPixmap()
image_data = base64.b64decode(logo_base64)
pixmap.loadFromData(image_data)
tray = QSystemTrayIcon()
tray.setIcon(pixmap)
tray.setVisible(True)
menu = QMenu()
show = QAction("Show")
show.triggered.connect(lambda: widget.show())
menu.addAction(show)
quit = QAction("Quit")
quit.triggered.connect(lambda: (closehelper(), force_exit()))
menu.addAction(quit)
tray.activated.connect(lambda reason: widget.show() if reason == QSystemTrayIcon.ActivationReason.Trigger else None)
tray.setContextMenu(menu)
def show_from_tray():
widget.show()
widget.raise_()
widget.activateWindow()
single.on_raise = show_from_tray
from data.hosts.megadb import ui_bridge, show_megadb_notification
ui_bridge.show_notification.connect(show_megadb_notification)
set_main_window(widget)
widget.show()
signal.signal(signal.SIGINT, signal.SIG_DFL)
sys.exit(app.exec())
def keyboardinterrupthandler(signum, frame):
closehelper()
force_exit()
def main():
# Begin counting startup time
start_time = time.perf_counter()
# Initialize UI Engine
app = QtWidgets.QApplication.instance() or QtWidgets.QApplication(sys.argv)
# Check if SoftwareManager is already running
check_running(app)
# Parse saved files
read_config()
logs = get_download_logs()
_, downloads = split_data(logs)
# Initialize Keyboardinterrupt signal
signal.signal(signal.SIGINT, keyboardinterrupthandler)
consoleLog("Starting SoftwareManager...")
# Get network interface info
list_interfaces()
init_interfaces()
consoleLog(f"Current Bound: {state.bound_interface}")
# Start background daemon threads
run_thread(threading.Thread(target=send_notification, args=(state.shutdown_event,), daemon=True))
run_thread(threading.Thread(target=update_log, args=(state.shutdown_event,), daemon=True))
run_thread(threading.Thread(target=check_deleted_files, args=(state.shutdown_event,), daemon=True))
# Start background non-daemon threads
run_thread(threading.Thread(target=check_completed, args=(downloads, state.autoresume)))
run_thread(threading.Thread(target=check_downloads, args=(downloads,)))
run_thread(threading.Thread(target=check_space, args=()))
# Finish counting startup time
elapsed = time.perf_counter() - start_time
consoleLog(f"Initialization completed in {elapsed:.2f}s. Launching GUI")
# Launch GUI
run_gui(app)
if __name__ == "__main__":
main()