Compare commits

..

6 Commits

10 changed files with 109 additions and 47 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ from core.utils.general.logs import consoleLog
def scrape_rutracker(search_text): def scrape_rutracker(search_text):
search = requests.get(f"{state.api_url}/search/{search_text}") search = requests.get(f"{state.api_url}/search?q={search_text}")
consoleLog("Sent request to server") consoleLog("Sent request to server")
if search: if search:
try: try:
+12 -13
View File
@@ -1,6 +1,9 @@
from core.utils.config.settings import save_settings from core.utils.config.settings import save_settings
from core.utils.data.state import state from core.utils.data.state import state
from core.utils.general.logs import consoleLog from core.utils.general.logs import consoleLog
from core.interface.utils.tabhelper import general_tab
from core.interface.utils.tabhelper import paths_tab
from core.interface.utils.tabhelper import network_tab
from PySide6 import QtWidgets from PySide6 import QtWidgets
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QLineEdit, QLineEdit,
@@ -13,7 +16,8 @@ from PySide6.QtWidgets import (
QSpinBox, QSpinBox,
QCheckBox, QCheckBox,
QFileDialog, QFileDialog,
QComboBox QComboBox,
QTabWidget,
) )
import platform import platform
@@ -23,10 +27,9 @@ 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(800, 550) dialog.setFixedSize(700, 450)
dialog.setLayout(QVBoxLayout()) dialog.setLayout(QVBoxLayout())
dialog.layout().addWidget(QLabel("Settings"))
def close_settings(): def close_settings():
dialog.reject() dialog.reject()
@@ -58,7 +61,6 @@ def settings_dialog(self):
autoresume_layout.addStretch() autoresume_layout.addStretch()
autoresume_checkbox.setChecked(state.autoresume) autoresume_checkbox.setChecked(state.autoresume)
autoresume_layout.addWidget(autoresume_checkbox) autoresume_layout.addWidget(autoresume_checkbox)
dialog.layout().addWidget(autoresume_container)
# transparent window checkbox # transparent window checkbox
@@ -73,7 +75,6 @@ def settings_dialog(self):
transparent_window_checkbox.setChecked(state.window_transparency) transparent_window_checkbox.setChecked(state.window_transparency)
transparent_window_checkbox.toggled.connect(lambda checked: setattr(state, 'window_transparency', checked)) transparent_window_checkbox.toggled.connect(lambda checked: setattr(state, 'window_transparency', checked))
transparent_window_layout.addWidget(transparent_window_checkbox) transparent_window_layout.addWidget(transparent_window_checkbox)
dialog.layout().addWidget(transparent_window_container)
################## ##################
# SERVER SETTING # # SERVER SETTING #
@@ -88,7 +89,6 @@ def settings_dialog(self):
api_url_container.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) api_url_container.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.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)
dialog.layout().addWidget(api_url_container)
################# #################
# DOWNLOAD PATH # # DOWNLOAD PATH #
@@ -103,7 +103,6 @@ def settings_dialog(self):
download_path_container.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) download_path_container.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
download_path_container.setLayout(download_path_layout) download_path_container.setLayout(download_path_layout)
download_path.setText(state.download_path) download_path.setText(state.download_path)
dialog.layout().addWidget(download_path_container)
def browse_download_path(): def browse_download_path():
dir_path = QFileDialog.getExistingDirectory(dialog, "Select Download Directory", state.download_path) dir_path = QFileDialog.getExistingDirectory(dialog, "Select Download Directory", state.download_path)
@@ -127,7 +126,6 @@ def settings_dialog(self):
image_path_container.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) image_path_container.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
image_path_container.setLayout(image_path_layout) image_path_container.setLayout(image_path_layout)
image_path.setText(state.image_path) image_path.setText(state.image_path)
dialog.layout().addWidget(image_path_container)
def browse_image_path(): def browse_image_path():
file_path = QFileDialog.getOpenFileName(dialog, "Select Image File", state.image_path, "Image Files (*.png *.jpg)")[0] file_path = QFileDialog.getOpenFileName(dialog, "Select Image File", state.image_path, "Image Files (*.png *.jpg)")[0]
@@ -154,7 +152,6 @@ def settings_dialog(self):
down_speed_limit_layout.addWidget(down_speed_limit) down_speed_limit_layout.addWidget(down_speed_limit)
down_speed_limit.setFixedWidth(180) down_speed_limit.setFixedWidth(180)
down_speed_limit.setFixedHeight(30) down_speed_limit.setFixedHeight(30)
dialog.layout().addWidget(down_speed_limit_container)
up_speed_limit_container = QWidget() up_speed_limit_container = QWidget()
up_speed_limit_layout = QHBoxLayout() up_speed_limit_layout = QHBoxLayout()
@@ -168,7 +165,6 @@ def settings_dialog(self):
up_speed_limit_layout.addWidget(up_speed_limit) up_speed_limit_layout.addWidget(up_speed_limit)
up_speed_limit.setFixedWidth(180) up_speed_limit.setFixedWidth(180)
up_speed_limit.setFixedHeight(30) up_speed_limit.setFixedHeight(30)
dialog.layout().addWidget(up_speed_limit_container)
###################### ######################
# CONNECTION CONFIGS # # CONNECTION CONFIGS #
@@ -186,7 +182,6 @@ def settings_dialog(self):
max_connections_layout.addWidget(max_connections) max_connections_layout.addWidget(max_connections)
max_connections.setFixedWidth(180) max_connections.setFixedWidth(180)
max_connections.setFixedHeight(30) max_connections.setFixedHeight(30)
dialog.layout().addWidget(max_connections_container)
#################### ####################
# DOWNLOAD CONFIGS # # DOWNLOAD CONFIGS #
@@ -204,7 +199,6 @@ def settings_dialog(self):
max_downloads_layout.addWidget(max_downloads) max_downloads_layout.addWidget(max_downloads)
max_downloads.setFixedWidth(180) max_downloads.setFixedWidth(180)
max_downloads.setFixedHeight(30) max_downloads.setFixedHeight(30)
dialog.layout().addWidget(max_downloads_container)
##################### #####################
# INTERFACE BINDING # # INTERFACE BINDING #
@@ -232,7 +226,6 @@ def settings_dialog(self):
interface_select.setFixedHeight(30) interface_select.setFixedHeight(30)
interface_layout.addWidget(interface_select) interface_layout.addWidget(interface_select)
interface_container.setLayout(interface_layout) interface_container.setLayout(interface_layout)
dialog.layout().addWidget(interface_container)
############### ###############
@@ -259,6 +252,12 @@ def settings_dialog(self):
layout.addWidget(cancel_btn) layout.addWidget(cancel_btn)
layout.addWidget(save_btn) layout.addWidget(save_btn)
self.tabs = QTabWidget()
self.tab1 = general_tab("General", autoresume_container, update_checkbox_container, transparent_window_container, self.tabs)
self.tab2 = paths_tab("Paths", download_path_container, image_path_container, self.tabs)
self.tab3 = network_tab("Network", interface_container, max_connections_container, max_downloads_container, up_speed_limit_container, down_speed_limit_container, api_url_container, self.tabs)
dialog.layout().addWidget(self.tabs)
dialog.layout().addLayout(layout) dialog.layout().addLayout(layout)
dialog.exec() dialog.exec()
+7 -7
View File
@@ -155,10 +155,10 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
# Table Widget for Item List # Table Widget for Item List
self.qtablewidget = QTableWidget() self.qtablewidget = QTableWidget()
self.qtablewidget.setColumnCount(2) self.qtablewidget.setColumnCount(4)
self.qtablewidget.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers) self.qtablewidget.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
self.qtablewidget.verticalHeader().setVisible(False) self.qtablewidget.verticalHeader().setVisible(False)
self.qtablewidget.setHorizontalHeaderLabels(["Post Title", "Author"]) self.qtablewidget.setHorizontalHeaderLabels(["Post Title", "Author", "Seeders", "Leechers"])
@@ -362,7 +362,6 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
# Tabs # Tabs
self.tabs = QTabWidget() self.tabs = QTabWidget()
self.tabs = QTabWidget()
self.tabs.setStyleSheet(""" self.tabs.setStyleSheet("""
QTabBar::tab { QTabBar::tab {
font-size: 11px; font-size: 11px;
@@ -384,16 +383,17 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
if state.image_path is not None and os.path.exists(state.image_path): if state.image_path is not None and os.path.exists(state.image_path):
self.image = QImage(state.image_path) self.image = QImage(state.image_path)
self.image = self.image.scaledToWidth(300, Qt.SmoothTransformation)
self.pixmap = QPixmap.fromImage(self.image) self.pixmap = QPixmap.fromImage(self.image)
self.overlay_label = QLabel(self) self.overlay_label = QLabel(self)
self.overlay_label.setPixmap(self.pixmap) self.overlay_label.setPixmap(self.pixmap)
self.overlay_label.adjustSize() self.overlay_label.adjustSize()
self.overlay_label.raise_() self.overlay_label.raise_()
offset_x = -1350 # offset_x = -1350
offset_y = -550 # offset_y = -550
x = self.width() - self.overlay_label.width() - offset_x x = self.width() - self.overlay_label.width() # - offset_x
y = self.height() - self.overlay_label.height() - offset_y y = self.height() - self.overlay_label.height() # - offset_y
self.overlay_label.move(x, y) self.overlay_label.move(x, y)
# temporarily disabled # temporarily disabled
+6 -2
View File
@@ -44,15 +44,19 @@ def return_pressed(self):
self.qtablewidget.clear() self.qtablewidget.clear()
self.show_empty_results(True) self.show_empty_results(True)
else: else:
state.post_titles, _, state.post_author = format_data(state.posts) state.post_titles, _, state.post_author, state.post_seeders, state.post_leechers = format_data(state.posts)
self.show_empty_results(False) self.show_empty_results(False)
self.qtablewidget.clear() self.qtablewidget.clear()
self.qtablewidget.setHorizontalHeaderLabels(["Post Title", "Author"]) self.qtablewidget.setHorizontalHeaderLabels(["Post Title", "Author", "Seeders", "Leechers"])
self.qtablewidget.setRowCount(len(state.post_titles)) self.qtablewidget.setRowCount(len(state.post_titles))
for i, author in enumerate(state.post_author): for i, author in enumerate(state.post_author):
self.qtablewidget.setItem(i, 1, QTableWidgetItem(author)) self.qtablewidget.setItem(i, 1, QTableWidgetItem(author))
for i, title in enumerate(state.post_titles): for i, title in enumerate(state.post_titles):
self.qtablewidget.setItem(i, 0, QTableWidgetItem(title)) self.qtablewidget.setItem(i, 0, QTableWidgetItem(title))
for i, seeders in enumerate(state.post_seeders):
self.qtablewidget.setItem(i, 2, QTableWidgetItem(seeders))
for i, leechers in enumerate(state.post_leechers):
self.qtablewidget.setItem(i, 3, QTableWidgetItem(leechers))
if state.debug == True: if state.debug == True:
consoleLog(f"Response Cached: {cached}") consoleLog(f"Response Cached: {cached}")
else: else:
+39
View File
@@ -15,3 +15,42 @@ def create_tab(title, searchbar, software_list, tabs, dlbutton, layout2):
tab.setLayout(layout) tab.setLayout(layout)
tabs.addTab(tab, title) tabs.addTab(tab, title)
return tab return tab
#################
# SETTINGS TABS #
#################
def general_tab(title, autoresume, update_checkbox, transparent_window, tabs):
tab = QWidget()
layout = QVBoxLayout()
layout.addWidget(autoresume)
layout.addWidget(update_checkbox)
layout.addWidget(transparent_window)
layout.addStretch()
tab.setLayout(layout)
tabs.addTab(tab, title)
return tab
def paths_tab(title, download_path, image_path, tabs):
tab = QWidget()
layout = QVBoxLayout()
layout.addWidget(download_path)
layout.addWidget(image_path)
layout.addStretch()
tab.setLayout(layout)
tabs.addTab(tab, title)
return tab
def network_tab(title, network_interface, max_connections, max_downloads, up_speed_limit, down_speed_limit, api_url, tabs):
tab = QWidget()
layout = QVBoxLayout()
layout.addWidget(network_interface)
layout.addWidget(max_connections)
layout.addWidget(max_downloads)
layout.addWidget(up_speed_limit)
layout.addWidget(down_speed_limit)
layout.addWidget(api_url)
layout.addStretch()
tab.setLayout(layout)
tabs.addTab(tab, title)
return tab
+25 -12
View File
@@ -8,16 +8,23 @@ def create_config():
config["General"] = { config["General"] = {
"debug": True, "debug": True,
"ignore_updates": f"{state.ignore_updates}",
"autoresume": f"{state.autoresume}",
"window_transparency": f"{state.window_transparency}"
}
config["Network"] = {
"api_url": f"{state.api_url}", "api_url": f"{state.api_url}",
"download_path": f"{state.download_path}", "download_path": f"{state.download_path}",
"download_speed_limit": f"{state.down_speed_limit}", "download_speed_limit": f"{state.down_speed_limit}",
"upload_speed_limit": f"{state.up_speed_limit}", "upload_speed_limit": f"{state.up_speed_limit}",
"ignore_updates": f"{state.ignore_updates}",
"image_path": f"{state.image_path}",
"autoresume": f"{state.autoresume}",
"max_connections": f"{state.max_connections}", "max_connections": f"{state.max_connections}",
"max_downloads": f"{state.max_downloads}", "max_downloads": f"{state.max_downloads}"
"window_transparency": f"{state.window_transparency}", }
config["Paths"] = {
"bound_interface": f"{state.bound_interface}",
"image_path": f"{state.image_path}"
} }
if platform.system() == "Windows": if platform.system() == "Windows":
@@ -49,16 +56,22 @@ def read_config():
config.read(config_file) config.read(config_file)
# General
state.debug = config.getboolean("General", "debug", fallback=state.debug) state.debug = config.getboolean("General", "debug", fallback=state.debug)
state.api_url = config.get("General", "api_url", fallback=state.api_url)
state.download_path = config.get("General", "download_path", fallback=state.download_path)
state.down_speed_limit = config.getint("General", "download_speed_limit", fallback=state.down_speed_limit)
state.up_speed_limit = config.getint("General", "upload_speed_limit", fallback=state.up_speed_limit)
state.ignore_updates = config.getboolean("General", "ignore_updates", fallback=state.ignore_updates) state.ignore_updates = config.getboolean("General", "ignore_updates", fallback=state.ignore_updates)
state.image_path = config.get("General", "image_path", fallback=state.image_path)
state.autoresume = config.getboolean("General", "autoresume", fallback=state.autoresume) state.autoresume = config.getboolean("General", "autoresume", fallback=state.autoresume)
state.max_connections = config.getint("General", "max_connections", fallback=state.max_connections)
state.max_downloads = config.getint("General", "max_downloads", fallback=state.max_downloads)
state.window_transparency = config.getboolean("General", "window_transparency", fallback=state.window_transparency) state.window_transparency = config.getboolean("General", "window_transparency", fallback=state.window_transparency)
# Network
state.api_url = config.get("Network", "api_url", fallback=state.api_url)
state.download_path = config.get("Network", "download_path", fallback=state.download_path)
state.down_speed_limit = config.getint("Network", "download_speed_limit", fallback=state.down_speed_limit)
state.up_speed_limit = config.getint("Network", "upload_speed_limit", fallback=state.up_speed_limit)
state.max_connections = config.getint("Network", "max_connections", fallback=state.max_connections)
state.max_downloads = config.getint("Network", "max_downloads", fallback=state.max_downloads)
# Paths
state.bound_interface = config.get("Paths", "bound_interface", fallback=state.bound_interface)
state.image_path = config.get("Paths", "image_path", fallback=state.image_path)
create_config() create_config()
+2
View File
@@ -11,6 +11,8 @@ class AppState(QObject):
self.post_titles: List[str] = [] self.post_titles: List[str] = []
self.post_urls: List[str] = [] self.post_urls: List[str] = []
self.post_author: List[str] = [] self.post_author: List[str] = []
self.post_seeders: List[str] = []
self.post_leechers: List[str] = []
self.version: str = "dev" self.version: str = "dev"
self._image_path: str = "" self._image_path: str = ""
self.ignore_updates: bool = False self.ignore_updates: bool = False
+2 -2
View File
@@ -15,12 +15,12 @@ def get_item_url(item, posts, post_titles): # softwarelist currentitem, post lis
return item return item
if state.tracker == "rutracker": if state.tracker == "rutracker":
item_dict = posts[post_index] item_dict = posts[post_index]
_, post_links, _ = format_data([item_dict]) _, post_links, _, _, _ = format_data([item_dict])
consoleLog(f"Found post URL: {post_links[0]}") consoleLog(f"Found post URL: {post_links[0]}")
return post_links[0] return post_links[0]
if state.tracker == "m0nkrus": if state.tracker == "m0nkrus":
item_dict = posts[post_index] item_dict = posts[post_index]
_, post_links, _ = format_data([item_dict]) _, post_links, _, _, _,= format_data([item_dict])
consoleLog(f"Found post URL: {post_links[0]}") consoleLog(f"Found post URL: {post_links[0]}")
return post_links[0] return post_links[0]
+3 -1
View File
@@ -15,8 +15,10 @@ def format_data(data):
post_author = [post["author"] for post in data] post_author = [post["author"] for post in data]
post_titles = [post["title"] for post in data] post_titles = [post["title"] for post in data]
post_links = [post["url"] for post in data] post_links = [post["url"] for post in data]
post_seeders = [post["seeders"] for post in data]
post_leechers = [post["leechers"] for post in data]
return post_titles, post_links, post_author return post_titles, post_links, post_author, post_seeders, post_leechers
+6 -3
View File
@@ -17,6 +17,7 @@ import platform
import signal import signal
import argparse import argparse
import sys import sys
import time
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
@@ -41,16 +42,17 @@ def keyboardinterrupthandler(signum, frame):
closehelper() closehelper()
if __name__ == "__main__": if __name__ == "__main__":
start_time = time.perf_counter()
read_config() read_config()
logs = get_download_logs() logs = get_download_logs()
count, downloads = split_data(logs) _, downloads = split_data(logs)
if args.debug: if args.debug:
state.debug = args.debug # override of read_config state.debug = args.debug # override of read_config
signal.signal(signal.SIGINT, keyboardinterrupthandler) signal.signal(signal.SIGINT, keyboardinterrupthandler)
consoleLog("Starting SoftwareManager...") consoleLog("Starting SoftwareManager...")
consoleLog("Fetching Network Interfaces...") consoleLog("Fetching Network Interfaces...")
list_interfaces() list_interfaces()
consoleLog("Initialiting Interface variables...") consoleLog("Initializing Interface variables...")
init_interfaces() init_interfaces()
consoleLog(f"Current Bound: {state.bound_interface}") consoleLog(f"Current Bound: {state.bound_interface}")
run_thread(threading.Thread(target=send_notification, args=(shutdown_event,), daemon=True)) run_thread(threading.Thread(target=send_notification, args=(shutdown_event,), daemon=True))
@@ -59,6 +61,7 @@ if __name__ == "__main__":
consoleLog("Started Thread: update_log") consoleLog("Started Thread: update_log")
run_thread(threading.Thread(target=check_completed, args=(downloads, state.autoresume))) run_thread(threading.Thread(target=check_completed, args=(downloads, state.autoresume)))
consoleLog("Started Thread: check_completed") consoleLog("Started Thread: check_completed")
consoleLog("Launching GUI") elapsed = time.perf_counter() - start_time
consoleLog(f"Initialization completed in {elapsed:.2f}s. Launching GUI")
run_gui() run_gui()