diff --git a/core/interface/gui.py b/core/interface/gui.py index 6b4e5bd..32f6d3e 100644 --- a/core/interface/gui.py +++ b/core/interface/gui.py @@ -14,26 +14,67 @@ from PySide6.QtWidgets import ( QTabWidget, QProgressBar, QHeaderView, + QMessageBox, ) from PySide6.QtGui import QIcon, QAction, QCloseEvent import darkdetect import threading +import platform +import requests as r +import os +import subprocess +import time +import sys +from core.utils.config.settings import save_settings from core.utils.general.wrappers import run_thread from core.utils.data.state import state from core.utils.network.download import download_selected +from core.utils.network.update_checker import check_for_updates from core.utils.general.shutdown import closehelper from core.interface.utils.tabhelper import create_tab from core.interface.utils.searchhelper import return_pressed from core.interface.dialogs.settings import settings_dialog from core.network.aria2_integration import dlprogress +def download_update(latest_version): + filename = "SoftwareManager-dev-windows.exe" + url = "https://github.com/KeksPirates/SoftwareManager/releases/latest/download/SoftwareManager-dev-windows.exe" + print("Downloading update...") + if os.path.exists(filename): + os.remove(filename) + response = r.get(url, allow_redirects=True) + with open(filename, "wb") as f: + f.write(response.content) + if not os.path.exists(filename): + raise FileNotFoundError(f"Executable not found") + subprocess.Popen([filename], shell=True) + time.sleep(0.5) + save_settings(version=latest_version) + sys.exit(0) class MainWindow(QtWidgets.QMainWindow, QWidget): def __init__(self): super().__init__() searchresults = [] + # Check for updates on Windows + if platform.system() == "Windows": + result = check_for_updates() + assets, latest_version = result + + if assets: + msg = QMessageBox() + msg.setIcon(QMessageBox.Information) + msg.setWindowTitle("Update Available") + msg.setText(f"A new version is available.") + msg.setInformativeText("Please visit the GitHub releases page to download the latest version.") + msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Ignore) + + response = msg.exec_() + if response == QMessageBox.Ok: + download_update(latest_version) + self.setWindowTitle("Software Manager") self.setGeometry(100, 100, 800, 600) @@ -142,7 +183,6 @@ class MainWindow(QtWidgets.QMainWindow, QWidget): self.tracker_list.addItems(["rutracker", "uztracker", "m0nkrus"]) self.tracker_list.activated.connect(self.set_tracker) - if darkdetect.isDark(): settings_action = QAction(QIcon("core/interface/assets/settings_dark.png"), "Settings", self) else: diff --git a/core/utils/config/config.py b/core/utils/config/config.py index 1bc75f7..0016fe8 100644 --- a/core/utils/config/config.py +++ b/core/utils/config/config.py @@ -3,11 +3,11 @@ import platform import configparser from core.utils.data.state import state - def create_config(): config = configparser.ConfigParser() - config["General"] = {"debug": True, "api_url": f"{state.api_url}", "aria2_threads": f"{state.aria2_threads}", "download_path": f"{state.download_path}", f"speed_limit": f"{state.speed_limit}"} + config["General"] = {"debug": True, "api_url": f"{state.api_url}", "aria2_threads": f"{state.aria2_threads}", "download_path": f"{state.download_path}", f"speed_limit": f"{state.speed_limit}", + "version": f"{state.version}"} if platform.system() == "Windows": config_dir = os.environ.get("APPDATA", os.path.expanduser("~\\AppData\\Roaming")) @@ -42,4 +42,4 @@ def read_config(): state.aria2_threads = config.getint("General", "aria2_threads") state.download_path = config.get("General", "download_path") state.speed_limit = config.getint("General", "speed_limit") - + state.version = config.get("General", "version") diff --git a/core/utils/config/settings.py b/core/utils/config/settings.py index 2095581..b284f5e 100644 --- a/core/utils/config/settings.py +++ b/core/utils/config/settings.py @@ -5,18 +5,45 @@ def restart_aria2c(): import main # had to do this because of circle import :( import signal import atexit - main.kill_aria2server() - state.aria2process.wait() - state.aria2process = main.run_aria2server() - signal.signal(signal.SIGINT, main.keyboardinterrupthandler) - atexit.unregister(main.kill_aria2server) - atexit.register(main.kill_aria2server) + import time -def save_settings(thread_count, close, apiurl, download_path, speed_limit): - state.aria2_threads = thread_count - state.api_url = apiurl - state.download_path = download_path - state.speed_limit = speed_limit + try: + main.kill_aria2server() + except Exception as e: + print(f"Warning: aria2server kill failed: {e}") + + try: + if state.aria2process: + state.aria2process.wait(timeout=3) + except Exception as e: + print(f"Warning: aria2process wait failed: {e}") + + time.sleep(0.5) + + try: + state.aria2process = main.run_aria2server() + except Exception as e: + print(f"Error: failed to restart aria2server: {e}") + return + + try: + signal.signal(signal.SIGINT, main.keyboardinterrupthandler) + atexit.unregister(main.kill_aria2server) + atexit.register(main.kill_aria2server) + except Exception as e: + print(f"Warning: signal/atexit setup failed: {e}") + +def save_settings(thread_count=None, close=lambda: None, apiurl=None, download_path=None, speed_limit=None, version=None): + if thread_count is not None: + state.aria2_threads = thread_count + if apiurl is not None: + state.api_url = apiurl + if download_path is not None: + state.download_path = download_path + if speed_limit is not None: + state.speed_limit = speed_limit + if version is not None: + state.version = version create_config() restart_aria2c() diff --git a/core/utils/data/state.py b/core/utils/data/state.py index 633415e..17e7e3d 100644 --- a/core/utils/data/state.py +++ b/core/utils/data/state.py @@ -9,6 +9,7 @@ class AppState: post_urls: List[str] post_author: List[str] downloads: List[str] + version: str debug: bool = False tracker: str = "rutracker" api_url: str = "https://api.michijackson.xyz" @@ -19,4 +20,4 @@ class AppState: aria2p: Any = None aria2_threads: int = 4 -state = AppState(posts=[], post_titles=[], post_urls=[], post_author=[], downloads=[], download_path="") +state = AppState(posts=[], post_titles=[], post_urls=[], post_author=[], downloads=[], download_path="", version="") diff --git a/main.py b/main.py index eb75bb9..baab2d4 100644 --- a/main.py +++ b/main.py @@ -2,7 +2,7 @@ from core.interface.gui import MainWindow from core.utils.data.state import state from core.network.aria2_integration import aria2server from core.network.aria2_integration import send_notification -from core.utils.general.shutdown import kill_aria2server, closehelper, shutdown_event +from core.utils.general.shutdown import closehelper, shutdown_event from core.utils.general.wrappers import run_thread from core.utils.config.config import read_config from PySide6 import QtWidgets @@ -14,12 +14,10 @@ import argparse import sys - parser = argparse.ArgumentParser() parser.add_argument("--debug", action="store_true") args = parser.parse_args() - def run_gui(): app = QtWidgets.QApplication([]) if darkdetect.isDark: