Add configurable image overlay settings

Introduce configurable image overlay options and persist them. Added new state fields (image_width, image_offset, image_enabled) with defaults and wired them into the image overlay: the image display now respects the enabled flag, uses image_width for scaling and image_offset for placement. Extended the Settings dialog (resized, API field sizing) with a new Image tab containing enable checkbox, width and offset spinboxes, and included these values when saving. Updated config read/write to include an Image section so settings persist across runs and extended save_settings to accept image_width and image_offset. Minor import/order cleanup in image dialog.
This commit is contained in:
Vxrtrauter
2026-04-04 02:06:06 +02:00
parent b59768bcff
commit cb7e74a224
5 changed files with 77 additions and 10 deletions
+7 -6
View File
@@ -1,12 +1,11 @@
from PySide6.QtCore import Qt, QSize, QEvent, QObject
from PySide6.QtGui import QImage, QPixmap from PySide6.QtGui import QImage, QPixmap
from PySide6.QtWidgets import QLabel from PySide6.QtWidgets import QLabel
from utils.data.state import state from utils.data.state import state
from PySide6.QtCore import Qt, QSize, QEvent, QObject
import os import os
class Image(QObject):
TARGET_WIDTH = 300
class Image(QObject):
def __init__(self, parent): def __init__(self, parent):
super().__init__(parent) super().__init__(parent)
self.application = parent self.application = parent
@@ -26,6 +25,8 @@ class Image(QObject):
return False return False
def _load_and_display(self, image_path): def _load_and_display(self, image_path):
if state.image_enabled is not True:
return
self._current_image_path = image_path self._current_image_path = image_path
parent = self.application parent = self.application
image = QImage(image_path) image = QImage(image_path)
@@ -34,7 +35,7 @@ class Image(QObject):
return return
scaled_image = image.scaledToWidth( scaled_image = image.scaledToWidth(
self.TARGET_WIDTH, Qt.TransformationMode.SmoothTransformation int(state.image_width), Qt.TransformationMode.SmoothTransformation
) )
max_width = parent.width() max_width = parent.width()
@@ -51,8 +52,8 @@ class Image(QObject):
self.overlay_label.adjustSize() self.overlay_label.adjustSize()
self.overlay_label.raise_() self.overlay_label.raise_()
x = parent.width() - self.overlay_label.width() - 100 x = parent.width() - self.overlay_label.width() - int(state.image_offset)
y = parent.height() - self.overlay_label.height() - 100 y = parent.height() - self.overlay_label.height() - int(state.image_offset)
self.overlay_label.move(x, y) self.overlay_label.move(x, y)
self.overlay_label.show() self.overlay_label.show()
+49 -2
View File
@@ -29,7 +29,7 @@ def settings_dialog(self):
consoleLog("Settings dialog opened") consoleLog("Settings dialog opened")
dialog = QDialog(self) dialog = QDialog(self)
dialog.setWindowTitle("Settings") dialog.setWindowTitle("Settings")
dialog.setFixedSize(700, 450) dialog.setFixedSize(580, 400)
dialog_layout = QVBoxLayout() dialog_layout = QVBoxLayout()
dialog.setLayout(dialog_layout) dialog.setLayout(dialog_layout)
@@ -92,6 +92,8 @@ def settings_dialog(self):
api_url_container.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed) api_url_container.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed)
api_url_container.setLayout(api_url_layout) api_url_container.setLayout(api_url_layout)
api_url.setText(state.api_url) api_url.setText(state.api_url)
api_url.setFixedWidth(180)
api_url.setFixedHeight(30)
# Download Path # Download Path
@@ -158,6 +160,46 @@ def settings_dialog(self):
image_path_layout.addWidget(browse_button) image_path_layout.addWidget(browse_button)
browse_button.clicked.connect(browse_image_path) browse_button.clicked.connect(browse_image_path)
# Image Settings
enable_image_container = QWidget()
enable_image_layout = QHBoxLayout()
enable_image_checkbox = QCheckBox()
enable_image_container.setLayout(enable_image_layout)
enable_image_layout.addWidget(QLabel("Enable Image: "))
enable_image_layout.addStretch()
enable_image_checkbox.setChecked(state.image_enabled)
enable_image_checkbox.toggled.connect(lambda checked: setattr(state, 'image_enabled', checked))
enable_image_layout.addWidget(enable_image_checkbox)
image_width_container = QWidget()
image_width_layout = QHBoxLayout()
image_width_layout.addWidget(QLabel("Image Width: "))
image_width = QSpinBox()
image_width.setMinimum(0)
image_width.setMaximum(10000000)
image_width.setValue(state.image_width)
image_width_container.setLayout(image_width_layout)
image_width_layout.addWidget(image_width)
image_width.setFixedWidth(180)
image_width.setFixedHeight(30)
image_offset_container = QWidget()
image_offset_layout = QHBoxLayout()
image_offset_layout.addWidget(QLabel("Corner image_offset: "))
image_offset = QSpinBox()
image_offset.setMinimum(0)
image_offset.setMaximum(10000000)
image_offset.setValue(state.image_offset)
image_offset_container.setLayout(image_offset_layout)
image_offset_layout.addWidget(image_offset)
image_offset.setFixedWidth(180)
image_offset.setFixedHeight(30)
# Speed Limiting # Speed Limiting
down_speed_limit_container = QWidget() down_speed_limit_container = QWidget()
@@ -255,7 +297,10 @@ def settings_dialog(self):
autoresume_checkbox.isChecked(), autoresume_checkbox.isChecked(),
max_connections.value(), max_connections.value(),
max_downloads.value(), max_downloads.value(),
interface_select.currentText())) interface_select.currentText(),
image_width.value(),
image_offset.value()
))
cancel_btn.clicked.connect(dialog.reject) cancel_btn.clicked.connect(dialog.reject)
layout.addWidget(cancel_btn) layout.addWidget(cancel_btn)
@@ -263,9 +308,11 @@ def settings_dialog(self):
tabs = QtWidgets.QTabWidget() tabs = QtWidgets.QTabWidget()
create_tab("General", [autoresume_container, update_checkbox_container, transparent_window_container], tabs=tabs, stretch=True) create_tab("General", [autoresume_container, update_checkbox_container, transparent_window_container], tabs=tabs, stretch=True)
create_tab("Image", [enable_image_container, image_width_container, image_offset_container], tabs=tabs, stretch=True)
create_tab("Paths", [download_path_container, image_path_container], tabs=tabs, stretch=True) create_tab("Paths", [download_path_container, image_path_container], tabs=tabs, stretch=True)
create_tab("Network", [interface_container, max_connections_container, max_downloads_container, up_speed_limit_container, down_speed_limit_container, api_url_container], tabs=tabs, stretch=True) create_tab("Network", [interface_container, max_connections_container, max_downloads_container, up_speed_limit_container, down_speed_limit_container, api_url_container], tabs=tabs, stretch=True)
dialog_layout.addWidget(tabs) dialog_layout.addWidget(tabs)
dialog_layout.addLayout(layout) dialog_layout.addLayout(layout)
+12
View File
@@ -28,6 +28,12 @@ def create_config():
"image_path": f"{state.image_path}" "image_path": f"{state.image_path}"
} }
config["Image"] = {
"enable_image": f"{state.image_enabled}",
"image_width": f"{state.image_width}",
"image_offset": f"{state.image_offset}"
}
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"))
else: else:
@@ -77,4 +83,10 @@ def read_config():
state.download_path = config.get("Paths", "download_path", fallback=state.download_path) state.download_path = config.get("Paths", "download_path", fallback=state.download_path)
state.image_path = config.get("Paths", "image_path", fallback=state.image_path) state.image_path = config.get("Paths", "image_path", fallback=state.image_path)
# Image
state.image_enabled = config.getboolean("Image", "enable_image", fallback=state.image_enabled)
state.image_width = config.getint("Image", "image_width", fallback=state.image_width)
state.image_offset = config.getint("Image", "image_offset", fallback=state.image_offset)
create_config() create_config()
+6 -2
View File
@@ -5,7 +5,7 @@ from utils.data.state import state
def save_settings(close=lambda: None, apiurl=None, download_path=None, down_speed_limit=None, up_speed_limit=None, image_path=None, autoresume=None, max_connections=None, max_downloads=None, bound_interface=None): def save_settings(close=lambda: None, apiurl=None, download_path=None, down_speed_limit=None, up_speed_limit=None, image_path=None, autoresume=None, max_connections=None, max_downloads=None, bound_interface=None, image_width=None, image_offset=None):
if apiurl is not None: if apiurl is not None:
state.api_url = apiurl state.api_url = apiurl
if download_path is not None: if download_path is not None:
@@ -24,8 +24,12 @@ def save_settings(close=lambda: None, apiurl=None, download_path=None, down_spee
state.max_downloads = max_downloads state.max_downloads = max_downloads
if bound_interface is not None: if bound_interface is not None:
state.bound_interface = None if bound_interface == "None" else bound_interface state.bound_interface = None if bound_interface == "None" else bound_interface
if image_width is not None:
state.image_width = image_width
if image_offset is not None:
state.image_offset = image_offset
update_settings() update_settings() # Update LibTorrent Session Settings
consoleLog("Saved Settings") consoleLog("Saved Settings")
create_config() create_config()
close() close()
+3
View File
@@ -29,6 +29,9 @@ class AppState(QObject):
self.interfaces: List = [] self.interfaces: List = []
self.active_interfaces: List = [] self.active_interfaces: List = []
self.bound_interface: Any = None self.bound_interface: Any = None
self.image_width: int = 300 # Default to 300px
self.image_offset: int = 50
self.image_enabled: bool = False
# Trackers / Scraping # Trackers / Scraping
self.posts: list[Dict[str,str]] | None = None # titles, urls, author, seeders, leechers self.posts: list[Dict[str,str]] | None = None # titles, urls, author, seeders, leechers