From c531b8aa74c43b63c9620599c10bb5cf2401a143 Mon Sep 17 00:00:00 2001 From: GenevensiS <66968533+G-e-n-e-v-e-n-s-i-S@users.noreply.github.com> Date: Mon, 18 May 2026 23:25:22 +0200 Subject: [PATCH] Add option to download missing stylesheets on startup --- CMakeLists.txt | 2 +- CMakeSettings.json | 18 +++ data/ch-s.mse-locale/locale | 22 +++- data/ch-t.mse-locale/locale | 22 +++- data/da.mse-locale/locale | 22 +++- data/de.mse-locale/locale | 19 ++- data/en.mse-locale/locale | 19 ++- data/es.mse-locale/locale | 22 +++- data/fr.mse-locale/locale | 19 ++- data/it.mse-locale/locale | 19 ++- data/jp.mse-locale/locale | 22 +++- data/ko.mse-locale/locale | 22 +++- data/pl.mse-locale/locale | 22 +++- data/pt-br.mse-locale/locale | 25 +++- data/ru.mse-locale/locale | 22 +++- src/data/format/apprentice.cpp | 2 +- src/data/installer.cpp | 22 ++++ src/data/installer.hpp | 3 +- src/data/stylesheet.cpp | 14 +- src/gfx/generated_image.cpp | 4 +- src/gui/add_csv_window.cpp | 2 +- src/gui/add_json_window.cpp | 2 +- src/gui/auto_replace_window.cpp | 2 +- src/gui/bulk_modification_window.cpp | 2 +- src/gui/card_link_window.cpp | 2 +- src/gui/card_select_window.cpp | 2 +- src/gui/control/card_list_column_select.cpp | 2 +- src/gui/downloadable_installers.hpp | 6 +- src/gui/html_export_window.cpp | 4 +- src/gui/image_slice_window.cpp | 2 +- src/gui/images_export_window.cpp | 2 +- src/gui/new_window.cpp | 139 +++++++++++++++++--- src/gui/new_window.hpp | 24 +++- src/gui/packages_window.cpp | 40 +++--- src/gui/packages_window.hpp | 4 +- src/gui/preferences_window.cpp | 17 ++- src/gui/set/cards_panel.cpp | 2 +- src/gui/set/console_panel.cpp | 2 +- src/gui/set/keywords_panel.cpp | 2 +- src/gui/set/panel.hpp | 3 +- src/gui/set/random_pack_panel.cpp | 4 +- src/gui/set/set_info_panel.cpp | 2 +- src/gui/set/stats_panel.cpp | 2 +- src/gui/set/style_panel.cpp | 33 +++-- src/gui/set/style_panel.hpp | 8 +- src/gui/set/window.cpp | 7 + src/gui/set/window.hpp | 4 +- src/gui/web_request_window.cpp | 2 +- src/gui/welcome_window.cpp | 8 +- src/util/io/package.cpp | 7 +- src/util/io/package_manager.cpp | 87 +++++++++--- src/util/io/package_manager.hpp | 27 ++-- src/util/version.cpp | 10 +- src/util/window_id.hpp | 11 +- 54 files changed, 638 insertions(+), 177 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c47fdd1..daf7cd59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ if( NOT HUNSPELL_FOUND ) endif() # You will most likely get a message about being unable to open hunspell-1.7.lib because pkgconf forgets to add the actual path to -# HUNSPELL_LIBRARIES. If so, uncomment the below line and point it to the correct vcpkg root folder/library. +# HUNSPELL_LIBRARIES. If so, uncomment the below line and point it to the correct vcpkg root folder/library. (For debug builds, add "debug\\" just before "lib\\") #set(HUNSPELL_LIBRARIES "C:\\PATH\\TO\\ROOT\\vcpkg\\installed\\${VCPKG_TARGET_TRIPLET}\\lib\\hunspell-1.7.lib") message("-- Does this have a full path? If not, and it's just a file name, it's broken: Found Hunspell at ${HUNSPELL_LIBRARIES}") diff --git a/CMakeSettings.json b/CMakeSettings.json index c4ae2e2d..3a238ab3 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -18,6 +18,24 @@ } ] }, + { + "name": "x64-Debug-static", + "generator": "Ninja", + "configurationType": "Debug", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "-DVCPKG_TARGET_TRIPLET=x64-windows-static", + "buildCommandArgs": "-v", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x64_x64" ], + "variables": [ + { + "name": "VCPKG_MANIFEST_FEATURES", + "value": "fonts", + "type": "STRING" + } + ] + }, { "name": "x86-Debug", "generator": "Ninja", diff --git a/data/ch-s.mse-locale/locale b/data/ch-s.mse-locale/locale index 498e935e..a02ff594 100644 --- a/data/ch-s.mse-locale/locale +++ b/data/ch-s.mse-locale/locale @@ -1,4 +1,4 @@ -mse version: 2.5.8 +mse version: 2.6.0 installer group: Magic Set Editor/translations/chinese simplified full name: 简体中文 (Simplified Chinese) version: 2026-02-28 @@ -620,6 +620,16 @@ label: stylesheet not found: 你要打开的套牌使用的是 "%s" 样式表 这个样式表在你的系统里没有找到,请选择其他方案 + #TODO: Localize + searching online: Searching online... + #TODO: Localize + searching online fail: Not found online + #TODO: Localize + found online downloading: Found online! Downloading... + #TODO: Localize + found online installing: Found online! Installing... + #TODO: Localize + found online fail: Installation failed # preferences dialog language: 语言 @@ -904,6 +914,10 @@ button: upgrade group: 全部升级 remove group: 全部移除 + # stylesheet not found dialog + #TODO: Localize + find package online: Search Online + ############################################################## Titles in the GUI title: # window titles @@ -1064,6 +1078,12 @@ error: file not found package like: 没有找到文件:'%s' 在 '%s' 文件包中 如果你尝试从别的文件包中打开文件, 使用以下格式"/package/filename" + #TODO: Localize + file not found package like init: + File not found: '%s' in package '%s' + If this folder is empty or unused, delete it. + #TODO: Localize + package name parse error: Unable to parse package name '%s' file parse error: 处理文件发生错误:'%s' %s diff --git a/data/ch-t.mse-locale/locale b/data/ch-t.mse-locale/locale index 67fa6acc..82440b57 100644 --- a/data/ch-t.mse-locale/locale +++ b/data/ch-t.mse-locale/locale @@ -1,4 +1,4 @@ -mse version: 2.5.8 +mse version: 2.6.0 installer group: Magic Set Editor/translations/chinese traditional full name: 繁體中文 (Traditional Chinese) version: 2026-02-28 @@ -618,6 +618,16 @@ label: stylesheet not found: 你要打開的套牌使用的是 "%s" 樣式表 這個樣式表在你的系統里沒有找到,請選擇其他方案 + #TODO: Localize + searching online: Searching online... + #TODO: Localize + searching online fail: Not found online + #TODO: Localize + found online downloading: Found online! Downloading... + #TODO: Localize + found online installing: Found online! Installing... + #TODO: Localize + found online fail: Installation failed # preferences dialog language: 語言 @@ -902,6 +912,10 @@ button: upgrade group: 全部昇級 remove group: 全部移除 + # stylesheet not found dialog + #TODO: Localize + find package online: Search Online + ############################################################## Titles in the GUI title: # window titles @@ -1062,6 +1076,12 @@ error: file not found package like: 沒有找到文件:'%s' 在 '%s' 文件包中 如果你嘗試從別的文件包中打開文件, 使用以下格式"/package/filename" + #TODO: Localize + file not found package like init: + File not found: '%s' in package '%s' + If this folder is empty or unused, delete it. + #TODO: Localize + package name parse error: Unable to parse package name '%s' file parse error: 處理文件發生錯誤:'%s' %s diff --git a/data/da.mse-locale/locale b/data/da.mse-locale/locale index 55f420f2..429be569 100644 --- a/data/da.mse-locale/locale +++ b/data/da.mse-locale/locale @@ -1,4 +1,4 @@ -mse version: 2.5.8 +mse version: 2.6.0 installer group: Magic Set Editor/translations/danish full name: Dansk (Danish) version: 2026-02-28 @@ -630,6 +630,16 @@ label: stylesheet not found: Sættet du har åbner bruger stilen "%s". Denne stil er ikke i dit system, vælg venligst et alternativ. + #TODO: Localize + searching online: Searching online... + #TODO: Localize + searching online fail: Not found online + #TODO: Localize + found online downloading: Found online! Downloading... + #TODO: Localize + found online installing: Found online! Installing... + #TODO: Localize + found online fail: Installation failed # preferences dialog language: Sprog @@ -920,6 +930,10 @@ button: upgrade group: &Opgradér Alt remove group: &Fjern Alt + # stylesheet not found dialog + #TODO: Localize + find package online: Search Online + ############################################################## Titles in the GUI title: # window titles @@ -1086,6 +1100,12 @@ error: file not found package like: File not found: '%s' in package '%s' If you are trying to open a file from another package, use "/package/filename" + #TODO: Localize + file not found package like init: + File not found: '%s' in package '%s' + If this folder is empty or unused, delete it. + #TODO: Localize + package name parse error: Unable to parse package name '%s' file parse error: Error while parsing file: '%s' %s diff --git a/data/de.mse-locale/locale b/data/de.mse-locale/locale index 7ff2e995..972c78ef 100644 --- a/data/de.mse-locale/locale +++ b/data/de.mse-locale/locale @@ -1,4 +1,4 @@ -mse version: 2.5.8 +mse version: 2.6.0 installer group: Magic Set Editor/translations/german full name: Deutsch (German) version: 2026-02-28 @@ -21,7 +21,7 @@ menu: export images: Alle Bilder exportieren... export apprentice: &Karte exportieren... export mws: Magic &Workstation... - check updates: Nach Updates schauen... + check updates: Aktualisierungen / Neue Stylesheets... print preview: Druckvorschau... print: &Drucken... Ctrl+P reload data: Daten neu laden Ctrl+F5 @@ -581,7 +581,13 @@ label: # stylesheet not found dialog stylesheet not found: Die ausgewählte Edition benutzt das Stylesheet "%s" . - Leider konnte es nicht gefunden werden. Bitte probieren Sie ein anderes. + Dieses Stylesheet wurde auf Ihrem System nicht gefunden. + Bitte wählen Sie eine Alternative oder suchen Sie online danach. + searching online: Online-Suche... + searching online fail: Nicht gefunden + found online downloading: Online gefunden! Wird heruntergeladen... + found online installing: Online gefunden! Wird installiert... + found online fail: Installation fehlgeschlagen # preferences dialog language: Sprache @@ -836,6 +842,9 @@ button: upgrade group: Gruppe aktualisieren remove group: Gruppe entfernen + # stylesheet not found dialog + find package online: Online Suchen + ############################################################## Titles in the GUI title: # window titles @@ -984,6 +993,10 @@ error: file not found package like: Datei nicht gefunden: '%s' im Package '%s' Wenn Sie versuchen sollten, die Datei von einem anderen Package zu laden, verwenden Sie "/package/filename" + file not found package like init: + Datei nicht gefunden: '%s' im Package '%s' + Wenn dieser Ordner leer oder nicht verwendet ist, löschen Sie ihn. + package name parse error: Packagename '%s' konnte nicht analysiert werden. file parse error: Fehler beim Parsen von Datei: '%s' %s diff --git a/data/en.mse-locale/locale b/data/en.mse-locale/locale index c20242e8..2d70ba7f 100644 --- a/data/en.mse-locale/locale +++ b/data/en.mse-locale/locale @@ -1,4 +1,4 @@ -mse version: 2.5.8 +mse version: 2.6.0 installer group: Magic Set Editor/translations/english full name: English version: 2026-02-28 @@ -21,7 +21,7 @@ menu: export images: All Card I&mages... export apprentice: &Apprentice... export mws: Magic &Workstation... - check updates: Check &Updates... + check updates: Check &Updates / New Styles... print preview: Print Pre&view... print: &Print... Ctrl+P reload data: Reload Data Ctrl+F5 @@ -582,7 +582,13 @@ label: # stylesheet not found dialog stylesheet not found: The set you are trying to open uses the stylesheet "%s". - This stylesheet is not found on your system, please select an alternative. + This stylesheet is not found on your system. + Please select an alternative, or look for it online. + searching online: Searching online... + searching online fail: Not found online + found online downloading: Found online! Downloading... + found online installing: Found online! Installing... + found online fail: Installation failed # preferences dialog language: Language @@ -837,6 +843,9 @@ button: upgrade group: &Update Group remove group: &Remove Group + # stylesheet not found dialog + find package online: Search Online + ############################################################## Titles in the GUI title: # window titles @@ -985,6 +994,10 @@ error: file not found package like: File not found: '%s' in package '%s' If you are trying to open a file from another package, use "/package/filename" + file not found package like init: + File not found: '%s' in package '%s' + If this folder is empty or unused, delete it. + package name parse error: Unable to parse package name '%s' file parse error: Error while parsing file: '%s' %s diff --git a/data/es.mse-locale/locale b/data/es.mse-locale/locale index 33cddd6f..fff7ed4f 100644 --- a/data/es.mse-locale/locale +++ b/data/es.mse-locale/locale @@ -1,4 +1,4 @@ -mse version: 2.5.8 +mse version: 2.6.0 installer group: Magic Set Editor/translations/spanish full name: Español (Spanish) version: 2026-02-28 @@ -621,6 +621,16 @@ label: stylesheet not found: El Set que estás intentando abrir usa el estilo "%s". Este estilo no se encuentra en tu sistema, por favor selecciona otro. + #TODO: Localize + searching online: Searching online... + #TODO: Localize + searching online fail: Not found online + #TODO: Localize + found online downloading: Found online! Downloading... + #TODO: Localize + found online installing: Found online! Installing... + #TODO: Localize + found online fail: Installation failed # preferences dialog language: Idioma @@ -905,6 +915,10 @@ button: upgrade group: A&ctualizar Todos remove group: Q&uitar Todos + # stylesheet not found dialog + #TODO: Localize + find package online: Search Online + ############################################################## Titles in the GUI title: # window titles @@ -1065,6 +1079,12 @@ error: file not found package like: Archivo no encontrado: '%s' en el paquete '%s' Si estás intentando abrir un archivo de otro paquete, usa "/package/filename" + #TODO: Localize + file not found package like init: + File not found: '%s' in package '%s' + If this folder is empty or unused, delete it. + #TODO: Localize + package name parse error: Unable to parse package name '%s' file parse error: Error mientras se analizaba el archivo: '%s' %s diff --git a/data/fr.mse-locale/locale b/data/fr.mse-locale/locale index d4ae69e5..c00e9045 100644 --- a/data/fr.mse-locale/locale +++ b/data/fr.mse-locale/locale @@ -1,4 +1,4 @@ -mse version: 2.5.8 +mse version: 2.6.0 installer group: Magic Set Editor/translations/french full name: Français (French) version: 2026-02-28 @@ -21,7 +21,7 @@ menu: export images: Toutes les I&mages de Carte... export apprentice: &Apprentice... export mws: Magic &Workstation... - check updates: Vérifier les Mises à Jo&ur... + check updates: Mises à Jo&ur / Nouveaux Styles... print preview: Aperçu d'&Impression... print: &Imprimer... Ctrl+P reload data: Recharger les Données Ctrl+F5 @@ -582,7 +582,13 @@ label: # stylesheet not found dialog stylesheet not found: Le Set que vous essayez d'ouvrir utilise le Style "%s". - Ce Style n'a pas été trouvé sur votre ordinateur. Selectionnez une alternative. + Ce Style n'a pas été trouvé sur votre ordinateur. + Selectionnez une alternative, ou cherchez en ligne. + searching online: Recherche en ligne... + searching online fail: Introuvable en ligne + found online downloading: Trouvé en ligne! Téléchargement... + found online installing: Trouvé en ligne! Installation... + found online fail: Échec de l’installation # preferences dialog language: Langue @@ -836,6 +842,9 @@ button: upgrade group: &Mettre à jour le groupe remove group: &Supprimer le groupe + # stylesheet not found dialog + find package online: Chercher En Ligne + ############################################################## Titles in the GUI title: # window titles @@ -984,6 +993,10 @@ error: file not found package like: Fichier non trouvé: '%s' dans le package '%s' Si vous essayez d'ouvrir un fichier d'un autre package, utilisez "/package/fichier" + file not found package like init: + Fichier non trouvé: '%s' dans le package '%s' + Si ce dossier est vide ou inutilisé, supprimez-le. + package name parse error: Impossible d'analyser le nom du package '%s'. file parse error: Erreur lors de la lecture du fichier: '%s' %s diff --git a/data/it.mse-locale/locale b/data/it.mse-locale/locale index 973cd2f5..d8118058 100644 --- a/data/it.mse-locale/locale +++ b/data/it.mse-locale/locale @@ -1,4 +1,4 @@ -mse version: 2.5.8 +mse version: 2.6.0 installer group: Magic Set Editor/translations/italian full name: Italiano (Italian) version: 2026-02-28 @@ -21,7 +21,7 @@ menu: export images: I&mmagini Carte... export apprentice: &Apprentice... export mws: Magic &Workstation... - check updates: Cerca aggiornamenti... + check updates: Aggiornamenti / Nuovi Stili... print preview: Anteprima di S&tampa... print: &Stampa... Ctrl+P reload data: Ricarica dati Ctrl+F5 @@ -582,7 +582,13 @@ label: # stylesheet not found dialog stylesheet not found: Il set che stai cercando di aprire usa lo stile "%s". - Questo stile non è stato trovato sul tuo sistema, scegli un'alternativa. + Questo stile non è stato trovato sul tuo sistema. + Seleziona un'alternativa o cercalo online. + searching online: Ricerca online in corso... + searching online fail: Non trovato online + found online downloading: Trovato online! Download in corso... + found online installing: Trovato online! Installazione in corso... + found online fail: Installazione non riuscita # preferences dialog language: Lingua @@ -836,6 +842,9 @@ button: upgrade group: &Aggiorna il gruppo remove group: &Rimuovi il gruppo + # stylesheet not found dialog + find package online: Cerca online + ############################################################## Titles in the GUI title: # window titles @@ -984,6 +993,10 @@ error: file not found package like: File non trovato: '%s' nel pacchetto '%s' Se si sta tentando di aprire un file da un altro pacchetto, utilizzare "/package/filename" + file not found package like init: + File non trovato: '%s' nel pacchetto '%s' + Se questa cartella è vuota o inutilizzata, eliminala. + package name parse error: Impossibile analizzare il nome del pacchetto '%s' file parse error: Errore analizzando il file: '%s' %s diff --git a/data/jp.mse-locale/locale b/data/jp.mse-locale/locale index 142309bb..05a8ff6d 100644 --- a/data/jp.mse-locale/locale +++ b/data/jp.mse-locale/locale @@ -1,4 +1,4 @@ -mse version: 2.5.8 +mse version: 2.6.0 installer group: Magic Set Editor/translations/japanese full name: 日本語 (Japanese) version: 2026-02-28 @@ -620,6 +620,16 @@ label: stylesheet not found: あなたが始めようとしているセットがスタイルシートを使う "%s"。 このstylesheetがあなたのシステムで見つからないで、選択肢を選んでください。 + #TODO: Localize + searching online: Searching online... + #TODO: Localize + searching online fail: Not found online + #TODO: Localize + found online downloading: Found online! Downloading... + #TODO: Localize + found online installing: Found online! Installing... + #TODO: Localize + found online fail: Installation failed # preferences dialog language: 言語 @@ -904,6 +914,10 @@ button: upgrade group: すべてアップグレードする remove group: すべて削除する + # stylesheet not found dialog + #TODO: Localize + find package online: Search Online + ############################################################## Titles in the GUI title: # window titles @@ -1065,6 +1079,12 @@ error: file not found package like: ファイルが見つかりません '%s' パッケージの '%s' しようとしている場合は、別のパッケージからファイルを開くには、使用する "/パッケージ/ファイル名" + #TODO: Localize + file not found package like init: + File not found: '%s' in package '%s' + If this folder is empty or unused, delete it. + #TODO: Localize + package name parse error: Unable to parse package name '%s' file parse error: ファイルをパースし誤り: '%s' %s diff --git a/data/ko.mse-locale/locale b/data/ko.mse-locale/locale index b36302a9..cf8b412f 100644 --- a/data/ko.mse-locale/locale +++ b/data/ko.mse-locale/locale @@ -1,4 +1,4 @@ -mse version: 2.5.8 +mse version: 2.6.0 installer group: Magic Set Editor/translations/korean full name: 한국어 (Korean) version: 2026-02-28 @@ -625,6 +625,16 @@ label: stylesheet not found: 열려고 하는 세트는 스타일시트 '%s'을 사용합니다. 이 스타일시트를 시스템에서 찾을 수 없습니다. 대체 스타일을 선택하십시오. + #TODO: Localize + searching online: Searching online... + #TODO: Localize + searching online fail: Not found online + #TODO: Localize + found online downloading: Found online! Downloading... + #TODO: Localize + found online installing: Found online! Installing... + #TODO: Localize + found online fail: Installation failed # preferences dialog language: 언어 @@ -910,6 +920,10 @@ button: upgrade group: 모두 업그레이드 remove group: 모두 제거 + # stylesheet not found dialog + #TODO: Localize + find package online: Search Online + ############################################################## Titles in the GUI title: # window titles @@ -1071,6 +1085,12 @@ error: file not found package like: 파일을 찾을 수 없습니다: '%s' 패키지에 '%s' 다른 패키지의 파일을 열려고 하는 경우 다음을 사용하십시오. "/패키지 이름/파일 이름" + #TODO: Localize + file not found package like init: + File not found: '%s' in package '%s' + If this folder is empty or unused, delete it. + #TODO: Localize + package name parse error: Unable to parse package name '%s' file parse error: 파일을 구문 분석하는 중 오류가 발생했습니다.: '%s' %s diff --git a/data/pl.mse-locale/locale b/data/pl.mse-locale/locale index 62b4fd53..90af263b 100644 --- a/data/pl.mse-locale/locale +++ b/data/pl.mse-locale/locale @@ -1,4 +1,4 @@ -mse version: 2.5.8 +mse version: 2.6.0 installer group: Magic Set Editor/translations/polski full name: Polski (Polish) version: 2026-02-28 @@ -660,6 +660,16 @@ label: stylesheet not found: Zestaw który próbujesz otworzyć używa stylu z arkusz "%s". Nie udało się znaleźć tego arkuszu, wybierz jakiś inny. + #TODO: Localize + searching online: Searching online... + #TODO: Localize + searching online fail: Not found online + #TODO: Localize + found online downloading: Found online! Downloading... + #TODO: Localize + found online installing: Found online! Installing... + #TODO: Localize + found online fail: Installation failed # preferences dialog language: Język @@ -958,6 +968,10 @@ button: upgrade group: &Uaktualnij wszystkie remove group: &Usuń wszystkie + # stylesheet not found dialog + #TODO: Localize + find package online: Search Online + ############################################################## Titles in the GUI title: # window titles @@ -1121,6 +1135,12 @@ error: file not found package like: Nie znaleziono pliku: '%s' w paczce '%s' Jeśli próbujesz otworzyć plik z innej paczki, użyj "/paczka/plik" + #TODO: Localize + file not found package like init: + File not found: '%s' in package '%s' + If this folder is empty or unused, delete it. + #TODO: Localize + package name parse error: Unable to parse package name '%s' file parse error: Błąd parsowania pliku: '%s' %s diff --git a/data/pt-br.mse-locale/locale b/data/pt-br.mse-locale/locale index e424896f..addae14b 100644 --- a/data/pt-br.mse-locale/locale +++ b/data/pt-br.mse-locale/locale @@ -1,4 +1,4 @@ -mse version: 2.5.8 +mse version: 2.6.0 installer group: Magic Set Editor/translations/portuguese brazilian full name: Português do Brasil (Brazilian Portuguese) version: 2026-02-28 @@ -21,7 +21,7 @@ menu: export images: Todas as I&magens dos Cards... export apprentice: &Apprentice... export mws: Magic &Workstation... - check updates: &Atualizações... + check updates: &Atualizações / Novas folhas de estilo... print preview: V&isualização da Imprensão... print: &Imprimir... Ctrl+P reload data: Recarregar Dados Ctrl+F5 @@ -582,8 +582,14 @@ label: # stylesheet not found dialog stylesheet not found: - A Edição está tentando abrir a folha de estilo "%s". - Esta folha de estilo não é compatível com o sistema padrão. Por favor escolha uma folha de estilo alternativa. + A Edição está tentando abrir a folha de estilo "%s". + Esta folha de estilo não é compatível com o sistema padrão. + Selecione uma alternativa ou procure-a online. + searching online: Pesquisando online... + searching online fail: Não encontrado online + found online downloading: Encontrado online! Baixando... + found online installing: Encontrado online! Instalando... + found online fail: Falha na instalação # preferences dialog language: Linguagem @@ -837,6 +843,9 @@ button: upgrade group: &Atualizar o grupo remove group: &Remover o grupo + # stylesheet not found dialog + find package online: Pesquisar online + ############################################################## Titles in the GUI title: # window titles @@ -981,10 +990,14 @@ action: ############################################################## Error messages error: # file related - file not found: O arquivo não foi encontrado: '%s' em pacotes '%s' + file not found: O arquivo não foi encontrado: '%s' no pacote '%s' file not found package like: - Arquivo nao encontrado: '%s' in package '%s' + Arquivo nao encontrado: '%s' no pacote '%s' Se você está tentando abrir um arquivo de outro pacote, use "/package/filename" + file not found package like init: + Arquivo nao encontrado: '%s' no pacote '%s' + Se esta pasta estiver vazia ou não for usada, exclua-a. + package name parse error: Não foi possível analisar o nome do pacote '%s' file parse error: Erro ao analisar o arquivo: '%s' %s diff --git a/data/ru.mse-locale/locale b/data/ru.mse-locale/locale index 6d93250b..5e6eb123 100644 --- a/data/ru.mse-locale/locale +++ b/data/ru.mse-locale/locale @@ -1,4 +1,4 @@ -mse version: 2.5.8 +mse version: 2.6.0 installer group: Magic Set Editor/translations/russian full name: Русский (Russian) version: 2026-02-28 @@ -648,6 +648,16 @@ label: stylesheet not found: Сет, который ты пытаешься открыть использует стиль "%s". Этого стиля не найдено в твоей системе, выбери альтернативу + #TODO: Localize + searching online: Searching online... + #TODO: Localize + searching online fail: Not found online + #TODO: Localize + found online downloading: Found online! Downloading... + #TODO: Localize + found online installing: Found online! Installing... + #TODO: Localize + found online fail: Installation failed # preferences dialog language: Язык @@ -946,6 +956,10 @@ button: upgrade group: Обновить все remove group: Удалить все + # stylesheet not found dialog + #TODO: Localize + find package online: Search Online + ############################################################## Titles in the GUI title: # window titles @@ -1114,6 +1128,12 @@ error: file not found package like: File not found: '%s' in package '%s' If you are trying to open a file from another package, use "/package/filename" + #TODO: Localize + file not found package like init: + File not found: '%s' in package '%s' + If this folder is empty or unused, delete it. + #TODO: Localize + package name parse error: Unable to parse package name '%s' file parse error: Error while parsing file: '%s' %s diff --git a/src/data/format/apprentice.cpp b/src/data/format/apprentice.cpp index 88dc2d43..e68f0e07 100644 --- a/src/data/format/apprentice.cpp +++ b/src/data/format/apprentice.cpp @@ -640,8 +640,8 @@ ApprenticeExportWindow::ApprenticeExportWindow(Window* parent, const SetP& set) s->Add(new wxStaticText(this, -1, _HELP_( "set code")), 0, wxALL, 4); s->AddSpacer(4); s->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | (wxALL & ~wxTOP), 8); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); } void ApprenticeExportWindow::onApprenticeBrowse(wxCommandEvent& ev) { diff --git a/src/data/installer.cpp b/src/data/installer.cpp index fc09d795..6fb81fcb 100644 --- a/src/data/installer.cpp +++ b/src/data/installer.cpp @@ -16,6 +16,7 @@ #include #include #include // load_resource_image +#include #include #include #include @@ -319,6 +320,27 @@ void InstallablePackage::determineStatus() { } } +bool InstallablePackage::ensureIsDownloaded() { + if (!installer) return true; // Nothing to download + if (installer->installer) return true; // Already loaded + if (installer->installer_url.empty()) return false; // No URL + // download installer + wxWebRequestSync request = wxWebSessionSync::GetDefault().CreateRequest(installer->installer_url); + auto const result = request.Execute(); + if (!result) { + throw Error(_ERROR_2_("can't download installer", description->name, installer->installer_url)); + } + wxInputStream* is(request.GetResponse().GetStream()); + installer->installer_file = wxFileName::CreateTempFileName(_("mse-installer")); + wxFileOutputStream os(installer->installer_file); + os.Write(*is); + os.Close(); + // open installer + installer->installer = make_intrusive(); + installer->installer->open(installer->installer_file); + return true; +} + bool InstallablePackage::willBeInstalled() const { return has(PACKAGE_ACT_INSTALL) || (has(PACKAGE_INSTALLED) && !has(PACKAGE_ACT_REMOVE)); diff --git a/src/data/installer.hpp b/src/data/installer.hpp index c6f1c87f..12ef0cf0 100644 --- a/src/data/installer.hpp +++ b/src/data/installer.hpp @@ -152,7 +152,8 @@ public: int old_automatic; void determineStatus(); - + bool ensureIsDownloaded(); + /// After the action, will the package be installed? bool willBeInstalled() const; diff --git a/src/data/stylesheet.cpp b/src/data/stylesheet.cpp index a06a13c8..bb183914 100644 --- a/src/data/stylesheet.cpp +++ b/src/data/stylesheet.cpp @@ -38,21 +38,13 @@ StyleSheetP StyleSheet::byGameAndName(const Game& game, const String& name) { return package_manager.open(full_name); } } catch (PackageNotFoundError& e) { - queue_message(MESSAGE_ERROR, _("Missing stylesheet: ") + full_name); - - // This causes a freeze when the set contains two cards that use the same missing StyleSheet, and the second one has styling_data - // Also, it's probably better to ask the user for an alternative for each missing StyleSheet individually - //if (stylesheet_for_reading()) { - // // we already have a stylesheet higher up, so just return a null pointer - // return StyleSheetP(); - //} - // load an alternative stylesheet - StyleSheetP ss = select_stylesheet(game, name); + StyleSheetP ss = select_stylesheet(game, full_name); if (ss) { stylesheet_alternatives[full_name] = ss->relativeFilename(); return ss; } else { + queue_message(MESSAGE_ERROR, _("Missing stylesheet: ") + full_name); throw e; } } @@ -103,8 +95,8 @@ void mark_dependency_value(const StyleSheet& stylesheet, const Dependency& dep) IMPLEMENT_REFLECTION(StyleSheet) { - REFLECT(game); REFLECT_BASE(Packaged); + REFLECT(game); REFLECT(card_width); REFLECT(card_height); REFLECT(card_dpi); diff --git a/src/gfx/generated_image.cpp b/src/gfx/generated_image.cpp index 51306719..4b80e3e5 100644 --- a/src/gfx/generated_image.cpp +++ b/src/gfx/generated_image.cpp @@ -816,8 +816,8 @@ ImportedImage::ImportedImage(Set* set, const String& filepath) { // determine save name loadpath = filepath; savename = normalize_internal_filename(loadpath); - savename.Replace(":", "-"); - savename.Replace("/", "-"); + savename.Replace(_(":"), _("-")); + savename.Replace(_("/"), _("-")); // does the file pointed to by filepath exist? if (!wxFileName(loadpath, wxPATH_UNIX).FileExists()) { diff --git a/src/gui/add_csv_window.cpp b/src/gui/add_csv_window.cpp index a38632e0..07928787 100644 --- a/src/gui/add_csv_window.cpp +++ b/src/gui/add_csv_window.cpp @@ -48,8 +48,8 @@ AddCSVWindow::AddCSVWindow(Window* parent, const SetP& set, bool sizer) s2->Add(CreateButtonSizer(wxOK | wxCANCEL), 1, wxEXPAND, 8); s->Add(s2, 0, wxEXPAND | wxALL, 12); file_browse->SetFocus(); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); SetSize(500, 110); } } diff --git a/src/gui/add_json_window.cpp b/src/gui/add_json_window.cpp index f6ca1867..ad8be17a 100644 --- a/src/gui/add_json_window.cpp +++ b/src/gui/add_json_window.cpp @@ -59,8 +59,8 @@ AddJSONWindow::AddJSONWindow(Window* parent, const SetP& set, bool sizer) s2->Add(CreateButtonSizer(wxOK | wxCANCEL), 1, wxEXPAND, 8); s->Add(s2, 0, wxEXPAND | wxALL, 12); file_browse->SetFocus(); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); SetSize(500, 110); } } diff --git a/src/gui/auto_replace_window.cpp b/src/gui/auto_replace_window.cpp index a00206a9..a76a6266 100644 --- a/src/gui/auto_replace_window.cpp +++ b/src/gui/auto_replace_window.cpp @@ -199,8 +199,8 @@ AutoReplaceWindow::AutoReplaceWindow(Window* parent, const Game& game) s4->Add(defaults, 0, wxALL & ~wxRIGHT, 8); s4->Add(CreateButtonSizer(wxOK | wxCANCEL), 1, wxALL, 8); s->Add(s4, 0, wxEXPAND); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); // Set default size SetSize(350, 450); // initialize values diff --git a/src/gui/bulk_modification_window.cpp b/src/gui/bulk_modification_window.cpp index 69f0a459..813aa331 100644 --- a/src/gui/bulk_modification_window.cpp +++ b/src/gui/bulk_modification_window.cpp @@ -85,8 +85,8 @@ BulkModificationWindow::BulkModificationWindow(Window* parent, const SetP& set, s1->AddButton(new wxButton(this, wxID_CANCEL)); s1->Realize(); s->Add(s1, 1, wxEXPAND | wxALL, 12); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); SetSize(600, 400); Layout(); } diff --git a/src/gui/card_link_window.cpp b/src/gui/card_link_window.cpp index 4ad2d9af..b0563a80 100644 --- a/src/gui/card_link_window.cpp +++ b/src/gui/card_link_window.cpp @@ -53,8 +53,8 @@ CardLinkWindow::CardLinkWindow(Window* parent, const SetP& set, const CardP& sel s2->Add(sel_none, 0, wxEXPAND | wxRIGHT, 8); s2->Add(CreateButtonSizer(wxOK | wxCANCEL), 1, wxEXPAND, 8); s->Add(s2, 0, wxEXPAND | (wxALL & ~wxTOP), 8); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); SetSize(600,500); } } diff --git a/src/gui/card_select_window.cpp b/src/gui/card_select_window.cpp index 0c0da474..4ae99c81 100644 --- a/src/gui/card_select_window.cpp +++ b/src/gui/card_select_window.cpp @@ -140,8 +140,8 @@ CardSelectWindow::CardSelectWindow(Window* parent, const SetP& set, const String s2->Add(sel_none, 0, wxEXPAND | wxRIGHT, 8); s2->Add(CreateButtonSizer(wxOK | wxCANCEL), 1, wxEXPAND, 8); s->Add(s2, 0, wxEXPAND | (wxALL & ~wxTOP), 8); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); SetSize(600,500); } } diff --git a/src/gui/control/card_list_column_select.cpp b/src/gui/control/card_list_column_select.cpp index e3bc2fe3..e28f4bba 100644 --- a/src/gui/control/card_list_column_select.cpp +++ b/src/gui/control/card_list_column_select.cpp @@ -34,8 +34,8 @@ CardListColumnSelectDialog::CardListColumnSelectDialog(Window* parent, const Gam s2->Add(s3, 0, wxEXPAND | (wxALL & ~wxTOP), 4); s->Add(s2 , 1, wxEXPAND | wxALL, 4); s->Add(CreateButtonSizer(wxOK | wxCANCEL) , 0, wxEXPAND | wxALL, 8); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); // Set default size SetSize(350, 450); // Initialize order list diff --git a/src/gui/downloadable_installers.hpp b/src/gui/downloadable_installers.hpp index 7d7c0835..3ee939ae 100644 --- a/src/gui/downloadable_installers.hpp +++ b/src/gui/downloadable_installers.hpp @@ -68,12 +68,12 @@ public: /// Show a dialog to inform the user that updates are available (if there are any) /// Call check_updates first. Call this function from an onIdle loop - inline void show_update_dialog(Window* parent) { + inline void show_update_dialog(Window* set_window) { if (shown_dialog || check_status != FOUND) return; // we already have the latest version, or this has already been displayed. shown_dialog = true; - wxMessageDialog dial = wxMessageDialog(parent, _LABEL_("updates found"), _TITLE_("updates available"), wxYES_NO); + wxMessageDialog dial = wxMessageDialog(set_window, _LABEL_("updates found"), _TITLE_("updates available"), wxYES_NO); if (dial.ShowModal() == wxID_YES) { - (new PackagesWindow(parent))->Show(); + (new PackagesWindow(set_window))->Show(); } } diff --git a/src/gui/html_export_window.cpp b/src/gui/html_export_window.cpp index cd643bfd..3332a275 100644 --- a/src/gui/html_export_window.cpp +++ b/src/gui/html_export_window.cpp @@ -44,11 +44,11 @@ HtmlExportWindow::HtmlExportWindow(Window* parent, const SetP& set, const Export s2->Add(s3, 7, wxEXPAND | wxLEFT, 8); s->Add(s2, 1, wxEXPAND | wxALL, 4); s->Add(CreateButtonSizer(wxOK | wxCANCEL) , 0, wxEXPAND | wxALL, 8); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); SetSize(700,500); // list - list->showData(set->game->name() + _("-*")); + list->showData(set->game->name() + _("*")); list->select(settings.gameSettingsFor(*set->game).default_export); } diff --git a/src/gui/image_slice_window.cpp b/src/gui/image_slice_window.cpp index 78754c20..bc09dde6 100644 --- a/src/gui/image_slice_window.cpp +++ b/src/gui/image_slice_window.cpp @@ -229,8 +229,8 @@ ImageSliceWindow::ImageSliceWindow(Window* parent, const Image& source, const St s5->AddStretchSpacer(1); s->Add(s5, 0, wxEXPAND); s->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxALL, 8); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); // Only now do we allow events to be processed. initialized = true; updateControls(); diff --git a/src/gui/images_export_window.cpp b/src/gui/images_export_window.cpp index d80258ab..b35b8870 100644 --- a/src/gui/images_export_window.cpp +++ b/src/gui/images_export_window.cpp @@ -43,8 +43,8 @@ ImagesExportWindow::ImagesExportWindow(Window* parent, const SetP& set, const Ex wxSizer* s3 = ExportWindowBase::Create(); s->Add(s3, 1, wxEXPAND | (wxALL & ~wxTOP), 8); s->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | (wxALL & ~wxTOP), 8); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); SetSize(500,-1); } diff --git a/src/gui/new_window.cpp b/src/gui/new_window.cpp index 456c0fda..c8c4d541 100644 --- a/src/gui/new_window.cpp +++ b/src/gui/new_window.cpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -56,8 +58,8 @@ NewSetWindow::NewSetWindow(Window* parent) s->Add(s3, wxSizerFlags().Expand().Border(wxALL, 6)); s->Add(stylesheet_list, 0, wxEXPAND | (wxALL & ~wxTOP), 4); s->Add(CreateButtonSizer(wxOK | wxCANCEL) , 0, wxEXPAND | wxALL, 8); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); // Resize Layout(); wxSize min_size = GetSizer()->GetMinSize() + GetSize() - GetClientSize(); @@ -177,10 +179,15 @@ StyleSheetP select_stylesheet(const Game& game, const String& failed_name) { SelectStyleSheetWindow::SelectStyleSheetWindow(Window* parent, const Game& game, const String& failed_name) : wxDialog(parent, wxID_ANY, _TITLE_("select stylesheet"), wxDefaultPosition, wxSize(830,320), wxDEFAULT_DIALOG_STYLE) , game(game) + , failed_name(failed_name) { wxBusyCursor wait; - // init controls - stylesheet_list = new PackageList (this, ID_STYLESHEET_LIST); + // init controls + ok_button = new wxButton (this, wxID_OK); + cancel_button = new wxButton (this, wxID_CANCEL); + find_online_button = new wxButton (this, ID_DOWNLOAD_STYLESHEET, _BUTTON_("find package online")); + stylesheet_list = new PackageList (this, ID_STYLESHEET_LIST); + find_online_status_text = new wxStaticText(this, wxID_ANY, _("")); wxStaticText* description = new wxStaticText(this, ID_GAME_LIST, _LABEL_1_("stylesheet not found", failed_name)); wxStaticText* stylesheet_text = new wxStaticText(this, ID_STYLESHEET_LIST, _LABEL_("style type")); @@ -195,18 +202,26 @@ SelectStyleSheetWindow::SelectStyleSheetWindow(Window* parent, const Game& game, s2->AddStretchSpacer(); s2->Add(stylesheet_filter, 1, wxRIGHT, 4); s->Add(s2, wxSizerFlags().Expand().Border(wxALL, 6)); - s->Add(stylesheet_list, 0, wxEXPAND | (wxALL & ~wxTOP), 4); - s->Add(CreateButtonSizer(wxOK | wxCANCEL) , 0, wxEXPAND | wxALL, 8); - s->SetSizeHints(this); + s->Add(stylesheet_list, 0, wxEXPAND | (wxALL & ~wxTOP), 4); + wxBoxSizer* s3 = new wxBoxSizer(wxHORIZONTAL); + s3->Add(find_online_button, 0, wxRIGHT, 8); + s3->Add(find_online_status_text, 1, wxALIGN_CENTER_VERTICAL); + s3->AddStretchSpacer(); + s3->Add(ok_button, 0, wxRIGHT, 4); + s3->Add(cancel_button, 0); + s->Add(s3, 0, wxEXPAND | wxALL, 8); SetSizer(s); + s->SetSizeHints(this); // init list - stylesheet_list->showData(game.name() + _("-*")); + stylesheet_list->showData(game.name() + _("*")); stylesheet_list->select(settings.gameSettingsFor(game).default_stylesheet); // Resize Layout(); wxSize min_size = GetSizer()->GetMinSize() + GetSize() - GetClientSize(); SetSize(830,min_size.y); - UpdateWindowUI(wxUPDATE_UI_RECURSE); + UpdateWindowUI(wxUPDATE_UI_RECURSE); + // start downloading the installer list + downloadable_installers.download(); } void SelectStyleSheetWindow::onStyleSheetSelect(wxCommandEvent&) { @@ -226,7 +241,88 @@ void SelectStyleSheetWindow::onStylesheetFilterUpdate(wxCommandEvent&) { else { stylesheet_list->setFilter(stylesheet_filter->getFilter()); } -} +} + +void SelectStyleSheetWindow::onFindOnline(wxCommandEvent&) { + if (searching_online) return; + searching_online = true; + find_online_status_text->SetLabel(_LABEL_("searching online")); + find_online_button->Enable(false); + //downloadable_installers.download(); +} + +void SelectStyleSheetWindow::tryAutoInstall() { + auto_installing = true; + searching_online = false; + wxBusyCursor busy; + // search for missing stylesheet + InstallablePackages packages; + package_manager.findAllInstalledPackages(packages); + FOR_EACH(inst, downloadable_installers.installers) { + merge(packages, inst); + } + FOR_EACH(p, packages) { + if (!p) continue; + p->determineStatus(); + } + InstallablePackageP target; + FOR_EACH(p, packages) { + if (!p || !p->description) continue; + if (p->description->name == failed_name) { + target = p; + break; + } + } + if (!target) { + find_online_status_text->SetLabel(_LABEL_("searching online fail")); + auto_installing = false; + return; + } + try { + // update UI + find_online_status_text->SetLabel(_LABEL_("found online downloading")); + ok_button->Enable(false); + cancel_button->Enable(false); + stylesheet_list->Enable(false); + stylesheet_filter->Enable(false); + Layout(); + Refresh(); + Update(); + wxSafeYield(this, true); + // resolve dependencies + PackageAction where = is_install_local(settings.install_type) ? PACKAGE_ACT_LOCAL : PACKAGE_ACT_GLOBAL; + bool action_ok = set_package_action(packages, target, PACKAGE_ACT_INSTALL | where); + if (!action_ok) throw Error(_("can't resolve dependencies")); + // download stylesheet and dependencies + FOR_EACH(p, packages) { + if (!p->has(PACKAGE_ACT_INSTALL)) continue; + p->ensureIsDownloaded(); + } + // update UI + find_online_status_text->SetLabel(_LABEL_("found online installing")); + Layout(); + Refresh(); + Update(); + wxSafeYield(this, true); + // install stylesheet and dependencies + FOR_EACH(p, packages) { + if (!p->has(PACKAGE_ACT_INSTALL)) continue; + bool package_ok = package_manager.install(*p); + if (!package_ok) throw Error(_("install package failed")); + } + // auto select stylesheet and exit + stylesheet = StyleSheet::byGameAndName(game, failed_name); + EndModal(wxID_OK); + } catch (const Error& e) { + handle_error(e); + auto_installing = false; + find_online_status_text->SetLabel(_LABEL_("found online fail")); + ok_button->Enable(true); + cancel_button->Enable(true); + stylesheet_list->Enable(true); + stylesheet_filter->Enable(true); + } +} void SelectStyleSheetWindow::OnOK(wxCommandEvent&) { done(); @@ -245,22 +341,29 @@ void SelectStyleSheetWindow::done() { void SelectStyleSheetWindow::onUpdateUI(wxUpdateUIEvent& ev) { switch (ev.GetId()) { case wxID_OK: - ev.Enable(stylesheet_list->hasSelection()); + if (!auto_installing) ev.Enable(stylesheet_list->hasSelection()); break; } } void SelectStyleSheetWindow::onIdle(wxIdleEvent& ev) { - // Stuff that must be done in the main thread - //handle_pending_errors(); // errors are ignored until set window is shown + if (searching_online && !auto_installing) { + // still downloading? + if (!downloadable_installers.download()) { + return; + } + // installer list ready + tryAutoInstall(); + } } BEGIN_EVENT_TABLE(SelectStyleSheetWindow, wxDialog) - EVT_GALLERY_SELECT (ID_STYLESHEET_LIST, SelectStyleSheetWindow::onStyleSheetSelect) - EVT_GALLERY_ACTIVATE(ID_STYLESHEET_LIST, SelectStyleSheetWindow::onStyleSheetActivate) - EVT_COMMAND_RANGE(ID_STYLESHEET_FILTER, ID_STYLESHEET_FILTER, wxEVT_COMMAND_TEXT_UPDATED, SelectStyleSheetWindow::onStylesheetFilterUpdate) - EVT_BUTTON (wxID_OK, SelectStyleSheetWindow::OnOK) - EVT_UPDATE_UI (wxID_ANY, SelectStyleSheetWindow::onUpdateUI) - EVT_IDLE ( SelectStyleSheetWindow::onIdle) + EVT_GALLERY_SELECT (ID_STYLESHEET_LIST, SelectStyleSheetWindow::onStyleSheetSelect) + EVT_GALLERY_ACTIVATE(ID_STYLESHEET_LIST, SelectStyleSheetWindow::onStyleSheetActivate) + EVT_COMMAND_RANGE (ID_STYLESHEET_FILTER, ID_STYLESHEET_FILTER, wxEVT_COMMAND_TEXT_UPDATED, SelectStyleSheetWindow::onStylesheetFilterUpdate) + EVT_BUTTON (ID_DOWNLOAD_STYLESHEET, SelectStyleSheetWindow::onFindOnline) + EVT_BUTTON (wxID_OK, SelectStyleSheetWindow::OnOK) + EVT_UPDATE_UI (wxID_ANY, SelectStyleSheetWindow::onUpdateUI) + EVT_IDLE ( SelectStyleSheetWindow::onIdle) END_EVENT_TABLE () diff --git a/src/gui/new_window.hpp b/src/gui/new_window.hpp index 9f427e72..e2fbd222 100644 --- a/src/gui/new_window.hpp +++ b/src/gui/new_window.hpp @@ -81,22 +81,32 @@ private: const Game& game; // gui items - PackageList* stylesheet_list; + PackageList* stylesheet_list; + + FilterCtrl* stylesheet_filter; + String stylesheet_filter_value; + + wxButton* ok_button, *cancel_button; + + wxButton* find_online_button; + wxStaticText* find_online_status_text; + bool searching_online = false; + bool auto_installing = false; + String failed_name; - FilterCtrl* stylesheet_filter; - String stylesheet_filter_value; - // --------------------------------------------------- : events void onStyleSheetSelect (wxCommandEvent&); void onStyleSheetActivate(wxCommandEvent&); void onStylesheetFilterUpdate(wxCommandEvent&); - + void onFindOnline(wxCommandEvent&); virtual void OnOK(wxCommandEvent&); void onUpdateUI(wxUpdateUIEvent&); - void onIdle(wxIdleEvent&); - + void onIdle(wxIdleEvent&); + + void tryAutoInstall(); + // we are done, close the window void done(); }; diff --git a/src/gui/packages_window.cpp b/src/gui/packages_window.cpp index 90290917..b79534e0 100644 --- a/src/gui/packages_window.cpp +++ b/src/gui/packages_window.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -131,9 +130,7 @@ END_EVENT_TABLE() // ----------------------------------------------------------------------------- : PackagesWindow -enum Action { - KEEP, INSTALL, UPGRADE, REMOVE -}; +DEFINE_EVENT_TYPE(EVENT_PACKAGE_LIST_CHANGED); PackagesWindow::PackagesWindow(Window* parent, bool download_package_list) : waiting_for_list(download_package_list) @@ -239,7 +236,7 @@ void PackagesWindow::onActionChange(wxCommandEvent& ev) { ); package_list->Refresh(false); UpdateWindowUI(wxUPDATE_UI_RECURSE); -} +} void PackagesWindow::onOk(wxCommandEvent& ev) { // count number of packages to change @@ -261,7 +258,7 @@ void PackagesWindow::onOk(wxCommandEvent& ev) { } } // anything to do? - if (!to_change) { + if (!to_change && !app_change) { ev.Skip(); return; } @@ -281,8 +278,6 @@ void PackagesWindow::onOk(wxCommandEvent& ev) { this, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_SMOOTH | wxSTAY_ON_TOP ); - // Clear package list - package_manager.reset(); // Download installers int package_pos = 0, step = 0; FOR_EACH(ip, installable_packages) { @@ -290,21 +285,8 @@ void PackagesWindow::onOk(wxCommandEvent& ev) { if (ip->has(PACKAGE_ACT_INSTALL) && ip->installer && !ip->installer->installer) { if (!progress.Update(step++, String::Format(_ERROR_("downloading updates"), ++package_pos, to_download))) { return; // aborted - } - // download installer - wxWebRequestSync request = wxWebSessionSync::GetDefault().CreateRequest(ip->installer->installer_url); - auto const result = request.Execute(); - if (!result) { - throw Error(_ERROR_2_("can't download installer", ip->description->name, ip->installer->installer_url)); - } - wxInputStream* is(request.GetResponse().GetStream()); - ip->installer->installer_file = wxFileName::CreateTempFileName(_("mse-installer")); - wxFileOutputStream os(ip->installer->installer_file); - os.Write(*is); - os.Close(); - // open installer - ip->installer->installer = make_intrusive(); - ip->installer->installer->open(ip->installer->installer_file); + } + ip->ensureIsDownloaded(); } } // Install stuff @@ -369,6 +351,8 @@ void PackagesWindow::onOk(wxCommandEvent& ev) { // } //} } + // Notify that packages have changed + sendEvent(); // Continue event propagation into the dialog window so that it closes. ev.Skip(); //%% TODO: will we delete packages? @@ -421,6 +405,9 @@ void PackagesWindow::onUpdateUI(wxUpdateUIEvent& ev) { package_list->allSelectedPackages([&](const InstallablePackageP& p) { return p->has(PACKAGE_ACT_REMOVE | where) || (!p->has(PACKAGE_INSTALLED) && !p->has(PACKAGE_ACT_INSTALL)); + }) && + package_list->anySelectedPackage([&](const InstallablePackageP& p) { + return p->has(PACKAGE_ACT_REMOVE | where); }) ); w->Enable( @@ -455,7 +442,12 @@ bool PackagesWindow::checkInstallerList(bool refresh) { UpdateWindowUI(wxUPDATE_UI_RECURSE); } return true; -} +} + +void PackagesWindow::sendEvent() { + wxCommandEvent ev(EVENT_PACKAGE_LIST_CHANGED, GetId()); + wxPostEvent(GetParent(), ev); +} BEGIN_EVENT_TABLE(PackagesWindow, wxDialog) EVT_LISTBOX (ID_PACKAGE_LIST, PackagesWindow::onPackageSelect) diff --git a/src/gui/packages_window.hpp b/src/gui/packages_window.hpp index 7333642c..7e02b146 100644 --- a/src/gui/packages_window.hpp +++ b/src/gui/packages_window.hpp @@ -50,6 +50,8 @@ private: /// Check whether we have downloaded the list of installers /** If the download is (partially) complete, update the installable_packages list */ - bool checkInstallerList(bool refresh = true); + bool checkInstallerList(bool refresh = true); + /// Notify that the package list has changed + void sendEvent(); }; diff --git a/src/gui/preferences_window.cpp b/src/gui/preferences_window.cpp index 6de24cc4..c38526fc 100644 --- a/src/gui/preferences_window.cpp +++ b/src/gui/preferences_window.cpp @@ -125,8 +125,8 @@ PreferencesWindow::PreferencesWindow(Window* parent) s->Add(nb, 1, wxEXPAND | (wxALL & ~wxBOTTOM), 8); s->AddSpacer(4); s->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | (wxALL & ~wxTOP), 8); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); } void PreferencesWindow::onOk(wxCommandEvent&) { @@ -177,7 +177,6 @@ GlobalPreferencesPage::GlobalPreferencesPage(Window* parent) dark_mode->SetSelection((int)settings.dark_mode_type); // init sizer wxSizer* s = new wxBoxSizer(wxVERTICAL); - s->SetSizeHints(this); wxSizer* s2 = new wxStaticBoxSizer(wxVERTICAL, this, _LABEL_("language")); s2->Add(new wxStaticText(this, wxID_ANY, _LABEL_("app language")), 0, wxALL, 4); s2->Add(language, 0, wxEXPAND | (wxALL & ~wxTOP), 4); @@ -191,6 +190,7 @@ GlobalPreferencesPage::GlobalPreferencesPage(Window* parent) s4->Add(new wxStaticText(this, wxID_ANY, _HELP_( "app language")), 0, wxALL, 4); s->Add(s4, 0, wxEXPAND | wxALL, 8); SetSizer(s); + s->SetSizeHints(this); } void GlobalPreferencesPage::store() { @@ -243,8 +243,8 @@ DisplayPreferencesPage::DisplayPreferencesPage(Window* parent) s3->Add(new wxStaticText(this, wxID_ANY, _LABEL_("percent of normal")),1, wxALL & ~wxRIGHT, 4); s2->Add(s3, 0, wxEXPAND | wxALL, 4); s->Add(s2, 0, wxEXPAND | wxALL, 8); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); } void DisplayPreferencesPage::store() { @@ -342,8 +342,8 @@ TransfersPreferencesPage::TransfersPreferencesPage(Window* parent) : Preferences s->Add(s2, 0, wxEXPAND | wxALL, 8); s->Add(s5, 0, wxEXPAND | wxALL, 8); export_scale->SetFocus(); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); } void TransfersPreferencesPage::store() { @@ -375,8 +375,8 @@ DirsPreferencesPage::DirsPreferencesPage(Window* parent) s3->Add(ab, 0, wxEXPAND); s2->Add(s3, 0, wxEXPAND | (wxALL & ~wxTOP), 4); s->Add(s2, 0, wxEXPAND | wxALL, 8); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); } void DirsPreferencesPage::store() { @@ -440,14 +440,17 @@ void UpdatePreferencesPage::store() { else settings.check_updates_what = CHECK_EVERYTHING; } -void UpdatePreferencesPage::onCheckUpdatesNow(wxCommandEvent&) { +void UpdatePreferencesPage::onCheckUpdatesNow(wxCommandEvent&) { + downloadable_installers.shown_dialog = true; downloadable_installers.check_updates_now(false); if (downloadable_installers.check_status == DownloadableInstallerList::CheckStatus::FAILED) { wxMessageBox(_ERROR_("checking updates failed"), _TITLE_("update check"), wxICON_ERROR | wxOK); } else if (downloadable_installers.check_status == DownloadableInstallerList::CheckStatus::NOT_FOUND) { wxMessageBox(_ERROR_("no updates"), _TITLE_("update check"), wxICON_INFORMATION | wxOK); } else { - (new PackagesWindow(GetParent()))->Show(); + wxWindow* set_window = this; + while (set_window->GetParent()) set_window = set_window->GetParent(); + (new PackagesWindow(set_window))->Show(); } } diff --git a/src/gui/set/cards_panel.cpp b/src/gui/set/cards_panel.cpp index 31270599..6cfdcea0 100644 --- a/src/gui/set/cards_panel.cpp +++ b/src/gui/set/cards_panel.cpp @@ -118,8 +118,8 @@ CardsPanel::CardsPanel(Window* parent, int id) link_grid_4->Add(link_viewer_4, wxGBPosition(1, 0), wxGBSpan(1, 2)); s->Add(s_left, 0, wxEXPAND | wxRIGHT, 2); s->Add(splitter, 1, wxEXPAND); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); // init menus menuCard = new wxMenu(); diff --git a/src/gui/set/console_panel.cpp b/src/gui/set/console_panel.cpp index 5127e3e7..d00d5acf 100644 --- a/src/gui/set/console_panel.cpp +++ b/src/gui/set/console_panel.cpp @@ -515,8 +515,8 @@ ConsolePanel::ConsolePanel(Window* parent, int id) // init sizer wxSizer* s = new wxBoxSizer(wxVERTICAL); s->Add(splitter, 1, wxEXPAND); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); // init menus menuConsole = new wxMenu(); diff --git a/src/gui/set/keywords_panel.cpp b/src/gui/set/keywords_panel.cpp index 854bf28c..0540154c 100644 --- a/src/gui/set/keywords_panel.cpp +++ b/src/gui/set/keywords_panel.cpp @@ -92,8 +92,8 @@ void KeywordsPanel::initControls() { // init sizer wxSizer* s = new wxBoxSizer(wxHORIZONTAL); s->Add(splitter, 1, wxEXPAND); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); //s->Add(new wxStaticText(this, wxID_ANY, _("Sorry, no keywords for now"),wxDefaultPosition,wxDefaultSize,wxALIGN_CENTER), 1, wxALIGN_CENTER); // TODO: Remove /* wxSizer* s2 = new wxBoxSizer(wxVERTICAL); diff --git a/src/gui/set/panel.hpp b/src/gui/set/panel.hpp index e9634d3a..15cabe63 100644 --- a/src/gui/set/panel.hpp +++ b/src/gui/set/panel.hpp @@ -24,8 +24,9 @@ class SetWindowPanel : public wxPanel, public SetView { public: SetWindowPanel(Window* parent, int id, bool autoTabbing = true); - /// We will probably want to respond to set changes + /// We will probably want to respond to set changes or package list changes virtual void onSetChange() {} + virtual void onPackageListChange() {} // // --------------------------------------------------- : Meta information // diff --git a/src/gui/set/random_pack_panel.cpp b/src/gui/set/random_pack_panel.cpp index 061ca462..33266a1b 100644 --- a/src/gui/set/random_pack_panel.cpp +++ b/src/gui/set/random_pack_panel.cpp @@ -301,8 +301,8 @@ CustomPackDialog::CustomPackDialog(Window* parent, const SetP& set, const PackTy totals->setGame(set->game); updateTotals(); // set sizer - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); } void CustomPackDialog::updateTotals() { @@ -417,8 +417,8 @@ void RandomPackPanel::initControls() { s2->Add(s3, 0, wxEXPAND | (wxALL & ~wxTOP), 4); s2->Add(card_list, 1, wxEXPAND); s->Add(s2, 1, wxEXPAND, 8); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); } RandomPackPanel::~RandomPackPanel() { diff --git a/src/gui/set/set_info_panel.cpp b/src/gui/set/set_info_panel.cpp index 7381ea93..36ef9366 100644 --- a/src/gui/set/set_info_panel.cpp +++ b/src/gui/set/set_info_panel.cpp @@ -22,8 +22,8 @@ SetInfoPanel::SetInfoPanel(Window* parent, int id) // init sizer wxSizer* s = new wxBoxSizer(wxVERTICAL); s->Add(editor, 1, wxEXPAND, 2); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); } void SetInfoPanel::onChangeSet() { diff --git a/src/gui/set/stats_panel.cpp b/src/gui/set/stats_panel.cpp index d7a8ad23..31f4bc19 100644 --- a/src/gui/set/stats_panel.cpp +++ b/src/gui/set/stats_panel.cpp @@ -330,8 +330,8 @@ void StatsPanel::initControls() { s->Add(categories, 0, wxEXPAND | wxRIGHT, 2); #endif s->Add(splitter, 1, wxEXPAND); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); // init menu menuGraph = new wxMenu(); diff --git a/src/gui/set/style_panel.cpp b/src/gui/set/style_panel.cpp index 1f1b7220..d99f874f 100644 --- a/src/gui/set/style_panel.cpp +++ b/src/gui/set/style_panel.cpp @@ -55,8 +55,8 @@ void StylePanel::initControls() { s4->Add(editor, 2, wxEXPAND, 0); s2->Add(s4, 1, wxEXPAND | wxALL, 2); s->Add(s2, 1, wxEXPAND, 8); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); } void StylePanel::initUI(wxToolBar* tb, wxMenuBar* mb) { @@ -95,13 +95,31 @@ bool StylePanel::Layout() { void StylePanel::onChangeSet() { if (!isInitialized()) return; - list->showData(set->game->name() + _("-*")); + list->showData(set->game->name() + _("*")); list->select(set->stylesheet->name(), false); editor->setSet(set); preview->setSet(set); card = CardP(); use_for_all->Enable(false); -} +} + +void StylePanel::onPackageListChange() { + if (!isInitialized()) return; + if (!list) return; + list->showData(set->game->name() + _("*")); + onFilterChange(); +} + +void StylePanel::onFilterChange() { + if (list->hasSelection()) { + StyleSheetP existingStylesheetSelection = list->getSelection(false); + list->setFilter(stylesheet_filter->getFilter()); + list->select(existingStylesheetSelection->name()); + } + else { + list->setFilter(stylesheet_filter->getFilter()); + } +} void StylePanel::onAction(const Action& action, bool undone) { if (!isInitialized()) return; @@ -139,14 +157,7 @@ void StylePanel::onAction(const Action& action, bool undone) { } void StylePanel::onStylesheetFilterUpdate(wxCommandEvent&) { - if (list->hasSelection()) { - StyleSheetP existingStylesheetSelection = list->getSelection(false); - list->setFilter(stylesheet_filter->getFilter()); - list->select(existingStylesheetSelection->name()); - } - else { - list->setFilter(stylesheet_filter->getFilter()); - } + onFilterChange(); } // ----------------------------------------------------------------------------- : Selection diff --git a/src/gui/set/style_panel.hpp b/src/gui/set/style_panel.hpp index e98ffefd..245684c5 100644 --- a/src/gui/set/style_panel.hpp +++ b/src/gui/set/style_panel.hpp @@ -22,14 +22,16 @@ class StylingEditor; class StylePanel : public SetWindowPanel { public: StylePanel(Window* parent, int id); - + void onChangeSet() override; + void onPackageListChange() override; + void onFilterChange(); void onAction(const Action&, bool undone) override; // --------------------------------------------------- : UI void initUI(wxToolBar*, wxMenuBar*) override; - + // --------------------------------------------------- : Clipboard bool canCut() const override; bool canCopy() const override; @@ -61,7 +63,7 @@ private: void onUseCustom(wxCommandEvent&); void onStylesheetFilterUpdate(wxCommandEvent&); - + /// Determine the best size for the list of stylesheets based on available space void updateListSize(); bool Layout() override; diff --git a/src/gui/set/window.cpp b/src/gui/set/window.cpp index 3a7ad4ac..fd3b0d62 100644 --- a/src/gui/set/window.cpp +++ b/src/gui/set/window.cpp @@ -856,6 +856,12 @@ void SetWindow::onMenuOpen(wxMenuEvent& ev) { void SetWindow::onIdle(wxIdleEvent& ev) { // Stuff that must be done in the main thread downloadable_installers.show_update_dialog(this); +} + +void SetWindow::onPackageListChange(wxCommandEvent&) { + FOR_EACH(p, panels) { + p->onPackageListChange(); + } } // ----------------------------------------------------------------------------- : Event table @@ -917,4 +923,5 @@ BEGIN_EVENT_TABLE(SetWindow, wxFrame) EVT_CARD_SELECT (wxID_ANY, SetWindow::onCardSelect) EVT_CARD_ACTIVATE (wxID_ANY, SetWindow::onCardActivate) EVT_SIZE_CHANGE (wxID_ANY, SetWindow::onSizeChange) + EVT_COMMAND (wxID_ANY, EVENT_PACKAGE_LIST_CHANGED, SetWindow::onPackageListChange) END_EVENT_TABLE () diff --git a/src/gui/set/window.hpp b/src/gui/set/window.hpp index 3f82cb48..d87e6f8d 100644 --- a/src/gui/set/window.hpp +++ b/src/gui/set/window.hpp @@ -176,6 +176,8 @@ private: void onIdle (wxIdleEvent&); - void onSizeChange (wxCommandEvent&); + void onSizeChange (wxCommandEvent&); + + void onPackageListChange (wxCommandEvent&); }; diff --git a/src/gui/web_request_window.cpp b/src/gui/web_request_window.cpp index ec0d1d6e..7a713528 100644 --- a/src/gui/web_request_window.cpp +++ b/src/gui/web_request_window.cpp @@ -27,8 +27,8 @@ WebRequestWindow::WebRequestWindow(const String& url, bool sizer) s->Add(address, 0, (wxALL & ~wxTOP), 4); s->Add(gauge, 0, wxEXPAND | wxALL, 8); s->Add(CreateButtonSizer(wxCANCEL), 1, wxEXPAND, 8); - s->SetSizeHints(this); SetSizer(s); + s->SetSizeHints(this); } // create web request diff --git a/src/gui/welcome_window.cpp b/src/gui/welcome_window.cpp index a3a65c97..3df006c6 100644 --- a/src/gui/welcome_window.cpp +++ b/src/gui/welcome_window.cpp @@ -124,8 +124,9 @@ void WelcomeWindow::onOpenSet(wxCommandEvent&) { wxBusyCursor wait; try { close(import_set(dlg->GetPath())); - } catch (Error& e) { - handle_error(_("Error loading set: ") + e.what()); + } catch (Error& e) { + wxMessageDialog dial = wxMessageDialog(this, _("Error loading set: ") + e.what(), _(""), wxOK|wxCENTRE|wxICON_ERROR); + dial.ShowModal(); } } } @@ -140,7 +141,8 @@ void WelcomeWindow::onOpenLast(wxCommandEvent&) { try { close( open_package(settings.recent_sets.front()) ); } catch (PackageNotFoundError& e) { - handle_error(_("Cannot find set ") + e.what() + _(" to open.")); + wxMessageDialog dial = wxMessageDialog(this, _("Cannot find set ") + e.what() + _(" to open."), _(""), wxOK|wxCENTRE|wxICON_ERROR); + dial.ShowModal(); // remove this package from the recent sets, so we don't get this error again settings.recent_sets.erase(settings.recent_sets.begin()); } diff --git a/src/util/io/package.cpp b/src/util/io/package.cpp index 5b38d001..60cfc8be 100644 --- a/src/util/io/package.cpp +++ b/src/util/io/package.cpp @@ -226,8 +226,9 @@ unique_ptr Package::openIn(const String& file) { } FileInfos::iterator it = files.find(normalize_internal_filename(file)); if (it == files.end()) { - // does it look like a relative filename? - if (size_t pos = filename.find(_(".mse-")) != String::npos) { + // does it look like a relative filename? + size_t pos = filename.find(_(".mse-")); + if (pos != String::npos) { // check for nested folder pos = filename.find_last_of(_("/\\")); String nestedFilename = filename + filename.SubString(pos, filename.size()) + wxFileName::GetPathSeparator() + file; @@ -235,7 +236,7 @@ unique_ptr Package::openIn(const String& file) { throw PackageError(_ERROR_1_("nested folder", filename)); } else { - throw PackageError(_ERROR_2_("file not found package like", file, filename)); + throw PackageNotFoundError(_ERROR_2_("file not found package like", file, filename)); } } } diff --git a/src/util/io/package_manager.cpp b/src/util/io/package_manager.cpp index f7c52422..ba79fb40 100644 --- a/src/util/io/package_manager.cpp +++ b/src/util/io/package_manager.cpp @@ -19,6 +19,7 @@ #include #include #include +#include // ----------------------------------------------------------------------------- : PackageManager : in memory @@ -31,21 +32,31 @@ void PackageManager::init() { if (!(local.valid() || global.valid())) throw Error(_("The MSE data files can not be found, there should be a directory called 'data' with these files. ") _("The expected place to find it in was either ") + wxStandardPaths::Get().GetDataDir() + _(" or ") + - wxStandardPaths::Get().GetUserDataDir()); + wxStandardPaths::Get().GetUserDataDir()); + local.deleteEmptyFolders(); + global.deleteEmptyFolders(); } void PackageManager::destroy() { loaded_packages.clear(); } void PackageManager::reset() { loaded_packages.clear(); -} +} -PackagedP PackageManager::openAny(const String& name_, bool just_header) { +void PackageManager::evictFromCache(const String& name_) { + String filename = normalizeFilename(cleanFilename(name_)); + loaded_packages.erase(filename); +} + +String PackageManager::cleanFilename(const String& name_) { String name = trim(name_); if (starts_with(name,_("/"))) name = name.substr(1); - if (starts_with(name,_(":NO-WARN-DEP:"))) name = name.substr(13); - // Attempt to load local data first. + if (starts_with(name,_(":NO-WARN-DEP:"))) name = name.substr(13); + return name; +} +String PackageManager::normalizeFilename(const String& name) { String filename; + // Attempt to load local data first. if (wxFileName(name).IsRelative()) { // local data dir? filename = normalize_filename(local.name(name)); @@ -55,8 +66,13 @@ PackagedP PackageManager::openAny(const String& name_, bool just_header) { } } else { // Absolute filename filename = normalize_filename(name); - } + } + return filename; +} +PackagedP PackageManager::openAny(const String& name_, bool just_header) { + String name = cleanFilename(name_); + String filename = normalizeFilename(name); // Is this package already loaded? PackagedP& p = loaded_packages[filename]; if (!p) { @@ -84,20 +100,24 @@ PackagedP PackageManager::openAny(const String& name_, bool just_header) { void PackageManager::findMatching(const String& pattern, vector& out) { // first find local packages String file = local.findFirstMatching(pattern); - while (!file.empty()) { - out.push_back(openAny(file, true)); + while (!file.empty()) { + if (local.checkForPackageFile(file)) { + out.push_back(openAny(file, true)); + } file = wxFindNextFile(); } // then global packages not already in the list file = global.findFirstMatching(pattern); - while (!file.empty()) { - PackagedP p = openAny(file, true); - if (find(out.begin(), out.end(), p) == out.end()) { - out.push_back(p); + while (!file.empty()) { + if (global.checkForPackageFile(file)) { + PackagedP p = openAny(file, true); + if (find(out.begin(), out.end(), p) == out.end()) { + out.push_back(p); + } } file = wxFindNextFile(); } -} +} bool PackageManager::existsInPackage(const String& name) { if (!name.empty() && name.GetChar(0) == _('/')) { @@ -213,7 +233,7 @@ void PackageManager::findAllInstalledPackages(vector& packa bool PackageManager::install(const InstallablePackage& package) { bool install_local = package.has(PACKAGE_ACT_LOCAL); return (install_local ? local : global).install(package); -} +} // ----------------------------------------------------------------------------- : PackageDirectory @@ -245,11 +265,22 @@ void PackageDirectory::init(const String& dir) { directory = dir; else directory.clear(); -} +} + +void PackageDirectory::deleteEmptyFolders() { + for (String file = findFirstMatching(_("*.mse-*")) ; !file.empty() ; file = wxFindNextFile()) { + if (!wxDir::Exists(file)) continue; + wxDir outerDir(file); + if (!outerDir.HasFiles() && !outerDir.HasSubDirs()) { + wxRmdir(file); + } + } +} String PackageDirectory::name(const String& name) const { return directory + _("/") + name; -} +} + bool PackageDirectory::exists(const String& filename) const { String fn = name(filename); return wxFileExists(fn) || wxDirExists(fn); @@ -263,6 +294,21 @@ String PackageDirectory::findFirstMatching(const String& pattern) const { bool compare_name(const PackageVersionP& a, const PackageVersionP& b) { return a->name < b->name; } + +bool PackageDirectory::checkForPackageFile(const String& folder_name) { + size_t package_pos = folder_name.find_last_of(_(".")); + if (package_pos == String::npos) { + queue_message(MESSAGE_WARNING, _ERROR_1_("package name parse error", folder_name)); + return false; + } + String package_name = folder_name.substr(package_pos+5); + String package_file = folder_name + wxFileName::GetPathSeparator() + package_name; + if (!wxFileExists(package_file) && !wxFileExists(directory + wxFileName::GetPathSeparator() + package_file)) { + queue_message(MESSAGE_WARNING, _ERROR_2_("file not found package like init", package_name, folder_name)); + return false; + } + return true; +} void PackageDirectory::installedPackages(vector& packages_out) { loadDatabase(); @@ -270,9 +316,11 @@ void PackageDirectory::installedPackages(vector& packages_o vector in_dir; for (String s = findFirstMatching(_("*.mse-*")) ; !s.empty() ; s = wxFindNextFile()) { size_t pos = s.find_last_of(_("/\\")); - if (pos != String::npos) s = s.substr(pos+1); + if (pos != String::npos) s = s.substr(pos+1); // TODO : check for valid package names - in_dir.push_back(s); + if (checkForPackageFile(s)) { + in_dir.push_back(s); + } } sort(in_dir.begin(), in_dir.end()); // merge with package database @@ -387,7 +435,8 @@ bool PackageDirectory::install(const InstallablePackage& package) { if (!rename_file_or_dir(n + _(".new"), n)) return false; bless(package.description->name); } - saveDatabase(); + saveDatabase(); + package_manager.evictFromCache(package.description->name); return true; } diff --git a/src/util/io/package_manager.hpp b/src/util/io/package_manager.hpp index 25bd57cb..9c4f19fb 100644 --- a/src/util/io/package_manager.hpp +++ b/src/util/io/package_manager.hpp @@ -60,8 +60,10 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(UpdateData) { class PackageDirectory { public: void init(bool local); - void init(const String& dir); - + void init(const String& dir); + + void deleteEmptyFolders(); + bool valid() const { return !directory.empty(); } /// Name of a package in this directory @@ -74,7 +76,10 @@ public: /// Find all packages that match a filename pattern (using wxFindFirst) String findFirstMatching(const String& pattern) const; - + + /// Verify that a package contains its titular file + bool checkForPackageFile(const String& package_name); + /// Get all installed packages void installedPackages(vector& packages); @@ -115,8 +120,10 @@ public: * we could get into fights with pool allocators used by ScriptValues */ void destroy(); /// Empty the list of packages, they will all be reloaded - void reset(); - + void reset(); + /// Clear a package from the list, it will be reloaded + void evictFromCache(const String& filename_or_name); + // --------------------------------------------------- : Packages in memory /// Open a package with the specified name (including extension) @@ -130,7 +137,11 @@ public: throw InternalError(format_string(_("Package %s loaded as wrong type"),name)); } } - + + /// Prepare a filename so that it can be used as a key in loaded_packages + String cleanFilename(const String& name); + String normalizeFilename(const String& name); + /// Open a package with the specified name, the type of package is determined by its extension! /** @param if just_header is true, then the package is not fully parsed. */ @@ -170,8 +181,8 @@ public: void findAllInstalledPackages(vector& packages); /// Install/uninstall a package, returns success - bool install(const InstallablePackage& package); - + bool install(const InstallablePackage& package); + // --------------------------------------------------- : Other package like things /// Get the directory for dictionary files diff --git a/src/util/version.cpp b/src/util/version.cpp index b35c6127..21abd65a 100644 --- a/src/util/version.cpp +++ b/src/util/version.cpp @@ -91,12 +91,12 @@ const Char* version_suffix = _(" (ascii build)"); * 2.0.2 : store game and stylesheet version numbers */ const Version file_version_locale = Version(2u, 0u, 2u); -const Version file_version_set = Version(2u, 0u, 2u); -const Version file_version_game = Version(0u, 3u, 8u); -const Version file_version_stylesheet = Version(0u, 3u, 8u); +const Version file_version_set = Version(2u, 6u, 0u); +const Version file_version_game = Version(2u, 6u, 0u); +const Version file_version_stylesheet = Version(2u, 6u, 0u); const Version file_version_symbol_font = Version(0u, 3u, 6u); const Version file_version_export_template = Version(0u, 3u, 7u); -const Version file_version_installer = Version(0u, 3u, 7u); +const Version file_version_installer = Version(2u, 6u, 0u); const Version file_version_symbol = Version(0u, 3u, 5u); const Version file_version_clipboard = Version(2u, 6u, 0u); -const Version file_version_script = Version(0u, 3u, 7u); +const Version file_version_script = Version(2u, 6u, 0u); diff --git a/src/util/window_id.hpp b/src/util/window_id.hpp index ce5493a5..06d26c9d 100644 --- a/src/util/window_id.hpp +++ b/src/util/window_id.hpp @@ -335,6 +335,13 @@ enum ControlID { ID_CARD_LINK_RELATION_1, ID_CARD_LINK_RELATION_2, ID_CARD_LINK_RELATION_3, - ID_CARD_LINK_RELATION_4, -}; + ID_CARD_LINK_RELATION_4, + // Select stylesheet window + ID_DOWNLOAD_STYLESHEET, +}; + +// ----------------------------------------------------------------------------- : Custom Events + +DECLARE_EVENT_TYPE(EVENT_PACKAGE_LIST_CHANGED, ); +