Compare commits

..

6 Commits

8 changed files with 64 additions and 30 deletions
+1 -7
View File
@@ -125,8 +125,6 @@ jobs:
--upx-binary="${{ env.UPX_BINARY }}" \
--noinclude-qt-translations \
--include-data-files=build_info.json=build_info.json \
--include-data-files=build_info.json=src/build_info.json \
--include-data-files=build_info.json=src/core/interface/build_info.json \
--output-filename=${{ env.APP_NAME }}.exe \
--output-dir=nuitka-build \
src/main.py
@@ -137,8 +135,6 @@ jobs:
run: |
pyinstaller --onefile --windowed \
--add-data "build_info.json:." \
--add-data "build_info.json:src/core" \
--add-data "build_info.json:src/core/interface" \
--exclude-module PyQt6 \
--exclude-module PyQt5 \
--hidden-import=backports.tarfile \
@@ -155,8 +151,6 @@ jobs:
run: |
pyinstaller --onefile \
--add-data "build_info.json:." \
--add-data "build_info.json:src/core" \
--add-data "build_info.json:src/core/interface" \
--exclude-module PyQt6 \
--exclude-module PyQt5 \
--hidden-import=backports.tarfile \
@@ -287,4 +281,4 @@ jobs:
release/SoftwareManager-dev-${{ needs.build.outputs.short_sha }}-macos
release/SHA256SUMS.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+20 -3
View File
@@ -1,18 +1,35 @@
from core.utils.network.update_checker import get_updates
from core.utils.network.updater import download_update
from PySide6.QtWidgets import QDialog, QMessageBox
from core.utils.logging.logs import consoleLog
from core.utils.data.state import state
from pathlib import Path
import platform
import json
import os
def check_version():
build_info_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "build_info.json")
def _get_build_info_path() -> (Path | None):
current_dir = Path(__file__).resolve().parent
for _ in range(6): # Climb max 6 directories
file = current_dir / "build_info.json"
if file.exists():
return file
# Go up one directory if file isn't found
current_dir = current_dir.parent
return None
def get_version() -> None:
# Get build info filepath
build_info_path = _get_build_info_path()
if os.path.exists(build_info_path):
with open(build_info_path, "r") as f:
build_info = json.load(f)
state.version = build_info.get("version")
else:
consoleLog(f"Could not find build info file (Path: {build_info_path})")
class UpdateDialog(QDialog):
def __init__(self, parent=None):
+19 -8
View File
@@ -5,6 +5,7 @@ from core.interface.dialogs.downloadlist import _create_download_list
from core.interface.assets.base64_icons import settings_white_base64
from core.interface.assets.base64_icons import settings_black_base64
from core.interface.dialogs.downloadlist import download_list_update
from core.interface.dialogs.update import get_version, UpdateDialog
from core.utils.logging.logs import consoleLog, flush_log_buffer
from core.interface.dialogs.downloadmodel import DownloadModel
from core.interface.utils.searchhelper import return_pressed
@@ -18,9 +19,7 @@ from core.utils.general.wrappers import run_thread
from core.interface.dialogs.image import Image
from core.utils.data.state import state
import core.interface.dialogs.hoverrowdelegate
import core.interface.dialogs.contextmenu
import core.interface.dialogs.update
from PySide6 import QtWidgets
from PySide6.QtCore import (
@@ -77,7 +76,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
pixmap.loadFromData(image_data)
self.setWindowIcon(QIcon(pixmap))
# set appid on windows
# Set AppID on Windows
if platform.system() == "Windows":
try:
import ctypes
@@ -86,23 +85,30 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
except Exception as e:
consoleLog(f"Could not set app ID: {e}")
# Get current version
# core.interface.dialogs.update
get_version()
UpdateDialog()
# Initialize Window
self.setWindowTitle("Software Manager")
self.setGeometry(100, 100, 800, 600)
self.controls = QWidget()
self.controlsLayout = QVBoxLayout()
# Searchbar
self.searchbar = QLineEdit()
self.searchbar.setPlaceholderText("Search for software...")
self.searchbar.setClearButtonEnabled(True)
self.searchbar.setMinimumHeight(30)
self.searchbar.returnPressed.connect(self._start_search)
# Download Button
self.dlbutton = QtWidgets.QPushButton("Download")
self.dlbutton.setCursor(Qt.CursorShape.PointingHandCursor)
# Dialog for empty results
self.emptyResults = QLabel("No Results")
self.emptyResults.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.emptyResults.hide()
@@ -157,23 +163,32 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
self.horizontal_layout.addWidget(self.emptyResults, stretch=3)
self.horizontal_layout.addWidget(state.trackertable)
# Tabs
self.tab1 = create_tab("Search", self.searchbar, state.trackertable, self.tabs, self.dlbutton, self.horizontal_layout)
self.tab2 = create_tab("Downloads", self.emptyDownload, self.downloadList, self.tabs, None, None)
# Corner Widget (Settings Button, Tracker list, Tab button container)
self.corner_widget = QWidget()
self.corner_layout = QHBoxLayout(self.corner_widget)
self.corner_layout.setContentsMargins(0, 0, 0, 0)
# Tracker list
self.tracker_list = QComboBox()
self.tracker_list.addItems(list(state.trackers.keys()))
self.tracker_list.setCursor(Qt.CursorShape.PointingHandCursor)
self.tracker_list.activated.connect(self.set_tracker)
self.corner_layout.addWidget(self.tracker_list)
# Settings button
self.settings_btn = QtWidgets.QToolButton()
self.settings_btn.setIconSize(QSize(21, 21))
self.settings_btn.setStyleSheet("background: transparent;")
self.settings_btn.setToolTip("Settings")
self.settings_btn.setCursor(Qt.CursorShape.PointingHandCursor)
self.settings_btn.clicked.connect(lambda: settings_dialog(self))
self.corner_layout.addWidget(self.settings_btn)
# Adjust theme based on system preferences
if darkdetect.isDark():
settings_white_pixmap = QPixmap()
settings_white = base64.b64decode(settings_white_base64)
@@ -185,11 +200,6 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
settings_black_pixmap.loadFromData(settings_black)
self.settings_btn.setIcon(QIcon(settings_black_pixmap))
self.settings_btn.setToolTip("Settings")
self.settings_btn.setCursor(Qt.CursorShape.PointingHandCursor)
self.settings_btn.clicked.connect(lambda: settings_dialog(self))
self.corner_layout.addWidget(self.settings_btn)
self.tab_wrapper = QWidget()
self.tab_layout = QVBoxLayout()
self.tab_layout.setContentsMargins(0, 0, 0, 0)
@@ -221,6 +231,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
self.version = QLabel(f"Version: {state.version}")
self.statusbar.addPermanentWidget(self.version, Qt.AlignmentFlag.AlignLeft)
# (\u2193) Arrow down, (\u2191) Arrow up
self.speed_label = QLabel("\u2193 0.0 kB/s \u2191 0.0 kB/s")
self.speed_label.setStyleSheet("padding-right: 6px;")
self.statusbar.addPermanentWidget(self.speed_label)
+2
View File
@@ -29,6 +29,7 @@ def get_active_interfaces():
def list_interfaces() -> None:
consoleLog("Fetching Network Interfaces...")
addrs = psutil.net_if_addrs()
stats = psutil.net_if_stats()
@@ -45,6 +46,7 @@ def list_interfaces() -> None:
consoleLog(f"Found Interface: {interface} [{status}]")
def init_interfaces():
consoleLog("Initializing Interface variables...")
addrs = psutil.net_if_addrs()
state.interfaces = list(addrs.keys())
state.active_interfaces = get_active_interfaces()
+1 -1
View File
@@ -1,3 +1,4 @@
from core.network.libtorrent_misc import cleanup_session
from core.utils.logging.logs import consoleLog
from core.utils.data.state import state
import os
@@ -5,7 +6,6 @@ import os
def closehelper():
state.shutdown_event.set()
try:
from core.network.libtorrent_misc import cleanup_session
cleanup_session()
except Exception as e:
consoleLog(f"Exception while cleaning up LibTorrent Session: {e}")
+8 -1
View File
@@ -1,2 +1,9 @@
from core.utils.logging.logs import consoleLog
def run_thread(thread):
thread.start()
target_name = thread._target.__name__
try:
thread.start()
consoleLog(f"Started Thread: {target_name}")
except Exception as e:
consoleLog(f"Exception while starting thread {target_name}: {e}")
+13 -10
View File
@@ -2,8 +2,10 @@ from core.network.libtorrent_misc import send_notification, update_log, check_de
from core.utils.logging.loghandler import split_data, check_completed, check_downloads
from core.network.interface import list_interfaces, init_interfaces
from core.utils.logging.logs import get_download_logs
from core.utils.logging.logs import set_main_window
from core.utils.general.shutdown import closehelper
from core.utils.general.wrappers import run_thread
from core.utils.general.shutdown import force_exit
from core.utils.config.config import read_config
from core.utils.logging.logs import consoleLog
from core.interface.gui import MainWindow
@@ -22,44 +24,45 @@ def run_gui():
qdarktheme.setup_theme("auto")
widget = MainWindow()
# Check OS for window transparency compatibility and apply
if state.window_transparency and platform.system() != "Windows":
widget.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
qdarktheme.setup_theme("auto", custom_colors={"background": "#00000000"})
from core.utils.logging.logs import set_main_window
set_main_window(widget)
widget.show()
sys.exit(app.exec())
def keyboardinterrupthandler(signum, frame):
closehelper()
from core.utils.general.shutdown import force_exit
force_exit()
def main():
# Begin counting startup time
start_time = time.perf_counter()
# Parse saved files
read_config()
logs = get_download_logs()
_, downloads = split_data(logs)
# Initialize Keyboardinterrupt signal
signal.signal(signal.SIGINT, keyboardinterrupthandler)
consoleLog("Starting SoftwareManager...")
consoleLog("Fetching Network Interfaces...")
# Get network interface info
list_interfaces()
consoleLog("Initializing Interface variables...")
init_interfaces()
consoleLog(f"Current Bound: {state.bound_interface}")
# Start background daemon threads
run_thread(threading.Thread(target=send_notification, args=(state.shutdown_event,), daemon=True))
consoleLog("Started Thread: send_notification")
run_thread(threading.Thread(target=update_log, args=(state.shutdown_event,), daemon=True))
consoleLog("Started Thread: update_log")
run_thread(threading.Thread(target=check_completed, args=(downloads, state.autoresume)))
consoleLog("Started Thread: check_completed")
run_thread(threading.Thread(target=check_deleted_files, args=(state.shutdown_event,), daemon=True))
consoleLog("Started Thread: check_deleted_files")
# Start background non-daemon threads
run_thread(threading.Thread(target=check_completed, args=(downloads, state.autoresume)))
run_thread(threading.Thread(target=check_downloads, args=(downloads,)))
consoleLog("Started Thread: check_downloads")
# Finish counting startup time
elapsed = time.perf_counter() - start_time
consoleLog(f"Initialization completed in {elapsed:.2f}s. Launching GUI")
# Launch GUI
run_gui()
if __name__ == "__main__":