diff options
| -rw-r--r-- | AboutWindow.py | 39 | ||||
| -rw-r--r-- | Soundboard.py | 1 | ||||
| -rw-r--r-- | SoundboardEngine.py | 9 | ||||
| -rw-r--r-- | SoundboardUpdater.py | 176 | ||||
| -rw-r--r-- | main.py | 11 |
5 files changed, 212 insertions, 24 deletions
diff --git a/AboutWindow.py b/AboutWindow.py index 83a8eaa..ab04d11 100644 --- a/AboutWindow.py +++ b/AboutWindow.py @@ -14,15 +14,10 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. -from PySide6.QtWidgets import ( - QVBoxLayout, - QWidget, - QLabel, - QPushButton -) - from PySide6.QtCore import QUrl from PySide6.QtGui import QDesktopServices +from PySide6.QtWidgets import QLabel, QPushButton, QVBoxLayout, QWidget + from Soundboard import Soundboard @@ -41,28 +36,36 @@ class AboutWindow(QWidget): layout.setSpacing(10) soundboard_info = QLabel( - f"Soundboard Name: {self.soundboard.soundboard_name}\n" + - f"Soundboard Author: {self.soundboard.soundboard_author}\n" + - f"Soundboard ID: {self.soundboard.soundboard_id}\n" + - f"Soundboard Version: {self.soundboard.soundboard_version}" + f"Soundboard Name: {self.soundboard.soundboard_name}\n" + + f"Soundboard Author: {self.soundboard.soundboard_author}\n" + + f"Soundboard ID: {self.soundboard.soundboard_id}\n" + + f"Soundboard Version: {self.soundboard.soundboard_version}" ) layout.addWidget(soundboard_info) app_info = QLabel( - "Soundboard Engine - Customizable soundboard.\n" + - f"Version - {self.app_version}\n" + - "Copyright (c) 2026 Vidhu Kant Sharma <vidhukant@vidhukant.com>\n" + - "This program comes with absolutely no warranty.\n" + - "See GNU GPL Version 3 or later for more details." + "Soundboard Engine - Customizable soundboard.\n" + + f"Version - {self.app_version}\n" + + "Copyright (c) 2026 Vidhu Kant Sharma <vidhukant@vidhukant.com>\n" + + "This program comes with absolutely no warranty.\n" + + "See GNU GPL Version 3 or later for more details." ) layout.addWidget(app_info) view_source_btn = QPushButton("View Source Code") - view_source_btn.clicked.connect(lambda: QDesktopServices.openUrl(QUrl("https://git.vidhukant.com/soundboard-engine/about"))) + view_source_btn.clicked.connect( + lambda: QDesktopServices.openUrl( + QUrl("https://git.vidhukant.com/soundboard-engine/about") + ) + ) layout.addWidget(view_source_btn) view_license_btn = QPushButton("View License") - view_license_btn.clicked.connect(lambda: QDesktopServices.openUrl(QUrl("https://git.vidhukant.com/soundboard-engine/tree/LICENSE"))) + view_license_btn.clicked.connect( + lambda: QDesktopServices.openUrl( + QUrl("https://git.vidhukant.com/soundboard-engine/tree/LICENSE") + ) + ) layout.addWidget(view_license_btn) self.setLayout(layout) diff --git a/Soundboard.py b/Soundboard.py index 32ddfa6..2dbb3ec 100644 --- a/Soundboard.py +++ b/Soundboard.py @@ -37,6 +37,7 @@ class Soundboard: self.soundboard_id = data["soundboard_id"] self.soundboard_author = data["soundboard_author"] self.soundboard_version = data["soundboard_version"] + self.update_url = data["update_url"] class SoundboardCategory: diff --git a/SoundboardEngine.py b/SoundboardEngine.py index 899f9d2..a9c3241 100644 --- a/SoundboardEngine.py +++ b/SoundboardEngine.py @@ -16,7 +16,6 @@ import random -from AboutWindow import AboutWindow from PySide6.QtWidgets import ( QMainWindow, QStackedWidget, @@ -24,16 +23,18 @@ from PySide6.QtWidgets import ( QWidget, ) +from AboutWindow import AboutWindow from AudioPlayer import AudioPlayer, PlayerStatus from CategoryCardWidget import CategoryCardWidget from CategoryListWidget import CategoryListWidget -from SoundListItemWidget import QHBoxLayout, QLabel from Soundboard import Soundboard +from SoundListItemWidget import QHBoxLayout, QLabel from SoundsListWidget import SoundsListWidget from StatusbarWidget import StatusbarWidget APP_VERSION = "0.1.0" + class SoundboardEngineWindow(QMainWindow): def __init__(self, soundboard: Soundboard, app_version): super().__init__() @@ -83,7 +84,9 @@ class SoundboardEngineWindow(QMainWindow): self.footer_layout.setContentsMargins(0, 0, 0, 10) self.footer_layout.addStretch() - self.footer_label = QLabel(f"Soundboard Engine {self.app_version} | <a href='about'>About</a>") + self.footer_label = QLabel( + f"Soundboard Engine {self.app_version} | <a href='about'>About</a>" + ) self.footer_label.linkActivated.connect(self.toggle_about_page) self.footer_layout.addWidget(self.footer_label) diff --git a/SoundboardUpdater.py b/SoundboardUpdater.py new file mode 100644 index 0000000..51674b6 --- /dev/null +++ b/SoundboardUpdater.py @@ -0,0 +1,176 @@ +# Soundboard Engine - customizable soundboard +# Copyright (C) 2026 Vidhu Kant Sharma <vidhukant@vidhukant.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +import shutil +import sys +import zipfile +from pathlib import Path + +import requests +from PySide6.QtCore import Qt, QThread, Signal +from PySide6.QtWidgets import QLabel, QPushButton, QVBoxLayout, QWidget + +from Soundboard import Soundboard + + +class SoundboardUpdaterWindow(QWidget): + start_soundboard = Signal() + + def __init__(self, soundboard: Soundboard): + super().__init__() + + self.soundboard = soundboard + + if soundboard.update_url.strip() != "": + self.worker = SoundboardUpdaterWorker(self.soundboard) + self.worker.start() + self.init_ui() + else: + self.start_soundboard.emit() + + def init_ui(self): + self.setWindowTitle("Soundboard Updater") + self.setFixedSize(300, 180) + + self.layout = QVBoxLayout(self) + self.status_label = QLabel("Updater coming soon") + self.layout.addWidget(self.status_label) + + self.btn_layout = QVBoxLayout() + + self.continue_btn = QPushButton("Continue Without Updating") + self.continue_btn.clicked.connect(self._start_soundboard) + self.btn_layout.addWidget(self.continue_btn) + + self.layout.addLayout(self.btn_layout) + + self.worker.no_update_found.connect(self._start_soundboard) + self.worker.update_found.connect(self._on_update_found) + self.worker.extracting.connect( + lambda: self.status_label.setText("Extracting update...") + ) + self.worker.extracting.connect( + lambda: self.status_label.setText("Copying files...") + ) + self.worker.update_completed.connect(self._on_update_completed) + + def _on_update_found(self, size): + self.status_label.setText(f"Update found ({size})") + + self.update_btn = QPushButton("Download Update") + self.update_btn.clicked.connect(self._on_download_update) + + self.btn_layout.addWidget(self.update_btn) + + def _on_download_update(self): + self.update_btn.setEnabled(False) + self.continue_btn.setEnabled(False) + self.status_label.setText("Downloading update...") + self.worker.start() + + def _on_update_completed(self): + self.status_label.setText("Update completed! Please restart soundboard") + self.update_btn.setVisible(False) + self.continue_btn.setVisible(False) + + def _start_soundboard(self): + self.start_soundboard.emit() + self.deleteLater() + + +class SoundboardUpdaterWorker(QThread): + update_found = Signal(str) + no_update_found = Signal() + extracting = Signal() + copying = Signal() + update_completed = Signal() + + def __init__(self, soundboard: Soundboard): + super().__init__() + + self.soundboard = soundboard + self.mode = "CHECKING_UPDATE" + + def run(self): + if self.mode == "CHECKING_UPDATE": + self._check_for_update() + else: + self._download_and_extract() + + def _check_for_update(self): + try: + res = requests.get(self.soundboard.update_url + "SOUNDBOARD_VERSION") + remote_version = res.text.strip() + + self.download_url = self.soundboard.update_url + remote_version + ".zip" + + if remote_version != self.soundboard.soundboard_version: + head = requests.head(self.download_url, timeout=5) + update_size = self.format_size( + int(head.headers.get("content-length", 0)) + ) + self.mode = "FOUND_UPDATE" + self.update_found.emit(update_size) + else: + self.no_update_found.emit() + except Exception as e: + print(e) + sys.exit(1) + + def _download_and_extract(self): + download_path = Path("temp_update.zip") + if download_path.exists(): + download_path.unlink() + + try: + res = requests.get(self.download_url) + + with open(download_path, "wb") as f: + f.write(res.content) + + self.extracting.emit() + + with zipfile.ZipFile(download_path, "r") as zip_ref: + zip_ref.extractall(Path.cwd()) + + if download_path.exists(): + download_path.unlink() + + self.copying.emit() + + extracted_path = Path("temp_update") + + shutil.copy2( + extracted_path / "soundboard.json", self.soundboard.soundboard_path + ) + + shutil.rmtree(Path.cwd() / "assets") + shutil.copytree(extracted_path / "assets", Path.cwd() / "assets") + + if extracted_path.exists(): + shutil.rmtree(extracted_path) + + self.update_completed.emit() + except Exception as e: + print(e) + sys.exit(1) + + def format_size(self, bytes_size): + if bytes_size >= 1024 * 1024: + return f"{bytes_size / (1024 * 1024):.1f} MB" + elif bytes_size >= 1024: + return f"{bytes_size / 1024:.1f} KB" + return f"{bytes_size} B" @@ -23,8 +23,9 @@ from PySide6.QtWidgets import QApplication from Soundboard import Soundboard from SoundboardEngine import SoundboardEngineWindow +from SoundboardUpdater import SoundboardUpdaterWindow -APP_VERSION = "0.1.1" +APP_VERSION = "0.2.0" if __name__ == "__main__": config_path = ( @@ -51,7 +52,11 @@ if __name__ == "__main__": app.setOrganizationName("VidhuKant") app.setApplicationName(_soundboard.soundboard_id) - window = SoundboardEngineWindow(_soundboard, APP_VERSION) - window.show() + main_window = SoundboardEngineWindow(_soundboard, APP_VERSION) + + updater = SoundboardUpdaterWindow(_soundboard) + updater.start_soundboard.connect(main_window.show) + + updater.show() sys.exit(app.exec()) |