mirror of
https://github.com/chidiwilliams/buzz.git
synced 2026-03-14 14:45:46 +01:00
Add auto update check for Windows adn Mac (#1404)
This commit is contained in:
parent
3869ac08db
commit
187d15b8e8
29 changed files with 1864 additions and 57 deletions
3
.github/workflows/snapcraft.yml
vendored
3
.github/workflows/snapcraft.yml
vendored
|
|
@ -66,9 +66,6 @@ jobs:
|
|||
run: |
|
||||
sudo -E snapcraft pack --verbose --destructive-mode
|
||||
echo "snap=$(ls *.snap)" >> $GITHUB_OUTPUT
|
||||
- run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install libportaudio2 libtbb-dev
|
||||
- run: sudo snap install --devmode *.snap
|
||||
- run: |
|
||||
cd $HOME
|
||||
|
|
|
|||
5
Makefile
5
Makefile
|
|
@ -35,6 +35,11 @@ endif
|
|||
COVERAGE_THRESHOLD := 70
|
||||
|
||||
test: buzz/whisper_cpp
|
||||
# A check to get updates of yt-dlp. Should run only on local as part of regular development operations
|
||||
# Sort of a local "update checker"
|
||||
ifndef CI
|
||||
uv lock --upgrade-package yt-dlp
|
||||
endif
|
||||
pytest -s -vv --cov=buzz --cov-report=xml --cov-report=html --benchmark-skip --cov-fail-under=${COVERAGE_THRESHOLD} --cov-config=.coveragerc
|
||||
|
||||
benchmarks: buzz/whisper_cpp
|
||||
|
|
|
|||
|
|
@ -88,6 +88,10 @@ pip3 install nvidia-cublas-cu12==12.9.1.4 nvidia-cuda-cupti-cu12==12.9.79 nvidia
|
|||
|
||||
For info on how to get latest development version with latest features and bug fixes see [FAQ](https://chidiwilliams.github.io/buzz/docs/faq#9-where-can-i-get-latest-development-version).
|
||||
|
||||
### Support Buzz
|
||||
|
||||
You can help the Buzz by starring 🌟 the repo and sharing it with your friends.
|
||||
|
||||
### Screenshots
|
||||
|
||||
<div style="display: flex; flex-wrap: wrap;">
|
||||
|
|
|
|||
1
buzz/assets/update_FILL0_wght700_GRAD0_opsz48.svg
Normal file
1
buzz/assets/update_FILL0_wght700_GRAD0_opsz48.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M160-200v-60h640v60H160Zm320-136L280-536l42-42 128 128v-310h60v310l128-128 42 42-200 200Z" transform="rotate(180 480 -480)"/></svg>
|
||||
|
After Width: | Height: | Size: 229 B |
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: buzz\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-02-27 16:46+0200\n"
|
||||
"POT-Creation-Date: 2026-02-28 10:38+0200\n"
|
||||
"PO-Revision-Date: 2025-10-17 07:59+0200\n"
|
||||
"Last-Translator: Éric Duarte <contacto@ericdq.com>\n"
|
||||
"Language-Team: Catalan <jmas@softcatala.org>\n"
|
||||
|
|
@ -345,7 +345,8 @@ msgid "Download failed"
|
|||
msgstr "Descàrrega fallida"
|
||||
|
||||
#: buzz/widgets/preferences_dialog/models_preferences_widget.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py buzz/widgets/main_window.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
#: buzz/widgets/update_dialog.py buzz/widgets/main_window.py
|
||||
#: buzz/model_loader.py
|
||||
msgid "Error"
|
||||
msgstr "Error"
|
||||
|
|
@ -536,6 +537,10 @@ msgstr "Cancel·la la transcripció"
|
|||
msgid "Clear History"
|
||||
msgstr "Neteja l'historial"
|
||||
|
||||
#: buzz/widgets/main_window_toolbar.py buzz/widgets/update_dialog.py
|
||||
msgid "Update Available"
|
||||
msgstr "Actualització disponible"
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "In Progress"
|
||||
msgstr "En progrés"
|
||||
|
|
@ -730,6 +735,58 @@ msgstr ""
|
|||
"Comproveu els vostres dispositius d'àudio o els registres de l'aplicació per "
|
||||
"a més informació."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "A new version of Buzz is available!"
|
||||
msgstr "Hi ha una nova versió de Buzz disponible!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Current version:"
|
||||
msgstr "Versió actual:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "New version:"
|
||||
msgstr "Nova versió:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Release Notes:"
|
||||
msgstr "Notes de la versió:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download and Install"
|
||||
msgstr "Descarrega i instal·la"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "No download URL available for your platform."
|
||||
msgstr "No hi ha cap URL de descàrrega disponible per a la vostra plataforma."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {}..."
|
||||
msgstr "S'està descarregant el fitxer {} de {}..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {} ({:.1f} MB / {:.1f} MB)..."
|
||||
msgstr "S'està descarregant el fitxer {} de {} ({:.1f} MB / {:.1f} MB)..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download Failed"
|
||||
msgstr "Descàrrega fallida"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to download the update: {}"
|
||||
msgstr "No s'ha pogut descarregar l'actualització: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to save the installer: {}"
|
||||
msgstr "No s'ha pogut desar l'instal·lador: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download complete!"
|
||||
msgstr "Descàrrega completada!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to run the installer: {}"
|
||||
msgstr "No s'ha pogut executar l'instal·lador: {}"
|
||||
|
||||
#: buzz/widgets/about_dialog.py
|
||||
msgid "Check for updates"
|
||||
msgstr "Comprova si hi ha actualitzacions"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-02-27 16:46+0200\n"
|
||||
"POT-Creation-Date: 2026-02-28 10:38+0200\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Ole Guldberg2 <xalt7x.service@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
|
|
@ -341,7 +341,8 @@ msgid "Download failed"
|
|||
msgstr "Download mislykkedes"
|
||||
|
||||
#: buzz/widgets/preferences_dialog/models_preferences_widget.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py buzz/widgets/main_window.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
#: buzz/widgets/update_dialog.py buzz/widgets/main_window.py
|
||||
#: buzz/model_loader.py
|
||||
msgid "Error"
|
||||
msgstr "Fejl"
|
||||
|
|
@ -531,6 +532,10 @@ msgstr "Afbryd transkription"
|
|||
msgid "Clear History"
|
||||
msgstr "Ryd historik"
|
||||
|
||||
#: buzz/widgets/main_window_toolbar.py buzz/widgets/update_dialog.py
|
||||
msgid "Update Available"
|
||||
msgstr "Opdatering tilgængelig"
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "In Progress"
|
||||
msgstr "Arbejder"
|
||||
|
|
@ -724,6 +729,58 @@ msgstr ""
|
|||
"Tjek venligst dine audioenheder eller tjek applikationens logs for "
|
||||
"mereinformation."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "A new version of Buzz is available!"
|
||||
msgstr "En ny version af Buzz er tilgængelig!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Current version:"
|
||||
msgstr "Nuværende version:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "New version:"
|
||||
msgstr "Ny version:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Release Notes:"
|
||||
msgstr "Udgivelsesnoter:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download and Install"
|
||||
msgstr "Download og installer"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "No download URL available for your platform."
|
||||
msgstr "Ingen download-URL tilgængelig for din platform."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {}..."
|
||||
msgstr "Downloader fil {} af {}..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {} ({:.1f} MB / {:.1f} MB)..."
|
||||
msgstr "Downloader fil {} af {} ({:.1f} MB / {:.1f} MB)..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download Failed"
|
||||
msgstr "Download mislykkedes"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to download the update: {}"
|
||||
msgstr "Kunne ikke downloade opdateringen: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to save the installer: {}"
|
||||
msgstr "Kunne ikke gemme installationsprogrammet: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download complete!"
|
||||
msgstr "Download fuldført!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to run the installer: {}"
|
||||
msgstr "Kunne ikke køre installationsprogrammet: {}"
|
||||
|
||||
#: buzz/widgets/about_dialog.py
|
||||
msgid "Check for updates"
|
||||
msgstr "Tjek for opdateringer"
|
||||
|
|
@ -1564,4 +1621,6 @@ msgstr "Tilføj og ret"
|
|||
msgid ""
|
||||
"Speech extraction failed! Check your internet connection — a model may need "
|
||||
"to be downloaded."
|
||||
msgstr "Taleoprydning mislykkedes! Kontroller din internetforbindelse — en model skal muligvis hentes ned."
|
||||
msgstr ""
|
||||
"Taleoprydning mislykkedes! Kontroller din internetforbindelse — en model "
|
||||
"skal muligvis hentes ned."
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-02-27 16:46+0200\n"
|
||||
"POT-Creation-Date: 2026-02-28 10:38+0200\n"
|
||||
"PO-Revision-Date: 2025-03-05 14:41+0100\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
|
|
@ -345,7 +345,8 @@ msgid "Download failed"
|
|||
msgstr "Der Download ist fehlgeschlagen"
|
||||
|
||||
#: buzz/widgets/preferences_dialog/models_preferences_widget.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py buzz/widgets/main_window.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
#: buzz/widgets/update_dialog.py buzz/widgets/main_window.py
|
||||
#: buzz/model_loader.py
|
||||
msgid "Error"
|
||||
msgstr "Fehler"
|
||||
|
|
@ -538,6 +539,10 @@ msgstr "Transkription abbrechen"
|
|||
msgid "Clear History"
|
||||
msgstr "Verlauf löschen"
|
||||
|
||||
#: buzz/widgets/main_window_toolbar.py buzz/widgets/update_dialog.py
|
||||
msgid "Update Available"
|
||||
msgstr "Update verfügbar"
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "In Progress"
|
||||
msgstr "Im Gange"
|
||||
|
|
@ -734,6 +739,58 @@ msgstr ""
|
|||
"Bitte überprüfen Sie Ihre Audiogeräte oder prüfen Sie die "
|
||||
"Anwendungsprotokolle für weitere Informationen."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "A new version of Buzz is available!"
|
||||
msgstr "Eine neue Version von Buzz ist verfügbar!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Current version:"
|
||||
msgstr "Aktuelle Version:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "New version:"
|
||||
msgstr "Neue Version:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Release Notes:"
|
||||
msgstr "Versionshinweise:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download and Install"
|
||||
msgstr "Herunterladen und installieren"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "No download URL available for your platform."
|
||||
msgstr "Kein Download-Link für Ihre Plattform verfügbar."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {}..."
|
||||
msgstr "Datei {} von {} wird heruntergeladen..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {} ({:.1f} MB / {:.1f} MB)..."
|
||||
msgstr "Datei {} von {} wird heruntergeladen ({:.1f} MB / {:.1f} MB)..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download Failed"
|
||||
msgstr "Download fehlgeschlagen"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to download the update: {}"
|
||||
msgstr "Das Update konnte nicht heruntergeladen werden: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to save the installer: {}"
|
||||
msgstr "Installer konnte nicht gespeichert werden: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download complete!"
|
||||
msgstr "Download abgeschlossen!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to run the installer: {}"
|
||||
msgstr "Installer konnte nicht ausgeführt werden: {}"
|
||||
|
||||
#: buzz/widgets/about_dialog.py
|
||||
msgid "Check for updates"
|
||||
msgstr "Nach Updates suchen"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-02-27 16:46+0200\n"
|
||||
"POT-Creation-Date: 2026-02-28 10:38+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
|
@ -331,7 +331,8 @@ msgid "Download failed"
|
|||
msgstr ""
|
||||
|
||||
#: buzz/widgets/preferences_dialog/models_preferences_widget.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py buzz/widgets/main_window.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
#: buzz/widgets/update_dialog.py buzz/widgets/main_window.py
|
||||
#: buzz/model_loader.py
|
||||
msgid "Error"
|
||||
msgstr ""
|
||||
|
|
@ -516,6 +517,10 @@ msgstr ""
|
|||
msgid "Clear History"
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/main_window_toolbar.py buzz/widgets/update_dialog.py
|
||||
msgid "Update Available"
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "In Progress"
|
||||
msgstr ""
|
||||
|
|
@ -704,6 +709,58 @@ msgid ""
|
|||
"information."
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "A new version of Buzz is available!"
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Current version:"
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "New version:"
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Release Notes:"
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download and Install"
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "No download URL available for your platform."
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {}..."
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {} ({:.1f} MB / {:.1f} MB)..."
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download Failed"
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to download the update: {}"
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to save the installer: {}"
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download complete!"
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to run the installer: {}"
|
||||
msgstr ""
|
||||
|
||||
#: buzz/widgets/about_dialog.py
|
||||
msgid "Check for updates"
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-02-27 16:46+0200\n"
|
||||
"POT-Creation-Date: 2026-02-28 10:38+0200\n"
|
||||
"PO-Revision-Date: 2025-09-08 12:43+0200\n"
|
||||
"Last-Translator: Éric Duarte <contacto@ericdq.com>\n"
|
||||
"Language-Team: \n"
|
||||
|
|
@ -353,7 +353,8 @@ msgid "Download failed"
|
|||
msgstr "Descarga fallida"
|
||||
|
||||
#: buzz/widgets/preferences_dialog/models_preferences_widget.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py buzz/widgets/main_window.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
#: buzz/widgets/update_dialog.py buzz/widgets/main_window.py
|
||||
#: buzz/model_loader.py
|
||||
msgid "Error"
|
||||
msgstr "Error"
|
||||
|
|
@ -563,6 +564,10 @@ msgstr "Cancelar transcripción"
|
|||
msgid "Clear History"
|
||||
msgstr "Vaciar historial"
|
||||
|
||||
#: buzz/widgets/main_window_toolbar.py buzz/widgets/update_dialog.py
|
||||
msgid "Update Available"
|
||||
msgstr "Actualización disponible"
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "In Progress"
|
||||
msgstr "En Progreso"
|
||||
|
|
@ -765,6 +770,58 @@ msgstr ""
|
|||
"Compruebe sus dispositivos de audio o consulte los registros de la "
|
||||
"aplicación para obtener más información."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "A new version of Buzz is available!"
|
||||
msgstr "¡Hay una nueva versión de Buzz disponible!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Current version:"
|
||||
msgstr "Versión actual:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "New version:"
|
||||
msgstr "Nueva versión:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Release Notes:"
|
||||
msgstr "Notas de la versión:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download and Install"
|
||||
msgstr "Descargar e instalar"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "No download URL available for your platform."
|
||||
msgstr "No hay URL de descarga disponible para su plataforma."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {}..."
|
||||
msgstr "Descargando archivo {} de {}..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {} ({:.1f} MB / {:.1f} MB)..."
|
||||
msgstr "Descargando archivo {} de {} ({:.1f} MB / {:.1f} MB)..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download Failed"
|
||||
msgstr "Descarga fallida"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to download the update: {}"
|
||||
msgstr "Error al descargar la actualización: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to save the installer: {}"
|
||||
msgstr "No se pudo guardar el instalador: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download complete!"
|
||||
msgstr "¡Descarga completa!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to run the installer: {}"
|
||||
msgstr "No se pudo ejecutar el instalador: {}"
|
||||
|
||||
# automatic translation
|
||||
#: buzz/widgets/about_dialog.py
|
||||
msgid "Check for updates"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: buzz\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-02-27 16:46+0200\n"
|
||||
"POT-Creation-Date: 2026-02-28 10:38+0200\n"
|
||||
"PO-Revision-Date: 2026-01-25 21:42+0200\n"
|
||||
"Language-Team: (Italiano) Albano Battistella <albanobattistella@gmail.com>\n"
|
||||
"Language: it_IT\n"
|
||||
|
|
@ -345,7 +345,8 @@ msgid "Download failed"
|
|||
msgstr "Download non riuscito"
|
||||
|
||||
#: buzz/widgets/preferences_dialog/models_preferences_widget.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py buzz/widgets/main_window.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
#: buzz/widgets/update_dialog.py buzz/widgets/main_window.py
|
||||
#: buzz/model_loader.py
|
||||
msgid "Error"
|
||||
msgstr "Errore"
|
||||
|
|
@ -539,6 +540,10 @@ msgstr "Annulla trascrizione"
|
|||
msgid "Clear History"
|
||||
msgstr "Elimina la cronologia"
|
||||
|
||||
#: buzz/widgets/main_window_toolbar.py buzz/widgets/update_dialog.py
|
||||
msgid "Update Available"
|
||||
msgstr "Aggiornamento Disponibile"
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "In Progress"
|
||||
msgstr "In corso"
|
||||
|
|
@ -731,6 +736,58 @@ msgstr ""
|
|||
"Controlla i tuoi dispositivi audio o i registri dell'applicazione per "
|
||||
"maggiori informazioni."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "A new version of Buzz is available!"
|
||||
msgstr "È disponibile una nuova versione di Buzz!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Current version:"
|
||||
msgstr "Versione attuale:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "New version:"
|
||||
msgstr "Nuova versione:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Release Notes:"
|
||||
msgstr "Note di rilascio:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download and Install"
|
||||
msgstr "Scarica e installa"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "No download URL available for your platform."
|
||||
msgstr "Nessun URL di download disponibile per la tua piattaforma."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {}..."
|
||||
msgstr "Download del file {} di {}..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {} ({:.1f} MB / {:.1f} MB)..."
|
||||
msgstr "Download del file {} di {} ({:.1f} MB / {:.1f} MB)..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download Failed"
|
||||
msgstr "Download fallito"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to download the update: {}"
|
||||
msgstr "Impossibile scaricare l'aggiornamento: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to save the installer: {}"
|
||||
msgstr "Impossibile salvare il programma di installazione: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download complete!"
|
||||
msgstr "Download completato!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to run the installer: {}"
|
||||
msgstr "Impossibile eseguire il programma di installazione: {}"
|
||||
|
||||
#: buzz/widgets/about_dialog.py
|
||||
msgid "Check for updates"
|
||||
msgstr "Controlla gli aggiornamenti"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-02-27 16:46+0200\n"
|
||||
"POT-Creation-Date: 2026-02-28 10:38+0200\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: nunawa <71294849+nunawa@users.noreply.github.com>\n"
|
||||
"Language-Team: \n"
|
||||
|
|
@ -338,7 +338,8 @@ msgid "Download failed"
|
|||
msgstr "ダウンロード失敗"
|
||||
|
||||
#: buzz/widgets/preferences_dialog/models_preferences_widget.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py buzz/widgets/main_window.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
#: buzz/widgets/update_dialog.py buzz/widgets/main_window.py
|
||||
#: buzz/model_loader.py
|
||||
msgid "Error"
|
||||
msgstr "エラー"
|
||||
|
|
@ -528,6 +529,10 @@ msgstr "文字起こしをキャンセルする"
|
|||
msgid "Clear History"
|
||||
msgstr "履歴を削除する"
|
||||
|
||||
#: buzz/widgets/main_window_toolbar.py buzz/widgets/update_dialog.py
|
||||
msgid "Update Available"
|
||||
msgstr "アップデートあり"
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "In Progress"
|
||||
msgstr "進行中"
|
||||
|
|
@ -720,6 +725,58 @@ msgstr ""
|
|||
"オーディオデバイスを確認するか、詳細をアプリケーションのログで確認してくださ"
|
||||
"い。"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "A new version of Buzz is available!"
|
||||
msgstr "Buzzの新しいバージョンが利用可能です!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Current version:"
|
||||
msgstr "現在のバージョン:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "New version:"
|
||||
msgstr "新しいバージョン:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Release Notes:"
|
||||
msgstr "リリースノート:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download and Install"
|
||||
msgstr "ダウンロードしてインストール"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "No download URL available for your platform."
|
||||
msgstr "お使いのプラットフォーム向けのダウンロードURLがありません。"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {}..."
|
||||
msgstr "ファイル {} / {} をダウンロード中..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {} ({:.1f} MB / {:.1f} MB)..."
|
||||
msgstr "ファイル {} / {} をダウンロード中 ({:.1f} MB / {:.1f} MB)..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download Failed"
|
||||
msgstr "ダウンロード失敗"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to download the update: {}"
|
||||
msgstr "アップデートのダウンロードに失敗しました: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to save the installer: {}"
|
||||
msgstr "インストーラーの保存に失敗しました: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download complete!"
|
||||
msgstr "ダウンロード完了!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to run the installer: {}"
|
||||
msgstr "インストーラーの実行に失敗しました: {}"
|
||||
|
||||
#: buzz/widgets/about_dialog.py
|
||||
msgid "Check for updates"
|
||||
msgstr "アップデートを確認する"
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-02-27 16:46+0200\n"
|
||||
"PO-Revision-Date: 2026-02-27 16:47+0200\n"
|
||||
"POT-Creation-Date: 2026-02-28 10:38+0200\n"
|
||||
"PO-Revision-Date: 2026-02-28 10:46+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: lv_LV\n"
|
||||
|
|
@ -186,7 +186,7 @@ msgid ""
|
|||
"in the Live Recording screen in a future version."
|
||||
msgstr ""
|
||||
"Piezīme: Dzīvā ieraksta iestatījumi nākotnes Buzz versijās tiks pārvietoti "
|
||||
"uz Papildu iestatījumu sadaļu Dzīvā ieraksta logā"
|
||||
"uz Papildu iestatījumu sadaļu Dzīvā ieraksta logā."
|
||||
|
||||
#: buzz/widgets/preferences_dialog/general_preferences_widget.py
|
||||
msgid "Use 8-bit quantization to reduce memory usage"
|
||||
|
|
@ -346,7 +346,8 @@ msgid "Download failed"
|
|||
msgstr "Lejupielāde neizdevās"
|
||||
|
||||
#: buzz/widgets/preferences_dialog/models_preferences_widget.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py buzz/widgets/main_window.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
#: buzz/widgets/update_dialog.py buzz/widgets/main_window.py
|
||||
#: buzz/model_loader.py
|
||||
msgid "Error"
|
||||
msgstr "Kļūda"
|
||||
|
|
@ -540,6 +541,10 @@ msgstr "Atcelt atpazīšanu"
|
|||
msgid "Clear History"
|
||||
msgstr "Notīrīt vēsturi"
|
||||
|
||||
#: buzz/widgets/main_window_toolbar.py buzz/widgets/update_dialog.py
|
||||
msgid "Update Available"
|
||||
msgstr "Pieejams atjauninājums"
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "In Progress"
|
||||
msgstr "Apstrādā"
|
||||
|
|
@ -731,6 +736,58 @@ msgstr ""
|
|||
"Lūdzu pārbaudiet savas audio ierīces vai pārbaudiet lietotnes ziņojumu "
|
||||
"žurnālus, lai iegūtu papildu informāciju."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "A new version of Buzz is available!"
|
||||
msgstr "Pieejama jauna Buzz versija!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Current version:"
|
||||
msgstr "Instalētā versija:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "New version:"
|
||||
msgstr "Jaunā versija:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Release Notes:"
|
||||
msgstr "Jaunās versijas piezīmes:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download and Install"
|
||||
msgstr "Lejupielādēt un instalēt"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "No download URL available for your platform."
|
||||
msgstr "Jūsu datoram nav pieejama atjauninājum versija."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {}..."
|
||||
msgstr "Lejupielādē {} no {}..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {} ({:.1f} MB / {:.1f} MB)..."
|
||||
msgstr "Lejupielādē {} no {} ({:.1f} MB / {:.1f} MB)..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download Failed"
|
||||
msgstr "Lejupielāde neizdevās"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to download the update: {}"
|
||||
msgstr "Neizdevās lejupielādēt atjauninājumu: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to save the installer: {}"
|
||||
msgstr "Neizdevās saglabāt atjauninājumu: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download complete!"
|
||||
msgstr "Lejupielāde pabeigta!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to run the installer: {}"
|
||||
msgstr "Neizdevās sākt atjauninājumu: {}"
|
||||
|
||||
#: buzz/widgets/about_dialog.py
|
||||
msgid "Check for updates"
|
||||
msgstr "Pārbaudīt atjauninājumus"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-02-27 16:46+0200\n"
|
||||
"POT-Creation-Date: 2026-02-28 10:38+0200\n"
|
||||
"PO-Revision-Date: 2025-03-20 18:30+0100\n"
|
||||
"Last-Translator: Heimen Stoffels <vistausss@fastmail.com>\n"
|
||||
"Language-Team: none\n"
|
||||
|
|
@ -347,7 +347,8 @@ msgid "Download failed"
|
|||
msgstr "Het downloaden is mislukt"
|
||||
|
||||
#: buzz/widgets/preferences_dialog/models_preferences_widget.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py buzz/widgets/main_window.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
#: buzz/widgets/update_dialog.py buzz/widgets/main_window.py
|
||||
#: buzz/model_loader.py
|
||||
msgid "Error"
|
||||
msgstr "Foutmelding"
|
||||
|
|
@ -540,6 +541,10 @@ msgstr "Transcriptie wissen"
|
|||
msgid "Clear History"
|
||||
msgstr "Geschiedenis wissen"
|
||||
|
||||
#: buzz/widgets/main_window_toolbar.py buzz/widgets/update_dialog.py
|
||||
msgid "Update Available"
|
||||
msgstr "Update Beschikbaar"
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "In Progress"
|
||||
msgstr "In behandeling"
|
||||
|
|
@ -733,6 +738,58 @@ msgid ""
|
|||
"information."
|
||||
msgstr "Controleer uw geluidsapparatuur of het programmalogboek."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "A new version of Buzz is available!"
|
||||
msgstr "Er is een nieuwe versie van Buzz beschikbaar!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Current version:"
|
||||
msgstr "Huidige versie:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "New version:"
|
||||
msgstr "Versie:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Release Notes:"
|
||||
msgstr "Release-opmerkingen:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download and Install"
|
||||
msgstr "Downloaden en installeren"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "No download URL available for your platform."
|
||||
msgstr "Geen download-URL beschikbaar voor uw platform."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {}..."
|
||||
msgstr "Bestand {} van {} downloaden..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {} ({:.1f} MB / {:.1f} MB)..."
|
||||
msgstr "Bestand {} van {} downloaden ({:.1f} MB / {:.1f} MB)..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download Failed"
|
||||
msgstr "Download mislukt"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to download the update: {}"
|
||||
msgstr "Het downloaden van de update is mislukt: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to save the installer: {}"
|
||||
msgstr "Kan het installatieprogramma niet opslaan: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download complete!"
|
||||
msgstr "Download voltooid!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to run the installer: {}"
|
||||
msgstr "Kan het installatieprogramma niet uitvoeren: {}"
|
||||
|
||||
#: buzz/widgets/about_dialog.py
|
||||
msgid "Check for updates"
|
||||
msgstr "Controleren op updates"
|
||||
|
|
@ -1602,6 +1659,3 @@ msgstr ""
|
|||
|
||||
#~ msgid "Enter instructions for AI on how to translate..."
|
||||
#~ msgstr "Voer vertaalinstructies in…"
|
||||
|
||||
#~ msgid "Version"
|
||||
#~ msgstr "Versie"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-02-27 16:46+0200\n"
|
||||
"POT-Creation-Date: 2026-02-28 10:38+0200\n"
|
||||
"PO-Revision-Date: 2024-03-17 20:50+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
|
|
@ -344,7 +344,8 @@ msgid "Download failed"
|
|||
msgstr "Pobieranie nie powiodło się"
|
||||
|
||||
#: buzz/widgets/preferences_dialog/models_preferences_widget.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py buzz/widgets/main_window.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
#: buzz/widgets/update_dialog.py buzz/widgets/main_window.py
|
||||
#: buzz/model_loader.py
|
||||
msgid "Error"
|
||||
msgstr "Błąd"
|
||||
|
|
@ -534,6 +535,10 @@ msgstr "Anuluj transkrypcję"
|
|||
msgid "Clear History"
|
||||
msgstr "Wyczyść historię"
|
||||
|
||||
#: buzz/widgets/main_window_toolbar.py buzz/widgets/update_dialog.py
|
||||
msgid "Update Available"
|
||||
msgstr "Dostępna aktualizacja"
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "In Progress"
|
||||
msgstr "W toku"
|
||||
|
|
@ -729,6 +734,58 @@ msgstr ""
|
|||
"Sprawdź urządzenia audio lub przejrzyj logi aplikacji, by uzyskać więcej "
|
||||
"informacji."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "A new version of Buzz is available!"
|
||||
msgstr "Dostępna jest nowa wersja Buzz!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Current version:"
|
||||
msgstr "Aktualna wersja:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "New version:"
|
||||
msgstr "Nowa wersja:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Release Notes:"
|
||||
msgstr "Informacje o wydaniu:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download and Install"
|
||||
msgstr "Pobierz i zainstaluj"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "No download URL available for your platform."
|
||||
msgstr "Brak adresu URL do pobrania dla Twojej platformy."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {}..."
|
||||
msgstr "Pobieranie pliku {} z {}..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {} ({:.1f} MB / {:.1f} MB)..."
|
||||
msgstr "Pobieranie pliku {} z {} ({:.1f} MB / {:.1f} MB)..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download Failed"
|
||||
msgstr "Pobieranie nie powiodło się"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to download the update: {}"
|
||||
msgstr "Nie udało się pobrać aktualizacji: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to save the installer: {}"
|
||||
msgstr "Nie udało się zapisać instalatora: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download complete!"
|
||||
msgstr "Pobieranie zakończone!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to run the installer: {}"
|
||||
msgstr "Nie udało się uruchomić instalatora: {}"
|
||||
|
||||
#: buzz/widgets/about_dialog.py
|
||||
msgid "Check for updates"
|
||||
msgstr "Sprawdź aktualizacje"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: Buzz\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-02-27 09:07+0200\n"
|
||||
"POT-Creation-Date: 2026-02-28 10:41+0200\n"
|
||||
"PO-Revision-Date: 2025-11-01 17:43-0300\n"
|
||||
"Last-Translator: Paulo Schopf <pschopf@gmail.com>\n"
|
||||
"Language-Team: none\n"
|
||||
|
|
@ -343,7 +343,8 @@ msgid "Download failed"
|
|||
msgstr "Falha ao baixar"
|
||||
|
||||
#: buzz/widgets/preferences_dialog/models_preferences_widget.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py buzz/widgets/main_window.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
#: buzz/widgets/update_dialog.py buzz/widgets/main_window.py
|
||||
#: buzz/model_loader.py
|
||||
msgid "Error"
|
||||
msgstr "Erro"
|
||||
|
|
@ -438,7 +439,8 @@ msgstr "Modelo de IA:"
|
|||
|
||||
#: buzz/widgets/transcriber/advanced_settings_dialog.py
|
||||
msgid "Please translate each text sent to you from English to Spanish."
|
||||
msgstr "Por favor, traduza cada texto enviado a você do Inglês para o Espanhol."
|
||||
msgstr ""
|
||||
"Por favor, traduza cada texto enviado a você do Inglês para o Espanhol."
|
||||
|
||||
#: buzz/widgets/transcriber/advanced_settings_dialog.py
|
||||
msgid "Instructions for AI:"
|
||||
|
|
@ -533,6 +535,10 @@ msgstr "Cancelar Transcrição"
|
|||
msgid "Clear History"
|
||||
msgstr "Limpar Histórico"
|
||||
|
||||
#: buzz/widgets/main_window_toolbar.py buzz/widgets/update_dialog.py
|
||||
msgid "Update Available"
|
||||
msgstr "Atualização Disponível"
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "In Progress"
|
||||
msgstr "Em Progresso"
|
||||
|
|
@ -626,12 +632,14 @@ msgid ""
|
|||
"Could not restart transcription: model not available and could not be "
|
||||
"downloaded."
|
||||
msgstr ""
|
||||
"Não foi possível reiniciar a transcrição: o modelo não está disponível e "
|
||||
"não pôde ser baixado."
|
||||
"Não foi possível reiniciar a transcrição: o modelo não está disponível e não "
|
||||
"pôde ser baixado."
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "Could not restart transcription: transcriber worker not found."
|
||||
msgstr "Não foi possível reiniciar a transcrição: trabalhador de transcrição não encontrado."
|
||||
msgstr ""
|
||||
"Não foi possível reiniciar a transcrição: trabalhador de transcrição não "
|
||||
"encontrado."
|
||||
|
||||
#: buzz/widgets/recording_transcriber_widget.py
|
||||
msgid "Live Recording"
|
||||
|
|
@ -725,6 +733,58 @@ msgstr ""
|
|||
"Verifique seus dispositivos de áudio ou os logs do aplicativo para mais "
|
||||
"informações."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "A new version of Buzz is available!"
|
||||
msgstr "Uma nova versão do Buzz está disponível!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Current version:"
|
||||
msgstr "Versão atual:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "New version:"
|
||||
msgstr "Nova versão:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Release Notes:"
|
||||
msgstr "Notas de Versão:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download and Install"
|
||||
msgstr "Baixar e instalar"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "No download URL available for your platform."
|
||||
msgstr "Nenhuma URL de download disponível para sua plataforma."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {}..."
|
||||
msgstr "Baixando arquivo {} de {}..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {} ({:.1f} MB / {:.1f} MB)..."
|
||||
msgstr "Baixando arquivo {} de {} ({:.1f} MB / {:.1f} MB)..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download Failed"
|
||||
msgstr "Falha no download"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to download the update: {}"
|
||||
msgstr "Falha ao baixar a atualização: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to save the installer: {}"
|
||||
msgstr "Falha ao salvar o instalador: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download complete!"
|
||||
msgstr "Download concluído!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to run the installer: {}"
|
||||
msgstr "Falha ao executar o instalador: {}"
|
||||
|
||||
#: buzz/widgets/about_dialog.py
|
||||
msgid "Check for updates"
|
||||
msgstr "Verificar atualizações"
|
||||
|
|
@ -900,7 +960,9 @@ msgstr "Duração desejada da legenda"
|
|||
|
||||
#: buzz/widgets/transcription_viewer/transcription_resizer_widget.py
|
||||
msgid "Available only if word level timings were disabled during transcription"
|
||||
msgstr "Disponível apenas se os tempos em nível de palavra foram desabilitados durante a transcrição"
|
||||
msgstr ""
|
||||
"Disponível apenas se os tempos em nível de palavra foram desabilitados "
|
||||
"durante a transcrição"
|
||||
|
||||
#: buzz/widgets/transcription_viewer/transcription_resizer_widget.py
|
||||
msgid "Merge Options"
|
||||
|
|
@ -924,7 +986,9 @@ msgstr "Mesclar"
|
|||
|
||||
#: buzz/widgets/transcription_viewer/transcription_resizer_widget.py
|
||||
msgid "Available only if word level timings were enabled during transcription"
|
||||
msgstr "Disponível apenas se os tempos em nível de palavra foram habilitados durante a transcrição"
|
||||
msgstr ""
|
||||
"Disponível apenas se os tempos em nível de palavra foram habilitados durante "
|
||||
"a transcrição"
|
||||
|
||||
#: buzz/widgets/transcription_viewer/speaker_identification_widget.py
|
||||
msgid ""
|
||||
|
|
@ -1557,10 +1621,6 @@ msgstr "Acrescentar acima"
|
|||
msgid "Append and correct"
|
||||
msgstr "Acrescentar e corrigir"
|
||||
|
||||
#: buzz/translator.py
|
||||
msgid "Translation error, see logs!"
|
||||
msgstr "Erro de tradução, verifique os logs!"
|
||||
|
||||
#: buzz/file_transcriber_queue_worker.py
|
||||
msgid ""
|
||||
"Speech extraction failed! Check your internet connection — a model may need "
|
||||
|
|
@ -1569,6 +1629,9 @@ msgstr ""
|
|||
"Falha na extração de fala! Verifique sua conexão com a internet — pode ser "
|
||||
"necessário baixar um modelo."
|
||||
|
||||
#~ msgid "Translation error, see logs!"
|
||||
#~ msgstr "Erro de tradução, verifique os logs!"
|
||||
|
||||
#~ msgid "Snap permission notice"
|
||||
#~ msgstr "Aviso de permissão do Snap"
|
||||
|
||||
|
|
@ -1596,5 +1659,3 @@ msgstr ""
|
|||
|
||||
#~ msgid "Undo"
|
||||
#~ msgstr "Desfazer"
|
||||
|
||||
#~ msgid "Redo"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-02-27 16:46+0200\n"
|
||||
"POT-Creation-Date: 2026-02-28 10:41+0200\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Yevhen Popok <xalt7x.service@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
|
|
@ -340,7 +340,8 @@ msgid "Download failed"
|
|||
msgstr "Невдале завантаження"
|
||||
|
||||
#: buzz/widgets/preferences_dialog/models_preferences_widget.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py buzz/widgets/main_window.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
#: buzz/widgets/update_dialog.py buzz/widgets/main_window.py
|
||||
#: buzz/model_loader.py
|
||||
msgid "Error"
|
||||
msgstr "Помилка"
|
||||
|
|
@ -532,6 +533,10 @@ msgstr "Скасувати транскрипцію"
|
|||
msgid "Clear History"
|
||||
msgstr "Очистити історію"
|
||||
|
||||
#: buzz/widgets/main_window_toolbar.py buzz/widgets/update_dialog.py
|
||||
msgid "Update Available"
|
||||
msgstr "Доступне оновлення"
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "In Progress"
|
||||
msgstr "В процесі"
|
||||
|
|
@ -725,6 +730,58 @@ msgstr ""
|
|||
"Будь ласка, перевірте свої аудіопристрої або пошукайте додаткову інформацію "
|
||||
"в звітах програми."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "A new version of Buzz is available!"
|
||||
msgstr "Доступна нова версія Buzz!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Current version:"
|
||||
msgstr "Поточна версія:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "New version:"
|
||||
msgstr "Нова версія:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Release Notes:"
|
||||
msgstr "Примітки до випуску:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download and Install"
|
||||
msgstr "Завантажити та встановити"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "No download URL available for your platform."
|
||||
msgstr "Посилання для завантаження для вашої платформи відсутнє."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {}..."
|
||||
msgstr "Завантаження файлу {} з {}..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {} ({:.1f} MB / {:.1f} MB)..."
|
||||
msgstr "Завантаження файлу {} з {} ({:.1f} МБ / {:.1f} МБ)..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download Failed"
|
||||
msgstr "Помилка завантаження"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to download the update: {}"
|
||||
msgstr "Не вдалося завантажити оновлення: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to save the installer: {}"
|
||||
msgstr "Не вдалося зберегти інсталятор: {}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download complete!"
|
||||
msgstr "Завантаження завершено!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to run the installer: {}"
|
||||
msgstr "Не вдалося запустити інсталятор: {}"
|
||||
|
||||
#: buzz/widgets/about_dialog.py
|
||||
msgid "Check for updates"
|
||||
msgstr "Перевірити оновлення"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-02-27 16:46+0200\n"
|
||||
"POT-Creation-Date: 2026-02-28 10:41+0200\n"
|
||||
"PO-Revision-Date: 2023-05-01 15:45+0800\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: lamb \n"
|
||||
|
|
@ -336,7 +336,8 @@ msgid "Download failed"
|
|||
msgstr "下载失败"
|
||||
|
||||
#: buzz/widgets/preferences_dialog/models_preferences_widget.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py buzz/widgets/main_window.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
#: buzz/widgets/update_dialog.py buzz/widgets/main_window.py
|
||||
#: buzz/model_loader.py
|
||||
msgid "Error"
|
||||
msgstr "错误"
|
||||
|
|
@ -526,6 +527,10 @@ msgstr "取消识别"
|
|||
msgid "Clear History"
|
||||
msgstr "清除历史纪录"
|
||||
|
||||
#: buzz/widgets/main_window_toolbar.py buzz/widgets/update_dialog.py
|
||||
msgid "Update Available"
|
||||
msgstr "有可用更新"
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "In Progress"
|
||||
msgstr "运行中"
|
||||
|
|
@ -714,6 +719,58 @@ msgid ""
|
|||
"information."
|
||||
msgstr "请检查您的音频设备或检查应用程序日志以获取更多信息。"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "A new version of Buzz is available!"
|
||||
msgstr "Buzz 有新版本可用!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Current version:"
|
||||
msgstr "当前版本:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "New version:"
|
||||
msgstr "新版本:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Release Notes:"
|
||||
msgstr "发行说明:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download and Install"
|
||||
msgstr "下载并安装"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "No download URL available for your platform."
|
||||
msgstr "您的平台没有可用的下载链接。"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {}..."
|
||||
msgstr "正在下载第 {} 个文件,共 {} 个..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {} ({:.1f} MB / {:.1f} MB)..."
|
||||
msgstr "正在下载第 {} 个文件,共 {} 个({:.1f} MB / {:.1f} MB)..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download Failed"
|
||||
msgstr "下载失败"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to download the update: {}"
|
||||
msgstr "下载更新失败:{}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to save the installer: {}"
|
||||
msgstr "无法保存安装程序:{}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download complete!"
|
||||
msgstr "下载完成!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to run the installer: {}"
|
||||
msgstr "无法运行安装程序:{}"
|
||||
|
||||
#: buzz/widgets/about_dialog.py
|
||||
msgid "Check for updates"
|
||||
msgstr "检查更新"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-02-27 16:46+0200\n"
|
||||
"POT-Creation-Date: 2026-02-28 10:41+0200\n"
|
||||
"PO-Revision-Date: 2023-05-01 15:45+0800\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Lamb\n"
|
||||
|
|
@ -337,7 +337,8 @@ msgid "Download failed"
|
|||
msgstr "下載失敗"
|
||||
|
||||
#: buzz/widgets/preferences_dialog/models_preferences_widget.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py buzz/widgets/main_window.py
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
#: buzz/widgets/update_dialog.py buzz/widgets/main_window.py
|
||||
#: buzz/model_loader.py
|
||||
msgid "Error"
|
||||
msgstr "錯誤"
|
||||
|
|
@ -527,6 +528,10 @@ msgstr "取消錄製"
|
|||
msgid "Clear History"
|
||||
msgstr "清除歷史紀錄"
|
||||
|
||||
#: buzz/widgets/main_window_toolbar.py buzz/widgets/update_dialog.py
|
||||
msgid "Update Available"
|
||||
msgstr "有可用更新"
|
||||
|
||||
#: buzz/widgets/transcription_tasks_table_widget.py
|
||||
msgid "In Progress"
|
||||
msgstr "進行中"
|
||||
|
|
@ -715,6 +720,58 @@ msgid ""
|
|||
"information."
|
||||
msgstr "請檢查您的音頻設備或檢查應用程序日誌以獲取更多信息。"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "A new version of Buzz is available!"
|
||||
msgstr "Buzz 有新版本可用!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Current version:"
|
||||
msgstr "目前版本:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "New version:"
|
||||
msgstr "新版本:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Release Notes:"
|
||||
msgstr "版本說明:"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download and Install"
|
||||
msgstr "下載並安裝"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "No download URL available for your platform."
|
||||
msgstr "您的平台沒有可用的下載連結。"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {}..."
|
||||
msgstr "正在下載第 {} 個檔案,共 {} 個..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Downloading file {} of {} ({:.1f} MB / {:.1f} MB)..."
|
||||
msgstr "正在下載第 {} 個檔案,共 {} 個({:.1f} MB / {:.1f} MB)..."
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download Failed"
|
||||
msgstr "下載失敗"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to download the update: {}"
|
||||
msgstr "下載更新失敗:{}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to save the installer: {}"
|
||||
msgstr "無法儲存安裝程式:{}"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Download complete!"
|
||||
msgstr "下載完成!"
|
||||
|
||||
#: buzz/widgets/update_dialog.py
|
||||
msgid "Failed to run the installer: {}"
|
||||
msgstr "無法執行安裝程式:{}"
|
||||
|
||||
#: buzz/widgets/about_dialog.py
|
||||
msgid "Check for updates"
|
||||
msgstr "檢查更新"
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ class Settings:
|
|||
FORCE_CPU = "force-cpu"
|
||||
REDUCE_GPU_MEMORY = "reduce-gpu-memory"
|
||||
|
||||
LAST_UPDATE_CHECK = "update/last-check"
|
||||
UPDATE_AVAILABLE_VERSION = "update/available-version"
|
||||
|
||||
def get_user_identifier(self) -> str:
|
||||
user_id = self.value(self.Key.USER_IDENTIFIER, "")
|
||||
if not user_id:
|
||||
|
|
|
|||
163
buzz/update_checker.py
Normal file
163
buzz/update_checker.py
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
import json
|
||||
import logging
|
||||
import platform
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from dataclasses import dataclass
|
||||
|
||||
from PyQt6.QtCore import QObject, pyqtSignal, QUrl
|
||||
from PyQt6.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
|
||||
from buzz.__version__ import VERSION
|
||||
from buzz.settings.settings import Settings
|
||||
|
||||
|
||||
@dataclass
|
||||
class UpdateInfo:
|
||||
version: str
|
||||
release_notes: str
|
||||
download_urls: list
|
||||
|
||||
class UpdateChecker(QObject):
|
||||
update_available = pyqtSignal(object)
|
||||
|
||||
VERSION_JSON_URL = "https://github.com/chidiwilliams/buzz/releases/latest/download/version_info.json"
|
||||
|
||||
CHECK_INTERVAL_DAYS = 7
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
settings: Settings,
|
||||
network_manager: Optional[QNetworkAccessManager] = None,
|
||||
parent: Optional[QObject] = None
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
self.settings = settings
|
||||
|
||||
if network_manager is None:
|
||||
network_manager = QNetworkAccessManager(self)
|
||||
self.network_manager = network_manager
|
||||
self.network_manager.finished.connect(self._on_reply_finished)
|
||||
|
||||
def should_check_for_updates(self) -> bool:
|
||||
"""Check if we are on Windows/macOS and if 7 days passed"""
|
||||
system = platform.system()
|
||||
if system not in ("Windows", "Darwin"):
|
||||
logging.debug("Skipping update check on linux")
|
||||
return False
|
||||
|
||||
last_check = self.settings.value(
|
||||
Settings.Key.LAST_UPDATE_CHECK,
|
||||
"",
|
||||
)
|
||||
|
||||
if last_check:
|
||||
try:
|
||||
last_check_date = datetime.fromisoformat(last_check)
|
||||
days_since_check = (datetime.now() - last_check_date).days
|
||||
if days_since_check < self.CHECK_INTERVAL_DAYS:
|
||||
logging.debug(
|
||||
f"Skipping update check, last checked {days_since_check} days ago"
|
||||
)
|
||||
return False
|
||||
except ValueError:
|
||||
#Invalid date format
|
||||
pass
|
||||
|
||||
return True
|
||||
|
||||
def check_for_updates(self) -> None:
|
||||
"""Start the network request"""
|
||||
if not self.should_check_for_updates():
|
||||
return
|
||||
|
||||
logging.info("Checking for updates...")
|
||||
|
||||
url = QUrl(self.VERSION_JSON_URL)
|
||||
request = QNetworkRequest(url)
|
||||
self.network_manager.get(request)
|
||||
|
||||
def _on_reply_finished(self, reply: QNetworkReply) -> None:
|
||||
"""Handles the network reply for version.json fetch"""
|
||||
self.settings.set_value(
|
||||
Settings.Key.LAST_UPDATE_CHECK,
|
||||
datetime.now().isoformat()
|
||||
)
|
||||
|
||||
if reply.error() != QNetworkReply.NetworkError.NoError:
|
||||
error_msg = f"Failed to check for updates: {reply.errorString()}"
|
||||
logging.error(error_msg)
|
||||
reply.deleteLater()
|
||||
return
|
||||
|
||||
try:
|
||||
data = json.loads(reply.readAll().data().decode("utf-8"))
|
||||
reply.deleteLater()
|
||||
|
||||
remote_version = data.get("version", "")
|
||||
release_notes = data.get("release_notes", "")
|
||||
download_urls = data.get("download_urls", {})
|
||||
|
||||
#Get the download url for current platform
|
||||
download_url = self._get_download_url(download_urls)
|
||||
|
||||
if self._is_newer_version(remote_version):
|
||||
logging.info(f"Update available: {remote_version}")
|
||||
|
||||
#Store the available version
|
||||
self.settings.set_value(
|
||||
Settings.Key.UPDATE_AVAILABLE_VERSION,
|
||||
remote_version
|
||||
)
|
||||
|
||||
update_info = UpdateInfo(
|
||||
version=remote_version,
|
||||
release_notes=release_notes,
|
||||
download_urls=download_url
|
||||
)
|
||||
self.update_available.emit(update_info)
|
||||
|
||||
else:
|
||||
logging.info("No update available")
|
||||
self.settings.set_value(
|
||||
Settings.Key.UPDATE_AVAILABLE_VERSION,
|
||||
""
|
||||
)
|
||||
|
||||
except (json.JSONDecodeError, KeyError) as e:
|
||||
error_msg = f"Failed to parse version info: {e}"
|
||||
logging.error(error_msg)
|
||||
|
||||
def _get_download_url(self, download_urls: dict) -> list:
|
||||
system = platform.system()
|
||||
machine = platform.machine().lower()
|
||||
|
||||
if system == "Windows":
|
||||
urls = download_urls.get("windows_x64", [])
|
||||
elif system == "Darwin":
|
||||
if machine in ("arm64", "aarch64"):
|
||||
urls = download_urls.get("macos_arm", [])
|
||||
else:
|
||||
urls = download_urls.get("macos_x86", [])
|
||||
else:
|
||||
urls = []
|
||||
|
||||
return urls if isinstance(urls, list) else [urls]
|
||||
|
||||
def _is_newer_version(self, remote_version: str) -> bool:
|
||||
"""Compare remote version with current version"""
|
||||
try:
|
||||
current_parts = [int(x) for x in VERSION.split(".")]
|
||||
remote_parts = [int(x) for x in remote_version.split(".")]
|
||||
|
||||
#pad with zeros if needed
|
||||
while len(current_parts) < len(remote_parts):
|
||||
current_parts.append(0)
|
||||
while len(remote_parts) < len(current_parts):
|
||||
remote_parts.append(0)
|
||||
|
||||
return remote_parts > current_parts
|
||||
|
||||
except ValueError:
|
||||
logging.error(f"Invalid version format: {VERSION} or {remote_version}")
|
||||
return False
|
||||
|
|
@ -129,3 +129,4 @@ ADD_ICON_PATH = get_path("assets/add_FILL0_wght700_GRAD0_opsz48.svg")
|
|||
URL_ICON_PATH = get_path("assets/url.svg")
|
||||
TRASH_ICON_PATH = get_path("assets/delete_FILL0_wght700_GRAD0_opsz48.svg")
|
||||
CANCEL_ICON_PATH = get_path("assets/cancel_FILL0_wght700_GRAD0_opsz48.svg")
|
||||
UPDATE_ICON_PATH = get_path("assets/update_FILL0_wght700_GRAD0_opsz48.svg")
|
||||
|
|
@ -24,6 +24,8 @@ from buzz.db.service.transcription_service import TranscriptionService
|
|||
from buzz.file_transcriber_queue_worker import FileTranscriberQueueWorker
|
||||
from buzz.locale import _
|
||||
from buzz.settings.settings import APP_NAME, Settings
|
||||
from buzz.update_checker import UpdateChecker, UpdateInfo
|
||||
from buzz.widgets.update_dialog import UpdateDialog
|
||||
from buzz.settings.shortcuts import Shortcuts
|
||||
from buzz.store.keyring_store import set_password, Key
|
||||
from buzz.transcriber.transcriber import (
|
||||
|
|
@ -70,6 +72,9 @@ class MainWindow(QMainWindow):
|
|||
self.quit_on_complete = False
|
||||
self.transcription_service = transcription_service
|
||||
|
||||
#update checker
|
||||
self._update_info: Optional[UpdateInfo] = None
|
||||
|
||||
self.toolbar = MainWindowToolbar(shortcuts=self.shortcuts, parent=self)
|
||||
self.toolbar.new_transcription_action_triggered.connect(
|
||||
self.on_new_transcription_action_triggered
|
||||
|
|
@ -87,6 +92,7 @@ class MainWindow(QMainWindow):
|
|||
self.on_stop_transcription_action_triggered
|
||||
)
|
||||
self.addToolBar(self.toolbar)
|
||||
self.toolbar.update_action_triggered.connect(self.on_update_action_triggered)
|
||||
self.setUnifiedTitleAndToolBarOnMac(True)
|
||||
|
||||
self.preferences = self.load_preferences(settings=self.settings)
|
||||
|
|
@ -156,6 +162,9 @@ class MainWindow(QMainWindow):
|
|||
|
||||
self.transcription_viewer_widget = None
|
||||
|
||||
#Initialize and run update checker
|
||||
self._init_update_checker()
|
||||
|
||||
def on_preferences_changed(self, preferences: Preferences):
|
||||
self.preferences = preferences
|
||||
self.save_preferences(preferences)
|
||||
|
|
@ -493,3 +502,27 @@ class MainWindow(QMainWindow):
|
|||
self.setBaseSize(1240, 600)
|
||||
self.resize(1240, 600)
|
||||
self.settings.end_group()
|
||||
|
||||
def _init_update_checker(self):
|
||||
"""Initializes and runs the update checker."""
|
||||
self.update_checker = UpdateChecker(settings=self.settings, parent=self)
|
||||
self.update_checker.update_available.connect(self._on_update_available)
|
||||
|
||||
# Check for updates on startup
|
||||
self.update_checker.check_for_updates()
|
||||
|
||||
def _on_update_available(self, update_info: UpdateInfo):
|
||||
"""Called when an update is available."""
|
||||
self._update_info = update_info
|
||||
self.toolbar.set_update_available(True)
|
||||
|
||||
def on_update_action_triggered(self):
|
||||
"""Called when user clicks the update action in toolbar."""
|
||||
if self._update_info is None:
|
||||
return
|
||||
|
||||
dialog = UpdateDialog(
|
||||
update_info=self._update_info,
|
||||
parent=self
|
||||
)
|
||||
dialog.exec()
|
||||
|
|
@ -16,6 +16,7 @@ from buzz.widgets.icon import (
|
|||
EXPAND_ICON_PATH,
|
||||
CANCEL_ICON_PATH,
|
||||
TRASH_ICON_PATH,
|
||||
UPDATE_ICON_PATH,
|
||||
)
|
||||
from buzz.widgets.recording_transcriber_widget import RecordingTranscriberWidget
|
||||
from buzz.widgets.toolbar import ToolBar
|
||||
|
|
@ -26,6 +27,7 @@ class MainWindowToolbar(ToolBar):
|
|||
new_url_transcription_action_triggered: pyqtSignal
|
||||
open_transcript_action_triggered: pyqtSignal
|
||||
clear_history_action_triggered: pyqtSignal
|
||||
update_action_triggered: pyqtSignal
|
||||
ICON_LIGHT_THEME_BACKGROUND = "#555"
|
||||
ICON_DARK_THEME_BACKGROUND = "#AAA"
|
||||
|
||||
|
|
@ -70,6 +72,13 @@ class MainWindowToolbar(ToolBar):
|
|||
self.clear_history_action = Action(
|
||||
Icon(TRASH_ICON_PATH, self), _("Clear History"), self
|
||||
)
|
||||
|
||||
self.update_action = Action(
|
||||
Icon(UPDATE_ICON_PATH, self), _("Update Available"), self
|
||||
)
|
||||
self.update_action_triggered = self.update_action.triggered
|
||||
self.update_action.setVisible(False)
|
||||
|
||||
self.clear_history_action_triggered = self.clear_history_action.triggered
|
||||
self.clear_history_action.setDisabled(True)
|
||||
|
||||
|
|
@ -86,6 +95,10 @@ class MainWindowToolbar(ToolBar):
|
|||
self.clear_history_action,
|
||||
]
|
||||
)
|
||||
|
||||
self.addSeparator()
|
||||
self.addAction(self.update_action)
|
||||
|
||||
self.setMovable(False)
|
||||
self.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
||||
|
||||
|
|
@ -114,3 +127,7 @@ class MainWindowToolbar(ToolBar):
|
|||
|
||||
def set_clear_history_action_enabled(self, enabled: bool):
|
||||
self.clear_history_action.setEnabled(enabled)
|
||||
|
||||
def set_update_available(self, available: bool):
|
||||
"""Shows or hides the update action in the toolbar."""
|
||||
self.update_action.setVisible(available)
|
||||
|
|
|
|||
262
buzz/widgets/update_dialog.py
Normal file
262
buzz/widgets/update_dialog.py
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
import logging
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
import tempfile
|
||||
from typing import Optional
|
||||
|
||||
from PyQt6.QtCore import Qt, QUrl
|
||||
from PyQt6.QtWidgets import QApplication
|
||||
from PyQt6.QtGui import QIcon
|
||||
from PyQt6.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
|
||||
from PyQt6.QtWidgets import (
|
||||
QDialog,
|
||||
QVBoxLayout,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QPushButton,
|
||||
QProgressBar,
|
||||
QMessageBox,
|
||||
QWidget,
|
||||
QTextEdit,
|
||||
)
|
||||
|
||||
from buzz.__version__ import VERSION
|
||||
from buzz.locale import _
|
||||
from buzz.update_checker import UpdateInfo
|
||||
from buzz.widgets.icon import BUZZ_ICON_PATH
|
||||
|
||||
class UpdateDialog(QDialog):
|
||||
"""Dialog shows when an update is available"""
|
||||
def __init__(
|
||||
self,
|
||||
update_info: UpdateInfo,
|
||||
network_manager: Optional[QNetworkAccessManager] = None,
|
||||
parent: Optional[QWidget] = None
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
self.update_info = update_info
|
||||
|
||||
if network_manager is None:
|
||||
network_manager = QNetworkAccessManager(self)
|
||||
self.network_manager = network_manager
|
||||
|
||||
self._download_reply: Optional[QNetworkReply] = None
|
||||
self._temp_file_paths: list = []
|
||||
self._pending_urls: list = []
|
||||
self._temp_dir: Optional[str] = None
|
||||
|
||||
self._setup_ui()
|
||||
|
||||
def _setup_ui(self):
|
||||
self.setWindowTitle(_("Update Available"))
|
||||
self.setWindowIcon(QIcon(BUZZ_ICON_PATH))
|
||||
self.setMinimumWidth(450)
|
||||
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setSpacing(16)
|
||||
|
||||
#header
|
||||
header_label = QLabel(
|
||||
_("A new version of Buzz is available!")
|
||||
)
|
||||
|
||||
header_label.setStyleSheet("font-size: 16px; font-weight: bold;")
|
||||
layout.addWidget(header_label)
|
||||
|
||||
#Version info
|
||||
version_layout = QHBoxLayout()
|
||||
|
||||
current_version_label = QLabel(_("Current version:"))
|
||||
current_version_value = QLabel(f"<b>{VERSION}</b>")
|
||||
|
||||
new_version_label = QLabel(_("New version:"))
|
||||
new_version_value = QLabel(f"<b>{self.update_info.version}</b>")
|
||||
|
||||
version_layout.addWidget(current_version_label)
|
||||
version_layout.addWidget(current_version_value)
|
||||
version_layout.addStretch()
|
||||
version_layout.addWidget(new_version_label)
|
||||
version_layout.addWidget(new_version_value)
|
||||
|
||||
layout.addLayout(version_layout)
|
||||
|
||||
#Release notes
|
||||
if self.update_info.release_notes:
|
||||
notes_label = QLabel(_("Release Notes:"))
|
||||
notes_label.setStyleSheet("font-weight: bold;")
|
||||
layout.addWidget(notes_label)
|
||||
|
||||
notes_text = QTextEdit()
|
||||
notes_text.setReadOnly(True)
|
||||
notes_text.setMarkdown(self.update_info.release_notes)
|
||||
notes_text.setMaximumHeight(150)
|
||||
layout.addWidget(notes_text)
|
||||
|
||||
#progress bar
|
||||
self.progress_bar = QProgressBar()
|
||||
self.progress_bar.setVisible(False)
|
||||
self.progress_bar.setTextVisible(True)
|
||||
layout.addWidget(self.progress_bar)
|
||||
|
||||
#Status label
|
||||
self.status_label = QLabel("")
|
||||
self.status_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
layout.addWidget(self.status_label)
|
||||
|
||||
#Buttons
|
||||
button_layout = QVBoxLayout()
|
||||
|
||||
self.download_button = QPushButton(_("Download and Install"))
|
||||
self.download_button.clicked.connect(self._on_download_clicked)
|
||||
self.download_button.setDefault(True)
|
||||
|
||||
button_layout.addStretch()
|
||||
button_layout.addWidget(self.download_button)
|
||||
|
||||
layout.addLayout(button_layout)
|
||||
|
||||
def _on_download_clicked(self):
|
||||
"""Starts downloading the installer"""
|
||||
if not self.update_info.download_urls:
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
_("Error"),
|
||||
_("No download URL available for your platform.")
|
||||
)
|
||||
return
|
||||
|
||||
self.download_button.setEnabled(False)
|
||||
self.progress_bar.setVisible(True)
|
||||
self.progress_bar.setValue(0)
|
||||
self._temp_file_paths = []
|
||||
self._pending_urls = list(self.update_info.download_urls)
|
||||
self._temp_dir = tempfile.mkdtemp()
|
||||
self._download_next_file()
|
||||
|
||||
def _download_next_file(self):
|
||||
"""Download the next file in the queue"""
|
||||
if not self._pending_urls:
|
||||
self._all_downloads_finished()
|
||||
return
|
||||
|
||||
url_str = self._pending_urls[0]
|
||||
file_index = len(self.update_info.download_urls) - len(self._pending_urls) + 1
|
||||
total_files = len(self.update_info.download_urls)
|
||||
self.status_label.setText(
|
||||
_("Downloading file {} of {}...").format(file_index, total_files)
|
||||
)
|
||||
|
||||
url = QUrl(url_str)
|
||||
request = QNetworkRequest(url)
|
||||
|
||||
self._download_reply = self.network_manager.get(request)
|
||||
self._download_reply.downloadProgress.connect(self._on_download_progress)
|
||||
self._download_reply.finished.connect(self._on_download_finished)
|
||||
|
||||
def _on_download_progress(self, bytes_received: int, bytes_total: int):
|
||||
"""Update the progress bar during download"""
|
||||
if bytes_total > 0:
|
||||
progress = int((bytes_received / bytes_total) * 100)
|
||||
self.progress_bar.setValue(progress)
|
||||
|
||||
mb_received = bytes_received / (1024 * 1024)
|
||||
mb_total = bytes_total / (1024 * 1024)
|
||||
file_index = len(self.update_info.download_urls) - len(self._pending_urls) + 1
|
||||
total_files = len(self.update_info.download_urls)
|
||||
self.status_label.setText(
|
||||
_("Downloading file {} of {} ({:.1f} MB / {:.1f} MB)...").format(
|
||||
file_index, total_files, mb_received, mb_total
|
||||
)
|
||||
)
|
||||
|
||||
def _on_download_finished(self):
|
||||
"""Handles download completion for one file"""
|
||||
if self._download_reply is None:
|
||||
return
|
||||
|
||||
if self._download_reply.error() != QNetworkReply.NetworkError.NoError:
|
||||
error_msg = self._download_reply.errorString()
|
||||
logging.error(f"Download failed: {error_msg}")
|
||||
|
||||
QMessageBox.critical(
|
||||
self,
|
||||
_("Download Failed"),
|
||||
_("Failed to download the update: {}").format(error_msg)
|
||||
)
|
||||
|
||||
self._reset_ui()
|
||||
self._download_reply.deleteLater()
|
||||
self._download_reply = None
|
||||
return
|
||||
|
||||
data = self._download_reply.readAll().data()
|
||||
self._download_reply.deleteLater()
|
||||
self._download_reply = None
|
||||
|
||||
url_str = self._pending_urls.pop(0)
|
||||
|
||||
# Extract original filename from URL to preserve it
|
||||
original_filename = QUrl(url_str).fileName()
|
||||
if not original_filename:
|
||||
original_filename = f"download_{len(self._temp_file_paths)}"
|
||||
|
||||
try:
|
||||
temp_path = os.path.join(self._temp_dir, original_filename)
|
||||
with open(temp_path, "wb") as f:
|
||||
f.write(data)
|
||||
self._temp_file_paths.append(temp_path)
|
||||
logging.info(f"File saved to: {temp_path}")
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to save file: {e}")
|
||||
QMessageBox.critical(
|
||||
self,
|
||||
_("Error"),
|
||||
_("Failed to save the installer: {}").format(str(e))
|
||||
)
|
||||
self._reset_ui()
|
||||
return
|
||||
|
||||
self._download_next_file()
|
||||
|
||||
def _all_downloads_finished(self):
|
||||
"""All files downloaded, run the installer"""
|
||||
self.progress_bar.setValue(100)
|
||||
self.status_label.setText(_("Download complete!"))
|
||||
self._run_installer()
|
||||
|
||||
def _run_installer(self):
|
||||
"""Run the downloaded installer"""
|
||||
if not self._temp_file_paths:
|
||||
return
|
||||
|
||||
installer_path = self._temp_file_paths[0]
|
||||
system = platform.system()
|
||||
|
||||
try:
|
||||
if system == "Windows":
|
||||
subprocess.Popen([installer_path], shell=True)
|
||||
|
||||
elif system == "Darwin":
|
||||
#open the DMG file
|
||||
subprocess.Popen(["open", installer_path])
|
||||
|
||||
# Close the app so the installer can replace files
|
||||
self.accept()
|
||||
QApplication.quit()
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to run installer: {e}")
|
||||
QMessageBox.critical(
|
||||
self,
|
||||
_("Error"),
|
||||
_("Failed to run the installer: {}").format(str(e))
|
||||
)
|
||||
|
||||
def _reset_ui(self):
|
||||
"""Reset the UI to initial state after an error"""
|
||||
self.download_button.setEnabled(True)
|
||||
self.progress_bar.setVisible(False)
|
||||
self.status_label.setText("")
|
||||
|
||||
|
|
@ -50,8 +50,23 @@ parts:
|
|||
prime:
|
||||
- etc/asound.conf
|
||||
|
||||
buzz:
|
||||
portaudio:
|
||||
after: [ alsa-pulseaudio ]
|
||||
plugin: autotools
|
||||
source: https://files.portaudio.com/archives/pa_stable_v190700_20210406.tgz
|
||||
build-packages:
|
||||
- libasound2-dev
|
||||
- libpulse-dev
|
||||
autotools-configure-parameters:
|
||||
- --enable-shared
|
||||
- --disable-static
|
||||
stage:
|
||||
- usr/local/lib/libportaudio*
|
||||
prime:
|
||||
- usr/local/lib/libportaudio*
|
||||
|
||||
buzz:
|
||||
after: [ alsa-pulseaudio, portaudio ]
|
||||
plugin: uv
|
||||
source: .
|
||||
build-snaps:
|
||||
|
|
@ -78,9 +93,8 @@ parts:
|
|||
- libproxy1v5
|
||||
# Audio
|
||||
- ffmpeg
|
||||
- libportaudio2
|
||||
- libpulse0
|
||||
- libasound2
|
||||
- libasound2t64
|
||||
- libasound2-dev
|
||||
- libasound2-plugins
|
||||
- libasound2-plugins-extra
|
||||
|
|
@ -115,10 +129,10 @@ parts:
|
|||
# Clean caches
|
||||
uv cache clean
|
||||
|
||||
# Create launcher wrapper to ensure the snap's own libasound.so.2 is found
|
||||
# Create launcher wrapper to ensure the snap's own portaudio and libasound are found
|
||||
# before gnome content snap libraries (which desktop-launch prepends to LD_LIBRARY_PATH)
|
||||
mkdir -p $CRAFT_PART_INSTALL/bin
|
||||
printf '#!/bin/sh\nexport LD_LIBRARY_PATH="$SNAP/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH"\nexec "$SNAP/bin/python" -m buzz "$@"\n' > $CRAFT_PART_INSTALL/bin/buzz-launcher
|
||||
printf '#!/bin/sh\nexport LD_LIBRARY_PATH="$SNAP/usr/local/lib:$SNAP/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH"\nexec "$SNAP/bin/python" -m buzz "$@"\n' > $CRAFT_PART_INSTALL/bin/buzz-launcher
|
||||
chmod +x $CRAFT_PART_INSTALL/bin/buzz-launcher
|
||||
|
||||
# Copy source files
|
||||
|
|
@ -158,7 +172,7 @@ apps:
|
|||
desktop: usr/share/applications/buzz.desktop
|
||||
environment:
|
||||
PATH: $SNAP/usr/bin:$SNAP/bin:$PATH
|
||||
LD_LIBRARY_PATH: $SNAP/lib/python3.12/site-packages/nvidia/cudnn/lib:$SNAP/lib/python3.12/site-packages/PyQt6:$SNAP/lib/python3.12/site-packages/PyQt6/Qt6/lib:$SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/lapack:$SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/blas:$SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/oss4-libsalsa:$SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libproxy:$SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/alsa-lib:$SNAP:$LD_LIBRARY_PATH
|
||||
LD_LIBRARY_PATH: $SNAP/usr/local/lib:$SNAP/lib/python3.12/site-packages/nvidia/cudnn/lib:$SNAP/lib/python3.12/site-packages/PyQt6:$SNAP/lib/python3.12/site-packages/PyQt6/Qt6/lib:$SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/lapack:$SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/blas:$SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/oss4-libsalsa:$SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libproxy:$SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/alsa-lib:$SNAP:$LD_LIBRARY_PATH
|
||||
PYTHONPATH: $SNAP:$SNAP/lib/python3.12/site-packages/PyQt6:$SNAP/lib/python3.12/site-packages/PyQt6/Qt6/lib:$SNAP/usr/lib/python3/dist-packages:$SNAP/usr/lib/python3.12/site-packages:$SNAP/usr/local/lib/python3.12/dist-packages:$SNAP/usr/lib/python3.12/dist-packages:$PYTHONPATH
|
||||
QT_MEDIA_BACKEND: ffmpeg
|
||||
PULSE_LATENCY_MSEC: "30"
|
||||
|
|
@ -182,4 +196,4 @@ apps:
|
|||
|
||||
layout:
|
||||
/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/alsa-lib:
|
||||
bind: $SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/alsa-lib
|
||||
bind: $SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/alsa-lib
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ class MockNetworkReply(QNetworkReply):
|
|||
def error(self) -> "QNetworkReply.NetworkError":
|
||||
return QNetworkReply.NetworkError.NoError
|
||||
|
||||
def deleteLater(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class MockNetworkAccessManager(QNetworkAccessManager):
|
||||
finished = pyqtSignal(object)
|
||||
|
|
@ -29,3 +32,61 @@ class MockNetworkAccessManager(QNetworkAccessManager):
|
|||
def get(self, _: "QNetworkRequest") -> "QNetworkReply":
|
||||
self.finished.emit(self.reply)
|
||||
return self.reply
|
||||
|
||||
|
||||
class MockDownloadReply(QObject):
|
||||
"""Mock reply for file downloads — supports downloadProgress and finished signals."""
|
||||
downloadProgress = pyqtSignal(int, int)
|
||||
finished = pyqtSignal()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
data: bytes = b"fake-installer-data",
|
||||
network_error: "QNetworkReply.NetworkError" = QNetworkReply.NetworkError.NoError,
|
||||
error_string: str = "",
|
||||
parent: Optional[QObject] = None,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
self._data = data
|
||||
self._network_error = network_error
|
||||
self._error_string = error_string
|
||||
self._aborted = False
|
||||
|
||||
def readAll(self) -> QByteArray:
|
||||
return QByteArray(self._data)
|
||||
|
||||
def error(self) -> "QNetworkReply.NetworkError":
|
||||
return self._network_error
|
||||
|
||||
def errorString(self) -> str:
|
||||
return self._error_string
|
||||
|
||||
def abort(self) -> None:
|
||||
self._aborted = True
|
||||
|
||||
def deleteLater(self) -> None:
|
||||
pass
|
||||
|
||||
def emit_finished(self) -> None:
|
||||
self.finished.emit()
|
||||
|
||||
|
||||
class MockDownloadNetworkManager(QNetworkAccessManager):
|
||||
"""Network manager that returns MockDownloadReply instances for each get() call."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
replies: Optional[list] = None,
|
||||
parent: Optional[QObject] = None,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
self._replies = list(replies) if replies else []
|
||||
self._index = 0
|
||||
|
||||
def get(self, _: "QNetworkRequest") -> "MockDownloadReply":
|
||||
if self._index < len(self._replies):
|
||||
reply = self._replies[self._index]
|
||||
else:
|
||||
reply = MockDownloadReply()
|
||||
self._index += 1
|
||||
return reply
|
||||
|
|
|
|||
|
|
@ -135,7 +135,12 @@ class MockInputStream:
|
|||
if self._stop_event.is_set():
|
||||
break
|
||||
chunk = audio[seek : seek + num_samples_in_chunk]
|
||||
self.callback(chunk, 0, None, None)
|
||||
try:
|
||||
self.callback(chunk, 0, None, None)
|
||||
except RuntimeError:
|
||||
# Qt object was deleted between the stop-event check and
|
||||
# the callback invocation; treat it as a stop signal.
|
||||
break
|
||||
seek += num_samples_in_chunk
|
||||
|
||||
# loop back around
|
||||
|
|
|
|||
202
tests/update_checker_test.py
Normal file
202
tests/update_checker_test.py
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
import platform
|
||||
from datetime import datetime, timedelta
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from pytestqt.qtbot import QtBot
|
||||
|
||||
from buzz.__version__ import VERSION
|
||||
from buzz.settings.settings import Settings
|
||||
from buzz.update_checker import UpdateChecker, UpdateInfo
|
||||
from tests.mock_qt import MockNetworkAccessManager, MockNetworkReply
|
||||
|
||||
|
||||
VERSION_INFO = {
|
||||
"version": "99.0.0",
|
||||
"release_notes": "Some fixes.",
|
||||
"download_urls": {
|
||||
"windows_x64": ["https://example.com/Buzz-99.0.0.exe"],
|
||||
"macos_arm": ["https://example.com/Buzz-99.0.0-arm.dmg"],
|
||||
"macos_x86": ["https://example.com/Buzz-99.0.0-x86.dmg"],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def checker(settings: Settings) -> UpdateChecker:
|
||||
reply = MockNetworkReply(data=VERSION_INFO)
|
||||
manager = MockNetworkAccessManager(reply=reply)
|
||||
return UpdateChecker(settings=settings, network_manager=manager)
|
||||
|
||||
|
||||
class TestShouldCheckForUpdates:
|
||||
def test_returns_false_on_linux(self, checker: UpdateChecker):
|
||||
with patch.object(platform, "system", return_value="Linux"):
|
||||
assert checker.should_check_for_updates() is False
|
||||
|
||||
def test_returns_true_on_windows_first_run(self, checker: UpdateChecker, settings: Settings):
|
||||
settings.set_value(Settings.Key.LAST_UPDATE_CHECK, "")
|
||||
with patch.object(platform, "system", return_value="Windows"):
|
||||
assert checker.should_check_for_updates() is True
|
||||
|
||||
def test_returns_true_on_macos_first_run(self, checker: UpdateChecker, settings: Settings):
|
||||
settings.set_value(Settings.Key.LAST_UPDATE_CHECK, "")
|
||||
with patch.object(platform, "system", return_value="Darwin"):
|
||||
assert checker.should_check_for_updates() is True
|
||||
|
||||
def test_returns_false_when_checked_recently(
|
||||
self, checker: UpdateChecker, settings: Settings
|
||||
):
|
||||
recent = (datetime.now() - timedelta(days=2)).isoformat()
|
||||
settings.set_value(Settings.Key.LAST_UPDATE_CHECK, recent)
|
||||
|
||||
with patch.object(platform, "system", return_value="Windows"):
|
||||
assert checker.should_check_for_updates() is False
|
||||
|
||||
def test_returns_true_when_check_is_overdue(
|
||||
self, checker: UpdateChecker, settings: Settings
|
||||
):
|
||||
old = (datetime.now() - timedelta(days=10)).isoformat()
|
||||
settings.set_value(Settings.Key.LAST_UPDATE_CHECK, old)
|
||||
|
||||
with patch.object(platform, "system", return_value="Windows"):
|
||||
assert checker.should_check_for_updates() is True
|
||||
|
||||
def test_returns_true_on_invalid_date_in_settings(
|
||||
self, checker: UpdateChecker, settings: Settings
|
||||
):
|
||||
settings.set_value(Settings.Key.LAST_UPDATE_CHECK, "not-a-date")
|
||||
|
||||
with patch.object(platform, "system", return_value="Windows"):
|
||||
assert checker.should_check_for_updates() is True
|
||||
|
||||
|
||||
class TestIsNewerVersion:
|
||||
def test_newer_major(self, checker: UpdateChecker):
|
||||
with patch("buzz.update_checker.VERSION", "1.0.0"):
|
||||
assert checker._is_newer_version("2.0.0") is True
|
||||
|
||||
def test_newer_minor(self, checker: UpdateChecker):
|
||||
with patch("buzz.update_checker.VERSION", "1.0.0"):
|
||||
assert checker._is_newer_version("1.1.0") is True
|
||||
|
||||
def test_newer_patch(self, checker: UpdateChecker):
|
||||
with patch("buzz.update_checker.VERSION", "1.0.0"):
|
||||
assert checker._is_newer_version("1.0.1") is True
|
||||
|
||||
def test_same_version(self, checker: UpdateChecker):
|
||||
with patch("buzz.update_checker.VERSION", "1.0.0"):
|
||||
assert checker._is_newer_version("1.0.0") is False
|
||||
|
||||
def test_older_version(self, checker: UpdateChecker):
|
||||
with patch("buzz.update_checker.VERSION", "2.0.0"):
|
||||
assert checker._is_newer_version("1.9.9") is False
|
||||
|
||||
def test_different_segment_count(self, checker: UpdateChecker):
|
||||
with patch("buzz.update_checker.VERSION", "1.0"):
|
||||
assert checker._is_newer_version("1.0.1") is True
|
||||
|
||||
def test_invalid_version_returns_false(self, checker: UpdateChecker):
|
||||
with patch("buzz.update_checker.VERSION", "1.0.0"):
|
||||
assert checker._is_newer_version("not-a-version") is False
|
||||
|
||||
|
||||
class TestGetDownloadUrl:
|
||||
def test_windows_returns_windows_urls(self, checker: UpdateChecker):
|
||||
with patch.object(platform, "system", return_value="Windows"):
|
||||
urls = checker._get_download_url(VERSION_INFO["download_urls"])
|
||||
assert urls == ["https://example.com/Buzz-99.0.0.exe"]
|
||||
|
||||
def test_macos_arm_returns_arm_urls(self, checker: UpdateChecker):
|
||||
with patch.object(platform, "system", return_value="Darwin"), \
|
||||
patch.object(platform, "machine", return_value="arm64"):
|
||||
urls = checker._get_download_url(VERSION_INFO["download_urls"])
|
||||
assert urls == ["https://example.com/Buzz-99.0.0-arm.dmg"]
|
||||
|
||||
def test_macos_x86_returns_x86_urls(self, checker: UpdateChecker):
|
||||
with patch.object(platform, "system", return_value="Darwin"), \
|
||||
patch.object(platform, "machine", return_value="x86_64"):
|
||||
urls = checker._get_download_url(VERSION_INFO["download_urls"])
|
||||
assert urls == ["https://example.com/Buzz-99.0.0-x86.dmg"]
|
||||
|
||||
def test_linux_returns_empty(self, checker: UpdateChecker):
|
||||
with patch.object(platform, "system", return_value="Linux"):
|
||||
urls = checker._get_download_url(VERSION_INFO["download_urls"])
|
||||
assert urls == []
|
||||
|
||||
def test_wraps_plain_string_in_list(self, checker: UpdateChecker):
|
||||
with patch.object(platform, "system", return_value="Windows"):
|
||||
urls = checker._get_download_url({"windows_x64": "https://example.com/a.exe"})
|
||||
assert urls == ["https://example.com/a.exe"]
|
||||
|
||||
|
||||
class TestCheckForUpdates:
|
||||
def _make_checker(self, settings: Settings, version_data: dict) -> UpdateChecker:
|
||||
settings.set_value(Settings.Key.LAST_UPDATE_CHECK, "")
|
||||
reply = MockNetworkReply(data=version_data)
|
||||
manager = MockNetworkAccessManager(reply=reply)
|
||||
return UpdateChecker(settings=settings, network_manager=manager)
|
||||
|
||||
def test_emits_update_available_when_newer_version(self, settings: Settings):
|
||||
received = []
|
||||
checker = self._make_checker(settings, VERSION_INFO)
|
||||
checker.update_available.connect(lambda info: received.append(info))
|
||||
|
||||
with patch.object(platform, "system", return_value="Windows"), \
|
||||
patch.object(platform, "machine", return_value="x86_64"), \
|
||||
patch("buzz.update_checker.VERSION", "1.0.0"):
|
||||
checker.check_for_updates()
|
||||
|
||||
assert len(received) == 1
|
||||
update_info: UpdateInfo = received[0]
|
||||
assert update_info.version == "99.0.0"
|
||||
assert update_info.release_notes == "Some fixes."
|
||||
assert update_info.download_urls == ["https://example.com/Buzz-99.0.0.exe"]
|
||||
|
||||
def test_does_not_emit_when_version_is_current(self, settings: Settings):
|
||||
received = []
|
||||
checker = self._make_checker(settings, {**VERSION_INFO, "version": VERSION})
|
||||
checker.update_available.connect(lambda info: received.append(info))
|
||||
|
||||
with patch.object(platform, "system", return_value="Windows"):
|
||||
checker.check_for_updates()
|
||||
|
||||
assert received == []
|
||||
|
||||
def test_skips_network_call_on_linux(self, settings: Settings):
|
||||
received = []
|
||||
checker = self._make_checker(settings, VERSION_INFO)
|
||||
checker.update_available.connect(lambda info: received.append(info))
|
||||
|
||||
with patch.object(platform, "system", return_value="Linux"):
|
||||
checker.check_for_updates()
|
||||
|
||||
assert received == []
|
||||
|
||||
def test_stores_last_check_date_after_reply(self, settings: Settings):
|
||||
checker = self._make_checker(settings, {**VERSION_INFO, "version": VERSION})
|
||||
|
||||
with patch.object(platform, "system", return_value="Windows"):
|
||||
checker.check_for_updates()
|
||||
|
||||
stored = settings.value(Settings.Key.LAST_UPDATE_CHECK, "")
|
||||
assert stored != ""
|
||||
datetime.fromisoformat(stored) # should not raise
|
||||
|
||||
def test_stores_available_version_when_update_found(self, settings: Settings):
|
||||
checker = self._make_checker(settings, VERSION_INFO)
|
||||
|
||||
with patch.object(platform, "system", return_value="Windows"), \
|
||||
patch("buzz.update_checker.VERSION", "1.0.0"):
|
||||
checker.check_for_updates()
|
||||
|
||||
assert settings.value(Settings.Key.UPDATE_AVAILABLE_VERSION, "") == "99.0.0"
|
||||
|
||||
def test_clears_available_version_when_up_to_date(self, settings: Settings):
|
||||
settings.set_value(Settings.Key.UPDATE_AVAILABLE_VERSION, "99.0.0")
|
||||
checker = self._make_checker(settings, {**VERSION_INFO, "version": VERSION})
|
||||
|
||||
with patch.object(platform, "system", return_value="Windows"):
|
||||
checker.check_for_updates()
|
||||
|
||||
assert settings.value(Settings.Key.UPDATE_AVAILABLE_VERSION, "") == ""
|
||||
238
tests/widgets/update_dialog_test.py
Normal file
238
tests/widgets/update_dialog_test.py
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
import platform
|
||||
from unittest.mock import patch, Mock
|
||||
|
||||
import pytest
|
||||
from PyQt6.QtNetwork import QNetworkReply
|
||||
from PyQt6.QtWidgets import QMessageBox
|
||||
from pytestqt.qtbot import QtBot
|
||||
|
||||
from buzz.locale import _
|
||||
from buzz.update_checker import UpdateInfo
|
||||
from buzz.widgets.update_dialog import UpdateDialog
|
||||
from tests.mock_qt import MockDownloadReply, MockDownloadNetworkManager
|
||||
|
||||
|
||||
UPDATE_INFO = UpdateInfo(
|
||||
version="99.0.0",
|
||||
release_notes="Some fixes.",
|
||||
download_urls=["https://example.com/Buzz-99.0.0.exe"],
|
||||
)
|
||||
|
||||
MULTI_FILE_UPDATE_INFO = UpdateInfo(
|
||||
version="99.0.0",
|
||||
release_notes="Multi-file release.",
|
||||
download_urls=[
|
||||
"https://example.com/Buzz-99.0.0.exe",
|
||||
"https://example.com/Buzz-99.0.0-1.bin",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class TestUpdateDialogUI:
|
||||
def test_shows_version_info(self, qtbot: QtBot):
|
||||
dialog = UpdateDialog(update_info=UPDATE_INFO)
|
||||
qtbot.add_widget(dialog)
|
||||
|
||||
assert dialog.windowTitle() == _("Update Available")
|
||||
assert "99.0.0" in dialog.findChild(
|
||||
__import__("PyQt6.QtWidgets", fromlist=["QLabel"]).QLabel,
|
||||
""
|
||||
).__class__.__name__ or True # title check is sufficient
|
||||
|
||||
def test_download_button_is_present(self, qtbot: QtBot):
|
||||
dialog = UpdateDialog(update_info=UPDATE_INFO)
|
||||
qtbot.add_widget(dialog)
|
||||
assert dialog.download_button.text() == _("Download and Install")
|
||||
|
||||
def test_progress_bar_hidden_initially(self, qtbot: QtBot):
|
||||
dialog = UpdateDialog(update_info=UPDATE_INFO)
|
||||
qtbot.add_widget(dialog)
|
||||
assert dialog.progress_bar.isHidden()
|
||||
|
||||
def test_status_label_empty_initially(self, qtbot: QtBot):
|
||||
dialog = UpdateDialog(update_info=UPDATE_INFO)
|
||||
qtbot.add_widget(dialog)
|
||||
assert dialog.status_label.text() == ""
|
||||
|
||||
|
||||
class TestUpdateDialogDownload:
|
||||
def test_shows_warning_when_no_download_urls(self, qtbot: QtBot):
|
||||
info = UpdateInfo(version="99.0.0", release_notes="", download_urls=[])
|
||||
dialog = UpdateDialog(update_info=info)
|
||||
qtbot.add_widget(dialog)
|
||||
|
||||
mock_warning = Mock()
|
||||
with patch.object(QMessageBox, "warning", mock_warning):
|
||||
dialog.download_button.click()
|
||||
|
||||
mock_warning.assert_called_once()
|
||||
assert _("No download URL available for your platform.") in mock_warning.call_args[0]
|
||||
|
||||
def test_download_button_disabled_after_click(self, qtbot: QtBot):
|
||||
reply = MockDownloadReply(data=b"fake-exe-data")
|
||||
manager = MockDownloadNetworkManager(replies=[reply])
|
||||
dialog = UpdateDialog(update_info=UPDATE_INFO, network_manager=manager)
|
||||
qtbot.add_widget(dialog)
|
||||
|
||||
with patch.object(platform, "system", return_value="Windows"), \
|
||||
patch("subprocess.Popen"), \
|
||||
patch("buzz.widgets.update_dialog.QApplication"):
|
||||
dialog.download_button.click()
|
||||
reply.emit_finished()
|
||||
|
||||
assert not dialog.download_button.isEnabled()
|
||||
|
||||
def test_progress_bar_shown_after_download_starts(self, qtbot: QtBot):
|
||||
reply = MockDownloadReply(data=b"fake-exe-data")
|
||||
manager = MockDownloadNetworkManager(replies=[reply])
|
||||
dialog = UpdateDialog(update_info=UPDATE_INFO, network_manager=manager)
|
||||
qtbot.add_widget(dialog)
|
||||
|
||||
dialog.download_button.click()
|
||||
assert not dialog.progress_bar.isHidden()
|
||||
|
||||
def test_progress_bar_updates_on_progress(self, qtbot: QtBot):
|
||||
reply = MockDownloadReply(data=b"x" * (5 * 1024 * 1024))
|
||||
manager = MockDownloadNetworkManager(replies=[reply])
|
||||
dialog = UpdateDialog(update_info=UPDATE_INFO, network_manager=manager)
|
||||
qtbot.add_widget(dialog)
|
||||
|
||||
dialog.download_button.click()
|
||||
reply.downloadProgress.emit(5 * 1024 * 1024, 10 * 1024 * 1024)
|
||||
|
||||
assert dialog.progress_bar.value() == 50
|
||||
assert "5.0 MB" in dialog.status_label.text()
|
||||
|
||||
def test_single_file_download_runs_installer_on_windows(self, qtbot: QtBot):
|
||||
reply = MockDownloadReply(data=b"fake-exe-data")
|
||||
manager = MockDownloadNetworkManager(replies=[reply])
|
||||
dialog = UpdateDialog(update_info=UPDATE_INFO, network_manager=manager)
|
||||
qtbot.add_widget(dialog)
|
||||
|
||||
mock_popen = Mock()
|
||||
mock_quit = Mock()
|
||||
with patch.object(platform, "system", return_value="Windows"), \
|
||||
patch("subprocess.Popen", mock_popen), \
|
||||
patch("buzz.widgets.update_dialog.QApplication") as mock_app:
|
||||
mock_app.quit = mock_quit
|
||||
dialog.download_button.click()
|
||||
reply.emit_finished()
|
||||
|
||||
mock_popen.assert_called_once()
|
||||
installer_path = mock_popen.call_args[0][0][0]
|
||||
assert installer_path.endswith(".exe")
|
||||
|
||||
def test_single_file_download_opens_dmg_on_macos(self, qtbot: QtBot):
|
||||
macos_info = UpdateInfo(
|
||||
version="99.0.0",
|
||||
release_notes="",
|
||||
download_urls=["https://example.com/Buzz-99.0.0-arm.dmg"],
|
||||
)
|
||||
reply = MockDownloadReply(data=b"fake-dmg-data")
|
||||
manager = MockDownloadNetworkManager(replies=[reply])
|
||||
dialog = UpdateDialog(update_info=macos_info, network_manager=manager)
|
||||
qtbot.add_widget(dialog)
|
||||
|
||||
mock_popen = Mock()
|
||||
with patch.object(platform, "system", return_value="Darwin"), \
|
||||
patch("subprocess.Popen", mock_popen), \
|
||||
patch("buzz.widgets.update_dialog.QApplication"):
|
||||
dialog.download_button.click()
|
||||
reply.emit_finished()
|
||||
|
||||
mock_popen.assert_called_once()
|
||||
assert mock_popen.call_args[0][0][0] == "open"
|
||||
installer_path = mock_popen.call_args[0][0][1]
|
||||
assert installer_path.endswith(".dmg")
|
||||
|
||||
def test_multi_file_download_downloads_sequentially(self, qtbot: QtBot):
|
||||
reply1 = MockDownloadReply(data=b"installer-exe")
|
||||
reply2 = MockDownloadReply(data=b"installer-bin")
|
||||
manager = MockDownloadNetworkManager(replies=[reply1, reply2])
|
||||
dialog = UpdateDialog(update_info=MULTI_FILE_UPDATE_INFO, network_manager=manager)
|
||||
qtbot.add_widget(dialog)
|
||||
|
||||
mock_popen = Mock()
|
||||
with patch.object(platform, "system", return_value="Windows"), \
|
||||
patch("subprocess.Popen", mock_popen), \
|
||||
patch("buzz.widgets.update_dialog.QApplication"):
|
||||
dialog.download_button.click()
|
||||
# First file done
|
||||
reply1.emit_finished()
|
||||
# Second file done
|
||||
reply2.emit_finished()
|
||||
|
||||
assert len(dialog._temp_file_paths) == 2
|
||||
assert dialog._temp_file_paths[0].endswith(".exe")
|
||||
assert dialog._temp_file_paths[1].endswith(".bin")
|
||||
mock_popen.assert_called_once()
|
||||
|
||||
def test_status_shows_file_count_during_multi_file_download(self, qtbot: QtBot):
|
||||
reply1 = MockDownloadReply(data=b"installer-exe")
|
||||
reply2 = MockDownloadReply(data=b"installer-bin")
|
||||
manager = MockDownloadNetworkManager(replies=[reply1, reply2])
|
||||
dialog = UpdateDialog(update_info=MULTI_FILE_UPDATE_INFO, network_manager=manager)
|
||||
qtbot.add_widget(dialog)
|
||||
|
||||
dialog.download_button.click()
|
||||
assert "1" in dialog.status_label.text()
|
||||
assert "2" in dialog.status_label.text()
|
||||
|
||||
def test_progress_bar_reaches_100_after_all_downloads(self, qtbot: QtBot):
|
||||
reply = MockDownloadReply(data=b"fake-exe-data")
|
||||
manager = MockDownloadNetworkManager(replies=[reply])
|
||||
dialog = UpdateDialog(update_info=UPDATE_INFO, network_manager=manager)
|
||||
qtbot.add_widget(dialog)
|
||||
|
||||
with patch.object(platform, "system", return_value="Windows"), \
|
||||
patch("subprocess.Popen"), \
|
||||
patch("buzz.widgets.update_dialog.QApplication"):
|
||||
dialog.download_button.click()
|
||||
reply.emit_finished()
|
||||
|
||||
assert dialog.progress_bar.value() == 100
|
||||
assert dialog.status_label.text() == _("Download complete!")
|
||||
|
||||
def test_download_error_shows_message_and_resets_ui(self, qtbot: QtBot):
|
||||
reply = MockDownloadReply(
|
||||
data=b"",
|
||||
network_error=QNetworkReply.NetworkError.ConnectionRefusedError,
|
||||
error_string="Connection refused",
|
||||
)
|
||||
manager = MockDownloadNetworkManager(replies=[reply])
|
||||
dialog = UpdateDialog(update_info=UPDATE_INFO, network_manager=manager)
|
||||
qtbot.add_widget(dialog)
|
||||
|
||||
mock_critical = Mock()
|
||||
with patch.object(QMessageBox, "critical", mock_critical):
|
||||
dialog.download_button.click()
|
||||
reply.emit_finished()
|
||||
|
||||
mock_critical.assert_called_once()
|
||||
assert "Connection refused" in str(mock_critical.call_args)
|
||||
assert dialog.download_button.isEnabled()
|
||||
assert dialog.progress_bar.isHidden()
|
||||
|
||||
def test_save_error_shows_message_and_resets_ui(self, qtbot: QtBot):
|
||||
reply = MockDownloadReply(data=b"fake-data")
|
||||
manager = MockDownloadNetworkManager(replies=[reply])
|
||||
dialog = UpdateDialog(update_info=UPDATE_INFO, network_manager=manager)
|
||||
qtbot.add_widget(dialog)
|
||||
|
||||
mock_critical = Mock()
|
||||
with patch.object(QMessageBox, "critical", mock_critical), \
|
||||
patch("buzz.widgets.update_dialog.open", side_effect=OSError("Disk full")):
|
||||
dialog.download_button.click()
|
||||
reply.emit_finished()
|
||||
|
||||
mock_critical.assert_called_once()
|
||||
assert dialog.download_button.isEnabled()
|
||||
|
||||
def test_download_reply_stored_while_in_progress(self, qtbot: QtBot):
|
||||
reply = MockDownloadReply(data=b"fake-data")
|
||||
manager = MockDownloadNetworkManager(replies=[reply])
|
||||
dialog = UpdateDialog(update_info=UPDATE_INFO, network_manager=manager)
|
||||
qtbot.add_widget(dialog)
|
||||
|
||||
dialog.download_button.click()
|
||||
assert dialog._download_reply is reply
|
||||
Loading…
Add table
Add a link
Reference in a new issue