Compare commits

..

5 Commits

36 changed files with 85 additions and 135 deletions
+47 -84
View File
@@ -57,13 +57,7 @@ jobs:
- name: Install Python dependencies
run: |
uv pip install -r requirements.txt
uv pip install Pillow
env:
UV_SYSTEM_PYTHON: 1
- name: Install Nuitka (Windows only)
if: runner.os == 'Windows'
run: uv pip install nuitka
uv pip install nuitka
env:
UV_SYSTEM_PYTHON: 1
@@ -88,29 +82,29 @@ jobs:
}
EOF
- name: Install UPX (Windows)
if: runner.os == 'Windows'
- name: Install UPX
shell: bash
run: |
curl -sL https://github.com/upx/upx/releases/download/v5.1.0/upx-5.1.0-win64.zip -o upx.zip
7z x upx.zip -oupx-dir
UPX_DIR="$(pwd)/upx-dir/upx-5.1.0-win64"
echo "$UPX_DIR" >> $GITHUB_PATH
export PATH="$UPX_DIR:$PATH"
echo "UPX_BINARY=$UPX_DIR/upx.exe" >> $GITHUB_ENV
if [ "$RUNNER_OS" == "Windows" ]; then
curl -sL https://github.com/upx/upx/releases/download/v5.1.0/upx-5.1.0-win64.zip -o upx.zip
7z x upx.zip -oupx-dir
UPX_DIR="$(pwd)/upx-dir/upx-5.1.0-win64"
echo "$UPX_DIR" >> $GITHUB_PATH
export PATH="$UPX_DIR:$PATH"
echo "UPX_BINARY=$UPX_DIR/upx.exe" >> $GITHUB_ENV
elif [ "$RUNNER_OS" == "Linux" ]; then
curl -sL https://github.com/upx/upx/releases/download/v5.1.0/upx-5.1.0-amd64_linux.tar.xz -o upx.tar.xz
tar xf upx.tar.xz
UPX_DIR="$(pwd)/upx-5.1.0-amd64_linux"
echo "$UPX_DIR" >> $GITHUB_PATH
export PATH="$UPX_DIR:$PATH"
echo "UPX_BINARY=$UPX_DIR/upx" >> $GITHUB_ENV
else
brew install upx
echo "UPX_BINARY=$(which upx)" >> $GITHUB_ENV
fi
upx --version | head -1
- name: Convert icon for Windows
if: runner.os == 'Windows'
shell: bash
run: |
python -c "
from PIL import Image
img = Image.open('src/core/interface/assets/logo.png')
img.save('app_icon.ico', format='ICO', sizes=[(256,256),(128,128),(64,64),(48,48),(32,32),(16,16)])
print('Icon converted successfully')
"
- name: Build with Nuitka (Windows)
if: runner.os == 'Windows'
shell: bash
@@ -121,70 +115,52 @@ jobs:
--onefile-tempdir-spec="{CACHE_DIR}/${{ env.APP_NAME }}/${{ env.VERSION }}" \
--assume-yes-for-downloads \
--windows-console-mode=disable \
--windows-icon-from-ico=app_icon.ico \
--enable-plugin=pyside6 \
--enable-plugin=upx \
--upx-binary="${{ env.UPX_BINARY }}" \
--noinclude-qt-translations \
--include-data-dir=core/interface/assets=core/interface/assets \
--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 \
--include-data-files=build_info.json=core/build_info.json \
--include-data-files=build_info.json=core/interface/build_info.json \
--output-filename=${{ env.APP_NAME }}.exe \
src/main.py
main.py
- name: Build with PyInstaller (Linux)
if: runner.os == 'Linux'
- name: Build with Nuitka (Unix)
if: runner.os != 'Windows'
shell: bash
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 \
--hidden-import=backports \
--hidden-import=jaraco.context \
--hidden-import=jaraco.text \
--hidden-import=jaraco.functools \
--name ${{ env.APP_NAME }} \
src/main.py
python -m nuitka \
--onefile \
--onefile-no-compression \
--onefile-tempdir-spec="{CACHE_DIR}/${{ env.APP_NAME }}/${{ env.VERSION }}" \
--assume-yes-for-downloads \
--enable-plugin=pyside6 \
--enable-plugin=upx \
--upx-binary="${{ env.UPX_BINARY }}" \
--include-data-dir=core/interface/assets=core/interface/assets \
--include-data-files=build_info.json=build_info.json \
--include-data-files=build_info.json=core/build_info.json \
--include-data-files=build_info.json=core/interface/build_info.json \
--output-filename=${{ env.APP_NAME }} \
main.py
- name: Build with PyInstaller (macOS)
if: runner.os == 'macOS'
- name: Prepare artifact
shell: bash
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 \
--hidden-import=backports \
--hidden-import=jaraco.context \
--hidden-import=jaraco.text \
--hidden-import=jaraco.functools \
--name ${{ env.APP_NAME }} \
src/main.py
- name: Rename artifact
shell: bash
run: |
mkdir -p dist-final
mkdir -p dist
if [ "$RUNNER_OS" == "Windows" ]; then
mv ${{ env.APP_NAME }}.exe dist-final/${{ matrix.artifact_name }}
mv ${{ env.APP_NAME }}.exe dist/${{ matrix.artifact_name }}
else
chmod +x dist/${{ env.APP_NAME }}
mv dist/${{ env.APP_NAME }} dist-final/${{ matrix.artifact_name }}
mv ${{ env.APP_NAME }} dist/${{ matrix.artifact_name }}
chmod +x dist/${{ matrix.artifact_name }}
fi
ls -la dist-final/
ls -la dist/
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}-build
path: dist-final/${{ matrix.artifact_name }}
path: dist/${{ matrix.artifact_name }}
retention-days: 1
release:
@@ -209,16 +185,9 @@ jobs:
chmod +x release/SoftwareManager-dev-*-linux release/SoftwareManager-dev-*-macos
ls -la release/
- name: Generate checksums
run: |
cd release
sha256sum * > SHA256SUMS.txt
cat SHA256SUMS.txt
- name: Generate release notes
run: |
SHORT_SHA="${{ needs.build.outputs.short_sha }}"
CHECKSUMS=$(cat release/SHA256SUMS.txt)
cat > release_notes.md << EOF
## Development Build
@@ -231,11 +200,6 @@ jobs:
- Linux: \`SoftwareManager-dev-${SHORT_SHA}-linux\`
- Windows: \`SoftwareManager-dev-${SHORT_SHA}-windows.exe\`
- macOS: \`SoftwareManager-dev-${SHORT_SHA}-macos\`
### SHA-256 Checksums
\`\`\`
${CHECKSUMS}
\`\`\`
EOF
cat release_notes.md
@@ -249,6 +213,5 @@ jobs:
release/SoftwareManager-dev-${{ needs.build.outputs.short_sha }}-linux
release/SoftwareManager-dev-${{ needs.build.outputs.short_sha }}-windows.exe
release/SoftwareManager-dev-${{ needs.build.outputs.short_sha }}-macos
release/SHA256SUMS.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+1 -1
View File
@@ -30,7 +30,7 @@ SoftwareManager is a Python-based GUI tool that simplifies searching and downloa
## Additional Information
- SoftwareManager is still in Development and most likely contains issues. Please report any bugs you find via the Issues tab. Contributions are also greatly appreciated.
- MacOS Builds haven't been properly tested - We're thankful to receive feedback.
- If you want to host your own server, clone our [server repository](https://github.com/KeksPirates/SoftwareManager-Server), enter your cookie for rutracker.org and run server.py. Detailed Instructions on how to get your rutracker cookie are in the README of the server repo.
- If you want to host your own server, clone the server branch of this repo, enter your cookie for rutracker.org and run server.py. Detailed Instructions on how to get your rutracker cookie are in the README of the server branch.
## Python Dependencies
(also included in requirements.txt)

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

@@ -1,4 +1,4 @@
from PySide6 import QtWidgets, QtCore, QtGui
from PySide6 import QtWidgets
from PySide6.QtCore import Qt, QTimer, QModelIndex, QAbstractTableModel, Signal, QEvent, QSize
from PySide6.QtWidgets import (
QLineEdit,
@@ -29,7 +29,6 @@ import libtorrent as lt
import time
import sys
import json
import base64
from core.utils.general.logs import consoleLog, remove_download_log, flush_log_buffer
from core.utils.general.wrappers import run_thread
from core.utils.data.state import state
@@ -38,9 +37,6 @@ from core.utils.network.update_checker import check_for_updates
from core.interface.utils.tabhelper import create_tab
from core.interface.utils.searchhelper import return_pressed
from core.interface.dialogs.settings import settings_dialog
from core.interface.assets.base64_icons import settings_black_base64
from core.interface.assets.base64_icons import settings_white_base64
from core.interface.assets.base64_icons import logo_base64
from core.network.libtorrent_misc import cleanup_session
from core.utils.general.shutdown import closehelper
@@ -76,10 +72,20 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
MainWindow._instance = self
self.log_signal.connect(self._on_log_signal)
pixmap = QPixmap()
image_data = base64.b64decode(logo_base64)
pixmap.loadFromData(image_data)
self.setWindowIcon(QIcon(pixmap))
def get_asset_path(filename):
if getattr(sys, 'frozen', False):
base_path = sys._MEIPASS
else:
base_path = os.path.dirname(__file__)
asset_path = os.path.join(base_path, 'core', 'interface', 'assets', filename)
if os.path.exists(asset_path):
return asset_path
return os.path.join('core', 'interface', 'assets', filename)
self.setWindowIcon(QIcon(get_asset_path("logo.png")))
if platform.system() == "Windows":
try:
@@ -96,22 +102,23 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
state.version = build_info.get("version")
# Check for updates on Windows
if state.ignore_updates is False and platform.system() == "Windows":
result = check_for_updates()
if result != (None, None):
assets, latest_version = result
if state.ignore_updates is False:
if platform.system() == "Windows":
result = check_for_updates()
if result != (None, None):
assets, latest_version = result
if assets:
msg = QMessageBox()
msg.setIcon(QMessageBox.Icon.Information)
msg.setWindowTitle("Update Available")
msg.setText("A new version is available.")
msg.setInformativeText("Press Ok to download the update.")
msg.setStandardButtons(QMessageBox.StandardButton.Ok | QMessageBox.StandardButton.Ignore)
if assets:
msg = QMessageBox()
msg.setIcon(QMessageBox.Icon.Information)
msg.setWindowTitle("Update Available")
msg.setText("A new version is available.")
msg.setInformativeText("Press Ok to download the update.")
msg.setStandardButtons(QMessageBox.StandardButton.Ok | QMessageBox.StandardButton.Ignore)
response = msg.exec_()
if response == QMessageBox.StandardButton.Ok:
download_update(latest_version)
response = msg.exec_()
if response == QMessageBox.StandardButton.Ok:
download_update(latest_version)
self.setWindowTitle("Software Manager")
self.setGeometry(100, 100, 800, 600)
@@ -410,18 +417,10 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
self.settings_btn = QtWidgets.QToolButton()
self.settings_btn.setIconSize(QSize(21, 21))
self.settings_btn.setStyleSheet("background: transparent;")
if darkdetect.isDark():
settings_white_pixmap = QPixmap()
settings_white = base64.b64decode(settings_white_base64)
settings_white_pixmap.loadFromData(settings_white)
self.settings_btn.setIcon(QIcon(settings_white_pixmap))
self.settings_btn.setIcon(QIcon(get_asset_path("settings_white.png")))
else:
settings_black_pixmap = QPixmap()
settings_black = base64.b64decode(settings_black_base64)
settings_black_pixmap.loadFromData(settings_black)
self.settings_btn.setIcon(QIcon(settings_black_pixmap))
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))
@@ -476,11 +475,10 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
MainWindow._instance.log_signal.emit(text)
def _on_log_signal(self, text):
if hasattr(self, 'consoleLog'):
self.consoleLog.append(text)
self.consoleLog.verticalScrollBar().setValue(
self.consoleLog.verticalScrollBar().maximum()
)
self.consoleLog.append(text)
self.consoleLog.verticalScrollBar().setValue(
self.consoleLog.verticalScrollBar().maximum()
)
def update_image_overlay(self, new_image_path):
self.image = QImage(new_image_path)
View File
+1 -1
View File
@@ -1,5 +1,5 @@
requests==2.32.2
PySide6-Essentials==6.10.1
PySide6==6.10.1
beautifulsoup4==4.13.5
darkdetect==0.7.1
pyinstaller==6.15.0
File diff suppressed because one or more lines are too long