mirror of
https://github.com/KeksPirates/SoftwareManager.git
synced 2026-08-03 17:39:42 +02:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e95ad11672 | |||
| 62c6afe350 | |||
| 1aaf56a4dc | |||
| 47b643d68b | |||
| de1c8577d6 | |||
| c835b8375c | |||
| e7291e8e99 | |||
| a4efe9185a | |||
| 86b4f023ac | |||
| 006da55aa0 | |||
| 214a389ad3 | |||
| d4005d7e86 | |||
| 08a45cb422 | |||
| c49726fe42 | |||
| ecc117dedc | |||
| c51fc9ea4a | |||
| 48ed11c248 | |||
| d672e3d85f | |||
| 564c0f2ac5 | |||
| 8a48c6c730 | |||
| 6432511639 | |||
| 054e1d0aa5 | |||
| 6f7a9e13f4 | |||
| 89de75c3d7 |
+10
-26
@@ -44,30 +44,22 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
|
||||
- name: Install system dependencies (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
libxcb-xinerama0 \
|
||||
libxkbcommon-x11-0 \
|
||||
libxcb-cursor0 \
|
||||
libxcb-keysyms1 \
|
||||
libxcb-render-util0 \
|
||||
libxcb-icccm4 \
|
||||
libxcb-image0 \
|
||||
libxcb-shape0 \
|
||||
libxcb-util1
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
version: "0.9.7"
|
||||
enable-cache: true
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
pip install pyinstaller backports.tarfile pillow
|
||||
uv pip install -r requirements.txt
|
||||
uv pip install pyinstaller backports.tarfile pillow
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
- name: Generate version
|
||||
id: version
|
||||
@@ -90,13 +82,6 @@ jobs:
|
||||
}
|
||||
EOF
|
||||
|
||||
- name: Download aria2c (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
mkdir -p deps
|
||||
C:\msys64\usr\bin\wget.exe https://github.com/aria2/aria2/releases/download/release-1.37.0/aria2-1.37.0-win-64bit-build1.zip
|
||||
unzip -j aria2-1.37.0-win-64bit-build1.zip aria2-1.37.0-win-64bit-build1/aria2c.exe -d deps/
|
||||
|
||||
- name: Build executable with PyInstaller (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: bash
|
||||
@@ -105,7 +90,6 @@ jobs:
|
||||
--add-data "build_info.json;." \
|
||||
--add-data "build_info.json;core" \
|
||||
--add-data "build_info.json;core/interface" \
|
||||
--add-data "deps/aria2c.exe;." \
|
||||
--add-data "core/interface/assets;core/interface/assets" \
|
||||
--icon "core/interface/assets/logo.png" \
|
||||
--exclude-module PyQt6 \
|
||||
|
||||
@@ -60,30 +60,20 @@ def settings_dialog(self):
|
||||
autoresume_layout.addWidget(autoresume_checkbox)
|
||||
dialog.layout().addWidget(autoresume_container)
|
||||
|
||||
#####################
|
||||
# DOWNLOAD SETTINGS #
|
||||
#####################
|
||||
thread_box = QSpinBox()
|
||||
thread_box.setMinimum(1)
|
||||
thread_box.setMaximum(16)
|
||||
thread_box.setValue(state.aria2_threads)
|
||||
|
||||
|
||||
# container for tight space
|
||||
thread_container = QWidget()
|
||||
thread_layout = QHBoxLayout()
|
||||
# transparent window checkbox
|
||||
transparent_window_container = QWidget()
|
||||
transparent_window_layout = QHBoxLayout()
|
||||
|
||||
thread_layout.addWidget(QLabel("Threads:"))
|
||||
thread_layout.addWidget(thread_box)
|
||||
thread_container.setLayout(thread_layout)
|
||||
thread_container.setMaximumHeight(80)
|
||||
|
||||
transparent_window_checkbox = QCheckBox()
|
||||
transparent_window_container.setLayout(transparent_window_layout)
|
||||
transparent_window_layout.addWidget(QLabel("Window Transparency (requires restart) (Linux/MacOS only): "))
|
||||
|
||||
# Dimensions
|
||||
thread_box.setFixedWidth(90)
|
||||
thread_box.setFixedHeight(30)
|
||||
|
||||
dialog.layout().addWidget(thread_container)
|
||||
transparent_window_layout.addStretch()
|
||||
transparent_window_checkbox.setChecked(state.window_transparency)
|
||||
transparent_window_checkbox.toggled.connect(lambda checked: setattr(state, 'window_transparency', checked))
|
||||
transparent_window_layout.addWidget(transparent_window_checkbox)
|
||||
dialog.layout().addWidget(transparent_window_container)
|
||||
|
||||
##################
|
||||
# SERVER SETTING #
|
||||
@@ -124,6 +114,30 @@ def settings_dialog(self):
|
||||
download_path_layout.addWidget(browse_button)
|
||||
browse_button.clicked.connect(browse_download_path)
|
||||
|
||||
###############
|
||||
# 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)
|
||||
|
||||
def browse_image_path():
|
||||
file_path = QFileDialog.getOpenFileName(dialog, "Select Image File", state.image_path, "Image Files (*.png *.jpg)")[0]
|
||||
if file_path:
|
||||
image_path.setText(file_path)
|
||||
|
||||
browse_button = QPushButton("📁")
|
||||
image_path_layout.addWidget(browse_button)
|
||||
browse_button.clicked.connect(browse_image_path)
|
||||
|
||||
##################
|
||||
# SPEED LIMITING #
|
||||
##################
|
||||
@@ -192,31 +206,6 @@ def settings_dialog(self):
|
||||
max_downloads.setFixedHeight(30)
|
||||
dialog.layout().addWidget(max_downloads_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)
|
||||
|
||||
def browse_image_path():
|
||||
file_path = QFileDialog.getOpenFileName(dialog, "Select Image File", state.image_path, "Image Files (*.png *.jpg)")[0]
|
||||
if file_path:
|
||||
image_path.setText(file_path)
|
||||
|
||||
browse_button = QPushButton("📁")
|
||||
image_path_layout.addWidget(browse_button)
|
||||
browse_button.clicked.connect(browse_image_path)
|
||||
|
||||
###############
|
||||
# SAVE/CANCEL #
|
||||
###############
|
||||
|
||||
+127
-30
@@ -1,12 +1,11 @@
|
||||
from PySide6 import QtWidgets
|
||||
from PySide6.QtCore import Qt, QTimer, QModelIndex, QAbstractTableModel, Signal, QEvent
|
||||
from PySide6.QtCore import Qt, QTimer, QModelIndex, QAbstractTableModel, Signal, QEvent, QSize
|
||||
from PySide6.QtWidgets import (
|
||||
QLineEdit,
|
||||
QTableView,
|
||||
QWidget,
|
||||
QVBoxLayout,
|
||||
QListWidget,
|
||||
QToolBar,
|
||||
QLabel,
|
||||
QHBoxLayout,
|
||||
QComboBox,
|
||||
@@ -16,13 +15,10 @@ from PySide6.QtWidgets import (
|
||||
QMessageBox,
|
||||
QTableWidget,
|
||||
QTextEdit,
|
||||
QStyle,
|
||||
QStyleOptionButton,
|
||||
QStyledItemDelegate,
|
||||
QApplication,
|
||||
)
|
||||
|
||||
from PySide6.QtGui import QIcon, QAction, QCloseEvent, QImage, QPixmap
|
||||
from PySide6.QtGui import QIcon, QCloseEvent, QImage, QPixmap, QContextMenuEvent
|
||||
import darkdetect
|
||||
import threading
|
||||
import platform
|
||||
@@ -33,7 +29,7 @@ import libtorrent as lt
|
||||
import time
|
||||
import sys
|
||||
import json
|
||||
from core.utils.general.logs import consoleLog
|
||||
from core.utils.general.logs import consoleLog, remove_download_log
|
||||
from core.utils.general.wrappers import run_thread
|
||||
from core.utils.data.state import state
|
||||
from core.utils.network.download import download_selected
|
||||
@@ -138,6 +134,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
||||
self.searchbar.returnPressed.connect(lambda: run_thread(threading.Thread(target=return_pressed, args=(self,)))) # Triggers data function thread on enter
|
||||
|
||||
self.dlbutton = QtWidgets.QPushButton("Download")
|
||||
self.dlbutton.setCursor(Qt.PointingHandCursor)
|
||||
self.libraryList = QListWidget()
|
||||
|
||||
self.emptyResults = QLabel("No Results")
|
||||
@@ -155,12 +152,14 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
||||
|
||||
# Table Widget for Item List
|
||||
self.qtablewidget = QTableWidget()
|
||||
|
||||
|
||||
self.qtablewidget.setColumnCount(2)
|
||||
self.qtablewidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
||||
self.qtablewidget.verticalHeader().setVisible(False)
|
||||
self.qtablewidget.setHorizontalHeaderLabels(["Post Title", "Author"])
|
||||
|
||||
|
||||
|
||||
header = self.qtablewidget.horizontalHeader()
|
||||
header.setSectionResizeMode(0, QHeaderView.Stretch)
|
||||
header.setSectionResizeMode(1, QHeaderView.Fixed)
|
||||
@@ -207,8 +206,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
||||
status = magnetdl.status()
|
||||
|
||||
if col == 0:
|
||||
is_paused = magnetdl.status().paused
|
||||
return "▶︎" if is_paused else "⏸︎"
|
||||
pass
|
||||
elif col == 1:
|
||||
return status.name if status.has_metadata else "Fetching metadata..."
|
||||
elif col == 2:
|
||||
@@ -275,7 +273,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
||||
status = magnetdl.status()
|
||||
|
||||
if status.state == lt.torrent_status.seeding:
|
||||
if state.download_path is not None and os.path.exists(state.download_path):
|
||||
if state.download_path and os.path.exists(state.download_path):
|
||||
if platform.system() == "Windows":
|
||||
os.startfile(os.path.normpath(state.download_path))
|
||||
elif platform.system() == "Linux":
|
||||
@@ -299,8 +297,6 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
||||
|
||||
def setEditorData(self, editor, index):
|
||||
button = editor.findChild(QtWidgets.QPushButton)
|
||||
|
||||
|
||||
|
||||
magnet_link = list(state.active_downloads.keys())[index.row()]
|
||||
magnetdl = state.active_downloads[magnet_link]
|
||||
@@ -312,8 +308,6 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
||||
else:
|
||||
button.setText("▶︎" if status.paused else "⏸︎")
|
||||
|
||||
|
||||
|
||||
def createEditor(self, parent, option, index):
|
||||
magnet_link = list(state.active_downloads.keys())[index.row()]
|
||||
magnetdl = state.active_downloads[magnet_link]
|
||||
@@ -334,7 +328,6 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
||||
layout.addStretch()
|
||||
widget.setLayout(layout)
|
||||
return widget
|
||||
|
||||
def editorEvent(self, event, model, option, index):
|
||||
if index.column() == 0 and event.type() == QEvent.Type.MouseButtonPress:
|
||||
self.clicked.emit(index.row())
|
||||
@@ -366,13 +359,24 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
||||
|
||||
# Tabs
|
||||
self.tabs = QTabWidget()
|
||||
self.tabs = QTabWidget()
|
||||
self.tabs.setStyleSheet("""
|
||||
QTabBar::tab {
|
||||
font-size: 11px;
|
||||
padding: 2px 8px;
|
||||
height: 25px;
|
||||
}
|
||||
QTabWidget::pane {
|
||||
margin-top: -20px;
|
||||
}
|
||||
""")
|
||||
|
||||
self.horizontal_layout = QHBoxLayout()
|
||||
self.horizontal_layout.addWidget(self.emptyResults, stretch=3)
|
||||
self.horizontal_layout.addWidget(self.qtablewidget)
|
||||
|
||||
self.tab1 = create_tab("Search", self.searchbar, self.qtablewidget, self.tabs, self.dlbutton, self.horizontal_layout)
|
||||
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)
|
||||
|
||||
if state.image_path is not None and os.path.exists(state.image_path):
|
||||
@@ -389,33 +393,58 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
||||
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)
|
||||
|
||||
self.corner_widget = QWidget()
|
||||
self.corner_layout = QHBoxLayout(self.corner_widget)
|
||||
self.corner_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
containerLayout.setAlignment(Qt.AlignmentFlag.AlignBottom)
|
||||
toolbar = QToolBar("Main Toolbar")
|
||||
self.addToolBar(toolbar)
|
||||
toolbar.setLayoutDirection(Qt.RightToLeft)
|
||||
|
||||
self.tracker_list = QComboBox()
|
||||
self.tracker_list.addItems(["rutracker", "uztracker", "m0nkrus"])
|
||||
self.tracker_list.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
self.tracker_list.activated.connect(self.set_tracker)
|
||||
self.corner_layout.addWidget(self.tracker_list)
|
||||
|
||||
self.settings_btn = QtWidgets.QToolButton()
|
||||
self.settings_btn.setIconSize(QSize(21, 21))
|
||||
self.settings_btn.setStyleSheet("background: transparent;")
|
||||
if darkdetect.isDark():
|
||||
settings_action = QAction(QIcon(get_asset_path("settings_white.png")), "Settings", self)
|
||||
self.settings_btn.setIcon(QIcon(get_asset_path("settings_white.png")))
|
||||
else:
|
||||
settings_action = QAction(QIcon(get_asset_path("settings_black.png")), "Settings", self)
|
||||
self.settings_btn.setIcon(QIcon(get_asset_path("settings_black.png")))
|
||||
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)
|
||||
|
||||
settings_action.triggered.connect(lambda: settings_dialog(self))
|
||||
toolbar.addAction(settings_action)
|
||||
toolbar.addWidget(self.tracker_list)
|
||||
self.tab_wrapper = QWidget()
|
||||
self.tab_layout = QVBoxLayout()
|
||||
self.tab_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.tab_layout.setSpacing(0)
|
||||
|
||||
|
||||
toolbar.setMovable(False)
|
||||
self.tab_bar_layout = QHBoxLayout()
|
||||
self.tab_bar_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.tab_bar_layout.setSpacing(0)
|
||||
|
||||
self.tab_bar_layout.addWidget(self.tabs.tabBar(), stretch=0)
|
||||
self.tab_bar_layout.addStretch()
|
||||
self.tab_bar_layout.addWidget(self.corner_widget, stretch=0)
|
||||
|
||||
self.tab_layout.addLayout(self.tab_bar_layout)
|
||||
self.tab_layout.addWidget(self.tabs)
|
||||
|
||||
|
||||
self.tab_wrapper.setLayout(self.tab_layout)
|
||||
|
||||
|
||||
containerLayout.addWidget(self.tab_wrapper)
|
||||
containerLayout.setAlignment(Qt.AlignmentFlag.AlignTop)
|
||||
|
||||
# self.progressbar.setValue(0)
|
||||
self.consoleLog.setReadOnly(True)
|
||||
self.consoleLog.setFixedHeight(150)
|
||||
containerLayout.addWidget(self.consoleLog)
|
||||
@@ -428,6 +457,11 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
||||
self.active_timer.timeout.connect(self.show_empty_downloads)
|
||||
self.active_timer.start(500)
|
||||
|
||||
self.context_menu = QtWidgets.QMenu(self)
|
||||
self.context_menu.addAction("Open Containing Folder", self.openFolderAction)
|
||||
self.context_menu.addAction("Copy Magnet URI", self.copyMagnetURIAction)
|
||||
self.context_menu.addAction("Cancel Download", self.cancelDownload)
|
||||
|
||||
@staticmethod
|
||||
def add_log(text):
|
||||
if MainWindow._instance:
|
||||
@@ -484,3 +518,66 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
||||
super().resizeEvent(event)
|
||||
table_width = self.qtablewidget.viewport().width()
|
||||
self.qtablewidget.setColumnWidth(1, int(table_width * 0.3))
|
||||
|
||||
def contextMenuEvent(self, event: QContextMenuEvent):
|
||||
if self.downloadList.underMouse():
|
||||
pos = self.downloadList.viewport().mapFromGlobal(event.globalPos())
|
||||
index = self.downloadList.indexAt(pos)
|
||||
|
||||
if index.isValid():
|
||||
row = index.row()
|
||||
self._context_menu_row = row
|
||||
self.context_menu.exec(event.globalPos())
|
||||
else:
|
||||
super().contextMenuEvent(event)
|
||||
|
||||
def openFolderAction(self):
|
||||
if not hasattr(self, '_context_menu_row'):
|
||||
return
|
||||
|
||||
row = self._context_menu_row
|
||||
if row < 0 or row >= len(state.active_downloads):
|
||||
return
|
||||
|
||||
magnet_link = list(state.active_downloads.keys())[row]
|
||||
magnetdl = state.active_downloads[magnet_link]
|
||||
|
||||
download_path = magnetdl.save_path()
|
||||
|
||||
if download_path and os.path.exists(download_path):
|
||||
if platform.system() == "Windows":
|
||||
os.startfile(os.path.normpath(download_path))
|
||||
elif platform.system() == "Linux":
|
||||
subprocess.Popen(["xdg-open", download_path])
|
||||
elif platform.system() == "Darwin":
|
||||
subprocess.Popen(["open", download_path])
|
||||
|
||||
def copyMagnetURIAction(self):
|
||||
if not hasattr(self, '_context_menu_row'):
|
||||
return
|
||||
|
||||
row = self._context_menu_row
|
||||
if row < 0 or row >= len(state.active_downloads):
|
||||
return
|
||||
|
||||
magnet_link = list(state.active_downloads.keys())[row]
|
||||
|
||||
clipboard = QtWidgets.QApplication.clipboard()
|
||||
clipboard.setText(magnet_link)
|
||||
|
||||
def cancelDownload(self):
|
||||
if not hasattr(self, '_context_menu_row'):
|
||||
return
|
||||
|
||||
row = self._context_menu_row
|
||||
if row < 0 or row >= len(state.active_downloads):
|
||||
return
|
||||
|
||||
magnet_link = list(state.active_downloads.keys())[row]
|
||||
magnetdl = state.active_downloads[magnet_link]
|
||||
|
||||
confirm = QMessageBox.question(self, "Cancel Download", f"Are you sure you want to cancel the download of '{magnetdl.status().name}'?", QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
|
||||
if confirm == QMessageBox.StandardButton.Yes:
|
||||
del state.active_downloads[magnet_link]
|
||||
remove_download_log(magnet_link)
|
||||
consoleLog(f"Cancelled download: {magnetdl.status().name}", True)
|
||||
|
||||
@@ -12,6 +12,6 @@ def create_tab(title, searchbar, software_list, tabs, dlbutton, layout2):
|
||||
layout.addWidget(software_list)
|
||||
if dlbutton:
|
||||
layout.addWidget(dlbutton)
|
||||
tab.setLayout(layout)
|
||||
tab.setLayout(layout)
|
||||
tabs.addTab(tab, title)
|
||||
return tab
|
||||
|
||||
@@ -89,6 +89,9 @@ def dl_status_loop():
|
||||
|
||||
def update_settings():
|
||||
|
||||
if state.dl_session is None:
|
||||
return
|
||||
|
||||
settings = {
|
||||
"upload_rate_limit": state.up_speed_limit,
|
||||
"download_rate_limit": state.down_speed_limit,
|
||||
@@ -97,4 +100,4 @@ def update_settings():
|
||||
}
|
||||
|
||||
state.dl_session.apply_settings(settings)
|
||||
consoleLog("Updated Settings")
|
||||
|
||||
|
||||
@@ -6,8 +6,19 @@ from core.utils.data.state import state
|
||||
def create_config():
|
||||
config = configparser.ConfigParser()
|
||||
|
||||
config["General"] = {"debug": True, "api_url": f"{state.api_url}", "download_path": f"{state.download_path}", f"download_speed_limit": f"{state.down_speed_limit}", f"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_downloads": f"{state.max_downloads}"}
|
||||
config["General"] = {
|
||||
"debug": True,
|
||||
"api_url": f"{state.api_url}",
|
||||
"download_path": f"{state.download_path}",
|
||||
"download_speed_limit": f"{state.down_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_downloads": f"{state.max_downloads}",
|
||||
"window_transparency": f"{state.window_transparency}",
|
||||
}
|
||||
|
||||
if platform.system() == "Windows":
|
||||
config_dir = os.environ.get("APPDATA", os.path.expanduser("~\\AppData\\Roaming"))
|
||||
@@ -48,5 +59,6 @@ def read_config():
|
||||
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)
|
||||
|
||||
create_config()
|
||||
create_config()
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
from core.network.libtorrent_int import update_settings
|
||||
from core.utils.data.state import state
|
||||
from core.utils.general.logs import consoleLog
|
||||
from .config import create_config
|
||||
|
||||
|
||||
@@ -20,5 +22,8 @@ def save_settings(close=lambda: None, apiurl=None, download_path=None, down_spee
|
||||
if max_downloads is not None:
|
||||
state.max_downloads = max_downloads
|
||||
|
||||
|
||||
update_settings()
|
||||
consoleLog("Saved Settings")
|
||||
create_config()
|
||||
close()
|
||||
|
||||
@@ -23,13 +23,10 @@ class AppState(QObject):
|
||||
self.down_speed_limit: int = 0
|
||||
self.max_connections: int = 200
|
||||
self.max_downloads: int = 10
|
||||
self.aria2process: Optional[Any] = None
|
||||
self.aria2: Any = None
|
||||
self.aria2p: Any = None
|
||||
self.aria2_threads: int = 4
|
||||
self.settings_path: str = None
|
||||
self.dl_session: Any = None
|
||||
self.active_downloads: List[str] = {}
|
||||
self.window_transparency: bool = False
|
||||
|
||||
@property
|
||||
def image_path(self) -> str:
|
||||
|
||||
@@ -41,6 +41,30 @@ def add_download_log(title, url, magnet_uri, completed) -> DownloadList:
|
||||
|
||||
return download_list
|
||||
|
||||
def remove_download_log(magnet_uri) -> DownloadList:
|
||||
downloads_file = os.path.join(state.settings_path, "downloads.json")
|
||||
|
||||
if os.path.exists(downloads_file) and os.path.getsize(downloads_file) > 0:
|
||||
try:
|
||||
with open(downloads_file, "r") as file:
|
||||
existing_data = json.load(file)
|
||||
downloads = [Download(**d) for d in existing_data.get("data", [])]
|
||||
except json.JSONDecodeError:
|
||||
downloads = []
|
||||
else:
|
||||
downloads = []
|
||||
|
||||
magnet_link = (magnet_uri or "").strip()
|
||||
downloads = [d for d in downloads if (getattr(d, 'magnet_uri', None) or "").strip() != magnet_link and (getattr(d, 'url', None) or "").strip() != magnet_link]
|
||||
|
||||
consoleLog(f"Removed {magnet_link} from Log File")
|
||||
|
||||
download_list = DownloadList(data=downloads, count=len(downloads))
|
||||
with open(downloads_file, "w") as file:
|
||||
json.dump(asdict(download_list), file, indent=4)
|
||||
|
||||
return download_list
|
||||
|
||||
def update_download_completed(magnet_uri, completed) -> DownloadList:
|
||||
downloads_file = os.path.join(state.settings_path, "downloads.json")
|
||||
|
||||
@@ -176,4 +200,4 @@ def consoleLog(text, printAnyways = False):
|
||||
pass
|
||||
|
||||
if state.debug or printAnyways:
|
||||
print(f"[{current_time}] {text}")
|
||||
print(f"[{current_time}] {text}")
|
||||
|
||||
@@ -8,29 +8,30 @@ from core.utils.general.wrappers import run_thread
|
||||
from core.utils.general.loghandler import split_data, check_completed
|
||||
from core.utils.config.config import read_config
|
||||
from PySide6 import QtWidgets
|
||||
from PySide6.QtCore import Qt
|
||||
import qdarktheme
|
||||
import darkdetect
|
||||
import threading
|
||||
import platform
|
||||
import signal
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--debug", action="store_true")
|
||||
parser.add_argument("--debug", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
def run_gui():
|
||||
app = QtWidgets.QApplication([])
|
||||
if darkdetect.isDark:
|
||||
app.setStyleSheet(qdarktheme.load_stylesheet("dark"))
|
||||
else:
|
||||
app.setStyleSheet(qdarktheme.load_stylesheet("light"))
|
||||
app = QtWidgets.QApplication.instance() or QtWidgets.QApplication(sys.argv)
|
||||
qdarktheme.setup_theme("auto")
|
||||
widget = MainWindow()
|
||||
|
||||
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.general.logs import set_main_window
|
||||
set_main_window(widget)
|
||||
|
||||
widget.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
requests==2.32.2
|
||||
PySide6==6.10.1
|
||||
beautifulsoup4==4.13.5
|
||||
darkdetect==0.8.0
|
||||
darkdetect==0.7.1
|
||||
pyinstaller==6.15.0
|
||||
pyqtdarktheme==0.1.7
|
||||
PyQtDarkTheme-fork==2.3.4
|
||||
aiohttp==3.13.0
|
||||
plyer==2.1.0
|
||||
psutil==7.1.0
|
||||
libtorrent==2.0.11
|
||||
libtorrent-windows-dll==0.0.3
|
||||
libtorrent-windows-dll==0.0.3
|
||||
|
||||
Reference in New Issue
Block a user