Compare commits

..

3 Commits

Author SHA1 Message Date
KeksNino 9d0d5332bf fixed updater 2025-10-31 13:45:30 +01:00
KeksNino 6d9991188a fixed config parser error handling 2025-10-31 03:22:47 +01:00
KeksNino f397bc18ce added option to display image in bottom right 2025-10-31 03:18:59 +01:00
6 changed files with 101 additions and 39 deletions
-1
View File
@@ -1,6 +1,5 @@
import requests import requests
import asyncio import asyncio
import aiohttp
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from core.utils.data.state import state from core.utils.data.state import state
+16 -1
View File
@@ -114,6 +114,21 @@ def settings_dialog(self):
speed_limit.setFixedHeight(30) speed_limit.setFixedHeight(30)
dialog.layout().addWidget(speed_limit_container) dialog.layout().addWidget(speed_limit_container)
###############
# IMAGE PATH #
###############
image_path_container = QWidget()
image_path_layout = QHBoxLayout()
image_path = QLineEdit()
image_path_layout.addWidget(QLabel("Image Path (requires restart):"))
image_path_layout.addWidget(image_path)
image_path_container.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
image_path_container.setLayout(image_path_layout)
image_path.setText(state.image_path)
dialog.layout().addWidget(image_path_container)
############### ###############
# SAVE/CANCEL # # SAVE/CANCEL #
############### ###############
@@ -122,7 +137,7 @@ def settings_dialog(self):
save_btn = QPushButton("Save") save_btn = QPushButton("Save")
cancel_btn = QPushButton("Cancel") cancel_btn = QPushButton("Cancel")
save_btn.clicked.connect(lambda: save_settings(thread_box.value(), close_settings, api_url.text(), download_path.text(), speed_limit.value())) save_btn.clicked.connect(lambda: save_settings(thread_box.value(), close_settings, api_url.text(), download_path.text(), speed_limit.value(), image_path.text()))
cancel_btn.clicked.connect(dialog.reject) cancel_btn.clicked.connect(dialog.reject)
layout.addWidget(cancel_btn) layout.addWidget(cancel_btn)
+32 -8
View File
@@ -1,6 +1,6 @@
from PySide6 import QtWidgets from PySide6 import QtWidgets
from PySide6 import QtCore from PySide6 import QtCore
from PySide6.QtCore import Qt, QTimer, QModelIndex, QAbstractTableModel from PySide6.QtCore import Qt, QTimer, QModelIndex, QAbstractTableModel, Signal
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QLineEdit, QLineEdit,
QTableView, QTableView,
@@ -18,7 +18,7 @@ from PySide6.QtWidgets import (
QTableWidget, QTableWidget,
) )
from PySide6.QtGui import QIcon, QAction, QCloseEvent from PySide6.QtGui import QIcon, QAction, QCloseEvent, QImage, QPixmap
import darkdetect import darkdetect
import threading import threading
import platform import platform
@@ -40,13 +40,10 @@ from core.network.aria2_integration import dlprogress
def download_update(latest_version): def download_update(latest_version):
old_filename = f"SoftwareManager-dev-{state.version.replace('-dev', '')}-windows.exe"
new_filename = f"SoftwareManager-dev-{latest_version.replace('-dev', '')}-windows.exe" new_filename = f"SoftwareManager-dev-{latest_version.replace('-dev', '')}-windows.exe"
url = f"https://github.com/KeksPirates/SoftwareManager/releases/latest/download/SoftwareManager-dev-{latest_version.replace('-dev', '')}-windows.exe" url = f"https://github.com/KeksPirates/SoftwareManager/releases/latest/download/SoftwareManager-dev-{latest_version.replace('-dev', '')}-windows.exe"
print("Downloading update...") print("Downloading update...")
if os.path.exists(old_filename):
os.remove(old_filename)
response = r.get(url, allow_redirects=True) response = r.get(url, allow_redirects=True)
with open(new_filename, "wb") as f: with open(new_filename, "wb") as f:
f.write(response.content) f.write(response.content)
@@ -54,6 +51,14 @@ def download_update(latest_version):
raise FileNotFoundError("Executable not found") raise FileNotFoundError("Executable not found")
subprocess.Popen([new_filename], shell=True) subprocess.Popen([new_filename], shell=True)
time.sleep(0.5) time.sleep(0.5)
msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setWindowTitle("New Version")
msg.setText("New version installed.")
msg.setInformativeText("Please remove the old exe.")
msg.setStandardButtons(QMessageBox.Ok)
sys.exit(0) sys.exit(0)
@@ -78,7 +83,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
msg.setIcon(QMessageBox.Information) msg.setIcon(QMessageBox.Information)
msg.setWindowTitle("Update Available") msg.setWindowTitle("Update Available")
msg.setText("A new version is available.") msg.setText("A new version is available.")
msg.setInformativeText("Please visit the GitHub releases page to download the latest version.") msg.setInformativeText("Press Ok to download the update.")
msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Ignore) msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Ignore)
response = msg.exec_() response = msg.exec_()
@@ -189,12 +194,25 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
self.tab2 = create_tab("Library", self.emptyLibrary, self.libraryList, self.tabs, None, None) self.tab2 = create_tab("Library", self.emptyLibrary, self.libraryList, self.tabs, None, None)
self.tab3 = create_tab("Downloads", self.emptyDownload, self.downloadList, self.tabs, None, None) self.tab3 = create_tab("Downloads", self.emptyDownload, self.downloadList, self.tabs, None, None)
self.image = QImage(state.image_path)
self.pixmap = QPixmap.fromImage(self.image)
self.overlay_label = QLabel(self)
self.overlay_label.setPixmap(self.pixmap)
self.overlay_label.adjustSize()
self.overlay_label.raise_()
offset_x = -1350
offset_y = -550
x = self.width() - self.overlay_label.width() - offset_x
y = self.height() - self.overlay_label.height() - offset_y
self.overlay_label.move(x, y)
# temporarily disabled
# state.image_changed.connect(self.update_image_overlay)
containerLayout.addWidget(self.tabs) containerLayout.addWidget(self.tabs)
containerLayout.setAlignment(Qt.AlignmentFlag.AlignBottom) containerLayout.setAlignment(Qt.AlignmentFlag.AlignBottom)
toolbar = QToolBar("Main Toolbar") toolbar = QToolBar("Main Toolbar")
self.addToolBar(toolbar) self.addToolBar(toolbar)
toolbar.setLayoutDirection(Qt.RightToLeft) toolbar.setLayoutDirection(Qt.RightToLeft)
@@ -205,7 +223,6 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
if darkdetect.isDark(): if darkdetect.isDark():
settings_action = QAction(QIcon("core/interface/assets/settings_white.png"), "Settings", self) settings_action = QAction(QIcon("core/interface/assets/settings_white.png"), "Settings", self)
else:
settings_action = QAction(QIcon("core/interface/assets/settings_black.png"), "Settings", self) settings_action = QAction(QIcon("core/interface/assets/settings_black.png"), "Settings", self)
settings_action.triggered.connect(lambda: settings_dialog(self)) settings_action.triggered.connect(lambda: settings_dialog(self))
@@ -225,6 +242,13 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
self.download_timer.timeout.connect(lambda: run_thread(threading.Thread(target=self.download_list_update))) self.download_timer.timeout.connect(lambda: run_thread(threading.Thread(target=self.download_list_update)))
self.download_timer.start(500) self.download_timer.start(500)
def update_image_overlay(self, new_image_path):
self.image = QImage(new_image_path)
self.pixmap = QPixmap.fromImage(self.image)
self.overlay_label.setPixmap(self.pixmap)
self.overlay_label.adjustSize()
def download_list_update(self): def download_list_update(self):
if self.download_model: if self.download_model:
self.download_model.layoutAboutToBeChanged.emit() self.download_model.layoutAboutToBeChanged.emit()
+15 -7
View File
@@ -7,7 +7,7 @@ def create_config():
config = configparser.ConfigParser() 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}",
"ignore_updates": f"{state.ignore_updates}"} "ignore_updates": f"{state.ignore_updates}", "image_path": f"{state.image_path}"}
if platform.system() == "Windows": if platform.system() == "Windows":
config_dir = os.environ.get("APPDATA", os.path.expanduser("~\\AppData\\Roaming")) config_dir = os.environ.get("APPDATA", os.path.expanduser("~\\AppData\\Roaming"))
@@ -37,9 +37,17 @@ def read_config():
config.read(config_file) config.read(config_file)
state.debug = config.getboolean("General", "debug") if state.debug is not None:
state.api_url = config.get("General", "api_url") state.debug = config.getboolean("General", "debug")
state.aria2_threads = config.getint("General", "aria2_threads") if state.api_url is not None:
state.download_path = config.get("General", "download_path") state.api_url = config.get("General", "api_url")
state.speed_limit = config.getint("General", "speed_limit") if state.aria2_threads is not None:
state.ignore_updates = config.getboolean("General", "ignore_updates") state.aria2_threads = config.getint("General", "aria2_threads")
if state.download_path is not None:
state.download_path = config.get("General", "download_path")
if state.speed_limit is not None:
state.speed_limit = config.getint("General", "speed_limit")
if state.ignore_updates is not None:
state.ignore_updates = config.getboolean("General", "ignore_updates")
if state.image_path is not None:
state.image_path = config.get("General", "image_path")
+3 -1
View File
@@ -13,7 +13,7 @@ def restart_aria2c():
atexit.unregister(kill_aria2server) atexit.unregister(kill_aria2server)
atexit.register(kill_aria2server) atexit.register(kill_aria2server)
def save_settings(thread_count=None, close=lambda: None, apiurl=None, download_path=None, speed_limit=None): def save_settings(thread_count=None, close=lambda: None, apiurl=None, download_path=None, speed_limit=None, image_path=None):
if thread_count is not None: if thread_count is not None:
state.aria2_threads = thread_count state.aria2_threads = thread_count
if apiurl is not None: if apiurl is not None:
@@ -22,6 +22,8 @@ def save_settings(thread_count=None, close=lambda: None, apiurl=None, download_p
state.download_path = download_path state.download_path = download_path
if speed_limit is not None: if speed_limit is not None:
state.speed_limit = speed_limit state.speed_limit = speed_limit
if image_path is not None:
state.image_path = image_path
create_config() create_config()
restart_aria2c() restart_aria2c()
+34 -20
View File
@@ -1,24 +1,38 @@
from dataclasses import dataclass from PySide6.QtCore import QObject, Signal
from typing import Optional, Any, List, Dict from typing import Optional, Any, List, Dict
from pathlib import Path from pathlib import Path
@dataclass class AppState(QObject):
class AppState: image_changed = Signal(str)
posts: List[Dict[str, Any]]
post_titles: List[str]
post_urls: List[str]
post_author: List[str]
downloads: List[str]
version: str
ignore_updates: bool = False
debug: bool = False
tracker: str = "rutracker"
api_url: str = "https://api.michijackson.xyz"
download_path: str = str(Path.home() / "Downloads")
speed_limit: int = 0
aria2process: Optional[Any] = None
aria2: Any = None
aria2p: Any = None
aria2_threads: int = 4
state = AppState(posts=[], post_titles=[], post_urls=[], post_author=[], downloads=[], download_path="", version="") def __init__(self):
super().__init__()
self.posts: List[Dict[str, Any]] = []
self.post_titles: List[str] = []
self.post_urls: List[str] = []
self.post_author: List[str] = []
self.downloads: List[str] = []
self.version: str
self._image_path: str = ""
self.ignore_updates: bool = False
self.debug: bool = False
self.tracker: str = "rutracker"
self.api_url: str = "https://api.michijackson.xyz"
self.download_path: str = str(Path.home() / "Downloads")
self.speed_limit: int = 0
self.aria2process: Optional[Any] = None
self.aria2: Any = None
self.aria2p: Any = None
self.aria2_threads: int = 4
@property
def image_path(self) -> str:
return self._image_path
@image_path.setter
def image_path(self, new_path: str):
if new_path != self._image_path:
self._image_path = new_path
self.image_changed.emit(new_path)
state = AppState()