From f397bc18ce2f982b629310d16dfd1b739309f360 Mon Sep 17 00:00:00 2001 From: KeksNino Date: Fri, 31 Oct 2025 03:18:59 +0100 Subject: [PATCH] added option to display image in bottom right --- core/data/scrapers/uztracker.py | 1 - core/interface/dialogs/settings.py | 19 +++++++++-- core/interface/gui.py | 27 ++++++++++++--- core/utils/config/config.py | 22 ++++++++---- core/utils/config/settings.py | 4 ++- core/utils/data/state.py | 54 +++++++++++++++++++----------- 6 files changed, 92 insertions(+), 35 deletions(-) diff --git a/core/data/scrapers/uztracker.py b/core/data/scrapers/uztracker.py index d39bbaf..def11ab 100644 --- a/core/data/scrapers/uztracker.py +++ b/core/data/scrapers/uztracker.py @@ -1,6 +1,5 @@ import requests import asyncio -import aiohttp from bs4 import BeautifulSoup from core.utils.data.state import state diff --git a/core/interface/dialogs/settings.py b/core/interface/dialogs/settings.py index 038af6d..11d64d3 100644 --- a/core/interface/dialogs/settings.py +++ b/core/interface/dialogs/settings.py @@ -114,6 +114,21 @@ def settings_dialog(self): speed_limit.setFixedHeight(30) 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 # ############### @@ -122,8 +137,8 @@ def settings_dialog(self): save_btn = QPushButton("Save") 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) layout.addWidget(cancel_btn) layout.addWidget(save_btn) diff --git a/core/interface/gui.py b/core/interface/gui.py index ac76a94..1119f93 100644 --- a/core/interface/gui.py +++ b/core/interface/gui.py @@ -1,6 +1,6 @@ from PySide6 import QtWidgets 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 ( QLineEdit, QTableView, @@ -18,7 +18,7 @@ from PySide6.QtWidgets import ( QTableWidget, ) -from PySide6.QtGui import QIcon, QAction, QCloseEvent +from PySide6.QtGui import QIcon, QAction, QCloseEvent, QImage, QPixmap import darkdetect import threading import platform @@ -189,12 +189,25 @@ class MainWindow(QtWidgets.QMainWindow, QWidget): 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.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.setAlignment(Qt.AlignmentFlag.AlignBottom) - toolbar = QToolBar("Main Toolbar") self.addToolBar(toolbar) toolbar.setLayoutDirection(Qt.RightToLeft) @@ -205,7 +218,6 @@ class MainWindow(QtWidgets.QMainWindow, QWidget): if darkdetect.isDark(): 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.triggered.connect(lambda: settings_dialog(self)) @@ -225,6 +237,13 @@ class MainWindow(QtWidgets.QMainWindow, QWidget): self.download_timer.timeout.connect(lambda: run_thread(threading.Thread(target=self.download_list_update))) 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): if self.download_model: self.download_model.layoutAboutToBeChanged.emit() diff --git a/core/utils/config/config.py b/core/utils/config/config.py index 7da80cf..c95e877 100644 --- a/core/utils/config/config.py +++ b/core/utils/config/config.py @@ -7,7 +7,7 @@ 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}", - "ignore_updates": f"{state.ignore_updates}"} + "ignore_updates": f"{state.ignore_updates}", "image_path": f"{state.image_path}"} if platform.system() == "Windows": config_dir = os.environ.get("APPDATA", os.path.expanduser("~\\AppData\\Roaming")) @@ -37,9 +37,17 @@ def read_config(): config.read(config_file) - state.debug = config.getboolean("General", "debug") - state.api_url = config.get("General", "api_url") - 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.ignore_updates = config.getboolean("General", "ignore_updates") + if state.debug is None: + state.debug = config.getboolean("General", "debug") + if state.api_url is None: + state.api_url = config.get("General", "api_url") + if state.aria2_threads is None: + state.aria2_threads = config.getint("General", "aria2_threads") + if state.download_path is None: + state.download_path = config.get("General", "download_path") + if state.speed_limit is None: + state.speed_limit = config.getint("General", "speed_limit") + if state.ignore_updates is None: + state.ignore_updates = config.getboolean("General", "ignore_updates") + if state.image_path is None: + state.image_path = config.get("General", "image_path") diff --git a/core/utils/config/settings.py b/core/utils/config/settings.py index 25bb68a..de8d1dd 100644 --- a/core/utils/config/settings.py +++ b/core/utils/config/settings.py @@ -13,7 +13,7 @@ def restart_aria2c(): atexit.unregister(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: state.aria2_threads = thread_count 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 if speed_limit is not None: state.speed_limit = speed_limit + if image_path is not None: + state.image_path = image_path create_config() restart_aria2c() diff --git a/core/utils/data/state.py b/core/utils/data/state.py index 19159fe..5cd3dab 100644 --- a/core/utils/data/state.py +++ b/core/utils/data/state.py @@ -1,24 +1,38 @@ -from dataclasses import dataclass +from PySide6.QtCore import QObject, Signal from typing import Optional, Any, List, Dict from pathlib import Path -@dataclass -class AppState: - 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 +class AppState(QObject): + image_changed = Signal(str) -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()