aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AboutWindow.py39
-rw-r--r--Soundboard.py1
-rw-r--r--SoundboardEngine.py9
-rw-r--r--SoundboardUpdater.py176
-rw-r--r--main.py11
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"
diff --git a/main.py b/main.py
index 8759b00..7b035d5 100644
--- a/main.py
+++ b/main.py
@@ -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())