From 17b6e40d60f3de2ff357c5dec878199452dd0c24 Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Mon, 23 Sep 2024 17:03:31 +0000 Subject: [PATCH 001/104] Translated using Weblate (Spanish) Currently translated at 100.0% (269 of 269 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/ --- LogarithmPlotter/i18n/lp_es.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/LogarithmPlotter/i18n/lp_es.ts b/LogarithmPlotter/i18n/lp_es.ts index 96cb5de..02b39ef 100644 --- a/LogarithmPlotter/i18n/lp_es.ts +++ b/LogarithmPlotter/i18n/lp_es.ts @@ -1825,7 +1825,7 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u integral(<from: number>, <to: number>, <f: ExecutableObject>) - integral(<desde: número>, <hasta: número>, <f: objeto ejecutable>) + integral(<desde: número>, <hasta: número>, <f: Objeto similar a una función>) @@ -1849,17 +1849,17 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u integral(<from: number>, <to: number>, <f: string>, <variable: string>) - + integral(<desde: número>, <hasta: número>, <f: cadena>, <variable: cadena>) derivative(<f: ExecutableObject>, <x: number>) - derivada(<f: ExecutableObject>, <x: number>) + derivative(<f: objeto similar a una función>, <x: número>) derivative(<f: string>, <variable: string>, <x: number>) - derivada(<f: string>, <variable: string>, <x: number>) + derivative(<f: cadena>, <variable: cadena>, <x: número>) From fbb85083c1254eea7bb4d7205f60249289c3f3c3 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 24 Sep 2024 19:39:53 +0000 Subject: [PATCH 002/104] Translated using Weblate (German) Currently translated at 100.0% (269 of 269 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/ --- LogarithmPlotter/i18n/lp_de.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LogarithmPlotter/i18n/lp_de.ts b/LogarithmPlotter/i18n/lp_de.ts index 0dbfa98..761283f 100644 --- a/LogarithmPlotter/i18n/lp_de.ts +++ b/LogarithmPlotter/i18n/lp_de.ts @@ -1825,7 +1825,7 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde integral(<from: number>, <to: number>, <f: ExecutableObject>) - integral(<von: Zahl>, <bis: Zahl>, <f: ExecutableObject>) + integral(<von: Zahl>, <bis: Zahl>, <f: Funktionsähnliches Objekt>) From f8ce98d4adf1b61229176ab75a9e3c357f1f139b Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 27 Sep 2024 04:15:34 +0200 Subject: [PATCH 003/104] Removing logplotter.svg file (duplicate) + adding PySide6-Addons as dependency --- README.md | 2 +- linux/debian/control | 2 +- linux/debian/depends | 2 +- linux/logarithmplotter.desktop | 2 +- linux/x-logarithm-plot.xml | 2 +- logplotter.svg | 64 ---------------------------------- scripts/build-wine.sh | 2 +- setup.py | 10 +++--- 8 files changed, 11 insertions(+), 75 deletions(-) delete mode 100644 logplotter.svg diff --git a/README.md b/README.md index e368435..8ae4d47 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ![icon](https://git.ad5001.eu/Ad5001/LogarithmPlotter/raw/branch/master/logplotter.svg) LogarithmPlotter +# ![icon](https://git.ad5001.eu/Ad5001/LogarithmPlotter/raw/branch/master/LogarithmPlotter/logarithmplotter.svg) LogarithmPlotter [![Build Status](https://ci.ad5001.eu/api/badges/Ad5001/LogarithmPlotter/status.svg)](https://ci.ad5001.eu/Ad5001/LogarithmPlotter) [![Translation status](https://hosted.weblate.org/widgets/logarithmplotter/-/logarithmplotter/svg-badge.svg)](https://hosted.weblate.org/engage/logarithmplotter/) diff --git a/linux/debian/control b/linux/debian/control index 57281bc..e63e970 100644 --- a/linux/debian/control +++ b/linux/debian/control @@ -3,7 +3,7 @@ Source: logarithmplotter Version: 0.6.0 Architecture: all Maintainer: Ad5001 -Depends: python3, python3-pip, python3-pyside6-essentials (>= 6.7.0), texlive-latex-base, dvipng +Depends: python3, python3-pip, python3-pyside6-essentials (>= 6.7.0), python3-pyside6-addons (>= 6.7), texlive-latex-base, dvipng Build-Depends: debhelper (>=11~), dh-python, dpkg-dev (>= 1.16.1~), python-setuptools, python3-all-dev (>=3.9) Section: science diff --git a/linux/debian/depends b/linux/debian/depends index 5eea4fd..c17dcdd 100644 --- a/linux/debian/depends +++ b/linux/debian/depends @@ -1 +1 @@ -python3, python3-pip, python3-pyside6-essentials (>= 6.7.0), texlive-latex-base, dvipng +python3, python3-pip, python3-pyside6-essentials (>= 6.7), python3-pyside6-addons (>= 6.7), texlive-latex-base, dvipng diff --git a/linux/logarithmplotter.desktop b/linux/logarithmplotter.desktop index 00c871f..70637c5 100644 --- a/linux/logarithmplotter.desktop +++ b/linux/logarithmplotter.desktop @@ -14,7 +14,7 @@ Comment[hu]=Bode-ábrák, sorozatok és újraosztási függvények létrehozása TryExec=logarithmplotter Exec=logarithmplotter %f -Icon=logplotter +Icon=logarithmplotter MimeType=application/x-logarithm-plot; Terminal=false StartupNotify=false diff --git a/linux/x-logarithm-plot.xml b/linux/x-logarithm-plot.xml index 31b5c9d..888641e 100644 --- a/linux/x-logarithm-plot.xml +++ b/linux/x-logarithm-plot.xml @@ -1,7 +1,7 @@ - Logarithm Plot File + Logarithmic Plot File Fichier Graphe Logarithmique diff --git a/logplotter.svg b/logplotter.svg deleted file mode 100644 index 77a2817..0000000 --- a/logplotter.svg +++ /dev/null @@ -1,64 +0,0 @@ - -LogarithmPlotter Icon v1.0image/svg+xmlLogarithmPlotter Icon v1.02021Ad5001(c) Ad5001 2021 - All rights reserved diff --git a/scripts/build-wine.sh b/scripts/build-wine.sh index 39b2312..95a5995 100644 --- a/scripts/build-wine.sh +++ b/scripts/build-wine.sh @@ -11,7 +11,7 @@ cd "LogarithmPlotter/i18n/" bash release.sh cd ../../ -wine pyinstaller --add-data "logplotter.svg;." \ +wine pyinstaller --add-data "LogarithmPlotter/logarithmplotter.svg;." \ --add-data "LogarithmPlotter/qml;qml" \ --add-data "LogarithmPlotter/i18n;i18n" \ --noconsole \ diff --git a/setup.py b/setup.py index 5d1aae7..4a4d2ea 100644 --- a/setup.py +++ b/setup.py @@ -99,11 +99,11 @@ if sys.platform == 'linux': data_files.append(('share/applications/', ['linux/logarithmplotter.desktop'])) data_files.append(('share/mime/packages/', ['linux/x-logarithm-plot.xml'])) data_files.append(('share/icons/hicolor/scalable/mimetypes/', ['linux/application-x-logarithm-plot.svg'])) - data_files.append(('share/icons/hicolor/scalable/apps/', ['logplotter.svg'])) + data_files.append(('share/icons/hicolor/scalable/apps/', ['LogarithmPlotter/logarithmplotter.svg'])) data_files.append((os.environ["PREFIX"] + '/applications/', ['linux/logarithmplotter.desktop'])) data_files.append((os.environ["PREFIX"] + '/mime/packages/', ['linux/x-logarithm-plot.xml'])) data_files.append((os.environ["PREFIX"] + '/icons/hicolor/scalable/mimetypes/', ['linux/application-x-logarithm-plot.svg'])) - data_files.append((os.environ["PREFIX"] + '/icons/hicolor/scalable/apps/', ['logplotter.svg'])) + data_files.append((os.environ["PREFIX"] + '/icons/hicolor/scalable/apps/', ['LogarithmPlotter/logarithmplotter.svg'])) if len(sys.argv) > 1: if sys.argv[1] == "install": os.makedirs(os.environ["PREFIX"] + '/applications/', exist_ok=True) @@ -114,15 +114,15 @@ if sys.platform == 'linux': copyfile(current_dir + '/linux/x-logarithm-plot.xml', os.environ["PREFIX"] + '/mime/packages/x-logarithm-plot.xml') copyfile(current_dir + '/linux/application-x-logarithm-plot.svg', os.environ["PREFIX"] + '/icons/hicolor/scalable/mimetypes/application-x-logarithm-plot.svg') - copyfile(current_dir + '/logplotter.svg', os.environ["PREFIX"] + '/icons/hicolor/scalable/apps/logplotter.svg') + copyfile(current_dir + '/LogarithmPlotter/logarithmplotter.svg', os.environ["PREFIX"] + '/icons/hicolor/scalable/apps/LogarithmPlotter/logarithmplotter.svg') elif sys.argv[1] == "uninstall": os.remove(os.environ["PREFIX"] + '/applications/logarithmplotter.desktop') os.remove(os.environ["PREFIX"] + '/mime/packages/x-logarithm-plot.xml') os.remove(os.environ["PREFIX"] + '/icons/hicolor/scalable/mimetypes/application-x-logarithm-plot.svg') - os.remove(os.environ["PREFIX"] + '/icons/hicolor/scalable/apps/logplotter.svg') + os.remove(os.environ["PREFIX"] + '/icons/hicolor/scalable/apps/LogarithmPlotter/logarithmplotter.svg') setuptools.setup( - install_requires=([] if "FLATPAK_INSTALL" in os.environ else ["PySide6-Essentials"]), + install_requires=([] if "FLATPAK_INSTALL" in os.environ else ["PySide6-Essentials", "PySide6-Addons"]), python_requires='>=3.9', name='logarithmplotter', From 80cea6d280302b59c29b424946cca1c9704e470c Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 26 Sep 2024 15:55:29 +0000 Subject: [PATCH 004/104] Translated using Weblate (Hungarian) Currently translated at 95.1% (256 of 269 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/ --- LogarithmPlotter/i18n/lp_hu.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LogarithmPlotter/i18n/lp_hu.ts b/LogarithmPlotter/i18n/lp_hu.ts index 8618a0b..313d8de 100644 --- a/LogarithmPlotter/i18n/lp_hu.ts +++ b/LogarithmPlotter/i18n/lp_hu.ts @@ -1717,7 +1717,7 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents baseValues - Kezdeményezési értékek + Kezdeményezési értékek color From c2eae30bd68b5370492259059a5ccb0bc8745f6e Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 27 Sep 2024 22:26:15 +0200 Subject: [PATCH 005/104] Updating qmldirs --- .../ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml | 4 ++-- .../eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Popup/qmldir | 8 ++++---- .../qml/eu/ad5001/LogarithmPlotter/Setting/qmldir | 4 ++-- LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/qmldir | 5 ++++- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml index d92c36b..f755a6f 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml @@ -71,8 +71,8 @@ ScrollView { id: typeVisibilityCheckBox checked: Modules.Objects.currentObjects[objType] != undefined ? Modules.Objects.currentObjects[objType].every(obj => obj.visible) : true onClicked: { - for(var obj of Modules.Objects.currentObjects[objType]) obj.visible = this.checked - for(var obj of objTypeList.editingRows) obj.objVisible = this.checked + for(const obj of Modules.Objects.currentObjects[objType]) obj.visible = this.checked + for(const obj of objTypeList.editingRows) obj.objVisible = this.checked objectListList.changed() } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml index 2dcd5c0..a1b9d82 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml @@ -227,7 +227,7 @@ Item { function deleteRecursively(object) { for(let toRemove of object.requiredBy) deleteRecursively(toRemove) - if(Modules.Objects.currentObjectsByName[object.name] != undefined) { + if(Modules.Objects.currentObjectsByName[object.name] !== undefined) { // Object still exists // Temporary fix for objects require not being propertly updated. object.requiredBy = [] diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/qmldir b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/qmldir index 8c0859f..3cf03fa 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/qmldir +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/qmldir @@ -1,11 +1,11 @@ module eu.ad5001.LogarithmPlotter.Popup -BaseDialog 1.0 BaseDialog.qml -About 1.0 About.qml Alert 1.0 Alert.qml +About 1.0 About.qml +BaseDialog 1.0 BaseDialog.qml +Changelog 1.0 Changelog.qml FileDialog 1.0 FileDialog.qml GreetScreen 1.0 GreetScreen.qml -Changelog 1.0 Changelog.qml -ThanksTo 1.0 ThanksTo.qml InsertCharacter 1.0 InsertCharacter.qml Preferences 1.0 Preferences.qml +ThanksTo 1.0 ThanksTo.qml diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/qmldir b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/qmldir index 8106e26..bb78bbe 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/qmldir +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/qmldir @@ -1,8 +1,8 @@ module eu.ad5001.LogarithmPlotter.Setting +AutocompletionCategory 1.0 AutocompletionCategory.qml ComboBoxSetting 1.0 ComboBoxSetting.qml +ExpressionEditor 1.0 ExpressionEditor.qml Icon 1.0 Icon.qml ListSetting 1.0 ListSetting.qml TextSetting 1.0 TextSetting.qml -ExpressionEditor 1.0 ExpressionEditor.qml -AutocompletionCategory 1.0 AutocompletionCategory.qml diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/qmldir b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/qmldir index ac68e47..3aeaa15 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/qmldir +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/qmldir @@ -1,4 +1,7 @@ module eu.ad5001.LogarithmPlotter +AppMenuBar 1.0 AppMenuBar.qml +LogGraphCanvas 1.0 LogGraphCanvas.qml +PickLocationOverlay 1.0 PickLocationOverlay.qml Settings 1.0 Settings.qml -Alert 1.0 Alert.qml +ViewPositionChangeOverlay 1.0 ViewPositionChangeOverlay.qml \ No newline at end of file From 7ef55e48e827808b210c53917c0f73469898c6b3 Mon Sep 17 00:00:00 2001 From: ovari Date: Tue, 1 Oct 2024 00:54:21 +0000 Subject: [PATCH 006/104] Translated using Weblate (Hungarian) Currently translated at 100.0% (269 of 269 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/ --- LogarithmPlotter/i18n/lp_hu.ts | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/LogarithmPlotter/i18n/lp_hu.ts b/LogarithmPlotter/i18n/lp_hu.ts index 313d8de..e03702f 100644 --- a/LogarithmPlotter/i18n/lp_hu.ts +++ b/LogarithmPlotter/i18n/lp_hu.ts @@ -39,7 +39,7 @@ &Load... - &Betöltés… + &Megnyitás… @@ -79,7 +79,7 @@ &Preferences - + &Beállítások @@ -394,7 +394,7 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. Preferences - + Beállítások @@ -606,7 +606,7 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. Close - + Bezárás @@ -707,17 +707,17 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. Save plot - Ábra mentése + Ábra mentése… Save plot as - Ábra mentése másként + Ábra mentése másként… Load plot - Ábra betöltése + Ábra megnyitása… Close @@ -808,7 +808,7 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. Spanish - + spanyol @@ -1055,7 +1055,7 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. Parse error [position %1]: %2 - + Elemzési hiba [hely %1]: %2 @@ -1386,7 +1386,11 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents - {} (https://ctan.org/pkg/{}) Make sure said package is installed, or disable the LaTeX rendering in LogarithmPlotter. - + A LaTeX telepítése nem tartalmaz néhány szükséges csomagot: + +- {} (https://ctan.org/pkg/{}) + +Győződjön meg arról, hogy az említett csomag telepítve van, vagy tiltsa le a LaTeX megjelenítést a LogarithmPlotterben. @@ -1692,7 +1696,7 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents approximate - Hozzávetőleges érték megjelenítése + Kerekített számított érték megjelenítése @@ -1753,7 +1757,7 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents general - + Általános @@ -1821,7 +1825,7 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents integral(<from: number>, <to: number>, <f: ExecutableObject>) - integrál(<alsó korlát: szám>, <felső korlát: szám>, <függvény: végrehajtható objektum>) + integral(<alsó korlát: szám>, <felső korlát: szám>, <f: függvényszerű objektum>) @@ -1850,7 +1854,7 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents derivative(<f: ExecutableObject>, <x: number>) - derivative(<függvény: VégrehajthatóObjektum>, <x: szám>) + derivative(<f: függvényszerű objektum>, <x: szám>) From a60ac79d83d9a91bee9f76c4df7105020de8ff42 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Wed, 9 Oct 2024 20:15:27 +0200 Subject: [PATCH 007/104] Updating translations to new folder structure. --- assets/i18n/lp_de.ts | 676 +++++++++++++++++++------------------ assets/i18n/lp_en.ts | 676 +++++++++++++++++++------------------ assets/i18n/lp_es.ts | 676 +++++++++++++++++++------------------ assets/i18n/lp_fr.ts | 676 +++++++++++++++++++------------------ assets/i18n/lp_hu.ts | 676 +++++++++++++++++++------------------ assets/i18n/lp_nb_NO.ts | 676 +++++++++++++++++++------------------ assets/i18n/lp_template.ts | 670 ++++++++++++++++++------------------ assets/i18n/update.sh | 4 +- 8 files changed, 2377 insertions(+), 2353 deletions(-) diff --git a/assets/i18n/lp_de.ts b/assets/i18n/lp_de.ts index 761283f..4f29919 100644 --- a/assets/i18n/lp_de.ts +++ b/assets/i18n/lp_de.ts @@ -4,27 +4,27 @@ About - + About LogarithmPlotter Über LogarithmPlotter - + LogarithmPlotter v%1 LogarithmPlotter v%1 - + 2D plotter software to make BODE plots, sequences and repartition functions. 2D-Grafiksoftware zur Erstellung von Bode-Diagramms, Folgen und Verteilungsfunktionen. - + Report a bug Bug melden - + Official website Offizielle Website @@ -32,57 +32,57 @@ AppMenuBar - + &File &Datei - + &Load... &Laden… - + &Save &Speichern - + Save &As... Speichern &Unter… - + &Quit &Ausfahrt - + &Edit &Bearbeiten - + &Undo &Lösen - + &Redo &Wiederherstellen - + &Copy plot Grafik &Kopieren - + &Preferences &Einstellung - + &Create &Erstellen @@ -123,52 +123,52 @@ Syntaktische Färbung - + &Help &Hilfe - + &Source code &Quellcode - + &Report a bug Fehler &Melden - + &User manual &Benutzerhandbuch - + &Changelog &Changelog - + &Help translating! &Hilfe beim Übersetzen! - + &Thanks &Danksagungen - + &About &Übrigens - + Save unsaved changes? Änderungen speichern? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Diese Grafik enthält ungespeicherte Änderungen. Dadurch gehen alle ungespeicherten Daten verloren. Fortfahren? @@ -176,7 +176,7 @@ BaseDialog - + Close Schließen @@ -191,12 +191,12 @@ Changelog - + Fetching changelog... Changelog abrufen… - + Close Schließen @@ -204,13 +204,13 @@ CustomPropertyList - - + + + Create new %1 + Neues %1objekt erstellen - + Pick on graph Aufnehmen auf Graph @@ -218,42 +218,42 @@ Dialog - + Edit properties of %1 %2 Eigenschaften von %1 %2 bearbeiten - + LogarithmPlotter - Invalid object name LogarithmPlotter - Ungültiger Objektname - + An object with the name '%1' already exists. Ein Objekt mit dem Namen '%1' existiert bereits. - + Name Name - + Label content Etikett - + null leer - + name Name - + name + value Name + Wert @@ -292,32 +292,32 @@ ExpressionEditor - + Object Properties Objekteigenschaften - + Variables Variablen - + Constants Konstanten - + Functions Funktionen - + Executable Objects Funktionsobjekte - + Objects Objekte @@ -325,12 +325,12 @@ FileDialog - + Export Logarithm Plot file Logarithmusgrafik exportieren - + Import Logarithm Plot file Logarithmusgrafik importieren @@ -338,12 +338,12 @@ GreetScreen - + Welcome to LogarithmPlotter Willkommen bei LogarithmPlotter - + Version %1 Version %1 @@ -382,22 +382,22 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" Syntaktische Färbung Thema: - + User manual Benutzerhandbuch - + Changelog Changelog - + Preferences Einstellung - + Close Schließen @@ -405,22 +405,22 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" HistoryBrowser - + Filter... Filtern… - + Redo > Wiederherstellen > - + > Now > Aktueller Stand - + < Undo < Rückgängig @@ -428,7 +428,7 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" ListSetting - + + Add Entry + Neuer Eintrag @@ -436,17 +436,17 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" LogarithmPlotter - + Objects Objekte - + Settings Einstellungen - + History Verlauf @@ -475,17 +475,17 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" Geladene Datei '%1'. - + Copied plot screenshot to clipboard! Grafik in die Zwischenablage kopiert! - + &Update &Aktualisieren - + &Update LogarithmPlotter LogarithmPlotter &aktualisieren @@ -493,7 +493,7 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" ObjectCreationGrid - + + Create new: + Neu erstellen: @@ -501,12 +501,12 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" ObjectLists - + Hide all %1 Alle %1 ausblenden - + Show all %1 Alle %1 anzeigen @@ -534,27 +534,27 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" ObjectRow - + Hide %1 %2 Ausblenden %1 %2 - + Show %1 %2 Anzeigen %1 %2 - + Set %1 %2 position Position von %1 %2 einstellen - + Delete %1 %2 %1 %2 löschen - + Pick new color for %1 %2 Neue Farbe für %1 %2 auswählen @@ -562,7 +562,7 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" PickLocationOverlay - + Pointer precision: Genauigkeit des Zeigers: @@ -571,32 +571,32 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" Am Gitter einrasten - + Snap to grid: Am Raster einrasten: - + Pick X X nehmen - + Pick Y Y nehmen - + Open picker settings Zeigereinstellungen öffnen - + Hide picker settings Zeigereinstellungen ausblenden - + (no pick selected) (keine Auswahl ausgewählt) @@ -604,7 +604,7 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" Preferences - + Close Schließen @@ -612,110 +612,110 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" Settings - - + + X Zoom Zoom auf X - - + + Y Zoom Zoom auf Y - - + + Min X Minimum X - - + + Max Y Maximum Y - + Max X Maximum X - + Min Y Minimum Y - - + + X Axis Step X-Achsen-Schritt - - + + Y Axis Step Y-Achsen-Schritt - - + + Line width Linienbreite - - + + Text size (px) Textgröße (px) - - + + X Label Etikett der X-Achse - - + + Y Label Etikett der Y-Achse - - + + X Log scale Logarithmische Skala in X - - + + Show X graduation X-Teilung anzeigen - - + + Show Y graduation Y-Teilung anzeigen - + Copy to clipboard Kopieren in die Zwischenablage - + Save plot Grafik speichern… - + Save plot as Grafik speichern unter… - + Load plot Grafik laden… @@ -727,96 +727,96 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" ThanksTo - + Thanks and Contributions - LogarithmPlotter Danksagungen und Beiträge - LogarithmPlotter - + Source code Quellcode - + Original library by Raphael Graf Originalbibliothek von Raphael Graf - + Source Quelle - + Ported to Javascript by Matthew Crumley Portiert auf JavaScript von Matthew Crumley - - - + + + Website Website - + Ported to QMLJS by Ad5001 Portiert auf QMLJS von Ad5001 - + Libraries included Einschließlich Bibliotheken - + Email E-Mail - + English Englisch - + French Französisch - + German Deutsch - + Hungarian Ungarisch - - - + + + Github GitHub - + Norwegian Norwegisch - + Spanish Spanisch - + Translations included Einschließlich Übersetzungen - + Improve Verbessern @@ -824,24 +824,24 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" bodemagnitude - + Bode Magnitude Bode-Magnitude - + Bode Magnitudes Bode-Magnituden - - + + low-pass Tiefpass - - + + high-pass Hochpass @@ -849,8 +849,8 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" bodemagnitudesum - - + + Bode Magnitudes Sum Bode-Magnituden Summe @@ -858,12 +858,12 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" bodephase - + Bode Phase Bode-Phase - + Bode Phases Bode-Phasen @@ -871,8 +871,8 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" bodephasesum - - + + Bode Phases Sum Bode-Phasen Summe @@ -880,12 +880,12 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" changelog - + Could not fetch changelog: Server error {}. Changelog konnte nicht geholt werden: Server-Fehler {}. - + Could not fetch update: {}. Changelog konnte nicht geholt werden: {}. @@ -893,8 +893,8 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" color - - + + %1 %2's color changed from %3 to %4. %1 %2 wurde von %3 bis %4 umgefärbt. @@ -902,27 +902,27 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" comment - + Ex: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ⁻*), ]0;1[, {3;4;5} Beispiel: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ-*), ]0;1[, {3;4;5} - + The following parameters are used when the definition domain is a non-continuous set. (Ex: ℕ, ℤ, sets like {0;3}...) Die folgenden Parameter werden verwendet, wenn der Definitionsbereich eine nicht kontinuierliche Menge ist. (Beispiel: ℕ, ℤ, Mengen wie {0;3}...) - + Note: Specify the probability for each value. Hinweis: Geben Sie die Wahrscheinlichkeit für jeden Wert an. - + Note: Use %1[n] to refer to %1ₙ, %1[n+1] for %1ₙ₊₁... Hinweis: Verwenden Sie %1[n], um sich auf %1ₙ zu beziehen, %1[n+1] für %1ₙ₊₁… - + If you have latex enabled, you can use use latex markup in between $$ to create equations. Wenn Sie Latex aktiviert haben, können Sie Latex-Auszeichnungen zwischen $$ verwenden, um Gleichungen zu erstellen. @@ -930,11 +930,11 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" control - - - - - + + + + + %1: %1: @@ -942,8 +942,8 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" create - - + + New %1 %2 created. Neu %1 %2 erstellt. @@ -951,8 +951,8 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" delete - - + + %1 %2 deleted. %1 %2 gelöscht. @@ -960,12 +960,12 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" distribution - + Repartition Verteilungsfunktion - + Repartition functions Verteilungsfunktionen @@ -973,12 +973,12 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" editproperty - + %1 of %2 %3 changed from "%4" to "%5". %1 von %2 %3 wurde von "%4" auf "%5" geändert. - + %1 of %2 changed from %3 to %4. %1 von %2 wurde von %3 auf %4 geändert. @@ -986,46 +986,46 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" error - - + + Cannot find property %1 of object %2. Eigenschaft %1 von Objekt %2 kann nicht gefunden werden. - + Undefined variable %1. Die Variable %1 ist nicht definiert. - + In order to be executed, object %1 must have at least one argument. Um als Funktion verwendet zu werden, benötigt das Objekt %1 mindestens ein Parameter. - + %1 cannot be executed. %1 ist keine Formel. - - - + + + Invalid expression. Ungültiger Ausdruck. - + Invalid expression (parity). Ungültiger Ausdruck (Parität). - + Unknown character "%1". Unbekanntes Schriftzeichen "%1". - - + + Illegal escape sequence: %1. Unzulässige Escapesequenz: %1. @@ -1034,12 +1034,12 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" Analysefehler [%1:%2]: %3 - + Expected %1 Erwartet %1 - + Unexpected %1 Unerwartetes %1 @@ -1052,104 +1052,104 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" Erwartete Variable für Zuweisung. - - + + Parse error [position %1]: %2 Analysefehler [Posten %1]: %2 - + Unexpected ".": member access is not permitted Unerwartetes ".": Mitgliederzugriff ist nicht erlaubt - + Unexpected "[]": arrays are disabled. Unerwartetes "[]": Arrays sind deaktiviert. - + Unexpected symbol: %1. Unerwartetes Symbol: %1. - - + + Function %1 must have at least one argument. Die Funktion %1 benötigt mindestens ein Parameter. - + First argument to map is not a function. Der erste Parameter von map ist keine Formel. - + Second argument to map is not an array. Der zweite Parameter von map ist kein Array. - + First argument to fold is not a function. Der erste Parameter für fold ist keine Formel. - + Second argument to fold is not an array. Der zweite Parameter für fold ist kein Array. - + First argument to filter is not a function. Der erste Parameter für filter ist keine Formel. - + Second argument to filter is not an array. Der zweite Parameter von filter ist kein Array. - + Second argument to indexOf is not a string or array. Der zweite Parameter von indexOf ist kein String oder Array. - + Second argument to join is not an array. Der zweite Parameter von join ist kein Array. - + EOF Ende des Ausdrucks - + No object found with names %1. Kein Objekt mit Namen %1 gefunden. - + No object found with name %1. Kein Objekt mit dem Namen %1 gefunden. - + Object cannot be dependent on itself. Ein Objekt kann nicht von sich selbst abhängen. - + Circular dependency detected. Object %1 depends on %2. Zirkuläre Abhängigkeit entdeckt. Objekt %1 hängt von %2 ab. - + Circular dependency detected. Objects %1 depend on %2. Zirkuläre Abhängigkeit entdeckt. Objekte %1 hängen von %2 ab. - + Error while parsing expression for property %1: %2 @@ -1160,7 +1160,7 @@ Evaluated expression: %3 Ausdruck analysiert: %3 - + Error while attempting to draw %1 %2: %3 @@ -1174,13 +1174,13 @@ Die letzte Änderung wurde rückgängig gemacht. expression - - + + LogarithmPlotter - Parsing error LogarithmPlotter - Analysefehler - + Error while parsing expression for property %1: %2 @@ -1191,27 +1191,27 @@ Evaluated expression: %3 Ausdruck analysiert: %3 - + LogarithmPlotter - Drawing error LogarithmPlotter - Fehler - + Automatically close parenthesises and brackets Klammern automatisch schließen - + Enable syntax highlighting Syntaxhervorhebung einschalten - + Enable autocompletion Automatische Vervollständigung einschalten - + Color Scheme Syntaktische Färbung @@ -1219,12 +1219,12 @@ Ausdruck analysiert: %3 function - + Function Funktion - + Functions Funktionen @@ -1251,17 +1251,17 @@ Ausdruck analysiert: %3 general - + Check for updates on startup Beim Starten auf Updates prüfen - + Reset redo stack automaticly Wiederherstellen-Stapel automatisch zurücksetzen - + Enable LaTeX rendering LaTeX-Rendering aktivieren @@ -1308,32 +1308,36 @@ Ausdruck analysiert: %3 Verlauf - + Saved plot to '%1'. Gespeicherte Grafik auf '%1'. - + Loading file '%1'. Laden der Datei '%1'. - + Unknown object type: %1. Unbekannter Objekttyp: %1. - + Invalid file provided. Ungültige Datei angegeben. - - Could not save file: - Die Datei konnte nicht gespeichert werden: + + Could not load file: + - + Could not save file: + Die Datei konnte nicht gespeichert werden: + + + Loaded file '%1'. Geladene Datei '%1'. @@ -1353,7 +1357,7 @@ Ausdruck analysiert: %3 latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. @@ -1362,12 +1366,12 @@ Wenn Sie bereits eine LaTeX-Distribution installiert haben, vergewissern Sie sic Andernfalls können Sie eine LaTeX-Distribution wie TeX Live unter https://tug.org/texlive/ herunterladen. - + DVIPNG was not found. Make sure you include it from your Latex distribution. DVIPNG wurde nicht gefunden. Stellen Sie sicher, dass Sie es aus Ihrer LaTeX-Distribution einbinden. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1380,7 +1384,7 @@ Der Prozess '{}' wurde mit einem Rückgabecode ungleich Null beendet { Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melden Sie einen Fehler, falls dies der Fall ist. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1393,7 +1397,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm Stellen Sie sicher, dass diese Pakete installiert sind, oder deaktivieren Sie das LaTeX-Rendering in LogarithmPlotter. - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1407,8 +1411,8 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde name - - + + %1 %2 renamed to %3. %1 %2 umbenannt in %3. @@ -1416,114 +1420,114 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde parameters - + above ↑ Über - + below ↓ Unter - - + + left ← Links - - + + right → Rechts - + above-left ↖ Oben links - + above-right ↗ Oben rechts - + below-left ↙ Unten links - + below-right ↘ Unten rechts - + center >|< Zentrum - + top ↑ Über - + bottom ↓ Unter - + top-left ↖ Oben links - + top-right ↗ Oben rechts - + bottom-left ↙ Unten links - + bottom-right ↘ Unten rechts - + application Anwendung - + function Funktion - + high Hoch - + low Tief - + Next to target Neben dem Ziel - + With label Mit Etikett - + Hidden Versteckt @@ -1542,12 +1546,12 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde point - + Point Punkt - + Points Punkte @@ -1555,12 +1559,12 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde position - + Position of %1 %2 set from "%3" to "%4". %1 %2 wurde von "%3" nach "%4" verschoben. - + Position of %1 set from %2 to %3. %1 wurde von %2 nach %3 verschoben. @@ -1568,158 +1572,158 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde prop - + expression Ausdruck - + definitionDomain Definitionsbereich - + destinationDomain Reichweite - - - - - - - - - - + + + + + + + + + + labelPosition Position des Etiketts - + displayMode Anzeigemodus - - - - - - - + + + + + + + labelX X-Position des Etiketts - - + + drawPoints Unentschiedene Punkte - - + + drawDashedLines Gestrichelte Linien anzeigen - - + + om_0 ω₀ - + pass Pass - + gain Größenordnung - + omGraduation Teilung auf ω zeigen - + phase Phase - + unit Einheit - - - + + + x X - - + + y Y - + pointStyle Punkt-Stil - + probabilities Wahrscheinlichkeiten - + text Inhalt - + disableLatex LaTeX-Rendering für diesen Text deaktivieren - + targetElement Zielobjekt - + approximate Berechneten Wert gerundet anzeigen - + rounding Rundung - + displayStyle Stil - + targetValuePosition Wertposition des Ziels - + defaultExpression Standardausdruck - + baseValues Initialisierungswerte @@ -1742,12 +1746,12 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde sequence - + Sequence Folge - + Sequences Folgen @@ -1755,17 +1759,17 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde settingCategory - + default Standardeinstellungen - + general Allgemeine - + editor Ausdruckseditor @@ -1787,12 +1791,12 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde text - + Text Text - + Texts Texte @@ -1800,22 +1804,22 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde update - + An update for LogarithmPlotter (v{}) is available. Ein Update für LogarithmPlotter (v{}) ist verfügbar. - + No update available. Keine Aktualisierung verfügbar. - + Could not fetch update information: Server error {}. Es konnten keine Aktualisierungsinformationen abgerufen werden: Server-Fehler {}. - + Could not fetch update information: {}. Es konnten keine Aktualisierungsinformationen abgerufen werden:{}. @@ -1823,22 +1827,22 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde usage - + integral(<from: number>, <to: number>, <f: ExecutableObject>) integral(<von: Zahl>, <bis: Zahl>, <f: Funktionsähnliches Objekt>) - - + + Usage: %1 Verwendung: %1 - - - + + + Usage: %1 %2 @@ -1847,17 +1851,17 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde %2 - + integral(<from: number>, <to: number>, <f: string>, <variable: string>) integral(<von: Zahl>, <bis: Zahl>, <f: String>, <Variablen: String>) - + derivative(<f: ExecutableObject>, <x: number>) derivative(<f: Funktionsähnliches Objekt>, <x: Zahl>) - + derivative(<f: string>, <variable: string>, <x: number>) derivative(<f: String>, <Variablen: String>, <x: Zahl>) @@ -1865,14 +1869,14 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde visibility - - + + %1 %2 shown. %1 %2 angezeigt. - - + + %1 %2 hidden. %1 %2 ausgeblendet. @@ -1880,12 +1884,12 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde xcursor - + X Cursor X Zeiger - + X Cursors X Zeiger diff --git a/assets/i18n/lp_en.ts b/assets/i18n/lp_en.ts index 92baeb1..4429a36 100644 --- a/assets/i18n/lp_en.ts +++ b/assets/i18n/lp_en.ts @@ -4,27 +4,27 @@ About - + About LogarithmPlotter About LogarithmPlotter - + LogarithmPlotter v%1 LogarithmPlotter v%1 - + 2D plotter software to make BODE plots, sequences and repartition functions. 2D plotter software to make Bode plots, sequences and distribution functions. - + Report a bug Report a bug - + Official website Official website @@ -32,57 +32,57 @@ AppMenuBar - + &File &File - + &Load... &Open… - + &Save &Save - + Save &As... Save &As… - + &Quit &Quit - + &Edit &Edit - + &Undo &Undo - + &Redo &Redo - + &Copy plot &Copy plot - + &Preferences &Preferences - + &Create &Create @@ -123,52 +123,52 @@ Color Scheme - + &Help &Help - + &Source code &Source code - + &Report a bug &Report a bug - + &User manual &User manual - + &Changelog &Changelog - + &Help translating! &Help translating! - + &Thanks &Thanks - + &About &About - + Save unsaved changes? Save unsaved changes? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? @@ -176,7 +176,7 @@ BaseDialog - + Close Close @@ -191,12 +191,12 @@ Changelog - + Fetching changelog... Fetching changelog… - + Close Close @@ -204,13 +204,13 @@ CustomPropertyList - - + + + Create new %1 + Create new %1 - + Pick on graph Pick on graph @@ -218,42 +218,42 @@ Dialog - + Edit properties of %1 %2 Edit properties of %1 %2 - + LogarithmPlotter - Invalid object name LogarithmPlotter - Invalid object name - + An object with the name '%1' already exists. An object with the name '%1' already exists. - + Name Name - + Label content Label content - + null null - + name name - + name + value name + value @@ -292,32 +292,32 @@ ExpressionEditor - + Object Properties Object Properties - + Variables Variables - + Constants Constants - + Functions Functions - + Executable Objects Function Objects - + Objects Objects @@ -325,12 +325,12 @@ FileDialog - + Export Logarithm Plot file Export Logarithm Plot file - + Import Logarithm Plot file Import Logarithm Plot file @@ -338,12 +338,12 @@ GreetScreen - + Welcome to LogarithmPlotter Welcome to LogarithmPlotter - + Version %1 Version %1 @@ -382,22 +382,22 @@ These settings can be changed at any time from the "Settings" menu.Color scheme: - + User manual User manual - + Changelog Changelog - + Preferences Preferences - + Close Close @@ -405,22 +405,22 @@ These settings can be changed at any time from the "Settings" menu. HistoryBrowser - + Filter... Filter… - + Redo > Redo > - + > Now > Now - + < Undo < Undo @@ -428,7 +428,7 @@ These settings can be changed at any time from the "Settings" menu. ListSetting - + + Add Entry + Add Entry @@ -436,17 +436,17 @@ These settings can be changed at any time from the "Settings" menu. LogarithmPlotter - + Objects Objects - + Settings Settings - + History History @@ -475,17 +475,17 @@ These settings can be changed at any time from the "Settings" menu.Loaded file '%1'. - + Copied plot screenshot to clipboard! Copied plot screenshot to clipboard! - + &Update &Update - + &Update LogarithmPlotter &Update LogarithmPlotter @@ -493,7 +493,7 @@ These settings can be changed at any time from the "Settings" menu. ObjectCreationGrid - + + Create new: + Create new: @@ -501,12 +501,12 @@ These settings can be changed at any time from the "Settings" menu. ObjectLists - + Hide all %1 Hide all %1 - + Show all %1 Show all %1 @@ -534,27 +534,27 @@ These settings can be changed at any time from the "Settings" menu. ObjectRow - + Hide %1 %2 Hide %1 %2 - + Show %1 %2 Show %1 %2 - + Set %1 %2 position Set %1 %2 position - + Delete %1 %2 Delete %1 %2 - + Pick new color for %1 %2 Pick new color for %1 %2 @@ -562,7 +562,7 @@ These settings can be changed at any time from the "Settings" menu. PickLocationOverlay - + Pointer precision: Pointer precision: @@ -571,32 +571,32 @@ These settings can be changed at any time from the "Settings" menu.Snap to grid - + Snap to grid: Snap to grid: - + Pick X Pick X - + Pick Y Pick Y - + Open picker settings Open picker settings - + Hide picker settings Hide picker settings - + (no pick selected) (no pick selected) @@ -604,7 +604,7 @@ These settings can be changed at any time from the "Settings" menu. Preferences - + Close Close @@ -612,110 +612,110 @@ These settings can be changed at any time from the "Settings" menu. Settings - - + + X Zoom X Zoom - - + + Y Zoom Y Zoom - - + + Min X Min X - - + + Max Y Max Y - + Max X Max X - + Min Y Min Y - - + + X Axis Step X Axis Step - - + + Y Axis Step Y Axis Step - - + + Line width Line width - - + + Text size (px) Text size (px) - - + + X Label X Label - - + + Y Label Y Label - - + + X Log scale X Log scale - - + + Show X graduation Show X graduation - - + + Show Y graduation Show Y graduation - + Copy to clipboard Copy to clipboard - + Save plot Save plot… - + Save plot as Save plot as… - + Load plot Open plot… @@ -727,96 +727,96 @@ These settings can be changed at any time from the "Settings" menu. ThanksTo - + Thanks and Contributions - LogarithmPlotter Thanks and Contributions - LogarithmPlotter - + Source code Source code - + Original library by Raphael Graf Original library by Raphael Graf - + Source Source - + Ported to Javascript by Matthew Crumley Ported to JavaScript by Matthew Crumley - - - + + + Website Website - + Ported to QMLJS by Ad5001 Ported to QMLJS by Ad5001 - + Libraries included Libraries included - + Email Email - + English English - + French French - + German German - + Hungarian Hungarian - - - + + + Github GitHub - + Norwegian Norwegian - + Spanish Spanish - + Translations included Translations included - + Improve Improve @@ -824,24 +824,24 @@ These settings can be changed at any time from the "Settings" menu. bodemagnitude - + Bode Magnitude Bode Magnitude - + Bode Magnitudes Bode Magnitudes - - + + low-pass low-pass - - + + high-pass high-pass @@ -849,8 +849,8 @@ These settings can be changed at any time from the "Settings" menu. bodemagnitudesum - - + + Bode Magnitudes Sum Bode Magnitudes Sum @@ -858,12 +858,12 @@ These settings can be changed at any time from the "Settings" menu. bodephase - + Bode Phase Bode Phase - + Bode Phases Bode Phases @@ -871,8 +871,8 @@ These settings can be changed at any time from the "Settings" menu. bodephasesum - - + + Bode Phases Sum Bode Phases Sum @@ -880,12 +880,12 @@ These settings can be changed at any time from the "Settings" menu. changelog - + Could not fetch changelog: Server error {}. Could not fetch changelog: Server error {}. - + Could not fetch update: {}. Could not fetch changelog: {}. @@ -893,8 +893,8 @@ These settings can be changed at any time from the "Settings" menu. color - - + + %1 %2's color changed from %3 to %4. %1 %2's color changed from %3 to %4. @@ -902,27 +902,27 @@ These settings can be changed at any time from the "Settings" menu. comment - + Ex: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ⁻*), ]0;1[, {3;4;5} Ex: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ⁻*), ]0;1[, {3;4;5} - + The following parameters are used when the definition domain is a non-continuous set. (Ex: ℕ, ℤ, sets like {0;3}...) The following parameters are used when the domain is a non-continuous set. (Ex: ℕ, ℤ, sets like {0;3}…) - + Note: Specify the probability for each value. Note: Specify the probability for each value. - + Note: Use %1[n] to refer to %1ₙ, %1[n+1] for %1ₙ₊₁... Note: Use %1[n] to refer to %1ₙ, %1[n+1] for %1ₙ₊₁… - + If you have latex enabled, you can use use latex markup in between $$ to create equations. If you have latex enabled, you can use use latex markup in between $$ to create equations. @@ -930,11 +930,11 @@ These settings can be changed at any time from the "Settings" menu. control - - - - - + + + + + %1: %1: @@ -942,8 +942,8 @@ These settings can be changed at any time from the "Settings" menu. create - - + + New %1 %2 created. New %1 %2 created. @@ -951,8 +951,8 @@ These settings can be changed at any time from the "Settings" menu. delete - - + + %1 %2 deleted. %1 %2 deleted. @@ -960,12 +960,12 @@ These settings can be changed at any time from the "Settings" menu. distribution - + Repartition Distribution - + Repartition functions Distribution functions @@ -973,12 +973,12 @@ These settings can be changed at any time from the "Settings" menu. editproperty - + %1 of %2 %3 changed from "%4" to "%5". %1 of %2 %3 changed from "%4" to "%5". - + %1 of %2 changed from %3 to %4. %1 of %2 changed from %3 to %4. @@ -986,46 +986,46 @@ These settings can be changed at any time from the "Settings" menu. error - - + + Cannot find property %1 of object %2. Cannot find property %1 of object %2. - + Undefined variable %1. Undefined variable %1. - + In order to be executed, object %1 must have at least one argument. In order to be executed, object %1 must have at least one argument. - + %1 cannot be executed. %1 is not a function. - - - + + + Invalid expression. Invalid expression. - + Invalid expression (parity). Invalid expression (parity). - + Unknown character "%1". Unknown character "%1". - - + + Illegal escape sequence: %1. Illegal escape sequence: %1. @@ -1034,12 +1034,12 @@ These settings can be changed at any time from the "Settings" menu.Parse error [%1:%2]: %3 - + Expected %1 Expected %1 - + Unexpected %1 Unexpected %1 @@ -1052,104 +1052,104 @@ These settings can be changed at any time from the "Settings" menu.Expected variable for assignment. - - + + Parse error [position %1]: %2 Parse error [position %1]: %2 - + Unexpected ".": member access is not permitted Unexpected ".": member access is not permitted - + Unexpected "[]": arrays are disabled. Unexpected "[]": arrays are disabled. - + Unexpected symbol: %1. Unexpected symbol: %1. - - + + Function %1 must have at least one argument. Function %1 must have at least one argument. - + First argument to map is not a function. First argument to map is not a function. - + Second argument to map is not an array. Second argument to map is not an array. - + First argument to fold is not a function. First argument to fold is not a function. - + Second argument to fold is not an array. Second argument to fold is not an array. - + First argument to filter is not a function. First argument to filter is not a function. - + Second argument to filter is not an array. Second argument to filter is not an array. - + Second argument to indexOf is not a string or array. Second argument to indexOf is not a string or array. - + Second argument to join is not an array. Second argument to join is not an array. - + EOF End of expression - + No object found with names %1. No object found with names %1. - + No object found with name %1. No object found with name %1. - + Object cannot be dependent on itself. Object cannot be dependent on itself. - + Circular dependency detected. Object %1 depends on %2. Circular dependency detected. Object %1 depends on %2. - + Circular dependency detected. Objects %1 depend on %2. Circular dependency detected. Objects %1 depend on %2. - + Error while parsing expression for property %1: %2 @@ -1160,7 +1160,7 @@ Evaluated expression: %3 Evaluated expression: %3 - + Error while attempting to draw %1 %2: %3 @@ -1174,13 +1174,13 @@ Undoing last change. expression - - + + LogarithmPlotter - Parsing error LogarithmPlotter - Parsing error - + Error while parsing expression for property %1: %2 @@ -1191,27 +1191,27 @@ Evaluated expression: %3 Evaluated expression: %3 - + LogarithmPlotter - Drawing error LogarithmPlotter - Drawing error - + Automatically close parenthesises and brackets Automatically close parentheses and brackets - + Enable syntax highlighting Enable syntax highlighting - + Enable autocompletion Enable autocompletion - + Color Scheme Color Scheme @@ -1219,12 +1219,12 @@ Evaluated expression: %3 function - + Function Function - + Functions Functions @@ -1251,17 +1251,17 @@ Evaluated expression: %3 general - + Check for updates on startup Check for updates on startup - + Reset redo stack automaticly Reset redo stack automatically - + Enable LaTeX rendering Enable LaTeX rendering @@ -1308,32 +1308,36 @@ Evaluated expression: %3 History - + Saved plot to '%1'. Saved plot to '%1'. - + Loading file '%1'. Loading file '%1'. - + Unknown object type: %1. Unknown object type: %1. - + Invalid file provided. Invalid file provided. - - Could not save file: - Could not save file: + + Could not load file: + - + Could not save file: + Could not save file: + + + Loaded file '%1'. Loaded file '%1'. @@ -1353,7 +1357,7 @@ Evaluated expression: %3 latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. @@ -1362,12 +1366,12 @@ If you already have a LaTeX distribution installed, make sure it's installe Otherwise, you can download a LaTeX distribution like TeX Live at https://tug.org/texlive/. - + DVIPNG was not found. Make sure you include it from your Latex distribution. DVIPNG was not found. Make sure you include it from your LaTeX distribution. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1380,7 +1384,7 @@ Process '{}' ended with a non-zero return code {}: Please make sure your LaTeX installation is correct and report a bug if so. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1393,7 +1397,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm Make sure said package is installed, or disable the LaTeX rendering in LogarithmPlotter. - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1407,8 +1411,8 @@ Please make sure your LaTeX installation is correct and report a bug if so. name - - + + %1 %2 renamed to %3. %1 %2 renamed to %3. @@ -1416,114 +1420,114 @@ Please make sure your LaTeX installation is correct and report a bug if so. parameters - + above ↑ Above - + below ↓ Below - - + + left ← Left - - + + right → Right - + above-left ↖ Above left - + above-right ↗ Above right - + below-left ↙ Below left - + below-right ↘ Below right - + center >|< Center - + top ↑ Top - + bottom ↓ Bottom - + top-left ↖ Top left - + top-right ↗ Top right - + bottom-left ↙ Bottom left - + bottom-right ↘ Bottom right - + application Application - + function Function - + high High - + low Low - + Next to target Next to target - + With label With label - + Hidden Hidden @@ -1542,12 +1546,12 @@ Please make sure your LaTeX installation is correct and report a bug if so. point - + Point Point - + Points Points @@ -1555,12 +1559,12 @@ Please make sure your LaTeX installation is correct and report a bug if so. position - + Position of %1 %2 set from "%3" to "%4". %1 %2 moved from "%3" to "%4". - + Position of %1 set from %2 to %3. %1 moved from %2 to %3. @@ -1568,158 +1572,158 @@ Please make sure your LaTeX installation is correct and report a bug if so. prop - + expression Expression - + definitionDomain Domain - + destinationDomain Range - - - - - - - - - - + + + + + + + + + + labelPosition Label position - + displayMode Display mode - - - - - - - + + + + + + + labelX Label's X position - - + + drawPoints Show points - - + + drawDashedLines Show dashed lines - - + + om_0 ω₀ - + pass Pass - + gain Magnitude gain - + omGraduation Show graduation on ω₀ - + phase Phase - + unit Unit to use - - - + + + x X - - + + y Y - + pointStyle Point style - + probabilities Probabilities list - + text Content - + disableLatex Disable LaTeX rendering for this text - + targetElement Object to target - + approximate Show rounded calculated value - + rounding Rounding - + displayStyle Display style - + targetValuePosition Target's value position - + defaultExpression Default expression - + baseValues Initialization values @@ -1742,12 +1746,12 @@ Please make sure your LaTeX installation is correct and report a bug if so. sequence - + Sequence Sequence - + Sequences Sequences @@ -1755,17 +1759,17 @@ Please make sure your LaTeX installation is correct and report a bug if so. settingCategory - + general General - + editor Expression Editor - + default Default settings @@ -1787,12 +1791,12 @@ Please make sure your LaTeX installation is correct and report a bug if so. text - + Text Text - + Texts Texts @@ -1800,22 +1804,22 @@ Please make sure your LaTeX installation is correct and report a bug if so. update - + An update for LogarithmPlotter (v{}) is available. An update for LogarithmPlotter (v{}) is available. - + No update available. No update available. - + Could not fetch update information: Server error {}. Could not fetch update information: Server error {}. - + Could not fetch update information: {}. Could not fetch update information: {}. @@ -1823,22 +1827,22 @@ Please make sure your LaTeX installation is correct and report a bug if so. usage - + integral(<from: number>, <to: number>, <f: ExecutableObject>) integral(<from: number>, <to: number>, <f: Function-like object>) - - + + Usage: %1 Usage: %1 - - - + + + Usage: %1 %2 @@ -1847,17 +1851,17 @@ Please make sure your LaTeX installation is correct and report a bug if so. - + integral(<from: number>, <to: number>, <f: string>, <variable: string>) integral(<from: number>, <to: number>, <f: string>, <variable: string>) - + derivative(<f: ExecutableObject>, <x: number>) derivative(<f: Function-like object>, <x: number>) - + derivative(<f: string>, <variable: string>, <x: number>) derivative(<f: string>, <variable: string>, <x: number>) @@ -1865,14 +1869,14 @@ Please make sure your LaTeX installation is correct and report a bug if so. visibility - - + + %1 %2 shown. %1 %2 shown. - - + + %1 %2 hidden. %1 %2 hidden. @@ -1880,12 +1884,12 @@ Please make sure your LaTeX installation is correct and report a bug if so. xcursor - + X Cursor X Cursor - + X Cursors X Cursors diff --git a/assets/i18n/lp_es.ts b/assets/i18n/lp_es.ts index 02b39ef..f5e3d12 100644 --- a/assets/i18n/lp_es.ts +++ b/assets/i18n/lp_es.ts @@ -4,27 +4,27 @@ About - + About LogarithmPlotter Sobre LogarithmPlotter - + LogarithmPlotter v%1 LogarithmPlotter v%1 - + 2D plotter software to make BODE plots, sequences and repartition functions. Software de trazado 2D para realizar gráficos de Bode, secuencias y funciones de distribución. - + Report a bug Informar de un error - + Official website Sitio web oficial @@ -32,57 +32,57 @@ AppMenuBar - + &File &Archivo - + &Load... &Abrir… - + &Save &Guardar - + Save &As... Guardar &como… - + &Quit &Salida - + &Edit &Editar - + &Undo &Cancelar - + &Redo &Reiniciar - + &Copy plot &Copiar el gráfico - + &Preferences &Preferencias - + &Create &Crear @@ -119,52 +119,52 @@ Esquema de colores - + &Help &Ayuda - + &Source code &Código fuente - + &Report a bug &Informar de un error - + &User manual &Manual del usuario - + &Changelog &Registro de cambios - + &Help translating! &¡Ayuda a la traducción! - + &Thanks &Agradecimientos - + &About &Acerca de - + Save unsaved changes? ¿Guardar los cambios no guardados? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Este gráfico contiene cambios sin guardar. Al hacer esto, se perderán todos los datos no guardados. ¿Continuar? @@ -176,7 +176,7 @@ BaseDialog - + Close Cerrar @@ -191,12 +191,12 @@ Changelog - + Fetching changelog... Obteniendo el registro de cambios… - + Close Cerrar @@ -204,13 +204,13 @@ CustomPropertyList - - + + + Create new %1 + Crear nuevo %1 - + Pick on graph Elegir en el gráfico @@ -218,42 +218,42 @@ Dialog - + Edit properties of %1 %2 Editar las propiedades de %1 %2 - + LogarithmPlotter - Invalid object name LogarithmPlotter - Nombre de objeto no válido - + An object with the name '%1' already exists. Ya existe un objeto con el nombre '%1'. - + Name - + Label content - + null - + name - + name + value nombre + valor @@ -292,32 +292,32 @@ ExpressionEditor - + Object Properties Propiedades de los objetos - + Variables - + Constants Constantes - + Functions Funciones - + Executable Objects Objetos de función - + Objects Objetos @@ -325,12 +325,12 @@ FileDialog - + Export Logarithm Plot file Exportar archivo de gráfico de logaritmos - + Import Logarithm Plot file Importar archivo de gráfico de logaritmos @@ -338,12 +338,12 @@ GreetScreen - + Welcome to LogarithmPlotter Bienvenid@ a LogarithmPlotter - + Version %1 @@ -352,22 +352,22 @@ Activar el renderizado de LaTeX - + User manual - + Changelog Registro de cambios - + Preferences Preferencias - + Close Cerrar @@ -405,22 +405,22 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes HistoryBrowser - + Filter... - + Redo > Rehacer > - + > Now > Ahora - + < Undo < Deshacer @@ -428,7 +428,7 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes ListSetting - + + Add Entry + Añadir entrada @@ -436,32 +436,32 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes LogarithmPlotter - + Objects Objetos - + Settings Ajustes - + History Historial - + Copied plot screenshot to clipboard! ¡Captura de pantalla del gráfico copiada al portapapeles! - + &Update &Actualizar - + &Update LogarithmPlotter &Actualizar LogarithmPlotter @@ -493,7 +493,7 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes ObjectCreationGrid - + + Create new: + Crear nuevo: @@ -501,12 +501,12 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes ObjectLists - + Hide all %1 Ocultar todo %1 - + Show all %1 Mostrar todo %1 @@ -534,27 +534,27 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes ObjectRow - + Hide %1 %2 Ocultar %1 %2 - + Show %1 %2 Mostrar %1 %2 - + Set %1 %2 position - + Delete %1 %2 - + Pick new color for %1 %2 Elegir nuevo color para %1 %2 @@ -562,37 +562,37 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes PickLocationOverlay - + Pointer precision: Precisión del puntero: - + Snap to grid: Ajustar a la cuadrícula: - + Pick X Elige X - + Pick Y Elige Y - + Open picker settings Abrir los ajustes del selector - + Hide picker settings Ocultar ajustes del selector - + (no pick selected) (sin selección) @@ -604,7 +604,7 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes Preferences - + Close Cerrar @@ -612,110 +612,110 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes Settings - - + + X Zoom - - + + Y Zoom - - + + Min X - - + + Max Y - + Max X - + Min Y - - + + X Axis Step Paso por eje X - - + + Y Axis Step Paso por eje Y - - + + Line width Anchura de la línea - - + + Text size (px) Tamaño del texto (px) - - + + X Label - - + + Y Label - - + + X Log scale Escala logarítmica en X - - + + Show X graduation Mostrar graduación del eje X - - + + Show Y graduation Mostrar graduación del eje Y - + Copy to clipboard Copiar al portapapeles - + Save plot Guardar gráfico… - + Save plot as Guardar gráfico como… - + Load plot Abrir gráfico… @@ -727,96 +727,96 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes ThanksTo - + Thanks and Contributions - LogarithmPlotter Agradecimientos y colaboraciones - LogarithmPlotter - + Source code - + Original library by Raphael Graf Biblioteca original de Raphael Graf - + Source - + Ported to Javascript by Matthew Crumley Portado a JavaScript por Matthew Crumley - - - + + + Website - + Ported to QMLJS by Ad5001 Portado a QMLJS por Ad5001 - + Libraries included Bibliotecas incluidas - + Email - + English - + French - + German - + Hungarian - - - + + + Github GitHub - + Norwegian - + Spanish Español - + Translations included Traducciones incluidas - + Improve Mejorar @@ -824,24 +824,24 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes bodemagnitude - + Bode Magnitude Magnitud de Bode - + Bode Magnitudes Magnitudes de Bode - - + + low-pass Filtro paso bajo - - + + high-pass Filtro paso alto @@ -849,8 +849,8 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes bodemagnitudesum - - + + Bode Magnitudes Sum Suma de las Magnitudes de Bode @@ -858,12 +858,12 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes bodephase - + Bode Phase Fase de Bode - + Bode Phases Fases de Bode @@ -871,8 +871,8 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes bodephasesum - - + + Bode Phases Sum Suma de las fases de Bode @@ -880,12 +880,12 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes changelog - + Could not fetch changelog: Server error {}. No se ha podido recuperar el registro de cambios: Error del servidor {}. - + Could not fetch update: {}. No se pudo obtener el registro de cambios: {}. @@ -893,8 +893,8 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes color - - + + %1 %2's color changed from %3 to %4. El color de %1 %2 cambió de %3 a %4. @@ -902,27 +902,27 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes comment - + Ex: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ⁻*), ]0;1[, {3;4;5} Ej: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ-*), ]0;1[, {3;4;5} - + The following parameters are used when the definition domain is a non-continuous set. (Ex: ℕ, ℤ, sets like {0;3}...) Los siguientes parámetros se utilizan cuando el dominio es un conjunto no continuo. (Ej: ℕ, ℤ, conjuntos como {0;3}...) - + Note: Specify the probability for each value. Nota: Especifique la probabilidad para cada valor. - + Note: Use %1[n] to refer to %1ₙ, %1[n+1] for %1ₙ₊₁... Nota: Utilice %1[n] para referirse a %1ₙ, %1[n+1] para %1ₙ₊₁… - + If you have latex enabled, you can use use latex markup in between $$ to create equations. Si tiene habilitado el latex, puede utilizar el marcado de latex entre $$ para crear ecuaciones. @@ -930,11 +930,11 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes control - - - - - + + + + + %1: @@ -942,8 +942,8 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes create - - + + New %1 %2 created. Se ha creado un nuevo %1 %2. @@ -951,8 +951,8 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes delete - - + + %1 %2 deleted. %1 %2 borrados. @@ -960,12 +960,12 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes distribution - + Repartition Distribución - + Repartition functions Funciones de distribución @@ -973,12 +973,12 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes editproperty - + %1 of %2 %3 changed from "%4" to "%5". %1 de %2 %3 cambió de "%4" a "%5". - + %1 of %2 changed from %3 to %4. %1 de %2 ha cambiado de %3 a %4. @@ -986,46 +986,46 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes error - - + + Cannot find property %1 of object %2. No se puede encontrar la propiedad %1 del objeto %2. - + Undefined variable %1. Variable %1 no definida. - + In order to be executed, object %1 must have at least one argument. Para ser ejecutado, el objeto %1 debe tener al menos un argumento. - + %1 cannot be executed. %1 no es una función. - - - + + + Invalid expression. Expresión incorrecta. - + Invalid expression (parity). Expresión no válida (paridad). - + Unknown character "%1". Carácter "%1" desconocido. - - + + Illegal escape sequence: %1. Secuencia de salida no válida: %1 . @@ -1034,109 +1034,109 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes Error de análisis [%1:%2]: %3 - - + + Parse error [position %1]: %2 Error en el análisis [posición%1 ]:%2 - + Expected %1 Previsto %1 - + Unexpected %1 Inesperado %1 - + Unexpected ".": member access is not permitted "." Inesperado: el acceso de miembros no está permitido - + Unexpected "[]": arrays are disabled. "[]" inesperado: las matrices están desactivadas. - + Unexpected symbol: %1. Símbolo inesperado: %1. - - + + Function %1 must have at least one argument. La función %1 debe tener al menos un argumento. - + First argument to map is not a function. El primer argumento de map no es una función. - + Second argument to map is not an array. El segundo argumento de map no es una matriz. - + First argument to fold is not a function. El primer argumento de fold no es una función. - + Second argument to fold is not an array. El segundo argumento de fold no es una matriz. - + First argument to filter is not a function. El primer argumento del filtro no es una función. - + Second argument to filter is not an array. El segundo argumento del filtro no es una matriz. - + Second argument to indexOf is not a string or array. El segundo argumento de indexOf no es una cadena ni una matriz. - + Second argument to join is not an array. El segundo argumento para unirse no es una matriz. - + No object found with names %1. No se ha encontrado ningún objeto con el nombre %1. - + No object found with name %1. Ningún objeto con el nombre %1 encontrado. - + Object cannot be dependent on itself. El objeto no puede depender de sí mismo. - + Circular dependency detected. Object %1 depends on %2. Dependencia circular detectada. El objeto %1 depende de %2. - + Circular dependency detected. Objects %1 depend on %2. Dependencia circular detectada. Los objetos %1 dependen de %2. - + Error while parsing expression for property %1: %2 @@ -1147,7 +1147,7 @@ Evaluated expression: %3 Expresión evaluada: %3 - + Error while attempting to draw %1 %2: %3 @@ -1166,7 +1166,7 @@ Deshaciendo el último cambio. Variable de asignación esperada. - + EOF Fin de la expresión @@ -1174,13 +1174,13 @@ Deshaciendo el último cambio. expression - - + + LogarithmPlotter - Parsing error LogarithmPlotter - Error de procesamiento - + Error while parsing expression for property %1: %2 @@ -1191,27 +1191,27 @@ Evaluated expression: %3 Expresión evaluada: %3 - + LogarithmPlotter - Drawing error - + Automatically close parenthesises and brackets Cerrar automáticamente paréntesis y corchetes - + Enable syntax highlighting Activar el resaltado sintáctico - + Enable autocompletion Activar autocompletar - + Color Scheme Esquema de colores @@ -1219,12 +1219,12 @@ Expresión evaluada: %3 function - + Function Función - + Functions Funciones @@ -1251,17 +1251,17 @@ Expresión evaluada: %3 general - + Check for updates on startup Comprobación de las actualizaciones al arrancar - + Reset redo stack automaticly Restablecer la pila de rehacer automáticamente - + Enable LaTeX rendering Activar el renderizado de LaTeX @@ -1320,32 +1320,36 @@ Expresión evaluada: %3 Objetos - + Saved plot to '%1'. Gráfico guardado en '%1'. - + Loading file '%1'. Cargando el archivo '%1'. - + Unknown object type: %1. Tipo de objeto desconocido: %1 . - + Invalid file provided. Se ha proporcionado un archivo no válido. - - Could not save file: - No se ha podido guardar el archivo: + + Could not load file: + - + Could not save file: + No se ha podido guardar el archivo: + + + Loaded file '%1'. Archivo cargado '%1'. @@ -1353,7 +1357,7 @@ Expresión evaluada: %3 latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. @@ -1362,12 +1366,12 @@ Si ya tiene instalada una distribución de LaTeX, asegúrese de que está instal De lo contrario, puede descargar una distribución de LaTeX como TeX Live en https://tug.org/texlive/. - + DVIPNG was not found. Make sure you include it from your Latex distribution. No se ha encontrado DVIPNG. Asegúrese de incluirlo en tu distribución LaTeX. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1380,7 +1384,7 @@ El proceso '{}' terminó con un código de retorno distinto de cero {} Por favor, asegúrate de que tu instalación de LaTeX es correcta e informe de un error si es así. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1393,7 +1397,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm Asegúrate de que dicho paquete está instalado, o desactive el renderizado LaTeX en LogarithmPlotter. - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1407,8 +1411,8 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u name - - + + %1 %2 renamed to %3. %1 %2 ha sido renombrado a %3. @@ -1416,114 +1420,114 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u parameters - + below ↓ Abajo - - + + left ← Izquierda - + above-left ↖ Arriba a la izquierda - + below-left ↙ Abajo a la izquierda - + below-right ↘ Arriba a la derecha - + center >|< Centro - + top ↑ Arriba - + above ↑ Arriba - - + + right → Derecha - + above-right ↗ Arriba a la derecha - + bottom ↓ Bajar - + top-right ↗ Arriba a la derecha - + application Aplicación - + Next to target Próximo al objetivo - + top-left ↖ Arriba a la izquierda - + bottom-left ↙ Abajo a la izquierda - + bottom-right ↘ Abajo a la derecha - + function Función - + high Alto - + low Bajo - + With label Con etiqueta - + Hidden Oculto @@ -1542,12 +1546,12 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u point - + Point Punto - + Points Puntos @@ -1555,12 +1559,12 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u position - + Position of %1 %2 set from "%3" to "%4". %1 %2 movido de "%3" a "%4". - + Position of %1 set from %2 to %3. %1 movido de %2 a %3. @@ -1568,153 +1572,153 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u prop - + expression Expresión - + definitionDomain Dominio - - + + om_0 ω₀ - + disableLatex Desactivar el renderizado LaTeX para este texto - + rounding Redondeo - - - - - - - + + + + + + + labelX Posición de la etiqueta en X - - + + drawPoints Mostrar puntos - - + + drawDashedLines Mostrar líneas discontinuas - + destinationDomain Rango - - - - - - - - - - + + + + + + + + + + labelPosition Posición de la etiqueta - + displayMode Modo de visualización - + pass Pasar - + gain Incremento de magnitud - + unit Unidad a usar - - + + y Y - + omGraduation Mostrar la graduación en ω₀ - + phase Fase - - - + + + x X - + pointStyle Estilo de puntos - + text Contenido - + probabilities Lista de probabilidades - + targetElement Objeto de destino - + approximate Mostrar el resultado redondeado - + displayStyle Estilo de visualización - + targetValuePosition Posición del valor del objetivo - + defaultExpression Expresión predeterminada @@ -1723,7 +1727,7 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u Color - + baseValues Valores de inicialización @@ -1742,12 +1746,12 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u sequence - + Sequences Secuencias - + Sequence Secuencia @@ -1755,17 +1759,17 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u settingCategory - + general General - + editor Editor de expresiones - + default Ajustes por defecto @@ -1787,12 +1791,12 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u text - + Texts Textos - + Text Texto @@ -1800,22 +1804,22 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u update - + An update for LogarithmPlotter (v{}) is available. Una actualización para LogarithmPlotter (v{}) está disponible. - + No update available. No hay ninguna actualización disponible. - + Could not fetch update information: Server error {}. No se ha podido obtener la información de la actualización: Error del servidor {}. - + Could not fetch update information: {}. No se pudo obtener información de la actualización: {}. @@ -1823,22 +1827,22 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u usage - + integral(<from: number>, <to: number>, <f: ExecutableObject>) integral(<desde: número>, <hasta: número>, <f: Objeto similar a una función>) - - + + Usage: %1 Uso: %1 - - - + + + Usage: %1 %2 @@ -1847,17 +1851,17 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u %2 - + integral(<from: number>, <to: number>, <f: string>, <variable: string>) integral(<desde: número>, <hasta: número>, <f: cadena>, <variable: cadena>) - + derivative(<f: ExecutableObject>, <x: number>) derivative(<f: objeto similar a una función>, <x: número>) - + derivative(<f: string>, <variable: string>, <x: number>) derivative(<f: cadena>, <variable: cadena>, <x: número>) @@ -1865,14 +1869,14 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u visibility - - + + %1 %2 shown. Se muestra %1 %2. - - + + %1 %2 hidden. Se oculta %1 %2. @@ -1880,12 +1884,12 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u xcursor - + X Cursor Cursor X - + X Cursors Cursores X diff --git a/assets/i18n/lp_fr.ts b/assets/i18n/lp_fr.ts index eeaa500..7df2b4f 100644 --- a/assets/i18n/lp_fr.ts +++ b/assets/i18n/lp_fr.ts @@ -4,27 +4,27 @@ About - + About LogarithmPlotter À propos de LogarithmPlotter - + LogarithmPlotter v%1 LogarithmPlotter v%1 - + 2D plotter software to make BODE plots, sequences and repartition functions. Logiciel de traçage 2D pour les diagrammes de Bode, les suites et les fonctions de répartition. - + Report a bug Rapport de bug - + Official website Site officiel @@ -32,57 +32,57 @@ AppMenuBar - + &File &Fichier - + &Load... &Ouvrir… - + &Save &Sauvegarder - + Save &As... Sauvegarde &Sous… - + &Quit &Quitter - + &Edit &Édition - + &Undo &Annuler - + &Redo &Rétablir - + &Copy plot &Copier le graphe - + &Preferences &Préférences - + &Create &Créer @@ -124,52 +124,52 @@ Coloration Syntaxique - + &Help &Aide - + &Source code &Code source - + &Report a bug &Rapport de bug - + &User manual Manuel d'&utilisation - + &Changelog &Historique des modifications - + &Help translating! &Aider à la traduction ! - + &Thanks &Remerciements - + &About &À propos - + Save unsaved changes? Sauvegarder les modifications ? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Ce graphe contient des modifications non sauvegardées. En faisant cela, toutes les données non sauvegardées seront perdues. Continuer ? @@ -177,7 +177,7 @@ BaseDialog - + Close Fermer @@ -192,12 +192,12 @@ Changelog - + Fetching changelog... Récupération de l'historique des modifications… - + Close Fermer @@ -205,13 +205,13 @@ CustomPropertyList - - + + + Create new %1 + Créer un nouvel objet %1 - + Pick on graph Prendre la position sur le graphe @@ -219,42 +219,42 @@ Dialog - + Edit properties of %1 %2 Changer les propriétés de %1 %2 - + LogarithmPlotter - Invalid object name LogarithmPlotter - Nom d'objet invalide - + An object with the name '%1' already exists. Un objet portant le nom '%1' existe déjà. - + Name Nom - + Label content Étiquette - + null vide - + name nom - + name + value nom + valeur @@ -294,32 +294,32 @@ ExpressionEditor - + Object Properties Propriétés de l'objet - + Variables Variables - + Constants Constantes - + Functions Fonctions - + Executable Objects Objets fonction - + Objects Objets @@ -327,12 +327,12 @@ FileDialog - + Export Logarithm Plot file Exporter le graphe Logarithmique - + Import Logarithm Plot file Importer un graphe Logarithmique @@ -340,12 +340,12 @@ GreetScreen - + Welcome to LogarithmPlotter Bienvenue sur LogarithmPlotter - + Version %1 Version %1 @@ -376,22 +376,22 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Thème de coloration syntaxique : - + User manual Manuel d'utilisation - + Changelog Historique des modifications - + Preferences Préférences - + Close Fermer @@ -407,22 +407,22 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P HistoryBrowser - + Filter... Filtrer… - + Redo > Rétablir > - + > Now > État actuel - + < Undo < Annuler @@ -430,7 +430,7 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P ListSetting - + + Add Entry + Nouvelle entrée @@ -438,17 +438,17 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P LogarithmPlotter - + Objects Objets - + Settings Paramètres - + History Historique @@ -477,17 +477,17 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Fichier '%1' chargé. - + Copied plot screenshot to clipboard! Image du graphe copiée dans le presse-papiers ! - + &Update &Mise à jour - + &Update LogarithmPlotter &Mettre à jour LogarithmPlotter @@ -495,7 +495,7 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P ObjectCreationGrid - + + Create new: + Créer : @@ -503,12 +503,12 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P ObjectLists - + Hide all %1 Cacher tous les %1 - + Show all %1 Montrer tous les %1 @@ -536,27 +536,27 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P ObjectRow - + Hide %1 %2 Cacher l'objet %1 %2 - + Show %1 %2 Montrer l'objet %1 %2 - + Set %1 %2 position Définir la position de l'objet %1 %2 - + Delete %1 %2 Supprimer l'objet %1 %2 - + Pick new color for %1 %2 Choisissez une nouvelle couleur pour %1 %2 @@ -564,7 +564,7 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P PickLocationOverlay - + Pointer precision: Précision du pointeur : @@ -573,32 +573,32 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Placement sur la grille - + Snap to grid: Placer sur la grille : - + Pick X Prendre la position X - + Pick Y Prendre la position Y - + Open picker settings Ouvrir les paramètres du pointeur - + Hide picker settings Cacher les paramètres du pointeur - + (no pick selected) (aucun axe sélectionné) @@ -606,7 +606,7 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Preferences - + Close Fermer @@ -614,110 +614,110 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Settings - - + + X Zoom Zoom en X - - + + Y Zoom Zoom en Y - - + + Min X Min X - - + + Max Y Max Y - + Max X Max X - + Min Y Min Y - - + + X Axis Step Pas de l'axe X - - + + Y Axis Step Pas de l'axe Y - - + + Line width Taille des lignes - - + + Text size (px) Taille du texte (px) - - + + X Label Label de l'axe X - - + + Y Label Label de l'axe Y - - + + X Log scale Échelle logarithmique en X - - + + Show X graduation Montrer la graduation de l'axe X - - + + Show Y graduation Montrer la graduation de l'axe Y - + Copy to clipboard Copier vers le presse-papiers - + Save plot Sauvegarder le graphe… - + Save plot as Sauvegarder le graphe sous… - + Load plot Ouvrir un graphe… @@ -729,96 +729,96 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P ThanksTo - + Thanks and Contributions - LogarithmPlotter Remerciements et contributions - LogarithmPlotter - + Source code Code source - + Original library by Raphael Graf Bibliothèque originale de Raphael Graf - + Source Source - + Ported to Javascript by Matthew Crumley Porté en JavaScript par Matthew Crumley - - - + + + Website Site web - + Ported to QMLJS by Ad5001 Porté à QMLJS par Ad5001 - + Libraries included Bibliothèques incluses - + Email Email - + English Anglais - + French Français - + German Allemand - + Hungarian Hongrois - - - + + + Github GitHub - + Norwegian Norvégien - + Spanish Espagnol - + Translations included Traductions incluses - + Improve Améliorer @@ -826,24 +826,24 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P bodemagnitude - + Bode Magnitude Gain de Bode - + Bode Magnitudes Gains de Bode - - + + low-pass passe-bas - - + + high-pass passe-haut @@ -851,8 +851,8 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P bodemagnitudesum - - + + Bode Magnitudes Sum Sommes des gains de Bode @@ -860,12 +860,12 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P bodephase - + Bode Phase Phase de Bode - + Bode Phases Phases de Bode @@ -873,8 +873,8 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P bodephasesum - - + + Bode Phases Sum Somme des phases de Bode @@ -882,12 +882,12 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P changelog - + Could not fetch changelog: Server error {}. Impossible de récupérer l'historique des modifications : Erreur de serveur {}. - + Could not fetch update: {}. Impossible de récupérer l'historique des modifications : {}. @@ -895,8 +895,8 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P color - - + + %1 %2's color changed from %3 to %4. La couleur du %1 %2 a été changée du %3 au %4. @@ -904,28 +904,28 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P comment - + Ex: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ⁻*), ]0;1[, {3;4;5} Par exemple : R+* (ℝ⁺*), N (ℕ), Z-* (ℤ⁻*), ]0;1[, {3;4;5} - + The following parameters are used when the definition domain is a non-continuous set. (Ex: ℕ, ℤ, sets like {0;3}...) Les paramètres suivants sont utilisés lorsque le domaine de définition est un ensemble non-continu. (Ex : ℕ, ℤ, des ensembles comme {0;3}…) - + Note: Specify the probability for each value. Note : Spécifiez la probabilité pour chaque valeur. - + Note: Use %1[n] to refer to %1ₙ, %1[n+1] for %1ₙ₊₁... Note : Utilisez %1[n] pour faire référence à %1ₙ, %1[n+1] pour %1ₙ₊₁... Note : Utilisez %1[n] pour faire référence à %1ₙ, %1[n+1] pour %1ₙ₊₁… - + If you have latex enabled, you can use use latex markup in between $$ to create equations. Si vous avez activé le rendu latex, vous pouvez utiliser les balises latex entre $$ pour créer des équations. @@ -933,11 +933,11 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P control - - - - - + + + + + %1: %1 : @@ -945,8 +945,8 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P create - - + + New %1 %2 created. Nouvel objet %1 %2 créé. @@ -954,8 +954,8 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P delete - - + + %1 %2 deleted. %1 %2 supprimé(e). @@ -963,12 +963,12 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P distribution - + Repartition Répartition - + Repartition functions Fonctions de répartition @@ -976,12 +976,12 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P editproperty - + %1 of %2 %3 changed from "%4" to "%5". %1 de %2 %3 modifiée de "%4" à "%5". - + %1 of %2 changed from %3 to %4. %1 de %2 modifiée de %3 à %4. @@ -989,46 +989,46 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P error - - + + Cannot find property %1 of object %2. Impossible de trouver la propriété %1 de l'objet %2. - + Undefined variable %1. La variable %1 n'est pas définie. - + In order to be executed, object %1 must have at least one argument. Pour être utilisé comme fonction, l'objet %1 nécessite au moins un argument. - + %1 cannot be executed. %1 n'est pas une fonction. - - - + + + Invalid expression. Formule invalide. - + Invalid expression (parity). Formule invalide (parité). - + Unknown character "%1". Le caractère "%1" est inconnu. - - + + Illegal escape sequence: %1. Séquence d'échappement illégale : %1. @@ -1037,12 +1037,12 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Erreur de syntaxe [%1:%2] : %3 - + Expected %1 %1 attendu - + Unexpected %1 %1 inattendu @@ -1055,104 +1055,104 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Une variable est attendue pour l'affectation. - - + + Parse error [position %1]: %2 Erreur de syntaxe [position %1] : %2 - + Unexpected ".": member access is not permitted "." inattendu : l'accès aux propriétés n'est pas autorisé - + Unexpected "[]": arrays are disabled. "[]" inattendu : les tableaux sont désactivés. - + Unexpected symbol: %1. Symbole inconnu : %1. - - + + Function %1 must have at least one argument. La fonction %1 nécessite au moins un argument. - + First argument to map is not a function. Le premier argument de map n'est pas une fonction. - + Second argument to map is not an array. Le deuxième argument de map n'est pas un tableau. - + First argument to fold is not a function. Le premier argument de fold n'est pas une fonction. - + Second argument to fold is not an array. Le deuxième argument de fold n'est pas un tableau. - + First argument to filter is not a function. Le premier argument de filter n'est pas une fonction. - + Second argument to filter is not an array. Le deuxième argument de filter n'est pas un tableau. - + Second argument to indexOf is not a string or array. Le deuxième argument de indexOf n'est ni chaîne de caractères ni un tableau. - + Second argument to join is not an array. Le deuxième argument de join n'est pas un tableau. - + EOF Fin de la formule - + No object found with names %1. Aucun objet trouvé ayant pour noms %1. - + No object found with name %1. Aucun objet avec le nom %1 n'a été trouvé. - + Object cannot be dependent on itself. Un objet ne peut pas dépendre de lui-même. - + Circular dependency detected. Object %1 depends on %2. Dépendance circulaire détectée. L'objet %1 dépend de %2. - + Circular dependency detected. Objects %1 depend on %2. Dépendance circulaire détectée. Les objets %1 dépendent de %2. - + Error while parsing expression for property %1: %2 @@ -1163,7 +1163,7 @@ Evaluated expression: %3 Formule analysée : %3 - + Error while attempting to draw %1 %2: %3 @@ -1177,13 +1177,13 @@ La dernière modification a été annulée. expression - - + + LogarithmPlotter - Parsing error LogarithmPlotter - Erreur de syntaxe - + Error while parsing expression for property %1: %2 @@ -1194,27 +1194,27 @@ Evaluated expression: %3 Formule analysée : %3 - + LogarithmPlotter - Drawing error LogarithmPlotter - Erreur - + Automatically close parenthesises and brackets Fermer automatiquement les parenthèses et les crochets - + Enable syntax highlighting Activer la coloration syntaxique - + Enable autocompletion Activer l'autocomplétion - + Color Scheme Coloration Syntaxique @@ -1222,12 +1222,12 @@ Formule analysée : %3 function - + Function Fonction - + Functions Fonctions @@ -1254,17 +1254,17 @@ Formule analysée : %3 general - + Check for updates on startup Vérifier la présence de mise à jour au démarrage - + Reset redo stack automaticly Réinitialiser la pile d'action "Rétablir" automatiquement - + Enable LaTeX rendering Activer le rendu LaTeX @@ -1323,32 +1323,36 @@ Formule analysée : %3 &Mettre à jour LogarithmPlotter - + Saved plot to '%1'. Graphe sauvegardé dans '%1'. - + Loading file '%1'. Chargement du fichier '%1'. - + Unknown object type: %1. Type d'objet inconnu : %1. - + Invalid file provided. Fichier fourni invalide. - - Could not save file: - Impossible de sauvegarder le fichier : + + Could not load file: + - + Could not save file: + Impossible de sauvegarder le fichier : + + + Loaded file '%1'. Fichier '%1' chargé. @@ -1356,7 +1360,7 @@ Formule analysée : %3 latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. @@ -1365,12 +1369,12 @@ Si vous avez déjà installé une distribution LaTeX, assurez-vous qu'elle Sinon, vous pouvez télécharger une distribution LaTeX comme TeX Live à l'adresse https://tug.org/texlive/. - + DVIPNG was not found. Make sure you include it from your Latex distribution. DVIPNG n'a pas été trouvé. Assurez-vous de l'inclure dans votre distribution LaTeX. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1383,7 +1387,7 @@ Le processus '{}' s'est terminé par un code de retour non nul {} Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c'est le cas. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1396,7 +1400,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm Assurez-vous que ce paquetage est installé, ou désactivez le rendu LaTeX dans LogarithmPlotter. - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1410,8 +1414,8 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c name - - + + %1 %2 renamed to %3. %1 %2 renommé(e) en %3. @@ -1419,114 +1423,114 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c parameters - + above ↑ Au dessus - + below ↓ En dessous - - + + left ← À gauche - - + + right → À droite - + above-left ↖ Au dessus à gauche - + above-right ↗ Au dessus à droite - + below-left ↙ En dessous à gauche - + below-right ↘ En dessous à droite - + center >|< Centré - + top ↑ Au dessus - + bottom ↓ En dessous - + top-left ↖ Au dessus à gauche - + top-right ↗ Au dessus à droite - + bottom-left ↙ En dessous à gauche - + bottom-right ↘ En dessous à droite - + application Application - + function Fonction - + high Haut - + low Bas - + Next to target A côté de la cible - + With label Avec l'étiquette - + Hidden Caché @@ -1545,12 +1549,12 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c point - + Point Point - + Points Points @@ -1558,12 +1562,12 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c position - + Position of %1 %2 set from "%3" to "%4". %1 %2 a été déplacé depuis "%3" vers "%4". - + Position of %1 set from %2 to %3. %1 a été déplacé depuis %2 vers %3. @@ -1571,158 +1575,158 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c prop - + expression Formule - + definitionDomain Domaine de définition - + destinationDomain Portée - - - - - - - - - - + + + + + + + + + + labelPosition Position de l'étiquette - + displayMode Mode d'affichage - - - - - - - + + + + + + + labelX Position en X de l'étiquette - - + + drawPoints Afficher les points - - + + drawDashedLines Afficher les pointillés - - + + om_0 ω₀ - + pass Passe - + gain Gain - + omGraduation Afficher la graduation sur ω₀ - + phase Phase - + unit Unité de la phase - - - + + + x X - - + + y Y - + pointStyle Style du point - + probabilities Liste de probabilités - + text Contenu - + disableLatex Désactiver le rendu LaTeX pour ce texte - + targetElement Objet à cibler - + approximate Afficher la valeur arrondie calculée - + rounding Arrondi - + displayStyle Style d'affichage - + targetValuePosition Position de la valeur de la cible - + defaultExpression Formule par défaut - + baseValues Valeurs d'initialisation @@ -1745,12 +1749,12 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c sequence - + Sequence Suite - + Sequences Suites @@ -1758,17 +1762,17 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c settingCategory - + general Général - + editor Éditeur de formule - + default Paramètres par défaut @@ -1790,12 +1794,12 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c text - + Text Texte - + Texts Textes @@ -1803,22 +1807,22 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c update - + An update for LogarithmPlotter (v{}) is available. Une mise à jour de LogarithmPlotter (v{}) est disponible. - + No update available. À jour. - + Could not fetch update information: Server error {}. Impossible de récupérer les informations de mise à jour. Erreur du serveur {}. - + Could not fetch update information: {}. Impossible de récupérer les informations de mise à jour. {}. @@ -1826,22 +1830,22 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c usage - + integral(<from: number>, <to: number>, <f: ExecutableObject>) integral(<de : nombre>, <à : nombre>, <f : Objet fonction>) - - + + Usage: %1 Emploi : %1 - - - + + + Usage: %1 %2 @@ -1850,17 +1854,17 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c %2 - + integral(<from: number>, <to: number>, <f: string>, <variable: string>) integral(<de : nombre>, <à : nombre>, <f : fonction chaîne>, <variable>) - + derivative(<f: ExecutableObject>, <x: number>) derivative(<f : Objet fonction>, <x : nombre>) - + derivative(<f: string>, <variable: string>, <x: number>) derivative(<f : fonction chaîne>, <variable>, <x : nombre>) @@ -1868,14 +1872,14 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c visibility - - + + %1 %2 shown. %1 %2 affiché(e). - - + + %1 %2 hidden. %1 %2 cachée(e). @@ -1883,12 +1887,12 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c xcursor - + X Cursor Curseur X - + X Cursors Curseurs X diff --git a/assets/i18n/lp_hu.ts b/assets/i18n/lp_hu.ts index e03702f..f817dd2 100644 --- a/assets/i18n/lp_hu.ts +++ b/assets/i18n/lp_hu.ts @@ -4,27 +4,27 @@ About - + About LogarithmPlotter LogarithmPlotter névjegye - + LogarithmPlotter v%1 LogarithmPlotter %1 verzió - + 2D plotter software to make BODE plots, sequences and repartition functions. Síkbeli ábrázolásszoftver Bode-ábrák, sorozatok és eloszlási funkciók készítéséhez. - + Report a bug Hiba bejelentése - + Official website Hivatalos honlap @@ -32,57 +32,57 @@ AppMenuBar - + &File &Fájl - + &Load... &Megnyitás… - + &Save &Mentés - + Save &As... Me&ntés másként… - + &Quit &Kilépés - + &Edit S&zerkesztés - + &Undo &Visszavonás - + &Redo &Ismétlés - + &Copy plot Ábra má&solása - + &Preferences &Beállítások - + &Create &Létrehozás @@ -123,52 +123,52 @@ Színséma - + &Help &Súgó - + &Source code &Forráskód - + &Report a bug &Hiba bejelentése - + &User manual &Használati utasítás - + &Changelog &Változásnapló - + &Help translating! &Segítség a fordításban! - + &Thanks &Köszönjük - + &About &Névjegy - + Save unsaved changes? Menti a változtatásokat? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Ez az ábra nem mentett változtatásokat tartalmaz. Ezzel az összes nem mentett adat elveszik. Folytatja? @@ -176,7 +176,7 @@ BaseDialog - + Close Bezárás @@ -191,12 +191,12 @@ Changelog - + Fetching changelog... Változásnapló lekérése… - + Close Kész @@ -204,13 +204,13 @@ CustomPropertyList - - + + + Create new %1 + Új %1 létrehozása - + Pick on graph Ábra kijelölése @@ -218,42 +218,42 @@ Dialog - + Edit properties of %1 %2 %1 %2 tulajdonságainak szerkesztése - + LogarithmPlotter - Invalid object name LogarithmPlotter - Érvénytelen objektumnév - + An object with the name '%1' already exists. A(z) „%1” nevű objektum már létezik. - + Name Név - + Label content Címketartalom - + null üres - + name név - + name + value név + érték @@ -292,32 +292,32 @@ ExpressionEditor - + Object Properties Objektumtulajdonságok - + Variables Változók - + Constants Állandók - + Functions Függvények - + Executable Objects Függvényobjektumok - + Objects Objektumok @@ -325,12 +325,12 @@ FileDialog - + Export Logarithm Plot file Logaritmus-ábra-fájl exportálása - + Import Logarithm Plot file Logaritmus-ábra-fájl importálása @@ -338,12 +338,12 @@ GreetScreen - + Welcome to LogarithmPlotter Isten hozott a LogarithmPlotter! - + Version %1 %1 verzió @@ -382,22 +382,22 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. Színséma: - + User manual Használati utasítás - + Changelog Változásnapló - + Preferences Beállítások - + Close Kész @@ -405,22 +405,22 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. HistoryBrowser - + Filter... Szűrő… - + Redo > Ismétlés > - + > Now > Most - + < Undo < Visszavonás @@ -428,7 +428,7 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. ListSetting - + + Add Entry + Bejegyzés hozzáadása @@ -436,17 +436,17 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. LogarithmPlotter - + Objects Tárgyak - + Settings Beállítások - + History Előzmények @@ -475,17 +475,17 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. A(z) „%1” fájl betöltve. - + Copied plot screenshot to clipboard! Ábra képernyőkép vágólapra másolva! - + &Update &Frissítés - + &Update LogarithmPlotter A LogarithmPlotter &frissítése @@ -493,7 +493,7 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. ObjectCreationGrid - + + Create new: + Új létrehozása: @@ -501,12 +501,12 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. ObjectLists - + Hide all %1 Összes %1 elrejtése - + Show all %1 Összes %1 megjelenítése @@ -534,27 +534,27 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. ObjectRow - + Hide %1 %2 %1 %2 elrejtése - + Show %1 %2 %1 %2 megjelenítése - + Set %1 %2 position %1 %2 helye beállítása - + Delete %1 %2 %1 %2 törlése - + Pick new color for %1 %2 Válasszon új színt a következőhöz: %1 %2 @@ -562,7 +562,7 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. PickLocationOverlay - + Pointer precision: Mutató pontossága: @@ -571,32 +571,32 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. Rácshoz illesztés - + Snap to grid: Rácshoz igazítás: - + Pick X X kijelölése - + Pick Y Y kijelölése - + Open picker settings Kijelölési beállítások megnyitása - + Hide picker settings Kijelölési beállítások elrejtése - + (no pick selected) (nincs kijelölés kiválasztva) @@ -604,7 +604,7 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. Preferences - + Close Bezárás @@ -612,110 +612,110 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. Settings - - + + X Zoom X-nagyítás - - + + Y Zoom Y-nagyítás - - + + Min X Legkisebb X - - + + Max Y Legnagyobb Y - + Max X Legnagyobb X - + Min Y Legkisebb Y - - + + X Axis Step X tengely lépésköze - - + + Y Axis Step Y tengely lépésköze - - + + Line width Vonalvastagság - - + + Text size (px) Szövegméret (képpont) - - + + X Label X címke - - + + Y Label Y címke - - + + X Log scale X tengely logaritmikus skálával - - + + Show X graduation X érettségi megjelenítése - - + + Show Y graduation Y érettségi megjelenítése - + Copy to clipboard Másolás a vágólapra - + Save plot Ábra mentése… - + Save plot as Ábra mentése másként… - + Load plot Ábra megnyitása… @@ -727,96 +727,96 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. ThanksTo - + Thanks and Contributions - LogarithmPlotter Köszönet és hozzájárulás - LogarithmPlotter - + Source code Forráskód - + Original library by Raphael Graf Eredeti könyvtár: Graf Raphael - + Source Forrás - + Ported to Javascript by Matthew Crumley JavaScript-átalakítás: Crumley Máté - - - + + + Website Honlap - + Ported to QMLJS by Ad5001 QMLJS-átalakítás: Ad5001 - + Libraries included Tartalmazott könyvtárak - + Email E-mail - + English angol - + French francia - + German német - + Hungarian magyar - - - + + + Github GitHub - + Norwegian norvég - + Spanish spanyol - + Translations included A felhasználói felület nyelvei - + Improve Fejlesztés @@ -824,24 +824,24 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. bodemagnitude - + Bode Magnitude Bode-nagyságrend - + Bode Magnitudes Bode-nagyságrendek - - + + low-pass aluláteresztő - - + + high-pass felüláteresztő @@ -849,8 +849,8 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. bodemagnitudesum - - + + Bode Magnitudes Sum Bode-nagyságrendek összege @@ -858,12 +858,12 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. bodephase - + Bode Phase Bode-fázis - + Bode Phases Bode-fázisok @@ -871,8 +871,8 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. bodephasesum - - + + Bode Phases Sum Bode-fázisok összege @@ -880,12 +880,12 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. changelog - + Could not fetch changelog: Server error {}. Nem sikerült lekérni a változásnaplót: Kiszolgálóhiba: {}. - + Could not fetch update: {}. Nem sikerült lekérni a változásnaplót: {}. @@ -893,8 +893,8 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. color - - + + %1 %2's color changed from %3 to %4. %1 %2 színe %3-ról %4-re változott. @@ -902,27 +902,27 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. comment - + Ex: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ⁻*), ]0;1[, {3;4;5} Példák: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ⁻*), ]0;1[, {3;4;5} - + The following parameters are used when the definition domain is a non-continuous set. (Ex: ℕ, ℤ, sets like {0;3}...) A következő paraméterek használatosak, ha a tartomány nem folytonos halmaz. (Példák: ℕ, ℤ, olyan halmazok, mint a {0;3}…) - + Note: Specify the probability for each value. Megjegyzés: Adja meg az egyes értékek valószínűségét. - + Note: Use %1[n] to refer to %1ₙ, %1[n+1] for %1ₙ₊₁... Megjegyzés: A(z) %1[n] használatával hivatkozhat erre: %1ₙ, a(z) %1[n+1] használatával hivatkozhat erre: %1ₙ₊₁, … - + If you have latex enabled, you can use use latex markup in between $$ to create equations. Ha a LaTeX engedélyezve van, a LaTeX-jelölés használható egyenletek létrehozására $$ között. @@ -930,11 +930,11 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. control - - - - - + + + + + %1: %1: @@ -942,8 +942,8 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. create - - + + New %1 %2 created. Új %1 %2 létrehozva. @@ -951,8 +951,8 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. delete - - + + %1 %2 deleted. %1 %2 törölve. @@ -960,12 +960,12 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. distribution - + Repartition Elosztás - + Repartition functions Elosztási függvények @@ -973,12 +973,12 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. editproperty - + %1 of %2 %3 changed from "%4" to "%5". %1/%2 %3 megváltozott. Régi érték: %4, új érték: %5. - + %1 of %2 changed from %3 to %4. %1/%2 megváltozott. Régi érték: %3, új érték: %4. @@ -986,46 +986,46 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. error - - + + Cannot find property %1 of object %2. A(z) %2 objektum %1 tulajdonsága nem található. - + Undefined variable %1. A(z) %1 változó nincs meghatározva. - + In order to be executed, object %1 must have at least one argument. A végrehajtáshoz a(z) %1 objektumnak legalább egy argumentummal kell rendelkeznie. - + %1 cannot be executed. A(z) %1 nem függvény. - - - + + + Invalid expression. Érvénytelen kifejezés. - + Invalid expression (parity). Érvénytelen kifejezés (paritás). - + Unknown character "%1". Ismeretlen karakter „%1”. - - + + Illegal escape sequence: %1. Érvénytelen kilépési sorozat: %1. @@ -1034,12 +1034,12 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. Elemzési hiba [%1:%2]: %3 - + Expected %1 Várható %1 - + Unexpected %1 Váratlan %1 @@ -1052,104 +1052,104 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. A hozzárendeléshez várt változó. - - + + Parse error [position %1]: %2 Elemzési hiba [hely %1]: %2 - + Unexpected ".": member access is not permitted Váratlan „.”: a tagok hozzáférése nem engedélyezett - + Unexpected "[]": arrays are disabled. Váratlan „[]”: a tömbök le vannak tiltva. - + Unexpected symbol: %1. Váratlan szimbólum: %1. - - + + Function %1 must have at least one argument. A(z) %1 függvénynek legalább egy argumentumnak kell lennie. - + First argument to map is not a function. Az első leképezési argumentum nem függvény. - + Second argument to map is not an array. A második leképezési argumentum nem tömb. - + First argument to fold is not a function. Az első behajtási argumentum nem függvény. - + Second argument to fold is not an array. A második behajtási argumentum nem tömb. - + First argument to filter is not a function. Az első szűrési argumentum nem függvény. - + Second argument to filter is not an array. A második szűrési argumentum nem tömb. - + Second argument to indexOf is not a string or array. Az indexOf második argumentuma nem karakterlánc vagy tömb. - + Second argument to join is not an array. A második csatlakozási argumentum nem tömb. - + EOF Kifejezés vége - + No object found with names %1. A(z) %1 nevű objektum nem található. - + No object found with name %1. A(z) %1 nevű objektum nem található. - + Object cannot be dependent on itself. Az objektum nem függhet önmagától. - + Circular dependency detected. Object %1 depends on %2. Körkörös függőség észlelve. A(z) %1-objektum a(z) %2-objektumtól függ. - + Circular dependency detected. Objects %1 depend on %2. Körkörös függőség észlelve. A(z) %1-objektumok a(z) %2-objektumtól függenek. - + Error while parsing expression for property %1: %2 @@ -1160,7 +1160,7 @@ Evaluated expression: %3 Kiértékelt kifejezés: %3 - + Error while attempting to draw %1 %2: %3 @@ -1174,13 +1174,13 @@ Az utolsó módosítás visszavonása. expression - - + + LogarithmPlotter - Parsing error LogarithmPlotter - Elemzési hiba - + Error while parsing expression for property %1: %2 @@ -1191,27 +1191,27 @@ Evaluated expression: %3 Kiértékelt kifejezés: %3 - + LogarithmPlotter - Drawing error LogarithmPlotter - Rajzolási hiba - + Automatically close parenthesises and brackets Zárójelek automatikus bezárása - + Enable syntax highlighting Mondattani kiemelés engedélyezése - + Enable autocompletion Automatikus befejezés engedélyezése - + Color Scheme Színséma @@ -1219,12 +1219,12 @@ Kiértékelt kifejezés: %3 function - + Function Függvény - + Functions Függvények @@ -1251,17 +1251,17 @@ Kiértékelt kifejezés: %3 general - + Check for updates on startup Frissítések keresése indításkor - + Reset redo stack automaticly Ismétlési verem önműködő visszaállítása - + Enable LaTeX rendering LaTeX-megjelenítés engedélyezése @@ -1304,32 +1304,36 @@ Kiértékelt kifejezés: %3 Előzmények - + Saved plot to '%1'. Ábra mentve ide: „%1”. - + Loading file '%1'. A(z) „%1” fájl betöltése folyamatban van. - + Unknown object type: %1. Ismeretlen objektumtípus: %1. - + Invalid file provided. A megadott fájl érvénytelen. - - Could not save file: - A fájl mentése nem sikerült: + + Could not load file: + - + Could not save file: + A fájl mentése nem sikerült: + + + Loaded file '%1'. A(z) „%1” fájl betöltve. @@ -1353,7 +1357,7 @@ Kiértékelt kifejezés: %3 latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. @@ -1362,12 +1366,12 @@ Ha már telepítve van egy LaTeX disztribúció, győződjön meg arról, hogy a Egyébként letölthet egy LaTeX disztribúciót, például a TeX Live-t a https://tug.org/texlive/ címről. - + DVIPNG was not found. Make sure you include it from your Latex distribution. DVIPNG nem található. Ügyeljen arra, hogy a LaTeX disztribúciójából tartalmazza. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1380,7 +1384,7 @@ A(z) „{}” folyamat nullától eltérő visszatérési kóddal ({}) végződ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelentse a hibát. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1393,7 +1397,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm Győződjön meg arról, hogy az említett csomag telepítve van, vagy tiltsa le a LaTeX megjelenítést a LogarithmPlotterben. - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1407,8 +1411,8 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents name - - + + %1 %2 renamed to %3. %1 %2 átnevezve erre: %3. @@ -1416,114 +1420,114 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents parameters - + above ↑ Felett - + below ↓ Alatt - - + + left ← Balra - - + + right → Jobbra - + above-left ↖ Felett, balra - + above-right ↗ Felett, jobbra - + below-left ↙ Alatt, balra - + below-right ↘ Alatt, jobbra - + center >|< Középre - + top ↑ Felső - + bottom ↓ Alsó - + top-left ↖ Bal felső - + top-right ↗ Jobb felső - + bottom-left ↙ Bal alsó - + bottom-right ↘ Jobb alsó - + application Alkalmazás - + function Függvény - + high Magas - + low Alul - + Next to target Cél mellé - + With label Címkével - + Hidden Rejtett @@ -1542,12 +1546,12 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents point - + Point Pont - + Points Pontok @@ -1555,12 +1559,12 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents position - + Position of %1 %2 set from "%3" to "%4". %1 %2 áthelyezve innen: „%3” ide: „%4”. - + Position of %1 set from %2 to %3. %1 áthelyezve innen: %2 ide: %3. @@ -1568,158 +1572,158 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents prop - + expression Kifejezés - + definitionDomain Abszcissza tartomány - + destinationDomain Ordináta tartomány - - - - - - - - - - + + + + + + + + + + labelPosition Címke helyzete - + displayMode Megjelenítési mód - - - - - - - + + + + + + + labelX Címke X helyzete - - + + drawPoints Pontok megjelenítése - - + + drawDashedLines Szaggatott vonalak megjelenítése - - + + om_0 ω₀ - + pass Áteresztő - + gain Nagyságrend nyeresége - + omGraduation ω₀ érettségi megjelenítése - + phase Fázis - + unit Egység használata - - - + + + x X - - + + y Y - + pointStyle Pontstílus - + probabilities Valószínűségek listája - + text Tartalom - + disableLatex LaTeX-megjelenítés letiltása ennél a szövegnél - + targetElement Tárgycél - + approximate Kerekített számított érték megjelenítése - + rounding Kerekítés - + displayStyle Megjelenítési stílus - + targetValuePosition Cél értékpozíciója - + defaultExpression Alapértelmezett kifejezés - + baseValues Kezdeményezési értékek @@ -1742,12 +1746,12 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents sequence - + Sequence Sorozat - + Sequences Sorozatok @@ -1755,17 +1759,17 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents settingCategory - + general Általános - + editor Kifejezésszerkesztő - + default Alapértelmezett ábra @@ -1787,12 +1791,12 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents text - + Text Szöveg - + Texts Szövegek @@ -1800,22 +1804,22 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents update - + An update for LogarithmPlotter (v{}) is available. Elérhető a Logaritmus-ábrázoló ({} verzió) frissítése. - + No update available. Nincs telepíthető frissítés. - + Could not fetch update information: Server error {}. Nem sikerült lekérni a frissítési adatokat: Kiszolgálóhiba: {}. - + Could not fetch update information: {}. Nem sikerült lekérni a frissítési adatokat: {}. @@ -1823,22 +1827,22 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents usage - + integral(<from: number>, <to: number>, <f: ExecutableObject>) integral(<alsó korlát: szám>, <felső korlát: szám>, <f: függvényszerű objektum>) - - + + Usage: %1 Használat: %1 - - - + + + Usage: %1 %2 @@ -1847,17 +1851,17 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents %2 - + integral(<from: number>, <to: number>, <f: string>, <variable: string>) integral(<alsó korlát: szám>, <felső korlát: szám>, <függvény: karakterlánc>, <változó: karakterlánc>) - + derivative(<f: ExecutableObject>, <x: number>) derivative(<f: függvényszerű objektum>, <x: szám>) - + derivative(<f: string>, <variable: string>, <x: number>) derivált(<függvény: karakterlánc>, <változó: karakterlánc>, <x: szám>) @@ -1865,14 +1869,14 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents visibility - - + + %1 %2 shown. %1 %2 megjelenítve. - - + + %1 %2 hidden. %1 %2 rejtve. @@ -1880,12 +1884,12 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents xcursor - + X Cursor X kurzor - + X Cursors X kurzorok diff --git a/assets/i18n/lp_nb_NO.ts b/assets/i18n/lp_nb_NO.ts index 5e94d77..b46ffe7 100644 --- a/assets/i18n/lp_nb_NO.ts +++ b/assets/i18n/lp_nb_NO.ts @@ -4,27 +4,27 @@ About - + About LogarithmPlotter Om - + LogarithmPlotter v%1 LogarithmPlotter v%1 - + 2D plotter software to make BODE plots, sequences and repartition functions. 2D-plotterprogramvare laget for opprettelse av Bode-diagram, sekvenser, og distribusjonsfunksjoner. - + Report a bug Rapporter en feil - + Official website @@ -32,57 +32,57 @@ AppMenuBar - + &File &Fil - + &Load... &Last inn … - + &Save &Lagre - + Save &As... Lagre &som … - + &Quit &Avslutt - + &Edit &Rediger - + &Undo &Angre - + &Redo &Gjenta - + &Copy plot &Kopier plott - + &Preferences - + &Create &Opprett @@ -99,52 +99,52 @@ Tilbakestill angrehistorikk automatisk - + &Help &Hjelp - + &Source code - + &Report a bug &Rapporter en feil - + &User manual - + &Changelog &Endringslogg - + &Help translating! &Hjelp til å oversette! - + &Thanks &Erkjennelser - + &About &Om - + Save unsaved changes? Lagre ikke-lagrede endringer? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Dette plottet inneholder ikke-lagrede endringer. Hvis du gjør dette, vil alle ikke-lagrede data gå tapt. Fortsette? @@ -152,7 +152,7 @@ BaseDialog - + Close Lukk @@ -167,12 +167,12 @@ Changelog - + Fetching changelog... Henter endringslogg… - + Close Lukk @@ -180,13 +180,13 @@ CustomPropertyList - - + + + Create new %1 + Opprett nytt %1 - + Pick on graph @@ -194,42 +194,42 @@ Dialog - + Edit properties of %1 %2 Rediger egenskaper for %1 %2 - + LogarithmPlotter - Invalid object name LogarithmPlotter - Ugyldig objektnavn - + An object with the name '%1' already exists. Et objekt med navnet '%1' finnes allerede. - + Name Navn - + Label content Etikett-innhold - + null NULL - + name navn - + name + value navn + veri @@ -268,32 +268,32 @@ ExpressionEditor - + Object Properties - + Variables - + Constants - + Functions Funksjoner - + Executable Objects - + Objects Objekter @@ -301,12 +301,12 @@ FileDialog - + Export Logarithm Plot file Eksporter logaritmeplott-fil - + Import Logarithm Plot file Importer logaritmeplott-fil @@ -314,12 +314,12 @@ GreetScreen - + Welcome to LogarithmPlotter Velkommen til LogarithmPlotter - + Version %1 Versjon %1 @@ -338,22 +338,22 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen.Tilbakesitll angrehistorikk når en ny handling legges til - + User manual - + Changelog - + Preferences - + Close Lukk @@ -361,22 +361,22 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. HistoryBrowser - + Filter... - + Redo > Angre > - + > Now > Nå - + < Undo < Angre @@ -384,7 +384,7 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. ListSetting - + + Add Entry @@ -392,17 +392,17 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. LogarithmPlotter - + Objects Objekter - + Settings Innstillinger - + History Historikk @@ -431,17 +431,17 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen.Lastet inn filen «%1». - + Copied plot screenshot to clipboard! Kopierte plott-skjermavbildning til utklippstavlen! - + &Update &Oppdater - + &Update LogarithmPlotter &Installer ny versjon av LogartimePlotter @@ -449,7 +449,7 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. ObjectCreationGrid - + + Create new: + Opprett ny: @@ -457,12 +457,12 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. ObjectLists - + Hide all %1 Skjul alle %1 - + Show all %1 Vis alle %1 @@ -490,27 +490,27 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. ObjectRow - + Hide %1 %2 Skjul %1 %2 - + Show %1 %2 Vis %1 %2 - + Set %1 %2 position Sett %1 %2 posisjon - + Delete %1 %2 Slett %1 %2 - + Pick new color for %1 %2 Velg ny farge for %1 %2 @@ -518,7 +518,7 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. PickLocationOverlay - + Pointer precision: Peker-presisjon: @@ -527,32 +527,32 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen.Fest til rutenett - + Snap to grid: - + Pick X - + Pick Y - + Open picker settings - + Hide picker settings - + (no pick selected) @@ -560,7 +560,7 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. Preferences - + Close Lukk @@ -568,110 +568,110 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. Settings - - + + X Zoom X-forstørrelse - - + + Y Zoom Y-forstørrelse - - + + Min X Min. X - - + + Max Y Maks. Y - + Max X Maks. X - + Min Y Min. Y - - + + X Axis Step X-aksesteg - - + + Y Axis Step Y-aksesteg - - + + Line width Linjebredde - - + + Text size (px) Tekststørrelse (piksler) - - + + X Label Navn på X-akse - - + + Y Label Navn på Y-akse - - + + X Log scale Logaritmisk skala i x - - + + Show X graduation Vis X-inndeling - - + + Show Y graduation Vis Y-inndeling - + Copy to clipboard Kopier til utklippstavle - + Save plot Lagre plott - + Save plot as Lagre plott som - + Load plot Last inn plott @@ -679,96 +679,96 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. ThanksTo - + Thanks and Contributions - LogarithmPlotter - + Source code - + Original library by Raphael Graf - + Source - + Ported to Javascript by Matthew Crumley Overført til JavaScript av Matthew Crumley - - - + + + Website - + Ported to QMLJS by Ad5001 - + Libraries included - + Email - + English - + French - + German - + Hungarian - - - + + + Github GitHub - + Norwegian - + Spanish - + Translations included - + Improve @@ -776,24 +776,24 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. bodemagnitude - + Bode Magnitude Bode-magnitude - + Bode Magnitudes Bode-magnituder - - + + low-pass lavpass - - + + high-pass høypass @@ -801,8 +801,8 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. bodemagnitudesum - - + + Bode Magnitudes Sum Bode-magnitudesum @@ -810,12 +810,12 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. bodephase - + Bode Phase Bode-fase - + Bode Phases Bode-faser @@ -823,8 +823,8 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. bodephasesum - - + + Bode Phases Sum Bode-fasesum @@ -832,12 +832,12 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. changelog - + Could not fetch changelog: Server error {}. - + Could not fetch update: {}. @@ -845,8 +845,8 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. color - - + + %1 %2's color changed from %3 to %4. @@ -854,27 +854,27 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. comment - + Ex: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ⁻*), ]0;1[, {3;4;5} - + The following parameters are used when the definition domain is a non-continuous set. (Ex: ℕ, ℤ, sets like {0;3}...) - + Note: Specify the probability for each value. - + Note: Use %1[n] to refer to %1ₙ, %1[n+1] for %1ₙ₊₁... - + If you have latex enabled, you can use use latex markup in between $$ to create equations. @@ -882,11 +882,11 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. control - - - - - + + + + + %1: @@ -894,8 +894,8 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. create - - + + New %1 %2 created. Ny %1 %2 opprettet. @@ -903,8 +903,8 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. delete - - + + %1 %2 deleted. %1 %2 slettet. @@ -912,12 +912,12 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. distribution - + Repartition Distribusjon - + Repartition functions Distribusjonsfunksjoner @@ -925,12 +925,12 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. editproperty - + %1 of %2 %3 changed from "%4" to "%5". %1 av %2 %3 endret fra «%4» til «%5». - + %1 of %2 changed from %3 to %4. @@ -938,32 +938,32 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. error - + No object found with names %1. - + No object found with name %1. - + Object cannot be dependent on itself. - + Circular dependency detected. Object %1 depends on %2. - + Circular dependency detected. Objects %1 depend on %2. - + Error while parsing expression for property %1: %2 @@ -971,7 +971,7 @@ Evaluated expression: %3 - + Error while attempting to draw %1 %2: %3 @@ -979,128 +979,128 @@ Undoing last change. - - + + Cannot find property %1 of object %2. - + Undefined variable %1. - + In order to be executed, object %1 must have at least one argument. - + %1 cannot be executed. - - - + + + Invalid expression. - + Invalid expression (parity). - + EOF - - + + Parse error [position %1]: %2 - + Expected %1 - + Unexpected %1 - + Unexpected ".": member access is not permitted - + Unexpected "[]": arrays are disabled. - + Unexpected symbol: %1. - - + + Function %1 must have at least one argument. - + First argument to map is not a function. - + Second argument to map is not an array. - + First argument to fold is not a function. - + Second argument to fold is not an array. - + First argument to filter is not a function. - + Second argument to filter is not an array. - + Second argument to indexOf is not a string or array. - + Second argument to join is not an array. - + Unknown character "%1". - - + + Illegal escape sequence: %1. @@ -1108,13 +1108,13 @@ Undoing last change. expression - - + + LogarithmPlotter - Parsing error - + Error while parsing expression for property %1: %2 @@ -1122,27 +1122,27 @@ Evaluated expression: %3 - + LogarithmPlotter - Drawing error - + Automatically close parenthesises and brackets - + Enable syntax highlighting - + Enable autocompletion - + Color Scheme @@ -1150,12 +1150,12 @@ Evaluated expression: %3 function - + Function Funksjon - + Functions Funksjoner @@ -1182,17 +1182,17 @@ Evaluated expression: %3 general - + Check for updates on startup Se etter nye versjoner ved programstart - + Reset redo stack automaticly Tilbakestill angrehistorikk automatisk - + Enable LaTeX rendering @@ -1235,32 +1235,36 @@ Evaluated expression: %3 Historikk - + Saved plot to '%1'. Lagret plott i «%1». - + Loading file '%1'. Laster inn «%1»-fil. - + Unknown object type: %1. Ukjent objekttype: %1. - + Invalid file provided. Ugyldig fil angitt. - - Could not save file: - Kunne ikke lagre fil: + + Could not load file: + - + Could not save file: + Kunne ikke lagre fil: + + + Loaded file '%1'. Lastet inn filen «%1». @@ -1280,19 +1284,19 @@ Evaluated expression: %3 latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. - + DVIPNG was not found. Make sure you include it from your Latex distribution. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1301,7 +1305,7 @@ Please make sure your latex installation is correct and report a bug if so. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1310,7 +1314,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1321,8 +1325,8 @@ Please make sure your latex installation is correct and report a bug if so. name - - + + %1 %2 renamed to %3. @@ -1330,114 +1334,114 @@ Please make sure your latex installation is correct and report a bug if so. parameters - + above - + below - - + + left - - + + right - + above-left - + above-right - + below-left - + below-right - + center - + top - + bottom - + top-left - + top-right - + bottom-left - + bottom-right - + application - + function - + high - + low - + Next to target - + With label - + Hidden @@ -1456,12 +1460,12 @@ Please make sure your latex installation is correct and report a bug if so. point - + Point Punkt - + Points Punkter @@ -1469,12 +1473,12 @@ Please make sure your latex installation is correct and report a bug if so. position - + Position of %1 %2 set from "%3" to "%4". - + Position of %1 set from %2 to %3. @@ -1482,158 +1486,158 @@ Please make sure your latex installation is correct and report a bug if so. prop - + expression - + definitionDomain - + destinationDomain - + displayMode - - - - - - - - - - + + + + + + + + + + labelPosition - - - - - - - + + + + + + + labelX - - + + drawPoints - - + + drawDashedLines - - + + om_0 - + pass - + gain - + omGraduation - + phase - + unit - - - + + + x - - + + y - + pointStyle - + probabilities - + defaultExpression - + baseValues - + text - + disableLatex - + targetElement - + approximate - + rounding - + displayStyle - + targetValuePosition @@ -1652,12 +1656,12 @@ Please make sure your latex installation is correct and report a bug if so. sequence - + Sequence Følge - + Sequences Følger @@ -1665,17 +1669,17 @@ Please make sure your latex installation is correct and report a bug if so. settingCategory - + general - + editor - + default @@ -1697,12 +1701,12 @@ Please make sure your latex installation is correct and report a bug if so. text - + Text Tekst - + Texts Tekster @@ -1710,22 +1714,22 @@ Please make sure your latex installation is correct and report a bug if so. update - + An update for LogarithmPlotter (v{}) is available. En ny versjon av LogartimePlotter (v{}) er tilgjengelig. - + No update available. Ingen nye versjoner. - + Could not fetch update information: Server error {}. Fant ikke ut om det er noen nye versjoner. Tjenerfeil {}. - + Could not fetch update information: {}. Kunne ikke hente info om hvorvidt det er nye versjoner: {}. @@ -1733,38 +1737,38 @@ Please make sure your latex installation is correct and report a bug if so. usage - + integral(<from: number>, <to: number>, <f: ExecutableObject>) - - + + Usage: %1 - - - + + + Usage: %1 %2 - + integral(<from: number>, <to: number>, <f: string>, <variable: string>) - + derivative(<f: ExecutableObject>, <x: number>) - + derivative(<f: string>, <variable: string>, <x: number>) @@ -1772,14 +1776,14 @@ Please make sure your latex installation is correct and report a bug if so. visibility - - + + %1 %2 shown. %1 %2 vist. - - + + %1 %2 hidden. %1 %2 skjult. @@ -1787,12 +1791,12 @@ Please make sure your latex installation is correct and report a bug if so. xcursor - + X Cursor X-peker - + X Cursors X-pekere diff --git a/assets/i18n/lp_template.ts b/assets/i18n/lp_template.ts index 7626f7b..9440730 100644 --- a/assets/i18n/lp_template.ts +++ b/assets/i18n/lp_template.ts @@ -4,27 +4,27 @@ About - + About LogarithmPlotter - + LogarithmPlotter v%1 - + 2D plotter software to make BODE plots, sequences and repartition functions. - + Report a bug - + Official website @@ -32,107 +32,107 @@ AppMenuBar - + &File - + &Load... - + &Save - + Save &As... - + &Quit - + &Edit - + &Undo - + &Redo - + &Copy plot - + &Preferences - + &Create - + &Help - + &Source code - + &Report a bug - + &User manual - + &Changelog - + &Help translating! - + &Thanks - + &About - + Save unsaved changes? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? @@ -140,7 +140,7 @@ BaseDialog - + Close @@ -148,12 +148,12 @@ Changelog - + Fetching changelog... - + Close @@ -161,13 +161,13 @@ CustomPropertyList - - + + + Create new %1 - + Pick on graph @@ -175,42 +175,42 @@ Dialog - + Edit properties of %1 %2 - + LogarithmPlotter - Invalid object name - + An object with the name '%1' already exists. - + Name - + Label content - + null - + name - + name + value @@ -218,32 +218,32 @@ ExpressionEditor - + Object Properties - + Variables - + Constants - + Functions - + Executable Objects - + Objects @@ -251,12 +251,12 @@ FileDialog - + Export Logarithm Plot file - + Import Logarithm Plot file @@ -264,32 +264,32 @@ GreetScreen - + Welcome to LogarithmPlotter - + Version %1 - + User manual - + Changelog - + Preferences - + Close @@ -297,22 +297,22 @@ HistoryBrowser - + Filter... - + Redo > - + > Now - + < Undo @@ -320,7 +320,7 @@ ListSetting - + + Add Entry @@ -328,32 +328,32 @@ LogarithmPlotter - + Objects - + Settings - + History - + Copied plot screenshot to clipboard! - + &Update - + &Update LogarithmPlotter @@ -361,7 +361,7 @@ ObjectCreationGrid - + + Create new: @@ -369,12 +369,12 @@ ObjectLists - + Hide all %1 - + Show all %1 @@ -382,27 +382,27 @@ ObjectRow - + Hide %1 %2 - + Show %1 %2 - + Set %1 %2 position - + Delete %1 %2 - + Pick new color for %1 %2 @@ -410,37 +410,37 @@ PickLocationOverlay - + Pointer precision: - + Snap to grid: - + Pick X - + Pick Y - + Open picker settings - + Hide picker settings - + (no pick selected) @@ -448,7 +448,7 @@ Preferences - + Close @@ -456,110 +456,110 @@ Settings - - + + X Zoom - - + + Y Zoom - - + + Min X - - + + Max Y - + Max X - + Min Y - - + + X Axis Step - - + + Y Axis Step - - + + Line width - - + + Text size (px) - - + + X Label - - + + Y Label - - + + X Log scale - - + + Show X graduation - - + + Show Y graduation - + Copy to clipboard - + Save plot - + Save plot as - + Load plot @@ -567,96 +567,96 @@ ThanksTo - + Thanks and Contributions - LogarithmPlotter - + Source code - + Original library by Raphael Graf - + Source - + Ported to Javascript by Matthew Crumley - - - + + + Website - + Ported to QMLJS by Ad5001 - + Libraries included - + Email - + English - + French - + German - + Hungarian - - - + + + Github - + Norwegian - + Spanish - + Translations included - + Improve @@ -664,24 +664,24 @@ bodemagnitude - + Bode Magnitude - + Bode Magnitudes - - + + low-pass - - + + high-pass @@ -689,8 +689,8 @@ bodemagnitudesum - - + + Bode Magnitudes Sum @@ -698,12 +698,12 @@ bodephase - + Bode Phase - + Bode Phases @@ -711,8 +711,8 @@ bodephasesum - - + + Bode Phases Sum @@ -720,12 +720,12 @@ changelog - + Could not fetch changelog: Server error {}. - + Could not fetch update: {}. @@ -733,8 +733,8 @@ color - - + + %1 %2's color changed from %3 to %4. @@ -742,27 +742,27 @@ comment - + Ex: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ⁻*), ]0;1[, {3;4;5} - + The following parameters are used when the definition domain is a non-continuous set. (Ex: ℕ, ℤ, sets like {0;3}...) - + Note: Specify the probability for each value. - + Note: Use %1[n] to refer to %1ₙ, %1[n+1] for %1ₙ₊₁... - + If you have latex enabled, you can use use latex markup in between $$ to create equations. @@ -770,11 +770,11 @@ control - - - - - + + + + + %1: @@ -782,8 +782,8 @@ create - - + + New %1 %2 created. @@ -791,8 +791,8 @@ delete - - + + %1 %2 deleted. @@ -800,12 +800,12 @@ distribution - + Repartition - + Repartition functions @@ -813,12 +813,12 @@ editproperty - + %1 of %2 %3 changed from "%4" to "%5". - + %1 of %2 changed from %3 to %4. @@ -826,32 +826,32 @@ error - + No object found with names %1. - + No object found with name %1. - + Object cannot be dependent on itself. - + Circular dependency detected. Object %1 depends on %2. - + Circular dependency detected. Objects %1 depend on %2. - + Error while parsing expression for property %1: %2 @@ -859,7 +859,7 @@ Evaluated expression: %3 - + Error while attempting to draw %1 %2: %3 @@ -867,128 +867,128 @@ Undoing last change. - - + + Cannot find property %1 of object %2. - + Undefined variable %1. - + In order to be executed, object %1 must have at least one argument. - + %1 cannot be executed. - - - + + + Invalid expression. - + Invalid expression (parity). - + EOF - - + + Parse error [position %1]: %2 - + Expected %1 - + Unexpected %1 - + Unexpected ".": member access is not permitted - + Unexpected "[]": arrays are disabled. - + Unexpected symbol: %1. - - + + Function %1 must have at least one argument. - + First argument to map is not a function. - + Second argument to map is not an array. - + First argument to fold is not a function. - + Second argument to fold is not an array. - + First argument to filter is not a function. - + Second argument to filter is not an array. - + Second argument to indexOf is not a string or array. - + Second argument to join is not an array. - + Unknown character "%1". - - + + Illegal escape sequence: %1. @@ -996,13 +996,13 @@ Undoing last change. expression - - + + LogarithmPlotter - Parsing error - + Error while parsing expression for property %1: %2 @@ -1010,27 +1010,27 @@ Evaluated expression: %3 - + LogarithmPlotter - Drawing error - + Automatically close parenthesises and brackets - + Enable syntax highlighting - + Enable autocompletion - + Color Scheme @@ -1038,12 +1038,12 @@ Evaluated expression: %3 function - + Function - + Functions @@ -1051,17 +1051,17 @@ Evaluated expression: %3 general - + Check for updates on startup - + Reset redo stack automaticly - + Enable LaTeX rendering @@ -1069,32 +1069,32 @@ Evaluated expression: %3 io - + Saved plot to '%1'. - + Loading file '%1'. - + Unknown object type: %1. - + Invalid file provided. - - Could not save file: + + Could not load file: - + Loaded file '%1'. @@ -1102,19 +1102,19 @@ Evaluated expression: %3 latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. - + DVIPNG was not found. Make sure you include it from your Latex distribution. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1123,7 +1123,7 @@ Please make sure your latex installation is correct and report a bug if so. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1132,7 +1132,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1143,8 +1143,8 @@ Please make sure your latex installation is correct and report a bug if so. name - - + + %1 %2 renamed to %3. @@ -1152,114 +1152,114 @@ Please make sure your latex installation is correct and report a bug if so. parameters - + above - + below - - + + left - - + + right - + above-left - + above-right - + below-left - + below-right - + center - + top - + bottom - + top-left - + top-right - + bottom-left - + bottom-right - + application - + function - + high - + low - + Next to target - + With label - + Hidden @@ -1267,12 +1267,12 @@ Please make sure your latex installation is correct and report a bug if so. point - + Point - + Points @@ -1280,12 +1280,12 @@ Please make sure your latex installation is correct and report a bug if so. position - + Position of %1 %2 set from "%3" to "%4". - + Position of %1 set from %2 to %3. @@ -1293,158 +1293,158 @@ Please make sure your latex installation is correct and report a bug if so. prop - + expression - + definitionDomain - + destinationDomain - + displayMode - - - - - - - - - - + + + + + + + + + + labelPosition - - - - - - - + + + + + + + labelX - - + + drawPoints - - + + drawDashedLines - - + + om_0 - + pass - + gain - + omGraduation - + phase - + unit - - - + + + x - - + + y - + pointStyle - + probabilities - + defaultExpression - + baseValues - + text - + disableLatex - + targetElement - + approximate - + rounding - + displayStyle - + targetValuePosition @@ -1452,12 +1452,12 @@ Please make sure your latex installation is correct and report a bug if so. sequence - + Sequence - + Sequences @@ -1465,17 +1465,17 @@ Please make sure your latex installation is correct and report a bug if so. settingCategory - + general - + editor - + default @@ -1483,12 +1483,12 @@ Please make sure your latex installation is correct and report a bug if so. text - + Text - + Texts @@ -1496,22 +1496,22 @@ Please make sure your latex installation is correct and report a bug if so. update - + An update for LogarithmPlotter (v{}) is available. - + No update available. - + Could not fetch update information: Server error {}. - + Could not fetch update information: {}. @@ -1519,38 +1519,38 @@ Please make sure your latex installation is correct and report a bug if so. usage - + integral(<from: number>, <to: number>, <f: ExecutableObject>) - - + + Usage: %1 - - - + + + Usage: %1 %2 - + integral(<from: number>, <to: number>, <f: string>, <variable: string>) - + derivative(<f: ExecutableObject>, <x: number>) - + derivative(<f: string>, <variable: string>, <x: number>) @@ -1558,14 +1558,14 @@ Please make sure your latex installation is correct and report a bug if so. visibility - - + + %1 %2 shown. - - + + %1 %2 hidden. @@ -1573,12 +1573,12 @@ Please make sure your latex installation is correct and report a bug if so. xcursor - + X Cursor - + X Cursors diff --git a/assets/i18n/update.sh b/assets/i18n/update.sh index 8d589d5..4ff172c 100755 --- a/assets/i18n/update.sh +++ b/assets/i18n/update.sh @@ -21,7 +21,7 @@ replace() { rm ../qml/eu/ad5001/LogarithmPlotter/js/index.mjs # Remove index which should not be scanned -files=$(find .. -name *.mjs) +files=$(find ../../common/src -name '*.mjs') for file in $files; do echo "Moving '$file' to '${file%.*}.js'..." mv "$file" "${file%.*}.js" @@ -38,7 +38,7 @@ done echo "----------------------------" echo "| Updating translations... |" echo "----------------------------" -lupdate -extensions js,qs,qml,py -recursive .. -ts lp_*.ts +lupdate -extensions js,qs,qml,py -recursive ../../common/src -recursive ../../runtime-pyside6/LogarithmPlotter -ts lp_*.ts # Updating locations in files for lp in *.ts; do echo "Replacing locations in $lp..." From 8c273f42204d828999ea3abdbe653fa8b940617f Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Wed, 9 Oct 2024 18:18:24 +0000 Subject: [PATCH 008/104] Translated using Weblate (English) Currently translated at 100.0% (269 of 269 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/ --- assets/i18n/lp_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/i18n/lp_en.ts b/assets/i18n/lp_en.ts index 4429a36..ab62387 100644 --- a/assets/i18n/lp_en.ts +++ b/assets/i18n/lp_en.ts @@ -1330,7 +1330,7 @@ Evaluated expression: %3 Could not load file: - + Could not load file: Could not save file: From 6b3cce42522a7efdf2d67d1c38f3a9edcb7b173a Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Wed, 9 Oct 2024 18:21:36 +0000 Subject: [PATCH 009/104] Translated using Weblate (German) Currently translated at 100.0% (269 of 269 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/ --- assets/i18n/lp_de.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/i18n/lp_de.ts b/assets/i18n/lp_de.ts index 4f29919..59980da 100644 --- a/assets/i18n/lp_de.ts +++ b/assets/i18n/lp_de.ts @@ -1330,7 +1330,7 @@ Ausdruck analysiert: %3 Could not load file: - + Datei konnte nicht geladen werden: Could not save file: From 40d86c8f823a7cdc69a52941d4bdb55f453cc913 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Wed, 9 Oct 2024 18:18:51 +0000 Subject: [PATCH 010/104] Translated using Weblate (French) Currently translated at 100.0% (269 of 269 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/ --- assets/i18n/lp_fr.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/i18n/lp_fr.ts b/assets/i18n/lp_fr.ts index 7df2b4f..a638be9 100644 --- a/assets/i18n/lp_fr.ts +++ b/assets/i18n/lp_fr.ts @@ -1345,7 +1345,7 @@ Formule analysée : %3 Could not load file: - + Impossible de charger le fichier : Could not save file: From b02ed87a29d0aac5a6c6c9656241fbc47ea64658 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 10 Oct 2024 04:56:09 +0200 Subject: [PATCH 011/104] Updating package-lock --- common/package-lock.json | 1503 +++++++++++++++++++------------------- 1 file changed, 738 insertions(+), 765 deletions(-) diff --git a/common/package-lock.json b/common/package-lock.json index 0b60cac..b90e4f5 100644 --- a/common/package-lock.json +++ b/common/package-lock.json @@ -41,12 +41,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.7", + "@babel/highlight": "^7.25.7", "picocolors": "^1.0.0" }, "engines": { @@ -54,31 +54,31 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", - "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.7.tgz", + "integrity": "sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.7.tgz", + "integrity": "sha512-yJ474Zv3cwiSOO9nXJuqzvwEeM+chDuQ8GJirw+pZ91sCGCyOZ3dJkVE09fTV0VEVzXyLWhh3G/AolYTPX7Mow==", "license": "MIT", "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helpers": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -94,54 +94,54 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", - "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", + "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6", + "@babel/types": "^7.25.7", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", + "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", - "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.7.tgz", + "integrity": "sha512-12xfNeKNH7jubQNm7PAkzlLwEmCs1tfuX3UjIw6vP6QXi+leKh6+LyC/+Ed4EIQermwd58wsyh070yjDHFlNGg==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", + "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", + "@babel/compat-data": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -150,17 +150,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", - "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.7.tgz", + "integrity": "sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.25.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/traverse": "^7.25.4", + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/traverse": "^7.25.7", "semver": "^6.3.1" }, "engines": { @@ -171,13 +171,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", - "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.7.tgz", + "integrity": "sha512-byHhumTj/X47wJ6C6eLpK7wW/WBEcnUeb7D0FNc/jFQnQVw7DOso3Zz5u9x/zLrFVkHa89ZGDbkAa1D54NdrCQ==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "regexpu-core": "^5.3.1", + "@babel/helper-annotate-as-pure": "^7.25.7", + "regexpu-core": "^6.1.1", "semver": "^6.3.1" }, "engines": { @@ -204,41 +204,41 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", - "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.7.tgz", + "integrity": "sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.8" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", + "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", + "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -248,35 +248,35 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", - "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.7.tgz", + "integrity": "sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==", "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", + "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", - "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.7.tgz", + "integrity": "sha512-kRGE89hLnPfcz6fTrlNU+uhgcwv0mBE4Gv3P9Ke9kLVJYpi4AMVVEElXvB5CabrPZW4nCM8P8UyyjrzCM0O2sw==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-wrap-function": "^7.25.0", - "@babel/traverse": "^7.25.0" + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-wrap-function": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -286,14 +286,14 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", - "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.7.tgz", + "integrity": "sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==", "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/traverse": "^7.25.0" + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -303,93 +303,93 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", + "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", - "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.7.tgz", + "integrity": "sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", + "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", - "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.7.tgz", + "integrity": "sha512-MA0roW3JF2bD1ptAaJnvcabsVlNQShUaThyJbCDD4bCp8NEgiFvpoqRI2YS22hHlc2thjO/fTg2ShLMC3jygAg==", "license": "MIT", "dependencies": { - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", - "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", + "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", "license": "MIT", "peer": true, "dependencies": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6" + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -399,12 +399,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", + "integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6" + "@babel/types": "^7.25.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -414,13 +414,13 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", - "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.7.tgz", + "integrity": "sha512-UV9Lg53zyebzD1DwQoT9mzkEKa922LNUp5YkTJ6Uta0RbyXaQNUgcvSt7qIu1PpPzVb6rd10OVNTzkyBGeVmxQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/traverse": "^7.25.3" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -430,12 +430,12 @@ } }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", - "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.7.tgz", + "integrity": "sha512-GDDWeVLNxRIkQTnJn2pDOM1pkCgYdSqPeT1a9vh9yIqu2uzzgw1zcqEb+IJOhy+dTBMlNdThrDIksr2o09qrrQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -445,12 +445,12 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", - "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.7.tgz", + "integrity": "sha512-wxyWg2RYaSUYgmd9MR0FyRGyeOMQE/Uzr1wzd/g5cf5bwi9A4v6HFdDm7y1MgDtod/fLOSTZY6jDgV0xU9d5bA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -460,14 +460,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", - "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.7.tgz", + "integrity": "sha512-Xwg6tZpLxc4iQjorYsyGMyfJE7nP5MV8t/Ka58BgiA7Jw0fRqQNcANlLfdJ/yvBt9z9LD2We+BEkT7vLqZRWng==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-transform-optional-chaining": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -477,13 +477,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", - "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.7.tgz", + "integrity": "sha512-UVATLMidXrnH+GMUIuxq55nejlj02HP7F5ETyBONzP6G87fPBogG4CH6kxrSrdIuAjdwNO9VzyaYsrZPscWUrw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/traverse": "^7.25.0" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -568,12 +568,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz", - "integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.7.tgz", + "integrity": "sha512-ZvZQRmME0zfJnDQnVBKYzHxXT7lYBB3Revz1GuS7oLXWMgqUPX4G+DDbT30ICClht9WKV34QVrZhSw6WdklwZQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -583,12 +583,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", - "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", + "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -740,12 +740,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", - "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.7.tgz", + "integrity": "sha512-EJN2mKxDwfOUCPxMO6MUI58RN3ganiRAG/MS/S3HfB6QFNjroAMelQo/gybyYq97WerCBAZoyrAoW8Tzdq2jWg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -755,15 +755,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz", - "integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.7.tgz", + "integrity": "sha512-4B6OhTrwYKHYYgcwErvZjbmH9X5TxQBsaBHdzEIB4l71gR5jh/tuHGlb9in47udL2+wVUcOz5XXhhfhVJwEpEg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-remap-async-to-generator": "^7.25.7", "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/traverse": "^7.25.4" + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -773,14 +773,14 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", - "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.7.tgz", + "integrity": "sha512-ZUCjAavsh5CESCmi/xCpX1qcCaAglzs/7tmuvoFnJgA1dM7gQplsguljoTg+Ru8WENpX89cQyAtWoaE0I3X3Pg==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-remap-async-to-generator": "^7.24.7" + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-remap-async-to-generator": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -790,12 +790,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", - "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.7.tgz", + "integrity": "sha512-xHttvIM9fvqW+0a3tZlYcZYSBpSWzGBFIt/sYG3tcdSzBB8ZeVgz2gBP7Df+sM0N1850jrviYSSeUuc+135dmQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -805,12 +805,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", - "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.7.tgz", + "integrity": "sha512-ZEPJSkVZaeTFG/m2PARwLZQ+OG0vFIhPlKHK/JdIMy8DbRJ/htz6LRrTFtdzxi9EHmcwbNPAKDnadpNSIW+Aow==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -820,13 +820,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz", - "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.7.tgz", + "integrity": "sha512-mhyfEW4gufjIqYFo9krXHJ3ElbFLIze5IDp+wQTxoPd+mwFb1NxatNAwmv8Q8Iuxv7Zc+q8EkiMQwc9IhyGf4g==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.4", - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -836,13 +836,13 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", - "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.7.tgz", + "integrity": "sha512-rvUUtoVlkDWtDWxGAiiQj0aNktTPn3eFynBcMC2IhsXweehwgdI9ODe+XjWw515kEmv22sSOTp/rxIRuTiB7zg==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { @@ -853,16 +853,16 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz", - "integrity": "sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.7.tgz", + "integrity": "sha512-9j9rnl+YCQY0IGoeipXvnk3niWicIB6kCsWRGLwX241qSXpbA4MKxtp/EdvFxsc4zI5vqfLxzOd0twIJ7I99zg==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-replace-supers": "^7.25.0", - "@babel/traverse": "^7.25.4", + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/traverse": "^7.25.7", "globals": "^11.1.0" }, "engines": { @@ -873,13 +873,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", - "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.7.tgz", + "integrity": "sha512-QIv+imtM+EtNxg/XBKL3hiWjgdLjMOmZ+XzQwSgmBfKbfxUjBzGgVPklUuE55eq5/uVoh8gg3dqlrwR/jw3ZeA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/template": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/template": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -889,12 +889,12 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", - "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.7.tgz", + "integrity": "sha512-xKcfLTlJYUczdaM1+epcdh1UGewJqr9zATgrNHcLBcV2QmfvPPEixo/sK/syql9cEmbr7ulu5HMFG5vbbt/sEA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -904,13 +904,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", - "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.7.tgz", + "integrity": "sha512-kXzXMMRzAtJdDEgQBLF4oaiT6ZCU3oWHgpARnTKDAqPkDJ+bs3NrZb310YYevR5QlRo3Kn7dzzIdHbZm1VzJdQ==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -920,12 +920,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", - "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.7.tgz", + "integrity": "sha512-by+v2CjoL3aMnWDOyCIg+yxU9KXSRa9tN6MbqggH5xvymmr9p4AMjYkNlQy4brMceBnUyHZ9G8RnpvT8wP7Cfg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -935,13 +935,13 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", - "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.7.tgz", + "integrity": "sha512-HvS6JF66xSS5rNKXLqkk7L9c/jZ/cdIVIcoPVrnl8IsVpLggTjXs8OWekbLHs/VtYDDh5WXnQyeE3PPUGm22MA==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.0", - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -951,12 +951,12 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", - "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.7.tgz", + "integrity": "sha512-UvcLuual4h7/GfylKm2IAA3aph9rwvAM2XBA0uPKU3lca+Maai4jBjjEVUS568ld6kJcgbouuumCBhMd/Yz17w==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { @@ -967,13 +967,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", - "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.7.tgz", + "integrity": "sha512-yjqtpstPfZ0h/y40fAXRv2snciYr0OAoMXY/0ClC7tm4C/nG5NJKmIItlaYlLbIVAWNfrYuy9dq1bE0SbX0PEg==", "license": "MIT", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -983,12 +983,12 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", - "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.7.tgz", + "integrity": "sha512-h3MDAP5l34NQkkNulsTNyjdaR+OiB0Im67VU//sFupouP8Q6m9Spy7l66DcaAQxtmCqGdanPByLsnwFttxKISQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { @@ -999,13 +999,13 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", - "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.7.tgz", + "integrity": "sha512-n/TaiBGJxYFWvpJDfsxSj9lEEE44BFM1EPGz4KEiTipTgkoFVVcCmzAL3qA7fdQU96dpo4gGf5HBx/KnDvqiHw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1015,14 +1015,14 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.25.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", - "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.7.tgz", + "integrity": "sha512-5MCTNcjCMxQ63Tdu9rxyN6cAWurqfrDZ76qvVPrGYdBxIj+EawuuxTu/+dgJlhK5eRz3v1gLwp6XwS8XaX2NiQ==", "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/traverse": "^7.25.1" + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1032,12 +1032,12 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", - "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.7.tgz", + "integrity": "sha512-Ot43PrL9TEAiCe8C/2erAjXMeVSnE/BLEx6eyrKLNFCCw5jvhTHKyHxdI1pA0kz5njZRYAnMO2KObGqOCRDYSA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { @@ -1048,12 +1048,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", - "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.7.tgz", + "integrity": "sha512-fwzkLrSu2fESR/cm4t6vqd7ebNIopz2QHGtjoU+dswQo/P6lwAG04Q98lliE3jkz/XqnbGFLnUcE0q0CVUf92w==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1063,12 +1063,12 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", - "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.7.tgz", + "integrity": "sha512-iImzbA55BjiovLyG2bggWS+V+OLkaBorNvc/yJoeeDQGztknRnDdYfp2d/UPmunZYEnZi6Lg8QcTmNMHOB0lGA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { @@ -1079,12 +1079,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", - "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.7.tgz", + "integrity": "sha512-Std3kXwpXfRV0QtQy5JJcRpkqP8/wG4XL7hSKZmGlxPlDqmpXtEPRmhF7ztnlTCtUN3eXRUJp+sBEZjaIBVYaw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1094,13 +1094,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", - "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.7.tgz", + "integrity": "sha512-CgselSGCGzjQvKzghCvDTxKHP3iooenLpJDO842ehn5D2G5fJB222ptnDwQho0WjEvg7zyoxb9P+wiYxiJX5yA==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1110,14 +1110,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", - "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.7.tgz", + "integrity": "sha512-L9Gcahi0kKFYXvweO6n0wc3ZG1ChpSFdgG+eV1WYZ3/dGbJK7vvk91FgGgak8YwRgrCuihF8tE/Xg07EkL5COg==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-simple-access": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1127,15 +1127,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", - "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.7.tgz", + "integrity": "sha512-t9jZIvBmOXJsiuyOwhrIGs8dVcD6jDyg2icw1VL4A/g+FnWyJKwUfSSU2nwJuMV2Zqui856El9u+ElB+j9fV1g==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.0", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.0" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1145,13 +1145,13 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", - "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.7.tgz", + "integrity": "sha512-p88Jg6QqsaPh+EB7I9GJrIqi1Zt4ZBHUQtjw3z1bzEXcLh6GfPqzZJ6G+G1HBGKUNukT58MnKG7EN7zXQBCODw==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1161,13 +1161,13 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", - "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.7.tgz", + "integrity": "sha512-BtAT9LzCISKG3Dsdw5uso4oV1+v2NlVXIIomKJgQybotJY3OwCwJmkongjHgwGKoZXd0qG5UZ12JUlDQ07W6Ow==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1177,12 +1177,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", - "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.7.tgz", + "integrity": "sha512-CfCS2jDsbcZaVYxRFo2qtavW8SpdzmBXC2LOI4oO0rP+JSRDxxF3inF4GcPsLgfb5FjkhXG5/yR/lxuRs2pySA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1192,12 +1192,12 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", - "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.7.tgz", + "integrity": "sha512-FbuJ63/4LEL32mIxrxwYaqjJxpbzxPVQj5a+Ebrc8JICV6YX8nE53jY+K0RZT3um56GoNWgkS2BQ/uLGTjtwfw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { @@ -1208,12 +1208,12 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", - "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.7.tgz", + "integrity": "sha512-8CbutzSSh4hmD+jJHIA8vdTNk15kAzOnFLVVgBSMGr28rt85ouT01/rezMecks9pkU939wDInImwCKv4ahU4IA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { @@ -1224,15 +1224,15 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", - "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.7.tgz", + "integrity": "sha512-1JdVKPhD7Y5PvgfFy0Mv2brdrolzpzSoUq2pr6xsR+m+3viGGeHEokFKsCgOkbeFOQxfB1Vt2F0cPJLRpFI4Zg==", "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.7" + "@babel/plugin-transform-parameters": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1242,13 +1242,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", - "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.7.tgz", + "integrity": "sha512-pWT6UXCEW3u1t2tcAGtE15ornCBvopHj9Bps9D2DsH15APgNVOTwwczGckX+WkAvBmuoYKRCFa4DK+jM8vh5AA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1258,12 +1258,12 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", - "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.7.tgz", + "integrity": "sha512-m9obYBA39mDPN7lJzD5WkGGb0GO54PPLXsbcnj1Hyeu8mSRz7Gb4b1A6zxNX32ZuUySDK4G6it8SDFWD1nCnqg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { @@ -1274,13 +1274,13 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", - "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.7.tgz", + "integrity": "sha512-h39agClImgPWg4H8mYVAbD1qP9vClFbEjqoJmt87Zen8pjqK8FTPUwrOXAvqu5soytwxrLMd2fx2KSCp2CHcNg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { @@ -1291,12 +1291,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", - "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.7.tgz", + "integrity": "sha512-FYiTvku63me9+1Nz7TOx4YMtW3tWXzfANZtrzHhUZrz4d47EEtMQhzFoZWESfXuAMMT5mwzD4+y1N8ONAX6lMQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1306,13 +1306,13 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz", - "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz", + "integrity": "sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.4", - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1322,14 +1322,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", - "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.7.tgz", + "integrity": "sha512-LzA5ESzBy7tqj00Yjey9yWfs3FKy4EmJyKOSWld144OxkTji81WWnUT8nkLUn+imN/zHL8ZQlOu/MTUAhHaX3g==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -1340,12 +1340,12 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", - "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.7.tgz", + "integrity": "sha512-lQEeetGKfFi0wHbt8ClQrUSUMfEeI3MMm74Z73T9/kuz990yYVtfofjf3NuA42Jy3auFOpbjDyCSiIkTs1VIYw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1355,12 +1355,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", - "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.7.tgz", + "integrity": "sha512-mgDoQCRjrY3XK95UuV60tZlFCQGXEtMg8H+IsW72ldw1ih1jZhzYXbJvghmAEpg5UVhhnCeia1CkGttUvCkiMQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "regenerator-transform": "^0.15.2" }, "engines": { @@ -1371,12 +1371,12 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", - "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.7.tgz", + "integrity": "sha512-3OfyfRRqiGeOvIWSagcwUTVk2hXBsr/ww7bLn6TRTuXnexA+Udov2icFOxFX9abaj4l96ooYkcNN1qi2Zvqwng==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1386,12 +1386,12 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", - "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.7.tgz", + "integrity": "sha512-uBbxNwimHi5Bv3hUccmOFlUy3ATO6WagTApenHz9KzoIdn0XeACdB12ZJ4cjhuB2WSi80Ez2FWzJnarccriJeA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1401,13 +1401,13 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", - "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.7.tgz", + "integrity": "sha512-Mm6aeymI0PBh44xNIv/qvo8nmbkpZze1KvR8MkEqbIREDxoiWTi18Zr2jryfRMwDfVZF9foKh060fWgni44luw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1417,12 +1417,12 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", - "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.7.tgz", + "integrity": "sha512-ZFAeNkpGuLnAQ/NCsXJ6xik7Id+tHuS+NT+ue/2+rn/31zcdnupCdmunOizEaP0JsUmTFSTOPoQY7PkK2pttXw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1432,12 +1432,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", - "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.7.tgz", + "integrity": "sha512-SI274k0nUsFFmyQupiO7+wKATAmMFf8iFgq2O+vVFXZ0SV9lNfT1NGzBEhjquFmD8I9sqHLguH+gZVN3vww2AA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1447,12 +1447,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", - "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.7.tgz", + "integrity": "sha512-OmWmQtTHnO8RSUbL0NTdtpbZHeNTnm68Gj5pA4Y2blFNh+V4iZR68V1qL9cI37J21ZN7AaCnkfdHtLExQPf2uA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1462,12 +1462,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", - "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.7.tgz", + "integrity": "sha512-BN87D7KpbdiABA+t3HbVqHzKWUDN3dymLaTnPFAMyc8lV+KN3+YzNhVRNdinaCPA4AUqx7ubXbQ9shRjYBl3SQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1477,13 +1477,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", - "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.7.tgz", + "integrity": "sha512-IWfR89zcEPQGB/iB408uGtSPlQd3Jpq11Im86vUgcmSTcoWAiQMCTOa2K2yNNqFJEBVICKhayctee65Ka8OB0w==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1493,13 +1493,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", - "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.7.tgz", + "integrity": "sha512-8JKfg/hiuA3qXnlLx8qtv5HWRbgyFx2hMMtpDDuU2rTckpKkGu4ycK5yYHwuEa16/quXfoxHBIApEsNyMWnt0g==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1509,13 +1509,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz", - "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.7.tgz", + "integrity": "sha512-YRW8o9vzImwmh4Q3Rffd09bH5/hvY0pxg+1H1i0f7APoUeg12G7+HhLj9ZFNIrYkgBXhIijPJ+IXypN0hLTIbw==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.2", - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1525,28 +1525,28 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz", - "integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.7.tgz", + "integrity": "sha512-Gibz4OUdyNqqLj+7OAvBZxOD7CklCtMA5/j0JgUEwOnaRULsPDXmic2iKxL2DX2vQduPR5wH2hjZas/Vr/Oc0g==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.4", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-validator-option": "^7.24.8", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", + "@babel/compat-data": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.24.7", - "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-assertions": "^7.25.7", + "@babel/plugin-syntax-import-attributes": "^7.25.7", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", @@ -1558,60 +1558,60 @@ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.24.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.4", - "@babel/plugin-transform-async-to-generator": "^7.24.7", - "@babel/plugin-transform-block-scoped-functions": "^7.24.7", - "@babel/plugin-transform-block-scoping": "^7.25.0", - "@babel/plugin-transform-class-properties": "^7.25.4", - "@babel/plugin-transform-class-static-block": "^7.24.7", - "@babel/plugin-transform-classes": "^7.25.4", - "@babel/plugin-transform-computed-properties": "^7.24.7", - "@babel/plugin-transform-destructuring": "^7.24.8", - "@babel/plugin-transform-dotall-regex": "^7.24.7", - "@babel/plugin-transform-duplicate-keys": "^7.24.7", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", - "@babel/plugin-transform-dynamic-import": "^7.24.7", - "@babel/plugin-transform-exponentiation-operator": "^7.24.7", - "@babel/plugin-transform-export-namespace-from": "^7.24.7", - "@babel/plugin-transform-for-of": "^7.24.7", - "@babel/plugin-transform-function-name": "^7.25.1", - "@babel/plugin-transform-json-strings": "^7.24.7", - "@babel/plugin-transform-literals": "^7.25.2", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", - "@babel/plugin-transform-member-expression-literals": "^7.24.7", - "@babel/plugin-transform-modules-amd": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.8", - "@babel/plugin-transform-modules-systemjs": "^7.25.0", - "@babel/plugin-transform-modules-umd": "^7.24.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", - "@babel/plugin-transform-new-target": "^7.24.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", - "@babel/plugin-transform-numeric-separator": "^7.24.7", - "@babel/plugin-transform-object-rest-spread": "^7.24.7", - "@babel/plugin-transform-object-super": "^7.24.7", - "@babel/plugin-transform-optional-catch-binding": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.8", - "@babel/plugin-transform-parameters": "^7.24.7", - "@babel/plugin-transform-private-methods": "^7.25.4", - "@babel/plugin-transform-private-property-in-object": "^7.24.7", - "@babel/plugin-transform-property-literals": "^7.24.7", - "@babel/plugin-transform-regenerator": "^7.24.7", - "@babel/plugin-transform-reserved-words": "^7.24.7", - "@babel/plugin-transform-shorthand-properties": "^7.24.7", - "@babel/plugin-transform-spread": "^7.24.7", - "@babel/plugin-transform-sticky-regex": "^7.24.7", - "@babel/plugin-transform-template-literals": "^7.24.7", - "@babel/plugin-transform-typeof-symbol": "^7.24.8", - "@babel/plugin-transform-unicode-escapes": "^7.24.7", - "@babel/plugin-transform-unicode-property-regex": "^7.24.7", - "@babel/plugin-transform-unicode-regex": "^7.24.7", - "@babel/plugin-transform-unicode-sets-regex": "^7.25.4", + "@babel/plugin-transform-arrow-functions": "^7.25.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.7", + "@babel/plugin-transform-async-to-generator": "^7.25.7", + "@babel/plugin-transform-block-scoped-functions": "^7.25.7", + "@babel/plugin-transform-block-scoping": "^7.25.7", + "@babel/plugin-transform-class-properties": "^7.25.7", + "@babel/plugin-transform-class-static-block": "^7.25.7", + "@babel/plugin-transform-classes": "^7.25.7", + "@babel/plugin-transform-computed-properties": "^7.25.7", + "@babel/plugin-transform-destructuring": "^7.25.7", + "@babel/plugin-transform-dotall-regex": "^7.25.7", + "@babel/plugin-transform-duplicate-keys": "^7.25.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.7", + "@babel/plugin-transform-dynamic-import": "^7.25.7", + "@babel/plugin-transform-exponentiation-operator": "^7.25.7", + "@babel/plugin-transform-export-namespace-from": "^7.25.7", + "@babel/plugin-transform-for-of": "^7.25.7", + "@babel/plugin-transform-function-name": "^7.25.7", + "@babel/plugin-transform-json-strings": "^7.25.7", + "@babel/plugin-transform-literals": "^7.25.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.7", + "@babel/plugin-transform-member-expression-literals": "^7.25.7", + "@babel/plugin-transform-modules-amd": "^7.25.7", + "@babel/plugin-transform-modules-commonjs": "^7.25.7", + "@babel/plugin-transform-modules-systemjs": "^7.25.7", + "@babel/plugin-transform-modules-umd": "^7.25.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.7", + "@babel/plugin-transform-new-target": "^7.25.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.7", + "@babel/plugin-transform-numeric-separator": "^7.25.7", + "@babel/plugin-transform-object-rest-spread": "^7.25.7", + "@babel/plugin-transform-object-super": "^7.25.7", + "@babel/plugin-transform-optional-catch-binding": "^7.25.7", + "@babel/plugin-transform-optional-chaining": "^7.25.7", + "@babel/plugin-transform-parameters": "^7.25.7", + "@babel/plugin-transform-private-methods": "^7.25.7", + "@babel/plugin-transform-private-property-in-object": "^7.25.7", + "@babel/plugin-transform-property-literals": "^7.25.7", + "@babel/plugin-transform-regenerator": "^7.25.7", + "@babel/plugin-transform-reserved-words": "^7.25.7", + "@babel/plugin-transform-shorthand-properties": "^7.25.7", + "@babel/plugin-transform-spread": "^7.25.7", + "@babel/plugin-transform-sticky-regex": "^7.25.7", + "@babel/plugin-transform-template-literals": "^7.25.7", + "@babel/plugin-transform-typeof-symbol": "^7.25.7", + "@babel/plugin-transform-unicode-escapes": "^7.25.7", + "@babel/plugin-transform-unicode-property-regex": "^7.25.7", + "@babel/plugin-transform-unicode-regex": "^7.25.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.7", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", "babel-plugin-polyfill-corejs3": "^0.10.6", "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.37.1", + "core-js-compat": "^3.38.1", "semver": "^6.3.1" }, "engines": { @@ -1635,16 +1635,10 @@ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "license": "MIT" - }, "node_modules/@babel/runtime": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", - "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", + "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==", "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -1654,30 +1648,30 @@ } }, "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", + "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/code-frame": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", - "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", + "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.6", - "@babel/parser": "^7.25.6", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -1686,13 +1680,13 @@ } }, "node_modules/@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", + "integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1991,9 +1985,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", + "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", "cpu": [ "arm" ], @@ -2004,9 +1998,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", + "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", "cpu": [ "arm64" ], @@ -2017,9 +2011,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", "cpu": [ "arm64" ], @@ -2030,9 +2024,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", + "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", "cpu": [ "x64" ], @@ -2043,9 +2037,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", + "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", "cpu": [ "arm" ], @@ -2056,9 +2050,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", + "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", "cpu": [ "arm" ], @@ -2069,9 +2063,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", + "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", "cpu": [ "arm64" ], @@ -2082,9 +2076,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", + "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", "cpu": [ "arm64" ], @@ -2095,9 +2089,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", "cpu": [ "ppc64" ], @@ -2108,9 +2102,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", "cpu": [ "riscv64" ], @@ -2121,9 +2115,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", "cpu": [ "s390x" ], @@ -2134,9 +2128,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", "cpu": [ "x64" ], @@ -2147,9 +2141,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", "cpu": [ "x64" ], @@ -2160,9 +2154,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", "cpu": [ "arm64" ], @@ -2173,9 +2167,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", "cpu": [ "ia32" ], @@ -2186,9 +2180,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", "cpu": [ "x64" ], @@ -2218,9 +2212,9 @@ "license": "MIT" }, "node_modules/@types/mocha": { - "version": "10.0.8", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.8.tgz", - "integrity": "sha512-HfMcUmy9hTMJh66VNcmeC9iVErIZJli2bszuXc6julh5YGuRb/W5OnkHjwLNYdFlMis0sY3If5SEAp+PktdJjw==", + "version": "10.0.9", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.9.tgz", + "integrity": "sha512-sicdRoWtYevwxjOHNMPTl3vSfJM6oyW8o1wXeI7uww6b6xHg8eBznQDNSGBCDJmsE8UMxP05JgZRtsKbTqt//Q==", "dev": true, "license": "MIT" }, @@ -2393,9 +2387,9 @@ "license": "ISC" }, "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", "funding": [ { "type": "opencollective", @@ -2412,8 +2406,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, @@ -2457,96 +2451,6 @@ } } }, - "node_modules/c8/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/c8/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/c8/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/c8/node_modules/test-exclude": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^10.4.1", - "minimatch": "^9.0.4" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/c8/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/c8/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -2561,9 +2465,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001663", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001663.tgz", - "integrity": "sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==", + "version": "1.0.30001667", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz", + "integrity": "sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==", "funding": [ { "type": "opencollective", @@ -2660,15 +2564,17 @@ } }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "license": "ISC", "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/color-convert": { @@ -2791,9 +2697,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.27", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.27.tgz", - "integrity": "sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw==", + "version": "1.5.34", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.34.tgz", + "integrity": "sha512-/TZAiChbAflBNjCg+VvstbcwAtIL/VdMFO3NgRFIzBjpvPzWOTIbbO8kNb6RwU4bt9TP7K+3KqBKw/lOU+Y+GA==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -2846,9 +2752,9 @@ } }, "node_modules/fdir": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.3.0.tgz", - "integrity": "sha512-QOnuT+BOtivR77wYvCWHfGt9s4Pz1VIMbD463vegT5MLqNXy8rYFT/lPVEqf/bhYeT6qmqrNHhsX+rWwe3rOCQ==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.0.tgz", + "integrity": "sha512-3oB133prH1o4j/L5lLW7uOCF1PlD+/It2L0eL/iAqWMB91RBbqTewABqxhj0ibBd90EEmWZq7ntIWzVaWcXTGQ==", "license": "MIT", "peerDependencies": { "picomatch": "^3 || ^4" @@ -2914,18 +2820,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2975,16 +2869,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", @@ -3230,33 +3114,6 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/istanbul-lib-report/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/istanbul-lib-report/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3340,15 +3197,15 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json5": { @@ -3479,14 +3336,11 @@ } }, "node_modules/loupe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz", - "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", + "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.1" - } + "license": "MIT" }, "node_modules/lru-cache": { "version": "5.1.1", @@ -3506,6 +3360,33 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -3564,6 +3445,18 @@ "node": ">= 14.0.0" } }, + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "node_modules/mocha/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -3603,6 +3496,35 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3826,15 +3748,15 @@ } }, "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", + "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", "license": "MIT", "dependencies": { - "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.11.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" }, @@ -3842,26 +3764,24 @@ "node": ">=4" } }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "license": "MIT" + }, "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.1.tgz", + "integrity": "sha512-1DHODs4B8p/mQHU9kr+jv8+wIC9mtG4eBHxWxIq5mhjE3D5oORhCc6deRKzTjs9DcfRFmj9BHSDguZklqCGFWQ==", "license": "BSD-2-Clause", "dependencies": { - "jsesc": "~0.5.0" + "jsesc": "~3.0.2" }, "bin": { "regjsparser": "bin/parser" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "bin": { - "jsesc": "bin/jsesc" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3889,12 +3809,12 @@ } }, "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -3904,22 +3824,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", "fsevents": "~2.3.2" } }, @@ -3954,12 +3874,6 @@ "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", "license": "MIT" }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "license": "MIT" - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -4021,6 +3935,18 @@ "node": ">=8" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/skip-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/skip-regex/-/skip-regex-1.0.2.tgz", @@ -4128,6 +4054,55 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/test-exclude": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^9.0.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -4191,9 +4166,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "funding": [ { "type": "opencollective", @@ -4210,8 +4185,8 @@ ], "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -4380,32 +4355,30 @@ "license": "ISC" }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "license": "MIT", "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-unparser": { From 934dd3ea1be6ab44d61e6df89399c37df35d5633 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 10 Oct 2024 05:25:34 +0200 Subject: [PATCH 012/104] Adding private fields for Modules --- common/src/module/canvas.mjs | 145 +++++++++++++++--------------- common/src/module/common.mjs | 18 ++-- common/src/module/expreval.mjs | 14 +-- common/src/module/io.mjs | 84 +++++++++-------- common/src/module/latex.mjs | 10 ++- common/src/module/preferences.mjs | 3 + 6 files changed, 144 insertions(+), 130 deletions(-) diff --git a/common/src/module/canvas.mjs b/common/src/module/canvas.mjs index e623034..2aa14ad 100644 --- a/common/src/module/canvas.mjs +++ b/common/src/module/canvas.mjs @@ -25,23 +25,20 @@ import Objects from "./objects.mjs" import History from "./history.mjs" class CanvasAPI extends Module { + /** @type {CanvasInterface} */ + #canvas = null + /** @type {CanvasRenderingContext2D} */ + #ctx = null + /** @type {{show(string, string, string)}} */ + #drawingErrorDialog = null + + constructor() { super("Canvas", { canvas: CanvasInterface, drawingErrorDialog: DialogInterface }) - - /** @type {CanvasInterface} */ - this._canvas = null - - /** @type {CanvasRenderingContext2D} */ - this._ctx = null - - /** - * @type {{show(string, string, string)}} - * @private - */ - this._drawingErrorDialog = null + /** * * @type {Object.} @@ -67,18 +64,18 @@ class CanvasAPI extends Module { */ initialize({ canvas, drawingErrorDialog }) { super.initialize({ canvas, drawingErrorDialog }) - this._canvas = canvas - this._drawingErrorDialog = drawingErrorDialog + this.#canvas = canvas + this.#drawingErrorDialog = drawingErrorDialog } get width() { if(!this.initialized) throw new Error("Attempting width before initialize!") - return this._canvas.width + return this.#canvas.width } get height() { if(!this.initialized) throw new Error("Attempting height before initialize!") - return this._canvas.height + return this.#canvas.height } /** @@ -87,7 +84,7 @@ class CanvasAPI extends Module { */ get xmin() { if(!this.initialized) throw new Error("Attempting xmin before initialize!") - return this._canvas.xmin + return this.#canvas.xmin } /** @@ -96,7 +93,7 @@ class CanvasAPI extends Module { */ get xzoom() { if(!this.initialized) throw new Error("Attempting xzoom before initialize!") - return this._canvas.xzoom + return this.#canvas.xzoom } /** @@ -105,7 +102,7 @@ class CanvasAPI extends Module { */ get ymax() { if(!this.initialized) throw new Error("Attempting ymax before initialize!") - return this._canvas.ymax + return this.#canvas.ymax } /** @@ -114,7 +111,7 @@ class CanvasAPI extends Module { */ get yzoom() { if(!this.initialized) throw new Error("Attempting yzoom before initialize!") - return this._canvas.yzoom + return this.#canvas.yzoom } /** @@ -123,7 +120,7 @@ class CanvasAPI extends Module { */ get xlabel() { if(!this.initialized) throw new Error("Attempting xlabel before initialize!") - return this._canvas.xlabel + return this.#canvas.xlabel } /** @@ -132,7 +129,7 @@ class CanvasAPI extends Module { */ get ylabel() { if(!this.initialized) throw new Error("Attempting ylabel before initialize!") - return this._canvas.ylabel + return this.#canvas.ylabel } /** @@ -141,7 +138,7 @@ class CanvasAPI extends Module { */ get linewidth() { if(!this.initialized) throw new Error("Attempting linewidth before initialize!") - return this._canvas.linewidth + return this.#canvas.linewidth } /** @@ -150,7 +147,7 @@ class CanvasAPI extends Module { */ get textsize() { if(!this.initialized) throw new Error("Attempting textsize before initialize!") - return this._canvas.textsize + return this.#canvas.textsize } /** @@ -159,7 +156,7 @@ class CanvasAPI extends Module { */ get logscalex() { if(!this.initialized) throw new Error("Attempting logscalex before initialize!") - return this._canvas.logscalex + return this.#canvas.logscalex } /** @@ -168,7 +165,7 @@ class CanvasAPI extends Module { */ get showxgrad() { if(!this.initialized) throw new Error("Attempting showxgrad before initialize!") - return this._canvas.showxgrad + return this.#canvas.showxgrad } /** @@ -177,7 +174,7 @@ class CanvasAPI extends Module { */ get showygrad() { if(!this.initialized) throw new Error("Attempting showygrad before initialize!") - return this._canvas.showygrad + return this.#canvas.showygrad } /** @@ -201,7 +198,7 @@ class CanvasAPI extends Module { requestPaint() { if(!this.initialized) throw new Error("Attempting requestPaint before initialize!") - this._canvas.requestPaint() + this.#canvas.requestPaint() } /** @@ -209,17 +206,17 @@ class CanvasAPI extends Module { */ redraw() { if(!this.initialized) throw new Error("Attempting redraw before initialize!") - this._ctx = this._canvas.getContext("2d") + this.#ctx = this.#canvas.getContext("2d") this._computeAxes() this._reset() this._drawGrid() this._drawAxes() this._drawLabels() - this._ctx.lineWidth = this.linewidth + this.#ctx.lineWidth = this.linewidth for(let objType in Objects.currentObjects) { for(let obj of Objects.currentObjects[objType]) { - this._ctx.strokeStyle = obj.color - this._ctx.fillStyle = obj.color + this.#ctx.strokeStyle = obj.color + this.#ctx.fillStyle = obj.color if(obj.visible) try { obj.draw(this) @@ -227,12 +224,12 @@ class CanvasAPI extends Module { // Drawing throws an error. Generally, it's due to a new modification (or the opening of a file) console.error(e) console.log(e.stack) - this._drawingErrorDialog.show(objType, obj.name, e.message) + this.#drawingErrorDialog.show(objType, obj.name, e.message) History.undo() } } } - this._ctx.lineWidth = 1 + this.#ctx.lineWidth = 1 } /** @@ -240,9 +237,9 @@ class CanvasAPI extends Module { * @private */ _computeAxes() { - let exprY = new Expression(`x*(${this._canvas.yaxisstep})`) + let exprY = new Expression(`x*(${this.#canvas.yaxisstep})`) let y1 = exprY.execute(1) - let exprX = new Expression(`x*(${this._canvas.xaxisstep})`) + let exprX = new Expression(`x*(${this.#canvas.xaxisstep})`) let x1 = exprX.execute(1) this.axesSteps = { x: { @@ -264,10 +261,10 @@ class CanvasAPI extends Module { */ _reset() { // Reset - this._ctx.fillStyle = "#FFFFFF" - this._ctx.strokeStyle = "#000000" - this._ctx.font = `${this.textsize}px sans-serif` - this._ctx.fillRect(0, 0, this.width, this.height) + this.#ctx.fillStyle = "#FFFFFF" + this.#ctx.strokeStyle = "#000000" + this.#ctx.font = `${this.textsize}px sans-serif` + this.#ctx.fillRect(0, 0, this.width, this.height) } /** @@ -275,7 +272,7 @@ class CanvasAPI extends Module { * @private */ _drawGrid() { - this._ctx.strokeStyle = "#C0C0C0" + this.#ctx.strokeStyle = "#C0C0C0" if(this.logscalex) { for(let xpow = -this.maxgradx; xpow <= this.maxgradx; xpow++) { for(let xmulti = 1; xmulti < 10; xmulti++) { @@ -299,7 +296,7 @@ class CanvasAPI extends Module { * @private */ _drawAxes() { - this._ctx.strokeStyle = "#000000" + this.#ctx.strokeStyle = "#000000" let axisypos = this.logscalex ? 1 : 0 this.drawXLine(axisypos) this.drawYLine(0) @@ -320,19 +317,19 @@ class CanvasAPI extends Module { let axisypx = this.x2px(this.logscalex ? 1 : 0) // X coordinate of Y axis let axisxpx = this.y2px(0) // Y coordinate of X axis // Labels - this._ctx.fillStyle = "#000000" - this._ctx.font = `${this.textsize}px sans-serif` - this._ctx.fillText(this.ylabel, axisypx + 10, 24) - let textWidth = this._ctx.measureText(this.xlabel).width - this._ctx.fillText(this.xlabel, this.width - 14 - textWidth, axisxpx - 5) + this.#ctx.fillStyle = "#000000" + this.#ctx.font = `${this.textsize}px sans-serif` + this.#ctx.fillText(this.ylabel, axisypx + 10, 24) + let textWidth = this.#ctx.measureText(this.xlabel).width + this.#ctx.fillText(this.xlabel, this.width - 14 - textWidth, axisxpx - 5) // Axis graduation labels - this._ctx.font = `${this.textsize - 4}px sans-serif` + this.#ctx.font = `${this.textsize - 4}px sans-serif` - let txtMinus = this._ctx.measureText("-").width + let txtMinus = this.#ctx.measureText("-").width if(this.showxgrad) { if(this.logscalex) { for(let xpow = -this.maxgradx; xpow <= this.maxgradx; xpow += 1) { - textWidth = this._ctx.measureText("10" + textsup(xpow)).width + textWidth = this.#ctx.measureText("10" + textsup(xpow)).width if(xpow !== 0) this.drawVisibleText("10" + textsup(xpow), this.x2px(Math.pow(10, xpow)) - textWidth / 2, axisxpx + 16 + (6 * (xpow === 1))) } @@ -350,13 +347,13 @@ class CanvasAPI extends Module { for(let y = 0; y < this.axesSteps.y.maxDraw; y += 1) { let drawY = y * this.axesSteps.y.value let txtY = this.axesSteps.y.expression.simplify(y).toString().replace(/^\((.+)\)$/, "$1") - textWidth = this._ctx.measureText(txtY).width + textWidth = this.#ctx.measureText(txtY).width this.drawVisibleText(txtY, axisypx - 6 - textWidth, this.y2px(drawY) + 4 + (10 * (y === 0))) if(y !== 0) this.drawVisibleText("-" + txtY, axisypx - 6 - textWidth - txtMinus, this.y2px(-drawY) + 4) } } - this._ctx.fillStyle = "#FFFFFF" + this.#ctx.fillStyle = "#FFFFFF" } // @@ -394,7 +391,7 @@ class CanvasAPI extends Module { drawVisibleText(text, x, y) { if(x > 0 && x < this.width && y > 0 && y < this.height) { text.toString().split("\n").forEach((txt, i) => { - this._ctx.fillText(txt, x, y + (this.textsize * i)) + this.#ctx.fillText(txt, x, y + (this.textsize * i)) }) } } @@ -409,8 +406,8 @@ class CanvasAPI extends Module { * @param {number} height */ drawVisibleImage(image, x, y, width, height) { - this._canvas.markDirty(Qt.rect(x, y, width, height)) - this._ctx.drawImage(image, x, y, width, height) + this.#canvas.markDirty(Qt.rect(x, y, width, height)) + this.#ctx.drawImage(image, x, y, width, height) } /** @@ -424,7 +421,7 @@ class CanvasAPI extends Module { let defaultHeight = this.textsize * 1.2 // Approximate but good enough! for(let txt of text.split("\n")) { theight += defaultHeight - if(this._ctx.measureText(txt).width > twidth) twidth = this._ctx.measureText(txt).width + if(this.#ctx.measureText(txt).width > twidth) twidth = this.#ctx.measureText(txt).width } return { "width": twidth, "height": theight } } @@ -494,10 +491,10 @@ class CanvasAPI extends Module { * @param {number} y2 */ drawLine(x1, y1, x2, y2) { - this._ctx.beginPath() - this._ctx.moveTo(x1, y1) - this._ctx.lineTo(x2, y2) - this._ctx.stroke() + this.#ctx.beginPath() + this.#ctx.moveTo(x1, y1) + this.#ctx.lineTo(x2, y2) + this.#ctx.stroke() } /** @@ -509,9 +506,9 @@ class CanvasAPI extends Module { * @param {number} dashPxSize */ drawDashedLine(x1, y1, x2, y2, dashPxSize = 6) { - this._ctx.setLineDash([dashPxSize / 2, dashPxSize]) + this.#ctx.setLineDash([dashPxSize / 2, dashPxSize]) this.drawLine(x1, y1, x2, y2) - this._ctx.setLineDash([]) + this.#ctx.setLineDash([]) } /** @@ -522,10 +519,10 @@ class CanvasAPI extends Module { */ renderLatexImage(ltxText, color, callback) { const onRendered = (imgData) => { - if(!this._canvas.isImageLoaded(imgData.source) && !this._canvas.isImageLoading(imgData.source)) { + if(!this.#canvas.isImageLoaded(imgData.source) && !this.#canvas.isImageLoading(imgData.source)) { // Wait until the image is loaded to callback. - this._canvas.loadImage(imgData.source) - this._canvas.imageLoaders[imgData.source] = [callback, imgData] + this.#canvas.loadImage(imgData.source) + this.#canvas.imageLoaders[imgData.source] = [callback, imgData] } else { // Callback directly callback(imgData) @@ -543,11 +540,11 @@ class CanvasAPI extends Module { // get font() { - return this._ctx.font + return this.#ctx.font } set font(value) { - return this._ctx.font = value + return this.#ctx.font = value } /** @@ -560,9 +557,9 @@ class CanvasAPI extends Module { * @param {boolean} counterclockwise */ arc(x, y, radius, startAngle, endAngle, counterclockwise = false) { - this._ctx.beginPath() - this._ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise) - this._ctx.stroke() + this.#ctx.beginPath() + this.#ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise) + this.#ctx.stroke() } /** @@ -572,9 +569,9 @@ class CanvasAPI extends Module { * @param {number} radius */ disc(x, y, radius) { - this._ctx.beginPath() - this._ctx.arc(x, y, radius, 0, 2 * Math.PI) - this._ctx.fill() + this.#ctx.beginPath() + this.#ctx.arc(x, y, radius, 0, 2 * Math.PI) + this.#ctx.fill() } /** @@ -585,7 +582,7 @@ class CanvasAPI extends Module { * @param {number} h */ fillRect(x, y, w, h) { - this._ctx.fillRect(x, y, w, h) + this.#ctx.fillRect(x, y, w, h) } } diff --git a/common/src/module/common.mjs b/common/src/module/common.mjs index b757f14..5fc9387 100644 --- a/common/src/module/common.mjs +++ b/common/src/module/common.mjs @@ -25,6 +25,10 @@ globalThis.Modules = globalThis.Modules || {} * Base class for global APIs in runtime. */ export class Module { + /** @type {string} */ + #name + /** @type {Object.} */ + #initializationParameters /** * @@ -33,8 +37,8 @@ export class Module { */ constructor(name, initializationParameters = {}) { console.log(`Loading module ${name}...`) - this.__name = name - this.__initializationParameters = initializationParameters + this.#name = name + this.#initializationParameters = initializationParameters this.initialized = false } @@ -45,15 +49,15 @@ export class Module { */ initialize(options) { if(this.initialized) - throw new Error(`Cannot reinitialize module ${this.__name}.`) - console.log(`Initializing ${this.__name}...`) - for(const [name, value] of Object.entries(this.__initializationParameters)) { + throw new Error(`Cannot reinitialize module ${this.#name}.`) + console.log(`Initializing ${this.#name}...`) + for(const [name, value] of Object.entries(this.#initializationParameters)) { if(!options.hasOwnProperty(name)) - throw new Error(`Option '${name}' of initialize of module ${this.__name} does not exist.`) + throw new Error(`Option '${name}' of initialize of module ${this.#name} does not exist.`) if(typeof value === "function" && value.prototype instanceof Interface) Interface.check_implementation(value, options[name]) else if(typeof value !== typeof options[name]) - throw new Error(`Option '${name}' of initialize of module ${this.__name} is not a '${value}' (${typeof options[name]}).`) + throw new Error(`Option '${name}' of initialize of module ${this.#name} is not a '${value}' (${typeof options[name]}).`) } this.initialized = true } diff --git a/common/src/module/expreval.mjs b/common/src/module/expreval.mjs index 854f928..964177c 100644 --- a/common/src/module/expreval.mjs +++ b/common/src/module/expreval.mjs @@ -35,15 +35,17 @@ const evalVariables = { } class ExprParserAPI extends Module { + #parser = new Parser() + constructor() { super("ExprParser") this.currentVars = {} - this._parser = new Parser() + this.#parser = new Parser() - this._parser.consts = Object.assign({}, this._parser.consts, evalVariables) + this.#parser.consts = Object.assign({}, this.#parser.consts, evalVariables) - this._parser.functions.integral = this.integral.bind(this) - this._parser.functions.derivative = this.derivative.bind(this) + this.#parser.functions.integral = this.integral.bind(this) + this.#parser.functions.derivative = this.derivative.bind(this) } /** @@ -68,7 +70,7 @@ class ExprParserAPI extends Module { [f, variable] = args if(typeof f !== "string" || typeof variable !== "string") throw EvalError(qsTranslate("usage", "Usage:\n%1").arg(usage2)) - f = this._parser.parse(f).toJSFunction(variable, this.currentVars) + f = this.#parser.parse(f).toJSFunction(variable, this.currentVars) } else throw EvalError(qsTranslate("usage", "Usage:\n%1\n%2").arg(usage1).arg(usage2)) return f @@ -79,7 +81,7 @@ class ExprParserAPI extends Module { * @returns {ExprEvalExpression} */ parse(expression) { - return this._parser.parse(expression) + return this.#parser.parse(expression) } integral(a, b, ...args) { diff --git a/common/src/module/io.mjs b/common/src/module/io.mjs index b6d40f5..e32f2cf 100644 --- a/common/src/module/io.mjs +++ b/common/src/module/io.mjs @@ -24,6 +24,12 @@ import { DialogInterface, RootInterface, SettingsInterface } from "./interface.m class IOAPI extends Module { + /** @type {RootInterface} */ + #rootElement + /** @type {SettingsInterface} */ + #settings + /** @type {{show: function(string)}} */ + #alert constructor() { super("IO", { @@ -46,9 +52,9 @@ class IOAPI extends Module { */ initialize({ root, settings, alert }) { super.initialize({ root, settings, alert }) - this.rootElement = root - this.settings = settings - this.alert = alert + this.#rootElement = root + this.#settings = settings + this.#alert = alert } /** @@ -69,27 +75,27 @@ class IOAPI extends Module { } } let settings = { - "xzoom": this.settings.xzoom, - "yzoom": this.settings.yzoom, - "xmin": this.settings.xmin, - "ymax": this.settings.ymax, - "xaxisstep": this.settings.xaxisstep, - "yaxisstep": this.settings.yaxisstep, - "xaxislabel": this.settings.xlabel, - "yaxislabel": this.settings.ylabel, - "logscalex": this.settings.logscalex, - "linewidth": this.settings.linewidth, - "showxgrad": this.settings.showxgrad, - "showygrad": this.settings.showygrad, - "textsize": this.settings.textsize, + "xzoom": this.#settings.xzoom, + "yzoom": this.#settings.yzoom, + "xmin": this.#settings.xmin, + "ymax": this.#settings.ymax, + "xaxisstep": this.#settings.xaxisstep, + "yaxisstep": this.#settings.yaxisstep, + "xaxislabel": this.#settings.xlabel, + "yaxislabel": this.#settings.ylabel, + "logscalex": this.#settings.logscalex, + "linewidth": this.#settings.linewidth, + "showxgrad": this.#settings.showxgrad, + "showygrad": this.#settings.showygrad, + "textsize": this.#settings.textsize, "history": History.serialize(), - "width": this.rootElement.width, - "height": this.rootElement.height, + "width": this.#rootElement.width, + "height": this.#rootElement.height, "objects": objs, "type": "logplotv1" } Helper.write(filename, JSON.stringify(settings)) - this.alert.show(qsTranslate("io", "Saved plot to '%1'.").arg(filename.split("/").pop())) + this.#alert.show(qsTranslate("io", "Saved plot to '%1'.").arg(filename.split("/").pop())) History.history.saved = true } @@ -101,32 +107,32 @@ class IOAPI extends Module { if(!this.initialized) throw new Error("Attempting loadDiagram before initialize!") if(!History.initialized) throw new Error("Attempting loadDiagram before history is initialized!") let basename = filename.split("/").pop() - this.alert.show(qsTranslate("io", "Loading file '%1'.").arg(basename)) + this.#alert.show(qsTranslate("io", "Loading file '%1'.").arg(basename)) let data = JSON.parse(Helper.load(filename)) let error = "" if(data.hasOwnProperty("type") && data["type"] === "logplotv1") { History.clear() // Importing settings - this.settings.saveFilename = filename - this.settings.xzoom = parseFloat(data["xzoom"]) || 100 - this.settings.yzoom = parseFloat(data["yzoom"]) || 10 - this.settings.xmin = parseFloat(data["xmin"]) || 5 / 10 - this.settings.ymax = parseFloat(data["ymax"]) || 24 - this.settings.xaxisstep = data["xaxisstep"] || "4" - this.settings.yaxisstep = data["yaxisstep"] || "4" - this.settings.xlabel = data["xaxislabel"] || "" - this.settings.ylabel = data["yaxislabel"] || "" - this.settings.logscalex = data["logscalex"] === true + this.#settings.saveFilename = filename + this.#settings.xzoom = parseFloat(data["xzoom"]) || 100 + this.#settings.yzoom = parseFloat(data["yzoom"]) || 10 + this.#settings.xmin = parseFloat(data["xmin"]) || 5 / 10 + this.#settings.ymax = parseFloat(data["ymax"]) || 24 + this.#settings.xaxisstep = data["xaxisstep"] || "4" + this.#settings.yaxisstep = data["yaxisstep"] || "4" + this.#settings.xlabel = data["xaxislabel"] || "" + this.#settings.ylabel = data["yaxislabel"] || "" + this.#settings.logscalex = data["logscalex"] === true if("showxgrad" in data) - this.settings.showxgrad = data["showxgrad"] + this.#settings.showxgrad = data["showxgrad"] if("showygrad" in data) - this.settings.textsize = data["showygrad"] + this.#settings.textsize = data["showygrad"] if("linewidth" in data) - this.settings.linewidth = data["linewidth"] + this.#settings.linewidth = data["linewidth"] if("textsize" in data) - this.settings.textsize = data["textsize"] - this.rootElement.height = parseFloat(data["height"]) || 500 - this.rootElement.width = parseFloat(data["width"]) || 1000 + this.#settings.textsize = data["textsize"] + this.#rootElement.height = parseFloat(data["height"]) || 500 + this.#rootElement.width = parseFloat(data["width"]) || 1000 // Importing objects Objects.currentObjects = {} @@ -158,18 +164,18 @@ class IOAPI extends Module { History.unserialize(...data["history"]) // Refreshing sidebar - this.rootElement.updateObjectsLists() + this.#rootElement.updateObjectsLists() } else { error = qsTranslate("io", "Invalid file provided.") } if(error !== "") { console.log(error) - this.alert.show(qsTranslate("io", "Could not load file: ") + error) + this.#alert.show(qsTranslate("io", "Could not load file: ") + error) // TODO: Error handling return } Canvas.redraw() - this.alert.show(qsTranslate("io", "Loaded file '%1'.").arg(basename)) + this.#alert.show(qsTranslate("io", "Loaded file '%1'.").arg(basename)) History.history.saved = true } diff --git a/common/src/module/latex.mjs b/common/src/module/latex.mjs index 8740160..8fabee4 100644 --- a/common/src/module/latex.mjs +++ b/common/src/module/latex.mjs @@ -60,6 +60,9 @@ class LatexRenderResult { } class LatexAPI extends Module { + /** @type {LatexInterface} */ + #latex = null + constructor() { super("Latex", { latex: LatexInterface, @@ -77,8 +80,7 @@ class LatexAPI extends Module { */ initialize({ latex, helper }) { super.initialize({ latex, helper }) - this.latex = latex - this.helper = helper + this.#latex = latex this.enabled = helper.getSettingBool("enable_latex") } @@ -93,7 +95,7 @@ class LatexAPI extends Module { */ findPrerendered(markup, fontSize, color) { if(!this.initialized) throw new Error("Attempting findPrerendered before initialize!") - const data = this.latex.findPrerendered(markup, fontSize, color) + const data = this.#latex.findPrerendered(markup, fontSize, color) let ret = null if(data !== "") ret = new LatexRenderResult(...data.split(",")) @@ -110,7 +112,7 @@ class LatexAPI extends Module { */ async requestAsyncRender(markup, fontSize, color) { if(!this.initialized) throw new Error("Attempting requestAsyncRender before initialize!") - let args = this.latex.render(markup, fontSize, color).split(",") + let args = this.#latex.render(markup, fontSize, color).split(",") return new LatexRenderResult(...args) } diff --git a/common/src/module/preferences.mjs b/common/src/module/preferences.mjs index afb795e..dea8677 100644 --- a/common/src/module/preferences.mjs +++ b/common/src/module/preferences.mjs @@ -20,6 +20,9 @@ import General from "../preferences/general.mjs" import Editor from "../preferences/expression.mjs" import DefaultGraph from "../preferences/default.mjs" +/** + * Module for application wide settings. + */ class PreferencesAPI extends Module { constructor() { super("Preferences") From 9663c335631ef0fa6eb4599aa3a48c94dc02c0b6 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 10 Oct 2024 05:33:01 +0200 Subject: [PATCH 013/104] Improving MJS lupdate hacky script to take private fields into account. --- assets/i18n/lp_de.ts | 36 ++++++++++++++++++------------------ assets/i18n/lp_en.ts | 36 ++++++++++++++++++------------------ assets/i18n/lp_es.ts | 36 ++++++++++++++++++------------------ assets/i18n/lp_fr.ts | 36 ++++++++++++++++++------------------ assets/i18n/lp_hu.ts | 36 ++++++++++++++++++------------------ assets/i18n/lp_nb_NO.ts | 36 ++++++++++++++++++------------------ assets/i18n/lp_template.ts | 36 ++++++++++++++++++------------------ assets/i18n/update.sh | 6 +++++- 8 files changed, 131 insertions(+), 127 deletions(-) diff --git a/assets/i18n/lp_de.ts b/assets/i18n/lp_de.ts index 59980da..4876e02 100644 --- a/assets/i18n/lp_de.ts +++ b/assets/i18n/lp_de.ts @@ -1308,27 +1308,27 @@ Ausdruck analysiert: %3 Verlauf - + Saved plot to '%1'. Gespeicherte Grafik auf '%1'. - + Loading file '%1'. Laden der Datei '%1'. - + Unknown object type: %1. Unbekannter Objekttyp: %1. - + Invalid file provided. Ungültige Datei angegeben. - + Could not load file: Datei konnte nicht geladen werden: @@ -1337,7 +1337,7 @@ Ausdruck analysiert: %3 Die Datei konnte nicht gespeichert werden: - + Loaded file '%1'. Geladene Datei '%1'. @@ -1759,17 +1759,17 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde settingCategory - + default Standardeinstellungen - + general Allgemeine - + editor Ausdruckseditor @@ -1827,22 +1827,22 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde usage - + integral(<from: number>, <to: number>, <f: ExecutableObject>) integral(<von: Zahl>, <bis: Zahl>, <f: Funktionsähnliches Objekt>) - - + + Usage: %1 Verwendung: %1 - - - + + + Usage: %1 %2 @@ -1851,17 +1851,17 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde %2 - + integral(<from: number>, <to: number>, <f: string>, <variable: string>) integral(<von: Zahl>, <bis: Zahl>, <f: String>, <Variablen: String>) - + derivative(<f: ExecutableObject>, <x: number>) derivative(<f: Funktionsähnliches Objekt>, <x: Zahl>) - + derivative(<f: string>, <variable: string>, <x: number>) derivative(<f: String>, <Variablen: String>, <x: Zahl>) diff --git a/assets/i18n/lp_en.ts b/assets/i18n/lp_en.ts index ab62387..b2dfaff 100644 --- a/assets/i18n/lp_en.ts +++ b/assets/i18n/lp_en.ts @@ -1308,27 +1308,27 @@ Evaluated expression: %3 History - + Saved plot to '%1'. Saved plot to '%1'. - + Loading file '%1'. Loading file '%1'. - + Unknown object type: %1. Unknown object type: %1. - + Invalid file provided. Invalid file provided. - + Could not load file: Could not load file: @@ -1337,7 +1337,7 @@ Evaluated expression: %3 Could not save file: - + Loaded file '%1'. Loaded file '%1'. @@ -1759,17 +1759,17 @@ Please make sure your LaTeX installation is correct and report a bug if so. settingCategory - + general General - + editor Expression Editor - + default Default settings @@ -1827,22 +1827,22 @@ Please make sure your LaTeX installation is correct and report a bug if so. usage - + integral(<from: number>, <to: number>, <f: ExecutableObject>) integral(<from: number>, <to: number>, <f: Function-like object>) - - + + Usage: %1 Usage: %1 - - - + + + Usage: %1 %2 @@ -1851,17 +1851,17 @@ Please make sure your LaTeX installation is correct and report a bug if so. - + integral(<from: number>, <to: number>, <f: string>, <variable: string>) integral(<from: number>, <to: number>, <f: string>, <variable: string>) - + derivative(<f: ExecutableObject>, <x: number>) derivative(<f: Function-like object>, <x: number>) - + derivative(<f: string>, <variable: string>, <x: number>) derivative(<f: string>, <variable: string>, <x: number>) diff --git a/assets/i18n/lp_es.ts b/assets/i18n/lp_es.ts index f5e3d12..14dd724 100644 --- a/assets/i18n/lp_es.ts +++ b/assets/i18n/lp_es.ts @@ -1320,27 +1320,27 @@ Expresión evaluada: %3 Objetos - + Saved plot to '%1'. Gráfico guardado en '%1'. - + Loading file '%1'. Cargando el archivo '%1'. - + Unknown object type: %1. Tipo de objeto desconocido: %1 . - + Invalid file provided. Se ha proporcionado un archivo no válido. - + Could not load file: @@ -1349,7 +1349,7 @@ Expresión evaluada: %3 No se ha podido guardar el archivo: - + Loaded file '%1'. Archivo cargado '%1'. @@ -1759,17 +1759,17 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u settingCategory - + general General - + editor Editor de expresiones - + default Ajustes por defecto @@ -1827,22 +1827,22 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u usage - + integral(<from: number>, <to: number>, <f: ExecutableObject>) integral(<desde: número>, <hasta: número>, <f: Objeto similar a una función>) - - + + Usage: %1 Uso: %1 - - - + + + Usage: %1 %2 @@ -1851,17 +1851,17 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u %2 - + integral(<from: number>, <to: number>, <f: string>, <variable: string>) integral(<desde: número>, <hasta: número>, <f: cadena>, <variable: cadena>) - + derivative(<f: ExecutableObject>, <x: number>) derivative(<f: objeto similar a una función>, <x: número>) - + derivative(<f: string>, <variable: string>, <x: number>) derivative(<f: cadena>, <variable: cadena>, <x: número>) diff --git a/assets/i18n/lp_fr.ts b/assets/i18n/lp_fr.ts index a638be9..2b1a26d 100644 --- a/assets/i18n/lp_fr.ts +++ b/assets/i18n/lp_fr.ts @@ -1323,27 +1323,27 @@ Formule analysée : %3 &Mettre à jour LogarithmPlotter - + Saved plot to '%1'. Graphe sauvegardé dans '%1'. - + Loading file '%1'. Chargement du fichier '%1'. - + Unknown object type: %1. Type d'objet inconnu : %1. - + Invalid file provided. Fichier fourni invalide. - + Could not load file: Impossible de charger le fichier : @@ -1352,7 +1352,7 @@ Formule analysée : %3 Impossible de sauvegarder le fichier : - + Loaded file '%1'. Fichier '%1' chargé. @@ -1762,17 +1762,17 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c settingCategory - + general Général - + editor Éditeur de formule - + default Paramètres par défaut @@ -1830,22 +1830,22 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c usage - + integral(<from: number>, <to: number>, <f: ExecutableObject>) integral(<de : nombre>, <à : nombre>, <f : Objet fonction>) - - + + Usage: %1 Emploi : %1 - - - + + + Usage: %1 %2 @@ -1854,17 +1854,17 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c %2 - + integral(<from: number>, <to: number>, <f: string>, <variable: string>) integral(<de : nombre>, <à : nombre>, <f : fonction chaîne>, <variable>) - + derivative(<f: ExecutableObject>, <x: number>) derivative(<f : Objet fonction>, <x : nombre>) - + derivative(<f: string>, <variable: string>, <x: number>) derivative(<f : fonction chaîne>, <variable>, <x : nombre>) diff --git a/assets/i18n/lp_hu.ts b/assets/i18n/lp_hu.ts index f817dd2..975c600 100644 --- a/assets/i18n/lp_hu.ts +++ b/assets/i18n/lp_hu.ts @@ -1304,27 +1304,27 @@ Kiértékelt kifejezés: %3 Előzmények - + Saved plot to '%1'. Ábra mentve ide: „%1”. - + Loading file '%1'. A(z) „%1” fájl betöltése folyamatban van. - + Unknown object type: %1. Ismeretlen objektumtípus: %1. - + Invalid file provided. A megadott fájl érvénytelen. - + Could not load file: @@ -1333,7 +1333,7 @@ Kiértékelt kifejezés: %3 A fájl mentése nem sikerült: - + Loaded file '%1'. A(z) „%1” fájl betöltve. @@ -1759,17 +1759,17 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents settingCategory - + general Általános - + editor Kifejezésszerkesztő - + default Alapértelmezett ábra @@ -1827,22 +1827,22 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents usage - + integral(<from: number>, <to: number>, <f: ExecutableObject>) integral(<alsó korlát: szám>, <felső korlát: szám>, <f: függvényszerű objektum>) - - + + Usage: %1 Használat: %1 - - - + + + Usage: %1 %2 @@ -1851,17 +1851,17 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents %2 - + integral(<from: number>, <to: number>, <f: string>, <variable: string>) integral(<alsó korlát: szám>, <felső korlát: szám>, <függvény: karakterlánc>, <változó: karakterlánc>) - + derivative(<f: ExecutableObject>, <x: number>) derivative(<f: függvényszerű objektum>, <x: szám>) - + derivative(<f: string>, <variable: string>, <x: number>) derivált(<függvény: karakterlánc>, <változó: karakterlánc>, <x: szám>) diff --git a/assets/i18n/lp_nb_NO.ts b/assets/i18n/lp_nb_NO.ts index b46ffe7..d278f03 100644 --- a/assets/i18n/lp_nb_NO.ts +++ b/assets/i18n/lp_nb_NO.ts @@ -1235,27 +1235,27 @@ Evaluated expression: %3 Historikk - + Saved plot to '%1'. Lagret plott i «%1». - + Loading file '%1'. Laster inn «%1»-fil. - + Unknown object type: %1. Ukjent objekttype: %1. - + Invalid file provided. Ugyldig fil angitt. - + Could not load file: @@ -1264,7 +1264,7 @@ Evaluated expression: %3 Kunne ikke lagre fil: - + Loaded file '%1'. Lastet inn filen «%1». @@ -1669,17 +1669,17 @@ Please make sure your latex installation is correct and report a bug if so. settingCategory - + general - + editor - + default @@ -1737,38 +1737,38 @@ Please make sure your latex installation is correct and report a bug if so. usage - + integral(<from: number>, <to: number>, <f: ExecutableObject>) - - + + Usage: %1 - - - + + + Usage: %1 %2 - + integral(<from: number>, <to: number>, <f: string>, <variable: string>) - + derivative(<f: ExecutableObject>, <x: number>) - + derivative(<f: string>, <variable: string>, <x: number>) diff --git a/assets/i18n/lp_template.ts b/assets/i18n/lp_template.ts index 9440730..0981f1b 100644 --- a/assets/i18n/lp_template.ts +++ b/assets/i18n/lp_template.ts @@ -1069,32 +1069,32 @@ Evaluated expression: %3 io - + Saved plot to '%1'. - + Loading file '%1'. - + Unknown object type: %1. - + Invalid file provided. - + Could not load file: - + Loaded file '%1'. @@ -1465,17 +1465,17 @@ Please make sure your latex installation is correct and report a bug if so. settingCategory - + general - + editor - + default @@ -1519,38 +1519,38 @@ Please make sure your latex installation is correct and report a bug if so. usage - + integral(<from: number>, <to: number>, <f: ExecutableObject>) - - + + Usage: %1 - - - + + + Usage: %1 %2 - + integral(<from: number>, <to: number>, <f: string>, <variable: string>) - + derivative(<f: ExecutableObject>, <x: number>) - + derivative(<f: string>, <variable: string>, <x: number>) diff --git a/assets/i18n/update.sh b/assets/i18n/update.sh index 4ff172c..ff96ef8 100755 --- a/assets/i18n/update.sh +++ b/assets/i18n/update.sh @@ -33,6 +33,8 @@ for file in $files; do replace "${file%.*}.js" "^export" "/*export*/" replace "${file%.*}.js" "async " "/*async */" replace "${file%.*}.js" "await" "/*await */" + replace "${file%.*}.js" " #" "// #" + replace "${file%.*}.js" "this.#" "/*this.#*/" done echo "----------------------------" @@ -55,7 +57,9 @@ for file in $files; do replace "$file" "/*async */" "async " replace "$file" "^/*export*/" "export" replace "$file" "^/*export default*/" "export default" + replace "$file" '.mjs"*/' '.mjs"' replace "$file" "^/*import" "import" replace "$file" "^/*export" "export" - replace "$file" '.mjs"*/$' '.mjs"' + replace "$file" "// #" " #" + replace "$file" "/*this.#*/" "this.#" done From bd346240bdbd9feaf0cabda43b39b23f1a8ebc9d Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Wed, 9 Oct 2024 18:30:49 +0000 Subject: [PATCH 014/104] Translated using Weblate (Spanish) Currently translated at 100.0% (269 of 269 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/ --- assets/i18n/lp_es.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/i18n/lp_es.ts b/assets/i18n/lp_es.ts index 14dd724..ef79648 100644 --- a/assets/i18n/lp_es.ts +++ b/assets/i18n/lp_es.ts @@ -1342,7 +1342,7 @@ Expresión evaluada: %3 Could not load file: - + No se pudo cargar el archivo: Could not save file: From af2950c3d21b6f12ddab60d4bde74875a0e9519a Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 10 Oct 2024 06:49:14 +0200 Subject: [PATCH 015/104] Starting Settings modules + implemented basic events for ECMAScript <=> Qt compat. --- common/src/events.mjs | 96 ++++++++++++++++++ common/src/lib/polyfills/js.mjs | 4 +- common/src/module/common.mjs | 4 +- common/src/module/interface.mjs | 4 +- common/src/module/settings.mjs | 173 ++++++++++++++++++++++++++++++++ 5 files changed, 276 insertions(+), 5 deletions(-) create mode 100644 common/src/events.mjs create mode 100644 common/src/module/settings.mjs diff --git a/common/src/events.mjs b/common/src/events.mjs new file mode 100644 index 0000000..f1ec970 --- /dev/null +++ b/common/src/events.mjs @@ -0,0 +1,96 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * We do not inherit the DOM's Event, because not only the DOM part is unnecessary, + * but also because it does not exist within Qt environments. + */ + + +export class BaseEvent { + /** + * @property {string} name - Name of the event. + */ + constructor(name) { + this.name = name + } +} + + +/** + * Base class for all classes which can emit events. + */ +export class BaseEventEmitter { + static emits = [] + + /** @type {Record} */ + #listeners = {} + + constructor() { + for(const eventType of this.constructor.emits) { + this.#listeners[eventType] = new Set() + } + } + + /** + * Adds a listener to an event that can be emitted by this object. + * + * @param {string} eventType - Name of the event to listen to. Throws an error if this object does not emit this kind of event. + * @param {function(BaseEvent)} eventListener - The function to be called back when the event is emitted. + */ + addEventListener(eventType, eventListener) { + if(!this.emits.includes(eventType)) { + const className = this.constructor.name + const eventTypes = this.constructor.emits.join(", ") + throw new Error(`Cannot listen to unknown event ${eventType} in class ${className}. ${className} only emits: ${eventTypes}`) + } + if(!this.#listeners[eventType].has(eventListener)) + this.#listeners[eventType].add(eventListener) + } + + /** + * Remvoes a listener from an event that can be emitted by this object. + * + * @param {string} eventType - Name of the event that was listened to. Throws an error if this object does not emit this kind of event. + * @param {function(BaseEvent)} eventListener - The function previously registered as a listener. + * @returns {boolean} True if the listener was removed, false if it was not found. + */ + removeEventListener(eventType, eventListener) { + if(!this.emits.includes(eventType)) { + const className = this.constructor.name + const eventTypes = this.constructor.emits.join(", ") + throw new Error(`Cannot listen to unknown event ${eventType} in class ${className}. ${className} only emits: ${eventTypes}`) + } + return this.#listeners[eventType].delete(eventListener) + + } + + /** + * Emits an event to all of its listeners. + * + * @param {BaseEvent} e + */ + emit(e) { + if(!(e instanceof BaseEvent)) + throw new Error("Cannot emit non event object.") + if(!this.emits.includes(e.name)) + throw new Error(`Cannot emit event '${e.name}' from class ${this.constructor.name}. ${this.constructor.name} can only emits: ${this.constructor.emits.join(", ")}.`) + for(const listener of this.#listeners[e.name]) + listener(e) + } +} diff --git a/common/src/lib/polyfills/js.mjs b/common/src/lib/polyfills/js.mjs index 43ed375..9bcf80c 100644 --- a/common/src/lib/polyfills/js.mjs +++ b/common/src/lib/polyfills/js.mjs @@ -1,4 +1,4 @@ -/** +/*! * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 * @@ -123,4 +123,4 @@ for(const [year, entries] of Object.entries(polyfills)) { for(const [context, functionName, polyfill] of entries.filter(x => x[0][x[1]] === undefined)) { context[functionName] = polyfill } -} \ No newline at end of file +} diff --git a/common/src/module/common.mjs b/common/src/module/common.mjs index 5fc9387..bdca62f 100644 --- a/common/src/module/common.mjs +++ b/common/src/module/common.mjs @@ -17,6 +17,7 @@ */ import { Interface } from "./interface.mjs" +import { BaseEventEmitter } from "../events.mjs" // Define Modules interface before they are imported. globalThis.Modules = globalThis.Modules || {} @@ -24,7 +25,7 @@ globalThis.Modules = globalThis.Modules || {} /** * Base class for global APIs in runtime. */ -export class Module { +export class Module extends BaseEventEmitter { /** @type {string} */ #name /** @type {Object.} */ @@ -36,6 +37,7 @@ export class Module { * @param {Object.} initializationParameters - List of parameters for the initialize function. */ constructor(name, initializationParameters = {}) { + super() console.log(`Loading module ${name}...`) this.#name = name this.#initializationParameters = initializationParameters diff --git a/common/src/module/interface.mjs b/common/src/module/interface.mjs index 9273c8f..f6e5a13 100644 --- a/common/src/module/interface.mjs +++ b/common/src/module/interface.mjs @@ -1,4 +1,4 @@ -/*! +/** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * * @author Ad5001 @@ -184,4 +184,4 @@ export class HelperInterface extends Interface { * @returns {string} the loaded data - just JSON encoded, requires the "LPFv1" mime to be stripped */ load = FUNCTION -} \ No newline at end of file +} diff --git a/common/src/module/settings.mjs b/common/src/module/settings.mjs new file mode 100644 index 0000000..4487dde --- /dev/null +++ b/common/src/module/settings.mjs @@ -0,0 +1,173 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import { Module } from "./common.mjs" +import { BaseEvent } from "../events.mjs" + + +/** + * Base event for when a setting was changed. + */ +class ChangedEvent extends BaseEvent { + /** + * + * @param {string} property - Name of the property that was chagned + * @param {string|number|boolean} oldValue - Old value of the property + * @param {string|number|boolean} newValue - Current (new) value of the property + * @param {boolean} byUser - True if the user is at the source of the change in the setting. + */ + constructor(property, oldValue, newValue, byUser) { + super("changed") + + this.property = property + this.oldValue = oldValue + this.newValue = newValue + this.byUser = byUser + } +} + +/** + * Module for graph settings. + */ +class SettingsAPI extends Module { + static emits = ["changed"] + + #properties = new Map([ + ['xzoom', 100], + ['yzoom', 10], + ['xmin', .5], + ['ymax', 25], + ['xaxisstep', "4"], + ['yaxisstep', "4"], + ['xlabel', ""], + ['ylabel', ""], + ['linewidth', 1], + ['textsize', 18], + ['logscalex', true], + ['showxgrad', true], + ['showygrad', true], + ]) + + constructor() { + super("Settings", { + helper: HelperInterface + }) + } + + initialize({ helper }) { + super.initialize({ helper }) + // Initialize default values. + for(const key of this.#properties.keys()) { + switch(typeof this.#properties.get(key)) { + case 'boolean': + this.set(key, helper.getSettingBool(key), false) + break + case 'number': + this.set(key, helper.getSettingInt(key), false) + break + case 'string': + this.set(key, helper.getSetting(key), false) + break + } + } + } + + /** + * Sets a setting to a given value + * + * @param {boolean} byUser - Set to true if the user is at the origin of this change. + */ + set(property, value, byUser) { + if(!this.#properties.has(property)) + throw new Error(`Property ${property} is not a setting.`) + const oldValue = this.#properties.get(property) + const propType = typeof oldValue + if(propType !== typeof value) + throw new Error(`Value of ${property} must be a ${propType}.`) + this.#properties.set(property, value) + this.emit(new ChangedEvent(property, oldValue, value, byUser === true)) + } + + /** + * Zoom on the x axis of the diagram. + * @returns {number} + */ + get xzoom() { return this.#properties.get("xzoom"); } + /** + * Zoom on the y axis of the diagram. + * @returns {number} + */ + get yzoom() { return this.#properties.get("yzoom"); } + /** + * Minimum x of the diagram. + * @returns {number} + */ + get xmin() { return this.#properties.get("xmin"); } + /** + * Maximum y of the diagram. + * @returns {number} + */ + get ymax() { return this.#properties.get("ymax"); } + /** + * Step of the x axis graduation (expression). + * @note Only available in non-logarithmic mode. + * @returns {string} + */ + get xaxisstep() { return this.#properties.get("xaxisstep"); } + /** + * Step of the y axis graduation (expression). + * @returns {string} + */ + get yaxisstep() { return this.#properties.get("yaxisstep"); } + /** + * Label used on the x axis. + * @returns {string} + */ + get xlabel() { return this.#properties.get("xlabel"); } + /** + * Label used on the y axis. + * @returns {string} + */ + get ylabel() { return this.#properties.get("ylabel"); } + /** + * Width of lines that will be drawn into the canvas. + * @returns {number} + */ + get linewidth() { return this.#properties.get("linewidth"); } + /** + * Font size of the text that will be drawn into the canvas. + * @returns {number} + */ + get textsize() { return this.#properties.get("textsize"); } + /** + * true if the canvas should be in logarithmic mode, false otherwise. + * @returns {boolean} + */ + get logscalex() { return this.#properties.get("logscalex"); } + /** + * true if the x graduation should be shown, false otherwise. + * @returns {boolean} + */ + get showxgrad() { return this.#properties.get("showxgrad"); } + /** + * true if the y graduation should be shown, false otherwise. + * @returns {boolean} + */ + get showygrad() { return this.#properties.get("showygrad"); } + +} From d1ac70a946700b2193e67f2617f151722dcbfb0c Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 10 Oct 2024 19:15:46 +0200 Subject: [PATCH 016/104] Switching a lot of stuff to new Settings module + Fixing a bug that did not load the showygrad setting properly. --- common/src/events.mjs | 13 ++- common/src/module/canvas.mjs | 27 +++--- common/src/module/index.mjs | 2 + common/src/module/interface.mjs | 2 +- common/src/module/io.mjs | 66 +++++++------ common/src/module/settings.mjs | 83 +++++++++-------- common/src/utils.mjs | 13 +++ .../LogarithmPlotter/LogGraphCanvas.qml | 93 +------------------ .../LogarithmPlotter/LogarithmPlotter.qml | 14 --- .../Setting/ExpressionEditor.qml | 16 ++-- .../ViewPositionChangeOverlay.qml | 48 +++++----- 11 files changed, 148 insertions(+), 229 deletions(-) diff --git a/common/src/events.mjs b/common/src/events.mjs index f1ec970..bed4dea 100644 --- a/common/src/events.mjs +++ b/common/src/events.mjs @@ -38,7 +38,7 @@ export class BaseEvent { export class BaseEventEmitter { static emits = [] - /** @type {Record} */ + /** @type {Record>} */ #listeners = {} constructor() { @@ -54,7 +54,7 @@ export class BaseEventEmitter { * @param {function(BaseEvent)} eventListener - The function to be called back when the event is emitted. */ addEventListener(eventType, eventListener) { - if(!this.emits.includes(eventType)) { + if(!this.constructor.emits.includes(eventType)) { const className = this.constructor.name const eventTypes = this.constructor.emits.join(", ") throw new Error(`Cannot listen to unknown event ${eventType} in class ${className}. ${className} only emits: ${eventTypes}`) @@ -71,7 +71,7 @@ export class BaseEventEmitter { * @returns {boolean} True if the listener was removed, false if it was not found. */ removeEventListener(eventType, eventListener) { - if(!this.emits.includes(eventType)) { + if(!this.constructor.emits.includes(eventType)) { const className = this.constructor.name const eventTypes = this.constructor.emits.join(", ") throw new Error(`Cannot listen to unknown event ${eventType} in class ${className}. ${className} only emits: ${eventTypes}`) @@ -88,8 +88,11 @@ export class BaseEventEmitter { emit(e) { if(!(e instanceof BaseEvent)) throw new Error("Cannot emit non event object.") - if(!this.emits.includes(e.name)) - throw new Error(`Cannot emit event '${e.name}' from class ${this.constructor.name}. ${this.constructor.name} can only emits: ${this.constructor.emits.join(", ")}.`) + if(!this.constructor.emits.includes(e.name)) { + const className = this.constructor.name + const eventTypes = this.constructor.emits.join(", ") + throw new Error(`Cannot emit event '${e.name}' from class ${className}. ${className} can only emit: ${eventTypes}`) + } for(const listener of this.#listeners[e.name]) listener(e) } diff --git a/common/src/module/canvas.mjs b/common/src/module/canvas.mjs index 2aa14ad..5d42f5e 100644 --- a/common/src/module/canvas.mjs +++ b/common/src/module/canvas.mjs @@ -23,6 +23,7 @@ import { Expression } from "../math/index.mjs" import Latex from "./latex.mjs" import Objects from "./objects.mjs" import History from "./history.mjs" +import Settings from "./settings.mjs" class CanvasAPI extends Module { /** @type {CanvasInterface} */ @@ -84,7 +85,7 @@ class CanvasAPI extends Module { */ get xmin() { if(!this.initialized) throw new Error("Attempting xmin before initialize!") - return this.#canvas.xmin + return Settings.xmin } /** @@ -93,7 +94,7 @@ class CanvasAPI extends Module { */ get xzoom() { if(!this.initialized) throw new Error("Attempting xzoom before initialize!") - return this.#canvas.xzoom + return Settings.xzoom } /** @@ -102,7 +103,7 @@ class CanvasAPI extends Module { */ get ymax() { if(!this.initialized) throw new Error("Attempting ymax before initialize!") - return this.#canvas.ymax + return Settings.ymax } /** @@ -111,7 +112,7 @@ class CanvasAPI extends Module { */ get yzoom() { if(!this.initialized) throw new Error("Attempting yzoom before initialize!") - return this.#canvas.yzoom + return Settings.yzoom } /** @@ -120,7 +121,7 @@ class CanvasAPI extends Module { */ get xlabel() { if(!this.initialized) throw new Error("Attempting xlabel before initialize!") - return this.#canvas.xlabel + return Settings.xlabel } /** @@ -129,7 +130,7 @@ class CanvasAPI extends Module { */ get ylabel() { if(!this.initialized) throw new Error("Attempting ylabel before initialize!") - return this.#canvas.ylabel + return Settings.ylabel } /** @@ -138,7 +139,7 @@ class CanvasAPI extends Module { */ get linewidth() { if(!this.initialized) throw new Error("Attempting linewidth before initialize!") - return this.#canvas.linewidth + return Settings.linewidth } /** @@ -147,7 +148,7 @@ class CanvasAPI extends Module { */ get textsize() { if(!this.initialized) throw new Error("Attempting textsize before initialize!") - return this.#canvas.textsize + return Settings.textsize } /** @@ -156,7 +157,7 @@ class CanvasAPI extends Module { */ get logscalex() { if(!this.initialized) throw new Error("Attempting logscalex before initialize!") - return this.#canvas.logscalex + return Settings.logscalex } /** @@ -165,7 +166,7 @@ class CanvasAPI extends Module { */ get showxgrad() { if(!this.initialized) throw new Error("Attempting showxgrad before initialize!") - return this.#canvas.showxgrad + return Settings.showxgrad } /** @@ -174,7 +175,7 @@ class CanvasAPI extends Module { */ get showygrad() { if(!this.initialized) throw new Error("Attempting showygrad before initialize!") - return this.#canvas.showygrad + return Settings.showygrad } /** @@ -237,9 +238,9 @@ class CanvasAPI extends Module { * @private */ _computeAxes() { - let exprY = new Expression(`x*(${this.#canvas.yaxisstep})`) + let exprY = new Expression(`x*(${Settings.yaxisstep})`) let y1 = exprY.execute(1) - let exprX = new Expression(`x*(${this.#canvas.xaxisstep})`) + let exprX = new Expression(`x*(${Settings.xaxisstep})`) let x1 = exprX.execute(1) this.axesSteps = { x: { diff --git a/common/src/module/index.mjs b/common/src/module/index.mjs index fe2e8d9..2530a00 100644 --- a/common/src/module/index.mjs +++ b/common/src/module/index.mjs @@ -17,6 +17,7 @@ */ import Objects from "./objects.mjs" +import Settings from "./settings.mjs" import ExprParser from "./expreval.mjs" import Latex from "./latex.mjs" import History from "./history.mjs" @@ -26,6 +27,7 @@ import Preferences from "./preferences.mjs" export default { Objects, + Settings, ExprParser, Latex, History, diff --git a/common/src/module/interface.mjs b/common/src/module/interface.mjs index f6e5a13..606ec4d 100644 --- a/common/src/module/interface.mjs +++ b/common/src/module/interface.mjs @@ -78,7 +78,7 @@ export class SettingsInterface extends Interface { showygrad = BOOLEAN } -export class CanvasInterface extends SettingsInterface { +export class CanvasInterface extends Interface { imageLoaders = OBJECT /** @type {function(string): CanvasRenderingContext2D} */ getContext = FUNCTION diff --git a/common/src/module/io.mjs b/common/src/module/io.mjs index e32f2cf..183ae01 100644 --- a/common/src/module/io.mjs +++ b/common/src/module/io.mjs @@ -20,22 +20,20 @@ import { Module } from "./common.mjs" import Objects from "./objects.mjs" import History from "./history.mjs" import Canvas from "./canvas.mjs" +import Settings from "./settings.mjs" import { DialogInterface, RootInterface, SettingsInterface } from "./interface.mjs" class IOAPI extends Module { /** @type {RootInterface} */ #rootElement - /** @type {SettingsInterface} */ - #settings /** @type {{show: function(string)}} */ #alert constructor() { super("IO", { alert: DialogInterface, - root: RootInterface, - settings: SettingsInterface + root: RootInterface }) /** * Path of the currently opened file. Empty if no file is opened. @@ -47,13 +45,11 @@ class IOAPI extends Module { /** * Initializes module with QML elements. * @param {RootInterface} root - * @param {SettingsInterface} settings * @param {{show: function(string)}} alert */ - initialize({ root, settings, alert }) { - super.initialize({ root, settings, alert }) + initialize({ root, alert }) { + super.initialize({ root, alert }) this.#rootElement = root - this.#settings = settings this.#alert = alert } @@ -75,19 +71,19 @@ class IOAPI extends Module { } } let settings = { - "xzoom": this.#settings.xzoom, - "yzoom": this.#settings.yzoom, - "xmin": this.#settings.xmin, - "ymax": this.#settings.ymax, - "xaxisstep": this.#settings.xaxisstep, - "yaxisstep": this.#settings.yaxisstep, - "xaxislabel": this.#settings.xlabel, - "yaxislabel": this.#settings.ylabel, - "logscalex": this.#settings.logscalex, - "linewidth": this.#settings.linewidth, - "showxgrad": this.#settings.showxgrad, - "showygrad": this.#settings.showygrad, - "textsize": this.#settings.textsize, + "xzoom": Settings.xzoom, + "yzoom": Settings.yzoom, + "xmin": Settings.xmin, + "ymax": Settings.ymax, + "xaxisstep": Settings.xaxisstep, + "yaxisstep": Settings.yaxisstep, + "xaxislabel": Settings.xlabel, + "yaxislabel": Settings.ylabel, + "logscalex": Settings.logscalex, + "linewidth": Settings.linewidth, + "showxgrad": Settings.showxgrad, + "showygrad": Settings.showygrad, + "textsize": Settings.textsize, "history": History.serialize(), "width": this.#rootElement.width, "height": this.#rootElement.height, @@ -113,24 +109,24 @@ class IOAPI extends Module { if(data.hasOwnProperty("type") && data["type"] === "logplotv1") { History.clear() // Importing settings - this.#settings.saveFilename = filename - this.#settings.xzoom = parseFloat(data["xzoom"]) || 100 - this.#settings.yzoom = parseFloat(data["yzoom"]) || 10 - this.#settings.xmin = parseFloat(data["xmin"]) || 5 / 10 - this.#settings.ymax = parseFloat(data["ymax"]) || 24 - this.#settings.xaxisstep = data["xaxisstep"] || "4" - this.#settings.yaxisstep = data["yaxisstep"] || "4" - this.#settings.xlabel = data["xaxislabel"] || "" - this.#settings.ylabel = data["yaxislabel"] || "" - this.#settings.logscalex = data["logscalex"] === true + Settings.set("saveFilename", filename, false) + Settings.set("xzoom", parseFloat(data["xzoom"]) || 100, false) + Settings.set("yzoom", parseFloat(data["yzoom"]) || 10, false) + Settings.set("xmin", parseFloat(data["xmin"]) || 5 / 10, false) + Settings.set("ymax", parseFloat(data["ymax"]) || 24, false) + Settings.set("xaxisstep", data["xaxisstep"] || "4", false) + Settings.set("yaxisstep", data["yaxisstep"] || "4", false) + Settings.set("xlabel", data["xaxislabel"] || "", false) + Settings.set("ylabel", data["yaxislabel"] || "", false) + Settings.set("logscalex", data["logscalex"] === true, false) if("showxgrad" in data) - this.#settings.showxgrad = data["showxgrad"] + Settings.set("showxgrad", data["showxgrad"], false) if("showygrad" in data) - this.#settings.textsize = data["showygrad"] + Settings.set("showygrad", data["showygrad"], false) if("linewidth" in data) - this.#settings.linewidth = data["linewidth"] + Settings.set("linewidth", data["linewidth"], false) if("textsize" in data) - this.#settings.textsize = data["textsize"] + Settings.set("textsize", data["textsize"], false) this.#rootElement.height = parseFloat(data["height"]) || 500 this.#rootElement.width = parseFloat(data["width"]) || 1000 diff --git a/common/src/module/settings.mjs b/common/src/module/settings.mjs index 4487dde..4d79ce2 100644 --- a/common/src/module/settings.mjs +++ b/common/src/module/settings.mjs @@ -18,6 +18,7 @@ import { Module } from "./common.mjs" import { BaseEvent } from "../events.mjs" +import { HelperInterface } from "./interface.mjs" /** @@ -48,19 +49,20 @@ class SettingsAPI extends Module { static emits = ["changed"] #properties = new Map([ - ['xzoom', 100], - ['yzoom', 10], - ['xmin', .5], - ['ymax', 25], - ['xaxisstep', "4"], - ['yaxisstep', "4"], - ['xlabel', ""], - ['ylabel', ""], - ['linewidth', 1], - ['textsize', 18], - ['logscalex', true], - ['showxgrad', true], - ['showygrad', true], + ["saveFilename", ""], + ["xzoom", 100], + ["yzoom", 10], + ["xmin", .5], + ["ymax", 25], + ["xaxisstep", "4"], + ["yaxisstep", "4"], + ["xlabel", ""], + ["ylabel", ""], + ["linewidth", 1], + ["textsize", 18], + ["logscalex", true], + ["showxgrad", true], + ["showygrad", true] ]) constructor() { @@ -74,14 +76,14 @@ class SettingsAPI extends Module { // Initialize default values. for(const key of this.#properties.keys()) { switch(typeof this.#properties.get(key)) { - case 'boolean': - this.set(key, helper.getSettingBool(key), false) + case "boolean": + this.set(key, helper.getSettingBool("default_graph."+key), false) break - case 'number': - this.set(key, helper.getSettingInt(key), false) + case "number": + this.set(key, helper.getSettingInt("default_graph."+key), false) break - case 'string': - this.set(key, helper.getSetting(key), false) + case "string": + this.set(key, helper.getSetting("default_graph."+key), false) break } } @@ -89,16 +91,20 @@ class SettingsAPI extends Module { /** * Sets a setting to a given value - * - * @param {boolean} byUser - Set to true if the user is at the origin of this change. + * + * @param {string} property + * @param {string|number|boolean} value + * @param {boolean} byUser - Set to true if the user is at the origin of this change. */ set(property, value, byUser) { - if(!this.#properties.has(property)) + if(!this.#properties.has(property)) { throw new Error(`Property ${property} is not a setting.`) + } const oldValue = this.#properties.get(property) + console.debug("Setting", property, "from", oldValue, "to", value, `(${typeof value}, ${byUser})`) const propType = typeof oldValue if(propType !== typeof value) - throw new Error(`Value of ${property} must be a ${propType}.`) + throw new Error(`Value of ${property} must be a ${propType} (${typeof value} provided).`) this.#properties.set(property, value) this.emit(new ChangedEvent(property, oldValue, value, byUser === true)) } @@ -107,67 +113,70 @@ class SettingsAPI extends Module { * Zoom on the x axis of the diagram. * @returns {number} */ - get xzoom() { return this.#properties.get("xzoom"); } + get xzoom() { return this.#properties.get("xzoom") } /** * Zoom on the y axis of the diagram. * @returns {number} */ - get yzoom() { return this.#properties.get("yzoom"); } + get yzoom() { return this.#properties.get("yzoom") } /** * Minimum x of the diagram. * @returns {number} */ - get xmin() { return this.#properties.get("xmin"); } + get xmin() { return this.#properties.get("xmin") } /** * Maximum y of the diagram. * @returns {number} */ - get ymax() { return this.#properties.get("ymax"); } + get ymax() { return this.#properties.get("ymax") } /** * Step of the x axis graduation (expression). * @note Only available in non-logarithmic mode. * @returns {string} */ - get xaxisstep() { return this.#properties.get("xaxisstep"); } + get xaxisstep() { return this.#properties.get("xaxisstep") } /** * Step of the y axis graduation (expression). * @returns {string} */ - get yaxisstep() { return this.#properties.get("yaxisstep"); } + get yaxisstep() { return this.#properties.get("yaxisstep") } /** * Label used on the x axis. * @returns {string} */ - get xlabel() { return this.#properties.get("xlabel"); } + get xlabel() { return this.#properties.get("xlabel") } /** * Label used on the y axis. * @returns {string} */ - get ylabel() { return this.#properties.get("ylabel"); } + get ylabel() { return this.#properties.get("ylabel") } /** * Width of lines that will be drawn into the canvas. * @returns {number} */ - get linewidth() { return this.#properties.get("linewidth"); } + get linewidth() { return this.#properties.get("linewidth") } /** * Font size of the text that will be drawn into the canvas. * @returns {number} */ - get textsize() { return this.#properties.get("textsize"); } + get textsize() { return this.#properties.get("textsize") } /** * true if the canvas should be in logarithmic mode, false otherwise. * @returns {boolean} */ - get logscalex() { return this.#properties.get("logscalex"); } + get logscalex() { return this.#properties.get("logscalex") } /** * true if the x graduation should be shown, false otherwise. * @returns {boolean} */ - get showxgrad() { return this.#properties.get("showxgrad"); } + get showxgrad() { return this.#properties.get("showxgrad") } /** * true if the y graduation should be shown, false otherwise. * @returns {boolean} */ - get showygrad() { return this.#properties.get("showygrad"); } - + get showygrad() { return this.#properties.get("showygrad") } } + +Modules.Settings = Modules.Settings || new SettingsAPI() +export default Modules.Settings + diff --git a/common/src/utils.mjs b/common/src/utils.mjs index 4f6b0c5..094147d 100644 --- a/common/src/utils.mjs +++ b/common/src/utils.mjs @@ -35,6 +35,19 @@ String.prototype.removeEnclosure = function() { return this.substring(1, this.length - 1) } +/** + * Rounds to a certain number of decimal places. + * From https://stackoverflow.com/a/48764436 + * + * @param {number} decimalPlaces + * @return {number} + */ +Number.prototype.toDecimalPrecision = function(decimalPlaces = 0) { + const p = Math.pow(10, decimalPlaces); + const n = (this * p) * (1 + Number.EPSILON); + return Math.round(n) / p; +} + const powerpos = { "-": "⁻", "+": "⁺", diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml index 38d05be..07b6002 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml @@ -30,104 +30,15 @@ import Qt.labs.platform as Native */ Canvas { id: canvas - anchors.top: separator.bottom + anchors.top: parent.top anchors.left: parent.left height: parent.height - 90 width: parent.width - - /*! - \qmlproperty double LogGraphCanvas::xmin - Minimum x of the diagram, provided from settings. - \sa Settings - */ - property double xmin: 0 - /*! - \qmlproperty double LogGraphCanvas::ymax - Maximum y of the diagram, provided from settings. - \sa Settings - */ - property double ymax: 0 - /*! - \qmlproperty double LogGraphCanvas::xzoom - Zoom on the x axis of the diagram, provided from settings. - \sa Settings - */ - property double xzoom: 10 - /*! - \qmlproperty double LogGraphCanvas::yzoom - Zoom on the y axis of the diagram, provided from settings. - \sa Settings - */ - property double yzoom: 10 - /*! - \qmlproperty string LogGraphCanvas::xaxisstep - Step of the x axis graduation, provided from settings. - \note: Only available in non-logarithmic mode. - \sa Settings - */ - property string xaxisstep: "4" - /*! - \qmlproperty string LogGraphCanvas::yaxisstep - Step of the y axis graduation, provided from settings. - \sa Settings - */ - property string yaxisstep: "4" - /*! - \qmlproperty string LogGraphCanvas::xlabel - Label used on the x axis, provided from settings. - \sa Settings - */ - property string xlabel: "" - /*! - \qmlproperty string LogGraphCanvas::ylabel - Label used on the y axis, provided from settings. - \sa Settings - */ - property string ylabel: "" - /*! - \qmlproperty double LogGraphCanvas::linewidth - Width of lines that will be drawn into the canvas, provided from settings. - \sa Settings - */ - property double linewidth: 1 - /*! - \qmlproperty double LogGraphCanvas::textsize - Font size of the text that will be drawn into the canvas, provided from settings. - \sa Settings - */ - property double textsize: 14 - /*! - \qmlproperty bool LogGraphCanvas::logscalex - true if the canvas should be in logarithmic mode, false otherwise. - Provided from settings. - \sa Settings - */ - property bool logscalex: false - /*! - \qmlproperty bool LogGraphCanvas::showxgrad - true if the x graduation should be shown, false otherwise. - Provided from settings. - \sa Settings - */ - property bool showxgrad: false - /*! - \qmlproperty bool LogGraphCanvas::showygrad - true if the y graduation should be shown, false otherwise. - Provided from settings. - \sa Settings - */ - property bool showygrad: false - /*! \qmlproperty var LogGraphCanvas::imageLoaders Dictionary of format {image: [callback.image data]} containing data for defered image loading. */ property var imageLoaders: {} - /*! - \qmlproperty var LogGraphCanvas::ctx - Cache for the 2D context so that it may be used asynchronously. - */ - property var ctx Component.onCompleted: { imageLoaders = {} @@ -155,7 +66,7 @@ Canvas { Object.keys(imageLoaders).forEach((key) => { if(isImageLoaded(key)) { // Calling callback - imageLoaders[key][0](canvas, ctx, imageLoaders[key][1]) + imageLoaders[key][0](imageLoaders[key][1]) delete imageLoaders[key] } }) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml index 8545153..d6b2c3f 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml @@ -145,20 +145,6 @@ ApplicationWindow { width: sidebar.inPortrait ? parent.width : parent.width - sidebar.width//*sidebar.position x: sidebar.width//*sidebar.position - xmin: settings.xmin - ymax: settings.ymax - xzoom: settings.xzoom - yzoom: settings.yzoom - xlabel: settings.xlabel - ylabel: settings.ylabel - yaxisstep: settings.yaxisstep - xaxisstep: settings.xaxisstep - logscalex: settings.logscalex - linewidth: settings.linewidth - textsize: settings.textsize - showxgrad: settings.showxgrad - showygrad: settings.showygrad - property bool firstDrawDone: false onPainted: if(!firstDrawDone) { diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml index afa3e09..a0c030a 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml @@ -175,17 +175,17 @@ Item { Icon { id: iconLabel anchors.top: parent.top - anchors.topMargin: icon == "" ? 0 : 3 - source: control.visible && icon != "" ? "../icons/" + control.icon : "" + anchors.topMargin: parent.icon == "" ? 0 : 3 + source: control.visible && parent.icon != "" ? "../icons/" + control.icon : "" width: height - height: icon == "" || !visible ? 0 : 24 + height: parent.icon == "" || !visible ? 0 : 24 color: sysPalette.windowText } Label { id: labelItem anchors.left: iconLabel.right - anchors.leftMargin: icon == "" ? 0 : 5 + anchors.leftMargin: parent.icon == "" ? 0 : 5 anchors.top: parent.top height: parent.height width: Math.max(85, implicitWidth) @@ -231,8 +231,8 @@ Item { onEditingFinished: { if(insertButton.focus || insertPopup.focus) return let value = text - if(value != "" && value.toString() != defValue) { - let expr = parse(value) + if(value != "" && value.toString() != parent.defValue) { + let expr = parent.parse(value) if(expr != null) { control.changed(expr) defValue = expr.toEditableString() @@ -280,10 +280,10 @@ Item { acPopupContent.itemSelected = 0 - if(event.text in openAndCloseMatches && autoClosing) { + if(event.text in parent.openAndCloseMatches && autoClosing) { let start = selectionStart insert(selectionStart, event.text) - insert(selectionEnd, openAndCloseMatches[event.text]) + insert(selectionEnd, parent.openAndCloseMatches[event.text]) cursorPosition = start+1 event.accepted = true } diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ViewPositionChangeOverlay.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ViewPositionChangeOverlay.qml index e8514d4..7a7072b 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ViewPositionChangeOverlay.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ViewPositionChangeOverlay.qml @@ -17,8 +17,6 @@ */ import QtQuick -import QtQuick.Controls -import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting /*! \qmltype ViewPositionChangeOverlay @@ -81,7 +79,7 @@ Item { property int prevY /*! \qmlproperty double ViewPositionChangeOverlay::baseZoomMultiplier - How much should the zoom be mutliplied/scrolled by for one scroll step (120° on the mouse wheel). + How much should the zoom be multiplied/scrolled by for one scroll step (120° on the mouse wheel). */ property double baseZoomMultiplier: 0.1 @@ -91,15 +89,15 @@ Item { cursorShape: pressed ? Qt.ClosedHandCursor : Qt.OpenHandCursor property int positionChangeTimer: 0 - function updatePosition(deltaX, deltaY) { + function updatePosition(deltaX, deltaY, isEnd) { const unauthorized = [NaN, Infinity, -Infinity] - const xmin = (Modules.Canvas.px2x(Modules.Canvas.x2px(settingsInstance.xmin)-deltaX)) - const ymax = settingsInstance.ymax + deltaY/canvas.yzoom + const xmin = (Modules.Canvas.px2x(Modules.Canvas.x2px(Modules.Settings.xmin)-deltaX)) + const ymax = Modules.Settings.ymax + deltaY/Modules.Settings.yzoom if(!unauthorized.includes(xmin)) - settingsInstance.xmin = xmin + Modules.Settings.set("xmin", xmin, isEnd) if(!unauthorized.includes(ymax)) - settingsInstance.ymax = ymax.toFixed(4) - settingsInstance.changed() + Modules.Settings.set("ymax", ymax.toDecimalPrecision(6), isEnd) + Modules.Canvas.requestPaint() parent.positionChanged(deltaX, deltaY) } @@ -113,9 +111,9 @@ Item { onPositionChanged: function(mouse) { positionChangeTimer++ if(positionChangeTimer == 3) { - let deltaX = mouse.x - prevX - let deltaY = mouse.y - prevY - updatePosition(deltaX, deltaY) + let deltaX = mouse.x - parent.prevX + let deltaY = mouse.y - parent.prevY + updatePosition(deltaX, deltaY, false) prevX = mouse.x prevY = mouse.y positionChangeTimer = 0 @@ -123,35 +121,35 @@ Item { } onReleased: function(mouse) { - let deltaX = mouse.x - prevX - let deltaY = mouse.y - prevY - updatePosition(deltaX, deltaY) + let deltaX = mouse.x - parent.prevX + let deltaY = mouse.y - parent.prevY + updatePosition(deltaX, deltaY, true) parent.endPositionChange(deltaX, deltaY) } onWheel: function(wheel) { // Scrolling let scrollSteps = Math.round(wheel.angleDelta.y / 120) - let zoomMultiplier = Math.pow(1+baseZoomMultiplier, Math.abs(scrollSteps)) + let zoomMultiplier = Math.pow(1+parent.baseZoomMultiplier, Math.abs(scrollSteps)) // Avoid floating-point rounding errors by removing the zoom *after* - let xZoomDelta = (settingsInstance.xzoom*zoomMultiplier - settingsInstance.xzoom) - let yZoomDelta = (settingsInstance.yzoom*zoomMultiplier - settingsInstance.yzoom) + let xZoomDelta = (Modules.Settings.xzoom*zoomMultiplier - Modules.Settings.xzoom) + let yZoomDelta = (Modules.Settings.yzoom*zoomMultiplier - Modules.Settings.yzoom) if(scrollSteps < 0) { // Negative scroll xZoomDelta *= -1 yZoomDelta *= -1 } - let newXZoom = (settingsInstance.xzoom+xZoomDelta).toFixed(0) - let newYZoom = (settingsInstance.yzoom+yZoomDelta).toFixed(0) + let newXZoom = (Modules.Settings.xzoom+xZoomDelta).toDecimalPrecision(0) + let newYZoom = (Modules.Settings.yzoom+yZoomDelta).toDecimalPrecision(0) // Check if we need to have more precision if(newXZoom < 10) - newXZoom = (settingsInstance.xzoom+xZoomDelta).toFixed(4) + newXZoom = (Modules.Settings.xzoom+xZoomDelta).toDecimalPrecision(4) if(newYZoom < 10) - newYZoom = (settingsInstance.yzoom+yZoomDelta).toFixed(4) + newYZoom = (Modules.Settings.yzoom+yZoomDelta).toDecimalPrecision(4) if(newXZoom > 0.5) - settingsInstance.xzoom = newXZoom + Modules.Settings.set("xzoom", newXZoom) if(newYZoom > 0.5) - settingsInstance.yzoom = newYZoom - settingsInstance.changed() + Modules.Settings.set("yzoom", newYZoom) + Modules.Canvas.requestPaint() } } } From 52f859349ac9b1ac6d3e26e8b2a1c795b069958f Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 10 Oct 2024 23:28:25 +0200 Subject: [PATCH 017/104] Converting actual settings to new Settings module. --- common/src/events.mjs | 5 +- common/src/module/io.mjs | 2 +- common/src/module/settings.mjs | 27 ++- common/src/preferences/default.mjs | 2 +- .../LogarithmPlotter/LogarithmPlotter.qml | 9 +- .../LogarithmPlotter/PickLocationOverlay.qml | 2 +- .../LogarithmPlotter/Setting/TextSetting.qml | 2 +- .../eu/ad5001/LogarithmPlotter/Settings.qml | 202 +++++++++++++----- 8 files changed, 176 insertions(+), 75 deletions(-) diff --git a/common/src/events.mjs b/common/src/events.mjs index bed4dea..4e95db6 100644 --- a/common/src/events.mjs +++ b/common/src/events.mjs @@ -53,7 +53,7 @@ export class BaseEventEmitter { * @param {string} eventType - Name of the event to listen to. Throws an error if this object does not emit this kind of event. * @param {function(BaseEvent)} eventListener - The function to be called back when the event is emitted. */ - addEventListener(eventType, eventListener) { + on(eventType, eventListener) { if(!this.constructor.emits.includes(eventType)) { const className = this.constructor.name const eventTypes = this.constructor.emits.join(", ") @@ -70,14 +70,13 @@ export class BaseEventEmitter { * @param {function(BaseEvent)} eventListener - The function previously registered as a listener. * @returns {boolean} True if the listener was removed, false if it was not found. */ - removeEventListener(eventType, eventListener) { + off(eventType, eventListener) { if(!this.constructor.emits.includes(eventType)) { const className = this.constructor.name const eventTypes = this.constructor.emits.join(", ") throw new Error(`Cannot listen to unknown event ${eventType} in class ${className}. ${className} only emits: ${eventTypes}`) } return this.#listeners[eventType].delete(eventListener) - } /** diff --git a/common/src/module/io.mjs b/common/src/module/io.mjs index 183ae01..0b4c6fa 100644 --- a/common/src/module/io.mjs +++ b/common/src/module/io.mjs @@ -62,7 +62,7 @@ class IOAPI extends Module { // Add extension if necessary if(["lpf"].indexOf(filename.split(".")[filename.split(".").length - 1]) === -1) filename += ".lpf" - this.saveFilename = filename + Settings.set("saveFilename", filename, false) let objs = {} for(let objType in Objects.currentObjects) { objs[objType] = [] diff --git a/common/src/module/settings.mjs b/common/src/module/settings.mjs index 4d79ce2..44a6593 100644 --- a/common/src/module/settings.mjs +++ b/common/src/module/settings.mjs @@ -48,6 +48,8 @@ class ChangedEvent extends BaseEvent { class SettingsAPI extends Module { static emits = ["changed"] + #nonConfigurable = ["saveFilename"] + #properties = new Map([ ["saveFilename", ""], ["xzoom", 100], @@ -75,16 +77,18 @@ class SettingsAPI extends Module { super.initialize({ helper }) // Initialize default values. for(const key of this.#properties.keys()) { - switch(typeof this.#properties.get(key)) { - case "boolean": - this.set(key, helper.getSettingBool("default_graph."+key), false) - break - case "number": - this.set(key, helper.getSettingInt("default_graph."+key), false) - break - case "string": - this.set(key, helper.getSetting("default_graph."+key), false) - break + if(!this.#nonConfigurable.includes(key)) { + switch(typeof this.#properties.get(key)) { + case "boolean": + this.set(key, helper.getSettingBool("default_graph."+key), false) + break + case "number": + this.set(key, helper.getSettingInt("default_graph."+key), false) + break + case "string": + this.set(key, helper.getSetting("default_graph."+key), false) + break + } } } } @@ -101,8 +105,9 @@ class SettingsAPI extends Module { throw new Error(`Property ${property} is not a setting.`) } const oldValue = this.#properties.get(property) - console.debug("Setting", property, "from", oldValue, "to", value, `(${typeof value}, ${byUser})`) const propType = typeof oldValue + if(byUser) + console.debug("Setting", property, "from", oldValue, "to", value, `(${typeof value}, ${byUser})`) if(propType !== typeof value) throw new Error(`Value of ${property} must be a ${propType} (${typeof value} provided).`) this.#properties.set(property, value) diff --git a/common/src/preferences/default.mjs b/common/src/preferences/default.mjs index 0fa9531..20d62e3 100644 --- a/common/src/preferences/default.mjs +++ b/common/src/preferences/default.mjs @@ -28,7 +28,7 @@ const XZOOM = new NumberSetting( const YZOOM = new NumberSetting( qsTranslate("Settings", "Y Zoom"), - "default_graph.xzoom", + "default_graph.yzoom", "yzoom", 0.1 ) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml index d6b2c3f..51abb46 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml @@ -42,7 +42,7 @@ ApplicationWindow { width: 1000 height: 500 color: sysPalette.window - title: "LogarithmPlotter " + (settings.saveFilename != "" ? " - " + settings.saveFilename.split('/').pop() : "") + (history.saved ? "" : "*") + title: "LogarithmPlotter" SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active } SystemPalette { id: sysPaletteIn; colorGroup: SystemPalette.Disabled } @@ -250,5 +250,12 @@ ApplicationWindow { Component.onCompleted: { Modules.IO.initialize({ root, settings, alert }) Modules.Latex.initialize({ latex: Latex, helper: Helper }) + Modules.Settings.on("changed", (evt) => { + if(evt.property === "saveFilename") { + const fileName = evt.newValue.split('/').pop().split('\\').pop() + if(fileName !== "") + title = `${fileName}` + } + }) } } diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml index 2fb45d4..680c310 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml @@ -285,7 +285,7 @@ Item { const axisX = Modules.Canvas.axesSteps.x.value const xpos = Modules.Canvas.px2x(picker.mouseX) if(snapToGridCheckbox.checked) { - if(canvas.logscalex) { + if(Modules.Settings.logscalex) { // Calculate the logged power let pow = Math.pow(10, Math.floor(Math.log10(xpos))) return pow*Math.round(xpos/pow) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml index b0a054a..3689dc1 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml @@ -37,7 +37,7 @@ Item { Emitted when the value of the text has been changed. The corresponding handler is \c onChanged. */ - signal changed(string newValue) + signal changed(var newValue) /*! \qmlproperty bool TextSetting::isInt diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml index 534556f..b440d07 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml @@ -121,11 +121,6 @@ ScrollView { \sa Settings */ property bool showygrad: Helper.getSettingBool('default_graph.showygrad') - /*! - \qmlproperty bool Settings::saveFilename - Path of the currently opened file. Empty if no file is opened. - */ - property string saveFilename: "" Column { spacing: 10 @@ -136,15 +131,18 @@ ScrollView { id: fdiag onAccepted: { var filePath = fdiag.currentFile.toString().substr(7) - settings.saveFilename = filePath + Modules.Settings.set("saveFilename", filePath) if(exportMode) { Modules.IO.saveDiagram(filePath) } else { Modules.IO.loadDiagram(filePath) - if(xAxisLabel.find(settings.xlabel) == -1) xAxisLabel.model.append({text: settings.xlabel}) - xAxisLabel.editText = settings.xlabel - if(yAxisLabel.find(settings.ylabel) == -1) yAxisLabel.model.append({text: settings.ylabel}) - yAxisLabel.editText = settings.ylabel + // Adding labels. + if(xAxisLabel.find(Modules.Settings.xlabel) === -1) + xAxisLabel.model.append({text: Modules.Settings.xlabel}) + xAxisLabel.editText = Modules.Settings.xlabel + if(yAxisLabel.find(Modules.Settings.ylabel) === -1) + yAxisLabel.model.append({text: Modules.Settings.ylabel}) + yAxisLabel.editText = Modules.Settings.ylabel } } } @@ -158,11 +156,16 @@ ScrollView { min: 0.1 icon: "settings/xzoom.svg" width: settings.settingWidth - value: settings.xzoom.toFixed(2) + onChanged: function(newValue) { - settings.xzoom = newValue + Modules.Settings.set("xzoom", newValue, true) settings.changed() } + + function update(newValue) { + value = Modules.Settings.xzoom.toFixed(2) + maxX.update() + } } Setting.TextSetting { @@ -173,11 +176,16 @@ ScrollView { label: qsTr("Y Zoom") icon: "settings/yzoom.svg" width: settings.settingWidth - value: settings.yzoom.toFixed(2) + onChanged: function(newValue) { - settings.yzoom = newValue + Modules.Settings.set("yzoom", newValue, true) settings.changed() } + + function update(newValue) { + value = Modules.Settings.yzoom.toFixed(2) + minY.update() + } } // Positioning the graph @@ -189,14 +197,18 @@ ScrollView { label: qsTr("Min X") icon: "settings/xmin.svg" width: settings.settingWidth - defValue: settings.xmin + onChanged: function(newValue) { - if(parseFloat(maxX.value) > newValue) { - settings.xmin = newValue - settings.changed() - } else { - alert.show("Minimum x value must be inferior to maximum.") - } + Modules.Settings.set("xmin", newValue, true) + settings.changed() + } + + function update(newValue) { + let newVal = Modules.Settings.xmin + if(newVal > 1e-5) + newVal = newVal.toDecimalPrecision(8) + value = newVal + maxX.update() } } @@ -208,11 +220,16 @@ ScrollView { label: qsTr("Max Y") icon: "settings/ymax.svg" width: settings.settingWidth - defValue: settings.ymax + onChanged: function(newValue) { - settings.ymax = newValue + Modules.Settings.set("ymax", newValue, true) settings.changed() } + + function update() { + value = Modules.Settings.ymax + minY.update() + } } Setting.TextSetting { @@ -223,15 +240,24 @@ ScrollView { label: qsTr("Max X") icon: "settings/xmax.svg" width: settings.settingWidth - defValue: Modules.Canvas.px2x(canvas.width).toFixed(2) + onChanged: function(xvaluemax) { - if(xvaluemax > settings.xmin) { - settings.xzoom = settings.xzoom * canvas.width/(Modules.Canvas.x2px(xvaluemax)) // Adjusting zoom to fit. = (end)/(px of current point) + if(xvaluemax > Modules.Settings.xmin) { + const newXZoom = Modules.Settings.xzoom * canvas.width/(Modules.Canvas.x2px(xvaluemax)) // Adjusting zoom to fit. = (end)/(px of current point) + Modules.Settings.set("xzoom", newXZoom, true) + zoomX.update() settings.changed() } else { alert.show("Maximum x value must be superior to minimum.") } } + + function update() { + let newVal = Modules.Canvas.px2x(canvas.width) + if(newVal > 1e-5) + newVal = newVal.toDecimalPrecision(8) + value = newVal + } } Setting.TextSetting { @@ -242,15 +268,21 @@ ScrollView { label: qsTr("Min Y") icon: "settings/ymin.svg" width: settings.settingWidth - defValue: Modules.Canvas.px2y(canvas.height).toFixed(2) + onChanged: function(yvaluemin) { if(yvaluemin < settings.ymax) { - settings.yzoom = settings.yzoom * canvas.height/(Modules.Canvas.y2px(yvaluemin)) // Adjusting zoom to fit. = (end)/(px of current point) + const newYZoom = Modules.Settings.yzoom * canvas.height/(Modules.Canvas.y2px(yvaluemin)) // Adjusting zoom to fit. = (end)/(px of current point) + Modules.Settings.set("yzoom", newYZoom, true) + zoomY.update() settings.changed() } else { alert.show("Minimum y value must be inferior to maximum.") } } + + function update() { + value = Modules.Canvas.px2y(canvas.height).toDecimalPrecision(8) + } } Setting.TextSetting { @@ -260,12 +292,16 @@ ScrollView { label: qsTr("X Axis Step") icon: "settings/xaxisstep.svg" width: settings.settingWidth - defValue: settings.xaxisstep - visible: !settings.logscalex + onChanged: function(newValue) { - settings.xaxisstep = newValue + Modules.Settings.set("xaxisstep", newValue, true) settings.changed() } + + function update() { + value = Modules.Settings.xaxisstep + visible = !Modules.Settings.logscalex + } } Setting.TextSetting { @@ -275,11 +311,13 @@ ScrollView { label: qsTr("Y Axis Step") icon: "settings/yaxisstep.svg" width: settings.settingWidth - defValue: settings.yaxisstep + onChanged: function(newValue) { - settings.yaxisstep = newValue + Modules.Settings.set("yaxisstep", newValue, true) settings.changed() } + + function update() { value = Modules.Settings.yaxisstep } } Setting.TextSetting { @@ -290,11 +328,13 @@ ScrollView { min: 1 icon: "settings/linewidth.svg" width: settings.settingWidth - defValue: settings.linewidth + onChanged: function(newValue) { - settings.linewidth = newValue + Modules.Settings.set("linewidth", newValue, true) settings.changed() } + + function update() { value = Modules.Settings.linewidth } } Setting.TextSetting { @@ -305,11 +345,13 @@ ScrollView { min: 1 icon: "settings/textsize.svg" width: settings.settingWidth - defValue: settings.textsize + onChanged: function(newValue) { - settings.textsize = newValue + Modules.Settings.set("textsize", newValue, true) settings.changed() } + + function update() { value = Modules.Settings.textsize } } Setting.ComboBoxSetting { @@ -318,24 +360,31 @@ ScrollView { width: settings.settingWidth label: qsTr('X Label') icon: "settings/xlabel.svg" + editable: true model: ListModel { ListElement { text: "" } ListElement { text: "x" } ListElement { text: "ω (rad/s)" } } - currentIndex: find(settings.xlabel) - editable: true + onAccepted: function(){ editText = JS.Utils.parseName(editText, false) - if (find(editText) === -1) model.append({text: editText}) - settings.xlabel = editText + if(find(editText) === -1) model.append({text: editText}) + currentIndex = find(editText) + Modules.Settings.set("xlabel", editText, true) settings.changed() } + onActivated: function(selectedId) { - settings.xlabel = model.get(selectedId).text + Modules.Settings.set("xlabel", model.get(selectedId).text, true) settings.changed() } - Component.onCompleted: editText = settings.xlabel + + function update() { + editText = Modules.Settings.xlabel + if(find(editText) === -1) model.append({text: editText}) + currentIndex = find(editText) + } } Setting.ComboBoxSetting { @@ -344,6 +393,7 @@ ScrollView { width: settings.settingWidth label: qsTr('Y Label') icon: "settings/ylabel.svg" + editable: true model: ListModel { ListElement { text: "" } ListElement { text: "y" } @@ -352,39 +402,52 @@ ScrollView { ListElement { text: "φ (deg)" } ListElement { text: "φ (rad)" } } - currentIndex: find(settings.ylabel) - editable: true + onAccepted: function(){ editText = JS.Utils.parseName(editText, false) - if (find(editText) === -1) model.append({text: editText, yaxisstep: root.yaxisstep}) - settings.ylabel = editText + if(find(editText) === -1) model.append({text: editText}) + currentIndex = find(editText) + Modules.Settings.set("ylabel", editText, true) settings.changed() } + onActivated: function(selectedId) { - settings.ylabel = model.get(selectedId).text + Modules.Settings.set("ylabel", model.get(selectedId).text, true) settings.changed() } - Component.onCompleted: editText = settings.ylabel + + function update() { + editText = Modules.Settings.ylabel + if(find(editText) === -1) model.append({text: editText}) + currentIndex = find(editText) + } } CheckBox { id: logScaleX - checked: settings.logscalex text: qsTr('X Log scale') onClicked: { - settings.logscalex = checked + Modules.Settings.set("logscalex", checked, true) + if(Modules.Settings.xmin <= 0) // Reset xmin to prevent crash. + Modules.Settings.set("xmin", .5) settings.changed() } + + function update() { + checked = Modules.Settings.logscalex + xAxisStep.update() + } } CheckBox { id: showXGrad - checked: settings.showxgrad text: qsTr('Show X graduation') onClicked: { - settings.showxgrad = checked + Modules.Settings.set("showxgrad", checked, true) settings.changed() } + + function update() { checked = Modules.Settings.showxgrad } } CheckBox { @@ -392,9 +455,10 @@ ScrollView { checked: settings.showygrad text: qsTr('Show Y graduation') onClicked: { - settings.showygrad = checked + Modules.Settings.set("showygrad", checked, true) settings.changed() } + function update() { checked = Modules.Settings.showygrad } } Button { @@ -440,10 +504,10 @@ ScrollView { Saves the current canvas in the opened file. If no file is currently opened, prompts to pick a save location. */ function save() { - if(settings.saveFilename == "") { + if(Modules.Settings.saveFilename == "") { saveAs() } else { - Modules.IO.saveDiagram(settings.saveFilename) + Modules.IO.saveDiagram(Modules.Settings.saveFilename) } } @@ -464,4 +528,30 @@ ScrollView { fdiag.exportMode = false fdiag.open() } + + /** + * Initializing the settings + */ + Component.onCompleted: function() { + const matchedElements = new Map([ + ["xzoom", zoomX], + ["yzoom", zoomY], + ["xmin", minX], + ["ymax", maxY], + ["xaxisstep", xAxisStep], + ["yaxisstep", yAxisStep], + ["xlabel", xAxisLabel], + ["ylabel", yAxisLabel], + ["linewidth", lineWidth], + ["textsize", textSize], + ["logscalex", logScaleX], + ["showxgrad", showXGrad], + ["showygrad", showYGrad] + ]) + Modules.Settings.on("changed", (evt) => { + if(matchedElements.has(evt.property)) + matchedElements.get(evt.property).update() + }) + Modules.Settings.initialize({ helper: Helper }) + } } From 54363b25bccb1696182dabe00ec3c03b10363a09 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 10 Oct 2024 23:56:42 +0200 Subject: [PATCH 018/104] Fixing issue with Replace All when replacement string includes source string. --- common/src/lib/polyfills/js.mjs | 5 +---- common/src/module/latex.mjs | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/common/src/lib/polyfills/js.mjs b/common/src/lib/polyfills/js.mjs index 9bcf80c..b412716 100644 --- a/common/src/lib/polyfills/js.mjs +++ b/common/src/lib/polyfills/js.mjs @@ -64,10 +64,7 @@ function arrayFlatMap(callbackFn, thisArg) { * @return {String} */ function stringReplaceAll(from, to) { - let str = this - while(str.includes(from)) - str = str.replace(from, to) - return str + return this.split(from).join(to) } diff --git a/common/src/module/latex.mjs b/common/src/module/latex.mjs index 8fabee4..a0e8401 100644 --- a/common/src/module/latex.mjs +++ b/common/src/module/latex.mjs @@ -261,7 +261,7 @@ class LatexAPI extends Module { throw new EvalError("Unknown operator " + item.value + ".") } break - case Instruction.IOP3: // Thirdiary operator + case Instruction.IOP3: // Ternary operator n3 = nstack.pop() n2 = nstack.pop() n1 = nstack.pop() From 2dc9234b228bf23c2ccfbad987d51d91ca99aad3 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 01:14:52 +0200 Subject: [PATCH 019/104] Decoupled History from QML --- common/src/events.mjs | 36 ++++-- common/src/lib/polyfills/js.mjs | 17 ++- common/src/module/history.mjs | 117 +++++++++++++++-- common/src/module/interface.mjs | 18 --- common/src/module/io.mjs | 2 +- common/src/module/settings.mjs | 6 +- .../eu/ad5001/LogarithmPlotter/AppMenuBar.qml | 6 +- .../LogarithmPlotter/History/History.qml | 122 +----------------- .../History/HistoryBrowser.qml | 89 +++++++++++-- .../LogarithmPlotter/History/HistoryItem.qml | 17 +-- 10 files changed, 239 insertions(+), 191 deletions(-) diff --git a/common/src/events.mjs b/common/src/events.mjs index 4e95db6..fbc8228 100644 --- a/common/src/events.mjs +++ b/common/src/events.mjs @@ -54,29 +54,41 @@ export class BaseEventEmitter { * @param {function(BaseEvent)} eventListener - The function to be called back when the event is emitted. */ on(eventType, eventListener) { - if(!this.constructor.emits.includes(eventType)) { - const className = this.constructor.name - const eventTypes = this.constructor.emits.join(", ") - throw new Error(`Cannot listen to unknown event ${eventType} in class ${className}. ${className} only emits: ${eventTypes}`) + if(eventType.includes(" ")) // Listen to several different events with the same listener. + for(const type of eventType.split(" ")) + this.on(type, eventListener) + else { + console.log("Listening to", eventType) + if(!this.constructor.emits.includes(eventType)) { + const className = this.constructor.name + const eventTypes = this.constructor.emits.join(", ") + throw new Error(`Cannot listen to unknown event ${eventType} in class ${className}. ${className} only emits: ${eventTypes}`) + } + if(!this.#listeners[eventType].has(eventListener)) + this.#listeners[eventType].add(eventListener) } - if(!this.#listeners[eventType].has(eventListener)) - this.#listeners[eventType].add(eventListener) } /** - * Remvoes a listener from an event that can be emitted by this object. + * Removes a listener from an event that can be emitted by this object. * * @param {string} eventType - Name of the event that was listened to. Throws an error if this object does not emit this kind of event. * @param {function(BaseEvent)} eventListener - The function previously registered as a listener. * @returns {boolean} True if the listener was removed, false if it was not found. */ off(eventType, eventListener) { - if(!this.constructor.emits.includes(eventType)) { - const className = this.constructor.name - const eventTypes = this.constructor.emits.join(", ") - throw new Error(`Cannot listen to unknown event ${eventType} in class ${className}. ${className} only emits: ${eventTypes}`) + if(eventType.includes(" ")) { // Unlisten to several different events with the same listener. + let found = false + for(const type of eventType.split(" ")) + found ||= this.off(eventType, eventListener) + } else { + if(!this.constructor.emits.includes(eventType)) { + const className = this.constructor.name + const eventTypes = this.constructor.emits.join(", ") + throw new Error(`Cannot listen to unknown event ${eventType} in class ${className}. ${className} only emits: ${eventTypes}`) + } + return this.#listeners[eventType].delete(eventListener) } - return this.#listeners[eventType].delete(eventListener) } /** diff --git a/common/src/lib/polyfills/js.mjs b/common/src/lib/polyfills/js.mjs index b412716..f8b910b 100644 --- a/common/src/lib/polyfills/js.mjs +++ b/common/src/lib/polyfills/js.mjs @@ -67,6 +67,19 @@ function stringReplaceAll(from, to) { return this.split(from).join(to) } +/** + * Returns the value of an element of the array at a given index. + * Accepts negative indexes. + * @this {Array|string} + * @param {number} index + * @return {*} + */ +function arrayAt(index) { + if(typeof index !== "number") + throw new Error(`${index} is not a number`) + return index >= 0 ? this[index] : this[this.length + index] +} + const polyfills = { 2017: [ @@ -95,8 +108,8 @@ const polyfills = { [String.prototype, "replaceAll", stringReplaceAll] ], 2022: [ - [Array.prototype, "at", notPolyfilled("Array.prototype.at")], - [String.prototype, "at", notPolyfilled("String.prototype.at")], + [Array.prototype, "at", arrayAt], + [String.prototype, "at", arrayAt], [Object, "hasOwn", notPolyfilled("Object.hasOwn")] ], 2023: [ diff --git a/common/src/module/history.mjs b/common/src/module/history.mjs index 8cd3f60..7406925 100644 --- a/common/src/module/history.mjs +++ b/common/src/module/history.mjs @@ -17,60 +17,151 @@ */ import { Module } from "./common.mjs" -import { HistoryInterface, NUMBER, STRING } from "./interface.mjs" +import { HelperInterface, HistoryInterface, NUMBER, STRING } from "./interface.mjs" +import { BaseEvent } from "../events.mjs" +import { Action, Actions } from "../history/index.mjs" + +class UpdatedEvent extends BaseEvent { + constructor() { + super("updated") + } +} + +class UndoneEvent extends BaseEvent { + constructor(action) { + super("undone") + this.undid = action + } +} + +class RedoneEvent extends BaseEvent { + constructor(action) { + super("redone") + this.redid = action + } +} + class HistoryAPI extends Module { + static emits = ["updated", "undone", "redone"] + + #helper + constructor() { super("History", { - historyObj: HistoryInterface, + helper: HelperInterface, themeTextColor: STRING, imageDepth: NUMBER, fontSize: NUMBER }) // History QML object - this.history = null + /** @type {Action[]} */ + this.undoStack = [] + /** @type {Action[]} */ + this.redoStack = [] + this.themeTextColor = "#FF0000" this.imageDepth = 2 this.fontSize = 28 } - initialize({ historyObj, themeTextColor, imageDepth, fontSize }) { - super.initialize({ historyObj, themeTextColor, imageDepth, fontSize }) - this.history = historyObj + /** + * @param {HelperInterface} historyObj + * @param {string} themeTextColor + * @param {number} imageDepth + * @param {number} fontSize + */ + initialize({ helper, themeTextColor, imageDepth, fontSize }) { + super.initialize({ helper, themeTextColor, imageDepth, fontSize }) + this.#helper = helper this.themeTextColor = themeTextColor this.imageDepth = imageDepth this.fontSize = fontSize } + /** + * Undoes the Action at the top of the undo stack and pushes it to the top of the redo stack. + */ undo() { if(!this.initialized) throw new Error("Attempting undo before initialize!") - this.history.undo() + if(this.undoStack.length > 0) { + const action = this.undoStack.pop() + action.undo() + this.redoStack.push(action) + this.emit(new UndoneEvent(action)) + } } + /** + * Redoes the Action at the top of the redo stack and pushes it to the top of the undo stack. + */ redo() { if(!this.initialized) throw new Error("Attempting redo before initialize!") - this.history.redo() + if(this.redoStack.length > 0) { + const action = this.redoStack.pop() + action.redo() + this.undoStack.push(action) + this.emit(new RedoneEvent(action)) + } } + /** + * Clears both undo and redo stacks completely. + */ clear() { if(!this.initialized) throw new Error("Attempting clear before initialize!") - this.history.clear() + this.undoStack = [] + this.redoStack = [] + this.emit(new UpdatedEvent()) } + /** + * Adds an instance of HistoryLib.Action to history. + * @param action + */ addToHistory(action) { if(!this.initialized) throw new Error("Attempting addToHistory before initialize!") - this.history.addToHistory(action) + if(action instanceof Action) { + console.log("Added new entry to history: " + action.getReadableString()) + this.undoStack.push(action) + if(this.#helper.getSettingBool("reset_redo_stack")) + this.redoStack = [] + this.emit(new UpdatedEvent()) + } } - unserialize(...data) { + /** + * Unserializes both the undo stack and redo stack from serialized content. + * @param {[string, any[]][]} undoSt + * @param {[string, any[]][]} redoSt + */ + unserialize(undoSt, redoSt) { if(!this.initialized) throw new Error("Attempting unserialize before initialize!") - this.history.unserialize(...data) + this.clear() + for(const [name, args] of undoSt) + this.undoStack.push( + new Actions[name](...args) + ) + for(const [name, args] of redoSt) + this.redoStack.push( + new Actions[name](...args) + ) + this.emit(new UpdatedEvent()) } + /** + * Serializes history into JSON-able content. + * @return {[[string, any[]], [string, any[]]]} + */ serialize() { if(!this.initialized) throw new Error("Attempting serialize before initialize!") - return this.history.serialize() + let undoSt = [], redoSt = []; + for(const action of this.undoStack) + undoSt.push([ action.type(), action.export() ]) + for(const action of this.redoStack) + redoSt.push([ action.type(), action.export() ]) + return [undoSt, redoSt] } } diff --git a/common/src/module/interface.mjs b/common/src/module/interface.mjs index 606ec4d..1ee65a3 100644 --- a/common/src/module/interface.mjs +++ b/common/src/module/interface.mjs @@ -60,24 +60,6 @@ export class Interface { } -export class SettingsInterface extends Interface { - width = NUMBER - height = NUMBER - xmin = NUMBER - ymax = NUMBER - xzoom = NUMBER - yzoom = NUMBER - xaxisstep = STRING - yaxisstep = STRING - xlabel = STRING - ylabel = STRING - linewidth = NUMBER - textsize = NUMBER - logscalex = BOOLEAN - showxgrad = BOOLEAN - showygrad = BOOLEAN -} - export class CanvasInterface extends Interface { imageLoaders = OBJECT /** @type {function(string): CanvasRenderingContext2D} */ diff --git a/common/src/module/io.mjs b/common/src/module/io.mjs index 0b4c6fa..8ca4b2b 100644 --- a/common/src/module/io.mjs +++ b/common/src/module/io.mjs @@ -21,7 +21,7 @@ import Objects from "./objects.mjs" import History from "./history.mjs" import Canvas from "./canvas.mjs" import Settings from "./settings.mjs" -import { DialogInterface, RootInterface, SettingsInterface } from "./interface.mjs" +import { DialogInterface, RootInterface } from "./interface.mjs" class IOAPI extends Module { diff --git a/common/src/module/settings.mjs b/common/src/module/settings.mjs index 44a6593..1530839 100644 --- a/common/src/module/settings.mjs +++ b/common/src/module/settings.mjs @@ -72,7 +72,11 @@ class SettingsAPI extends Module { helper: HelperInterface }) } - + + /** + * + * @param {HelperInterface} helper + */ initialize({ helper }) { super.initialize({ helper }) // Initialize default values. diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml index f26fd5b..8c3f2d1 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml @@ -76,18 +76,16 @@ MenuBar { Action { text: qsTr("&Undo") shortcut: StandardKey.Undo - onTriggered: history.undo() + onTriggered: Modules.History.undo() icon.name: 'edit-undo' icon.color: enabled ? sysPalette.windowText : sysPaletteIn.windowText - enabled: history.undoCount > 0 } Action { text: qsTr("&Redo") shortcut: StandardKey.Redo - onTriggered: history.redo() + onTriggered: Modules.History.redo() icon.name: 'edit-redo' icon.color: enabled ? sysPalette.windowText : sysPaletteIn.windowText - enabled: history.redoCount > 0 } Action { text: qsTr("&Copy plot") diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/History.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/History.qml index 47db5f3..88579e7 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/History.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/History.qml @@ -64,10 +64,7 @@ Item { Clears both undo and redo stacks completly. */ function clear() { - undoCount = 0 - redoCount = 0 - undoStack = [] - redoStack = [] + Modules.History.clear() } @@ -76,18 +73,7 @@ Item { Serializes history into JSON-able content. */ function serialize() { - let undoSt = [], redoSt = []; - for(let i = 0; i < undoCount; i++) - undoSt.push([ - undoStack[i].type(), - undoStack[i].export() - ]); - for(let i = 0; i < redoCount; i++) - redoSt.push([ - redoStack[i].type(), - redoStack[i].export() - ]); - return [undoSt, redoSt] + return Modules.History.serialize() } /*! @@ -95,14 +81,7 @@ Item { Unserializes both \c undoSt stack and \c redoSt stack from serialized content. */ function unserialize(undoSt, redoSt) { - clear(); - for(let i = 0; i < undoSt.length; i++) - undoStack.push(new JS.HistoryLib.Actions[undoSt[i][0]](...undoSt[i][1])) - for(let i = 0; i < redoSt.length; i++) - redoStack.push(new JS.HistoryLib.Actions[redoSt[i][0]](...redoSt[i][1])) - undoCount = undoSt.length; - redoCount = redoSt.length; - objectLists.update() + Modules.History.unserialize(undoSt, redoSt) } /*! @@ -110,16 +89,7 @@ Item { Adds an instance of HistoryLib.Action to history. */ function addToHistory(action) { - if(action instanceof JS.HistoryLib.Action) { - console.log("Added new entry to history: " + action.getReadableString()) - undoStack.push(action) - undoCount++; - if(Helper.getSettingBool("reset_redo_stack")) { - redoStack = [] - redoCount = 0 - } - saved = false - } + Modules.History.addToHistory(action) } /*! @@ -128,16 +98,7 @@ Item { By default, will update the graph and the object list. This behavior can be disabled by setting the \c updateObjectList to false. */ function undo(updateObjectList = true) { - if(undoStack.length > 0) { - var action = undoStack.pop() - action.undo() - if(updateObjectList) - objectLists.update() - redoStack.push(action) - undoCount--; - redoCount++; - saved = false - } + Modules.History.undo() } /*! @@ -146,77 +107,6 @@ Item { By default, will update the graph and the object list. This behavior can be disabled by setting the \c updateObjectList to false. */ function redo(updateObjectList = true) { - if(redoStack.length > 0) { - var action = redoStack.pop() - action.redo() - if(updateObjectList) - objectLists.update() - undoStack.push(action) - undoCount++; - redoCount--; - saved = false - } - } - - /*! - \qmlmethod void History::undoMultipleDefered(int toUndoCount) - Undoes several HistoryLib.Action at the top of the undo stack and pushes them to the top of the redo stack. - It undoes them deferedly to avoid overwhelming the computer while creating a cool short accelerated summary of all changes. - */ - function undoMultipleDefered(toUndoCount) { - undoTimer.toUndoCount = toUndoCount; - undoTimer.start() - if(toUndoCount > 0) - saved = false - } - - - /*! - \qmlmethod void History::redoMultipleDefered(int toRedoCount) - Redoes several HistoryLib.Action at the top of the redo stack and pushes them to the top of the undo stack. - It redoes them deferedly to avoid overwhelming the computer while creating a cool short accelerated summary of all changes. - */ - function redoMultipleDefered(toRedoCount) { - redoTimer.toRedoCount = toRedoCount; - redoTimer.start() - if(toRedoCount > 0) - saved = false - } - - Timer { - id: undoTimer - interval: 5; running: false; repeat: true - property int toUndoCount: 0 - onTriggered: { - if(toUndoCount > 0) { - historyObj.undo(toUndoCount % 4 == 1) // Only redraw once every 4 changes. - toUndoCount--; - } else { - running = false; - } - } - } - - Timer { - id: redoTimer - interval: 5; running: false; repeat: true - property int toRedoCount: 0 - onTriggered: { - if(toRedoCount > 0) { - historyObj.redo(toRedoCount % 4 == 1) // Only redraw once every 4 changes. - toRedoCount--; - } else { - running = false; - } - } - } - - Component.onCompleted: { - Modules.History.initialize({ - historyObj, - themeTextColor: sysPalette.windowText.toString(), - imageDepth: Screen.devicePixelRatio, - fontSize: 14 - }) + Modules.History.redo() } } diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml index 926b42a..d79cc84 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +pragma ComponentBehavior: Bound + import QtQuick.Controls import QtQuick import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting @@ -46,6 +48,18 @@ Item { true when the system is running with a dark theme, false otherwise. */ property bool darkTheme: isDarkTheme() + + /*! + \qmlproperty int HistoryBrowser::undoCount + Number of actions in the undo stack. + */ + property int undoCount: 0 + + /*! + \qmlproperty int HistoryBrowser::redoCount + Number of actions in the redo stack. + */ + property int redoCount: 0 Setting.TextSetting { id: filterInput @@ -76,19 +90,22 @@ Item { id: redoColumn anchors.right: parent.right anchors.top: parent.top - width: actionWidth + width: historyBrowser.actionWidth Repeater { - model: history.redoCount + model: historyBrowser.redoCount HistoryItem { id: redoButton - width: actionWidth + width: historyBrowser.actionWidth //height: actionHeight isRedo: true - idx: index darkTheme: historyBrowser.darkTheme hidden: !(filterInput.value == "" || content.includes(filterInput.value)) + onClicked: { + redoTimer.toRedoCount = Modules.History.redoStack.length-index + redoTimer.start() + } } } } @@ -101,14 +118,14 @@ Item { transform: Rotation { origin.x: 30; origin.y: 30; angle: 270} height: 70 width: 20 - visible: history.redoCount > 0 + visible: historyBrowser.redoCount > 0 } Rectangle { id: nowRect anchors.right: parent.right anchors.top: redoColumn.bottom - width: actionWidth + width: historyBrowser.actionWidth height: 40 color: sysPalette.highlight Text { @@ -124,20 +141,24 @@ Item { id: undoColumn anchors.right: parent.right anchors.top: nowRect.bottom - width: actionWidth + width: historyBrowser.actionWidth Repeater { - model: history.undoCount + model: historyBrowser.undoCount HistoryItem { id: undoButton - width: actionWidth + width: historyBrowser.actionWidth //height: actionHeight isRedo: false - idx: index darkTheme: historyBrowser.darkTheme hidden: !(filterInput.value == "" || content.includes(filterInput.value)) + + onClicked: { + undoTimer.toUndoCount = +index+1 + undoTimer.start() + } } } } @@ -150,7 +171,39 @@ Item { transform: Rotation { origin.x: 30; origin.y: 30; angle: 270} height: 60 width: 20 - visible: history.undoCount > 0 + visible: historyBrowser.undoCount > 0 + } + } + } + + Timer { + id: undoTimer + interval: 5; running: false; repeat: true + property int toUndoCount: 0 + onTriggered: { + if(toUndoCount > 0) { + Modules.History.undo() + if(toUndoCount % 3 === 1) + Modules.Canvas.requestPaint() + toUndoCount--; + } else { + running = false; + } + } + } + + Timer { + id: redoTimer + interval: 5; running: false; repeat: true + property int toRedoCount: 0 + onTriggered: { + if(toRedoCount > 0) { + Modules.History.redo() + if(toRedoCount % 3 === 1) + Modules.Canvas.requestPaint() + toRedoCount--; + } else { + running = false; } } } @@ -163,6 +216,18 @@ Item { let hex = sysPalette.windowText.toString() // We only check the first parameter, as on all normal OSes, text color is grayscale. return parseInt(hex.substr(1,2), 16) > 128 - + } + + Component.onCompleted: { + Modules.History.initialize({ + helper: Helper, + themeTextColor: sysPalette.windowText.toString(), + imageDepth: Screen.devicePixelRatio, + fontSize: 14 + }) + Modules.History.on("updated undone redone", () => { + undoCount = Modules.History.undoStack.length + redoCount = Modules.History.redoStack.length + }) } } diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryItem.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryItem.qml index f1e20a0..f37eb3b 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryItem.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryItem.qml @@ -41,17 +41,17 @@ Button { \qmlproperty bool HistoryItem::isRedo true if the action is in the redo stack, false othewise. */ - property bool isRedo + required property bool isRedo /*! - \qmlproperty int HistoryItem::idx + \qmlproperty int HistoryItem::index Index of the item within the HistoryBrowser list. */ - property int idx + required property int index /*! \qmlproperty bool HistoryItem::darkTheme true when the system is running with a dark theme, false otherwise. */ - property bool darkTheme + required property bool darkTheme /*! \qmlproperty bool HistoryItem::hidden true when the item is filtered out, false otherwise. @@ -61,7 +61,7 @@ Button { \qmlproperty int HistoryItem::historyAction Associated history action. */ - readonly property var historyAction: isRedo ? history.redoStack[idx] : history.undoStack[history.undoCount-idx-1] + readonly property var historyAction: isRedo ? Modules.History.redoStack.at(index) : Modules.History.undoStack.at(-index-1) /*! \qmlproperty int HistoryItem::actionHeight @@ -147,13 +147,6 @@ Button { ToolTip.visible: hovered ToolTip.delay: 200 ToolTip.text: content - - onClicked: { - if(isRedo) - history.redoMultipleDefered(history.redoCount-idx) - else - history.undoMultipleDefered(+idx+1) - } } From 448d94fee35d574832d73ed2195ce1fa35ae4d45 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 02:03:27 +0200 Subject: [PATCH 020/104] Fixed many issues with new History module, including saved status. + Fixed (old) bug that label content wasn't being saved. --- assets/i18n/lp_de.ts | 112 ++++++++-------- assets/i18n/lp_en.ts | 112 ++++++++-------- assets/i18n/lp_es.ts | 116 ++++++++-------- assets/i18n/lp_fr.ts | 112 ++++++++-------- assets/i18n/lp_hu.ts | 112 ++++++++-------- assets/i18n/lp_nb_NO.ts | 114 ++++++++-------- assets/i18n/lp_template.ts | 125 +++++++----------- common/src/module/history.mjs | 17 ++- common/src/module/interface.mjs | 1 - common/src/module/io.mjs | 49 +++++-- common/src/objs/bodephase.mjs | 2 +- .../eu/ad5001/LogarithmPlotter/AppMenuBar.qml | 2 +- .../History/HistoryBrowser.qml | 2 +- .../LogarithmPlotter/LogarithmPlotter.qml | 22 ++- .../ObjectLists/Editor/CustomPropertyList.qml | 16 ++- .../ObjectLists/Editor/Dialog.qml | 8 +- .../ObjectLists/ObjectCreationGrid.qml | 4 +- .../ObjectLists/ObjectRow.qml | 6 +- .../LogarithmPlotter/PickLocationOverlay.qml | 6 +- 19 files changed, 479 insertions(+), 459 deletions(-) diff --git a/assets/i18n/lp_de.ts b/assets/i18n/lp_de.ts index 4876e02..59a9725 100644 --- a/assets/i18n/lp_de.ts +++ b/assets/i18n/lp_de.ts @@ -67,22 +67,22 @@ &Lösen - + &Redo &Wiederherstellen - + &Copy plot Grafik &Kopieren - + &Preferences &Einstellung - + &Create &Erstellen @@ -123,52 +123,52 @@ Syntaktische Färbung - + &Help &Hilfe - + &Source code &Quellcode - + &Report a bug Fehler &Melden - + &User manual &Benutzerhandbuch - + &Changelog &Changelog - + &Help translating! &Hilfe beim Übersetzen! - + &Thanks &Danksagungen - + &About &Übrigens - + Save unsaved changes? Änderungen speichern? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Diese Grafik enthält ungespeicherte Änderungen. Dadurch gehen alle ungespeicherten Daten verloren. Fortfahren? @@ -205,12 +205,12 @@ CustomPropertyList - + + Create new %1 + Neues %1objekt erstellen - + Pick on graph Aufnehmen auf Graph @@ -238,9 +238,8 @@ Name - Label content - Etikett + Etikett @@ -405,24 +404,20 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" HistoryBrowser - Filter... - Filtern… + Filtern… - Redo > - Wiederherstellen > + Wiederherstellen > - > Now - > Aktueller Stand + > Aktueller Stand - < Undo - < Rückgängig + < Rückgängig @@ -475,17 +470,17 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" Geladene Datei '%1'. - + Copied plot screenshot to clipboard! Grafik in die Zwischenablage kopiert! - + &Update &Aktualisieren - + &Update LogarithmPlotter LogarithmPlotter &aktualisieren @@ -613,109 +608,109 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" Settings - + X Zoom Zoom auf X - + Y Zoom Zoom auf Y - + Min X Minimum X - + Max Y Maximum Y - + Max X Maximum X - + Min Y Minimum Y - + X Axis Step X-Achsen-Schritt - + Y Axis Step Y-Achsen-Schritt - + Line width Linienbreite - + Text size (px) Textgröße (px) - + X Label Etikett der X-Achse - + Y Label Etikett der Y-Achse - + X Log scale Logarithmische Skala in X - + Show X graduation X-Teilung anzeigen - + Show Y graduation Y-Teilung anzeigen - + Copy to clipboard Kopieren in die Zwischenablage - + Save plot Grafik speichern… - + Save plot as Grafik speichern unter… - + Load plot Grafik laden… @@ -1160,7 +1155,7 @@ Evaluated expression: %3 Ausdruck analysiert: %3 - + Error while attempting to draw %1 %2: %3 @@ -1191,7 +1186,7 @@ Evaluated expression: %3 Ausdruck analysiert: %3 - + LogarithmPlotter - Drawing error LogarithmPlotter - Fehler @@ -1308,27 +1303,27 @@ Ausdruck analysiert: %3 Verlauf - + Saved plot to '%1'. Gespeicherte Grafik auf '%1'. - + Loading file '%1'. Laden der Datei '%1'. - + Unknown object type: %1. Unbekannter Objekttyp: %1. - + Invalid file provided. Ungültige Datei angegeben. - + Could not load file: Datei konnte nicht geladen werden: @@ -1337,7 +1332,7 @@ Ausdruck analysiert: %3 Die Datei konnte nicht gespeichert werden: - + Loaded file '%1'. Geladene Datei '%1'. @@ -1731,6 +1726,11 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde color Farbe + + + labelContent + Etikett + repartition diff --git a/assets/i18n/lp_en.ts b/assets/i18n/lp_en.ts index b2dfaff..5f653a7 100644 --- a/assets/i18n/lp_en.ts +++ b/assets/i18n/lp_en.ts @@ -67,22 +67,22 @@ &Undo - + &Redo &Redo - + &Copy plot &Copy plot - + &Preferences &Preferences - + &Create &Create @@ -123,52 +123,52 @@ Color Scheme - + &Help &Help - + &Source code &Source code - + &Report a bug &Report a bug - + &User manual &User manual - + &Changelog &Changelog - + &Help translating! &Help translating! - + &Thanks &Thanks - + &About &About - + Save unsaved changes? Save unsaved changes? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? @@ -205,12 +205,12 @@ CustomPropertyList - + + Create new %1 + Create new %1 - + Pick on graph Pick on graph @@ -238,9 +238,8 @@ Name - Label content - Label content + Label content @@ -405,24 +404,20 @@ These settings can be changed at any time from the "Settings" menu. HistoryBrowser - Filter... - Filter… + Filter… - Redo > - Redo > + Redo > - > Now - > Now + > Now - < Undo - < Undo + < Undo @@ -475,17 +470,17 @@ These settings can be changed at any time from the "Settings" menu.Loaded file '%1'. - + Copied plot screenshot to clipboard! Copied plot screenshot to clipboard! - + &Update &Update - + &Update LogarithmPlotter &Update LogarithmPlotter @@ -613,109 +608,109 @@ These settings can be changed at any time from the "Settings" menu.Settings - + X Zoom X Zoom - + Y Zoom Y Zoom - + Min X Min X - + Max Y Max Y - + Max X Max X - + Min Y Min Y - + X Axis Step X Axis Step - + Y Axis Step Y Axis Step - + Line width Line width - + Text size (px) Text size (px) - + X Label X Label - + Y Label Y Label - + X Log scale X Log scale - + Show X graduation Show X graduation - + Show Y graduation Show Y graduation - + Copy to clipboard Copy to clipboard - + Save plot Save plot… - + Save plot as Save plot as… - + Load plot Open plot… @@ -1160,7 +1155,7 @@ Evaluated expression: %3 Evaluated expression: %3 - + Error while attempting to draw %1 %2: %3 @@ -1191,7 +1186,7 @@ Evaluated expression: %3 Evaluated expression: %3 - + LogarithmPlotter - Drawing error LogarithmPlotter - Drawing error @@ -1308,27 +1303,27 @@ Evaluated expression: %3 History - + Saved plot to '%1'. Saved plot to '%1'. - + Loading file '%1'. Loading file '%1'. - + Unknown object type: %1. Unknown object type: %1. - + Invalid file provided. Invalid file provided. - + Could not load file: Could not load file: @@ -1337,7 +1332,7 @@ Evaluated expression: %3 Could not save file: - + Loaded file '%1'. Loaded file '%1'. @@ -1731,6 +1726,11 @@ Please make sure your LaTeX installation is correct and report a bug if so.color Color + + + labelContent + Label content + repartition diff --git a/assets/i18n/lp_es.ts b/assets/i18n/lp_es.ts index ef79648..7a736b5 100644 --- a/assets/i18n/lp_es.ts +++ b/assets/i18n/lp_es.ts @@ -67,22 +67,22 @@ &Cancelar - + &Redo &Reiniciar - + &Copy plot &Copiar el gráfico - + &Preferences &Preferencias - + &Create &Crear @@ -119,52 +119,52 @@ Esquema de colores - + &Help &Ayuda - + &Source code &Código fuente - + &Report a bug &Informar de un error - + &User manual &Manual del usuario - + &Changelog &Registro de cambios - + &Help translating! &¡Ayuda a la traducción! - + &Thanks &Agradecimientos - + &About &Acerca de - + Save unsaved changes? ¿Guardar los cambios no guardados? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Este gráfico contiene cambios sin guardar. Al hacer esto, se perderán todos los datos no guardados. ¿Continuar? @@ -205,12 +205,12 @@ CustomPropertyList - + + Create new %1 + Crear nuevo %1 - + Pick on graph Elegir en el gráfico @@ -237,11 +237,6 @@ Name - - - Label content - - null @@ -405,24 +400,16 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes HistoryBrowser - - Filter... - - - - Redo > - Rehacer > + Rehacer > - > Now - > Ahora + > Ahora - < Undo - < Deshacer + < Deshacer @@ -451,17 +438,17 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes Historial - + Copied plot screenshot to clipboard! ¡Captura de pantalla del gráfico copiada al portapapeles! - + &Update &Actualizar - + &Update LogarithmPlotter &Actualizar LogarithmPlotter @@ -613,109 +600,109 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes Settings - + X Zoom - + Y Zoom - + Min X - + Max Y - + Max X - + Min Y - + X Axis Step Paso por eje X - + Y Axis Step Paso por eje Y - + Line width Anchura de la línea - + Text size (px) Tamaño del texto (px) - + X Label - + Y Label - + X Log scale Escala logarítmica en X - + Show X graduation Mostrar graduación del eje X - + Show Y graduation Mostrar graduación del eje Y - + Copy to clipboard Copiar al portapapeles - + Save plot Guardar gráfico… - + Save plot as Guardar gráfico como… - + Load plot Abrir gráfico… @@ -1147,7 +1134,7 @@ Evaluated expression: %3 Expresión evaluada: %3 - + Error while attempting to draw %1 %2: %3 @@ -1191,7 +1178,7 @@ Evaluated expression: %3 Expresión evaluada: %3 - + LogarithmPlotter - Drawing error @@ -1320,27 +1307,27 @@ Expresión evaluada: %3 Objetos - + Saved plot to '%1'. Gráfico guardado en '%1'. - + Loading file '%1'. Cargando el archivo '%1'. - + Unknown object type: %1. Tipo de objeto desconocido: %1 . - + Invalid file provided. Se ha proporcionado un archivo no válido. - + Could not load file: No se pudo cargar el archivo: @@ -1349,7 +1336,7 @@ Expresión evaluada: %3 No se ha podido guardar el archivo: - + Loaded file '%1'. Archivo cargado '%1'. @@ -1731,6 +1718,11 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u baseValues Valores de inicialización + + + labelContent + Contenido de la etiqueta + repartition diff --git a/assets/i18n/lp_fr.ts b/assets/i18n/lp_fr.ts index 2b1a26d..b693568 100644 --- a/assets/i18n/lp_fr.ts +++ b/assets/i18n/lp_fr.ts @@ -67,22 +67,22 @@ &Annuler - + &Redo &Rétablir - + &Copy plot &Copier le graphe - + &Preferences &Préférences - + &Create &Créer @@ -124,52 +124,52 @@ Coloration Syntaxique - + &Help &Aide - + &Source code &Code source - + &Report a bug &Rapport de bug - + &User manual Manuel d'&utilisation - + &Changelog &Historique des modifications - + &Help translating! &Aider à la traduction ! - + &Thanks &Remerciements - + &About &À propos - + Save unsaved changes? Sauvegarder les modifications ? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Ce graphe contient des modifications non sauvegardées. En faisant cela, toutes les données non sauvegardées seront perdues. Continuer ? @@ -206,12 +206,12 @@ CustomPropertyList - + + Create new %1 + Créer un nouvel objet %1 - + Pick on graph Prendre la position sur le graphe @@ -239,9 +239,8 @@ Nom - Label content - Étiquette + Étiquette @@ -407,24 +406,20 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P HistoryBrowser - Filter... - Filtrer… + Filtrer… - Redo > - Rétablir > + Rétablir > - > Now - > État actuel + > État actuel - < Undo - < Annuler + < Annuler @@ -477,17 +472,17 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Fichier '%1' chargé. - + Copied plot screenshot to clipboard! Image du graphe copiée dans le presse-papiers ! - + &Update &Mise à jour - + &Update LogarithmPlotter &Mettre à jour LogarithmPlotter @@ -615,109 +610,109 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Settings - + X Zoom Zoom en X - + Y Zoom Zoom en Y - + Min X Min X - + Max Y Max Y - + Max X Max X - + Min Y Min Y - + X Axis Step Pas de l'axe X - + Y Axis Step Pas de l'axe Y - + Line width Taille des lignes - + Text size (px) Taille du texte (px) - + X Label Label de l'axe X - + Y Label Label de l'axe Y - + X Log scale Échelle logarithmique en X - + Show X graduation Montrer la graduation de l'axe X - + Show Y graduation Montrer la graduation de l'axe Y - + Copy to clipboard Copier vers le presse-papiers - + Save plot Sauvegarder le graphe… - + Save plot as Sauvegarder le graphe sous… - + Load plot Ouvrir un graphe… @@ -1163,7 +1158,7 @@ Evaluated expression: %3 Formule analysée : %3 - + Error while attempting to draw %1 %2: %3 @@ -1194,7 +1189,7 @@ Evaluated expression: %3 Formule analysée : %3 - + LogarithmPlotter - Drawing error LogarithmPlotter - Erreur @@ -1323,27 +1318,27 @@ Formule analysée : %3 &Mettre à jour LogarithmPlotter - + Saved plot to '%1'. Graphe sauvegardé dans '%1'. - + Loading file '%1'. Chargement du fichier '%1'. - + Unknown object type: %1. Type d'objet inconnu : %1. - + Invalid file provided. Fichier fourni invalide. - + Could not load file: Impossible de charger le fichier : @@ -1352,7 +1347,7 @@ Formule analysée : %3 Impossible de sauvegarder le fichier : - + Loaded file '%1'. Fichier '%1' chargé. @@ -1734,6 +1729,11 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c color Couleur + + + labelContent + Étiquette + repartition diff --git a/assets/i18n/lp_hu.ts b/assets/i18n/lp_hu.ts index 975c600..a43da4d 100644 --- a/assets/i18n/lp_hu.ts +++ b/assets/i18n/lp_hu.ts @@ -67,22 +67,22 @@ &Visszavonás - + &Redo &Ismétlés - + &Copy plot Ábra má&solása - + &Preferences &Beállítások - + &Create &Létrehozás @@ -123,52 +123,52 @@ Színséma - + &Help &Súgó - + &Source code &Forráskód - + &Report a bug &Hiba bejelentése - + &User manual &Használati utasítás - + &Changelog &Változásnapló - + &Help translating! &Segítség a fordításban! - + &Thanks &Köszönjük - + &About &Névjegy - + Save unsaved changes? Menti a változtatásokat? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Ez az ábra nem mentett változtatásokat tartalmaz. Ezzel az összes nem mentett adat elveszik. Folytatja? @@ -205,12 +205,12 @@ CustomPropertyList - + + Create new %1 + Új %1 létrehozása - + Pick on graph Ábra kijelölése @@ -238,9 +238,8 @@ Név - Label content - Címketartalom + Címketartalom @@ -405,24 +404,20 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. HistoryBrowser - Filter... - Szűrő… + Szűrő… - Redo > - Ismétlés > + Ismétlés > - > Now - > Most + > Most - < Undo - < Visszavonás + < Visszavonás @@ -475,17 +470,17 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. A(z) „%1” fájl betöltve. - + Copied plot screenshot to clipboard! Ábra képernyőkép vágólapra másolva! - + &Update &Frissítés - + &Update LogarithmPlotter A LogarithmPlotter &frissítése @@ -613,109 +608,109 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. Settings - + X Zoom X-nagyítás - + Y Zoom Y-nagyítás - + Min X Legkisebb X - + Max Y Legnagyobb Y - + Max X Legnagyobb X - + Min Y Legkisebb Y - + X Axis Step X tengely lépésköze - + Y Axis Step Y tengely lépésköze - + Line width Vonalvastagság - + Text size (px) Szövegméret (képpont) - + X Label X címke - + Y Label Y címke - + X Log scale X tengely logaritmikus skálával - + Show X graduation X érettségi megjelenítése - + Show Y graduation Y érettségi megjelenítése - + Copy to clipboard Másolás a vágólapra - + Save plot Ábra mentése… - + Save plot as Ábra mentése másként… - + Load plot Ábra megnyitása… @@ -1160,7 +1155,7 @@ Evaluated expression: %3 Kiértékelt kifejezés: %3 - + Error while attempting to draw %1 %2: %3 @@ -1191,7 +1186,7 @@ Evaluated expression: %3 Kiértékelt kifejezés: %3 - + LogarithmPlotter - Drawing error LogarithmPlotter - Rajzolási hiba @@ -1304,27 +1299,27 @@ Kiértékelt kifejezés: %3 Előzmények - + Saved plot to '%1'. Ábra mentve ide: „%1”. - + Loading file '%1'. A(z) „%1” fájl betöltése folyamatban van. - + Unknown object type: %1. Ismeretlen objektumtípus: %1. - + Invalid file provided. A megadott fájl érvénytelen. - + Could not load file: @@ -1333,7 +1328,7 @@ Kiértékelt kifejezés: %3 A fájl mentése nem sikerült: - + Loaded file '%1'. A(z) „%1” fájl betöltve. @@ -1731,6 +1726,11 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents color Szín + + + labelContent + Címketartalom + repartition diff --git a/assets/i18n/lp_nb_NO.ts b/assets/i18n/lp_nb_NO.ts index d278f03..79657f6 100644 --- a/assets/i18n/lp_nb_NO.ts +++ b/assets/i18n/lp_nb_NO.ts @@ -67,22 +67,22 @@ &Angre - + &Redo &Gjenta - + &Copy plot &Kopier plott - + &Preferences - + &Create &Opprett @@ -99,52 +99,52 @@ Tilbakestill angrehistorikk automatisk - + &Help &Hjelp - + &Source code - + &Report a bug &Rapporter en feil - + &User manual - + &Changelog &Endringslogg - + &Help translating! &Hjelp til å oversette! - + &Thanks &Erkjennelser - + &About &Om - + Save unsaved changes? Lagre ikke-lagrede endringer? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Dette plottet inneholder ikke-lagrede endringer. Hvis du gjør dette, vil alle ikke-lagrede data gå tapt. Fortsette? @@ -181,12 +181,12 @@ CustomPropertyList - + + Create new %1 + Opprett nytt %1 - + Pick on graph @@ -214,9 +214,8 @@ Navn - Label content - Etikett-innhold + Etikett-innhold @@ -361,24 +360,16 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. HistoryBrowser - - Filter... - - - - Redo > - Angre > + Angre > - > Now - > Nå + > Nå - < Undo - < Angre + < Angre @@ -431,17 +422,17 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen.Lastet inn filen «%1». - + Copied plot screenshot to clipboard! Kopierte plott-skjermavbildning til utklippstavlen! - + &Update &Oppdater - + &Update LogarithmPlotter &Installer ny versjon av LogartimePlotter @@ -569,109 +560,109 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen.Settings - + X Zoom X-forstørrelse - + Y Zoom Y-forstørrelse - + Min X Min. X - + Max Y Maks. Y - + Max X Maks. X - + Min Y Min. Y - + X Axis Step X-aksesteg - + Y Axis Step Y-aksesteg - + Line width Linjebredde - + Text size (px) Tekststørrelse (piksler) - + X Label Navn på X-akse - + Y Label Navn på Y-akse - + X Log scale Logaritmisk skala i x - + Show X graduation Vis X-inndeling - + Show Y graduation Vis Y-inndeling - + Copy to clipboard Kopier til utklippstavle - + Save plot Lagre plott - + Save plot as Lagre plott som - + Load plot Last inn plott @@ -971,7 +962,7 @@ Evaluated expression: %3 - + Error while attempting to draw %1 %2: %3 @@ -1122,7 +1113,7 @@ Evaluated expression: %3 - + LogarithmPlotter - Drawing error @@ -1235,27 +1226,27 @@ Evaluated expression: %3 Historikk - + Saved plot to '%1'. Lagret plott i «%1». - + Loading file '%1'. Laster inn «%1»-fil. - + Unknown object type: %1. Ukjent objekttype: %1. - + Invalid file provided. Ugyldig fil angitt. - + Could not load file: @@ -1264,7 +1255,7 @@ Evaluated expression: %3 Kunne ikke lagre fil: - + Loaded file '%1'. Lastet inn filen «%1». @@ -1641,6 +1632,11 @@ Please make sure your latex installation is correct and report a bug if so.targetValuePosition + + + labelContent + Etikett-innhold + repartition diff --git a/assets/i18n/lp_template.ts b/assets/i18n/lp_template.ts index 0981f1b..81221dd 100644 --- a/assets/i18n/lp_template.ts +++ b/assets/i18n/lp_template.ts @@ -67,72 +67,72 @@ - + &Redo - + &Copy plot - + &Preferences - + &Create - + &Help - + &Source code - + &Report a bug - + &User manual - + &Changelog - + &Help translating! - + &Thanks - + &About - + Save unsaved changes? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? @@ -162,12 +162,12 @@ CustomPropertyList - + + Create new %1 - + Pick on graph @@ -194,11 +194,6 @@ Name - - - Label content - - null @@ -294,29 +289,6 @@ - - HistoryBrowser - - - Filter... - - - - - Redo > - - - - - > Now - - - - - < Undo - - - ListSetting @@ -343,17 +315,17 @@ - + Copied plot screenshot to clipboard! - + &Update - + &Update LogarithmPlotter @@ -457,109 +429,109 @@ Settings - + X Zoom - + Y Zoom - + Min X - + Max Y - + Max X - + Min Y - + X Axis Step - + Y Axis Step - + Line width - + Text size (px) - + X Label - + Y Label - + X Log scale - + Show X graduation - + Show Y graduation - + Copy to clipboard - + Save plot - + Save plot as - + Load plot @@ -859,7 +831,7 @@ Evaluated expression: %3 - + Error while attempting to draw %1 %2: %3 @@ -1010,7 +982,7 @@ Evaluated expression: %3 - + LogarithmPlotter - Drawing error @@ -1069,32 +1041,32 @@ Evaluated expression: %3 io - + Saved plot to '%1'. - + Loading file '%1'. - + Unknown object type: %1. - + Invalid file provided. - + Could not load file: - + Loaded file '%1'. @@ -1448,6 +1420,11 @@ Please make sure your latex installation is correct and report a bug if so.targetValuePosition + + + labelContent + + sequence diff --git a/common/src/module/history.mjs b/common/src/module/history.mjs index 7406925..2a38730 100644 --- a/common/src/module/history.mjs +++ b/common/src/module/history.mjs @@ -23,9 +23,16 @@ import { Action, Actions } from "../history/index.mjs" -class UpdatedEvent extends BaseEvent { +class ClearedEvent extends BaseEvent { constructor() { - super("updated") + super("cleared") + } +} + +class AddedEvent extends BaseEvent { + constructor(action) { + super("added") + this.action = action } } @@ -44,7 +51,7 @@ class RedoneEvent extends BaseEvent { } class HistoryAPI extends Module { - static emits = ["updated", "undone", "redone"] + static emits = ["cleared", "added", "undone", "redone"] #helper @@ -113,7 +120,7 @@ class HistoryAPI extends Module { if(!this.initialized) throw new Error("Attempting clear before initialize!") this.undoStack = [] this.redoStack = [] - this.emit(new UpdatedEvent()) + this.emit(new ClearedEvent()) } /** @@ -127,7 +134,7 @@ class HistoryAPI extends Module { this.undoStack.push(action) if(this.#helper.getSettingBool("reset_redo_stack")) this.redoStack = [] - this.emit(new UpdatedEvent()) + this.emit(new AddedEvent(action)) } } diff --git a/common/src/module/interface.mjs b/common/src/module/interface.mjs index 1ee65a3..db65ea2 100644 --- a/common/src/module/interface.mjs +++ b/common/src/module/interface.mjs @@ -79,7 +79,6 @@ export class CanvasInterface extends Interface { export class RootInterface extends Interface { width = NUMBER height = NUMBER - updateObjectsLists = FUNCTION } export class DialogInterface extends Interface { diff --git a/common/src/module/io.mjs b/common/src/module/io.mjs index 8ca4b2b..360a8fc 100644 --- a/common/src/module/io.mjs +++ b/common/src/module/io.mjs @@ -22,26 +22,59 @@ import History from "./history.mjs" import Canvas from "./canvas.mjs" import Settings from "./settings.mjs" import { DialogInterface, RootInterface } from "./interface.mjs" +import { BaseEvent } from "../events.mjs" +class LoadedEvent extends BaseEvent { + constructor() { + super("loaded") + } +} + +class SavedEvent extends BaseEvent { + constructor() { + super("saved") + } +} + +class ModifiedEvent extends BaseEvent { + constructor() { + super("modified") + } +} + class IOAPI extends Module { + static emits = ["loaded", "saved", "modified"] + /** @type {RootInterface} */ #rootElement /** @type {{show: function(string)}} */ #alert + #saved = true constructor() { super("IO", { alert: DialogInterface, root: RootInterface }) - /** - * Path of the currently opened file. Empty if no file is opened. - * @type {string} - */ - this.saveFileName = "" + + // Settings.on("changed", this.__emitModified.bind(this)) + console.log("Init IO", this) + History.on("added undone redone", this.__emitModified.bind(this)) } + __emitModified() { + this.#saved = false + this.emit(new ModifiedEvent()) + } + + + /** + * True if no changes have been made since last save, false otherwise. + * @return {boolean} + */ + get saved() { return this.#saved } + /** * Initializes module with QML elements. * @param {RootInterface} root @@ -92,7 +125,7 @@ class IOAPI extends Module { } Helper.write(filename, JSON.stringify(settings)) this.#alert.show(qsTranslate("io", "Saved plot to '%1'.").arg(filename.split("/").pop())) - History.history.saved = true + this.emit(new SavedEvent()) } /** @@ -159,8 +192,6 @@ class IOAPI extends Module { if("history" in data) History.unserialize(...data["history"]) - // Refreshing sidebar - this.#rootElement.updateObjectsLists() } else { error = qsTranslate("io", "Invalid file provided.") } @@ -172,7 +203,7 @@ class IOAPI extends Module { } Canvas.redraw() this.#alert.show(qsTranslate("io", "Loaded file '%1'.").arg(basename)) - History.history.saved = true + this.emit(new LoadedEvent()) } } diff --git a/common/src/objs/bodephase.mjs b/common/src/objs/bodephase.mjs index 9c93bba..800671e 100644 --- a/common/src/objs/bodephase.mjs +++ b/common/src/objs/bodephase.mjs @@ -63,7 +63,7 @@ export default class BodePhase extends ExecutableObject { // Create new point om_0 = Objects.createNewRegisteredObject("Point", [Objects.getNewName("ω"), this.color, "name"]) om_0.labelPosition = this.phase.execute() >= 0 ? "above" : "below" - History.history.addToHistory(new CreateNewObject(om_0.name, "Point", om_0.export())) + History.addToHistory(new CreateNewObject(om_0.name, "Point", om_0.export())) labelPosition = "below" } om_0.requiredBy.push(this) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml index 8c3f2d1..f4e2f35 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml @@ -117,7 +117,7 @@ MenuBar { icon.color: sysPalette.buttonText onTriggered: { var newObj = Modules.Objects.createNewRegisteredObject(modelData) - history.addToHistory(new JS.HistoryLib.CreateNewObject(newObj.name, modelData, newObj.export())) + Modules.History.addToHistory(new JS.HistoryLib.CreateNewObject(newObj.name, modelData, newObj.export())) objectLists.update() } } diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml index d79cc84..aca7943 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml @@ -225,7 +225,7 @@ Item { imageDepth: Screen.devicePixelRatio, fontSize: 14 }) - Modules.History.on("updated undone redone", () => { + Modules.History.on("cleared added undone redone", () => { undoCount = Modules.History.undoStack.length redoCount = Modules.History.redoStack.length }) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml index 51abb46..33967aa 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml @@ -42,7 +42,7 @@ ApplicationWindow { width: 1000 height: 500 color: sysPalette.window - title: "LogarithmPlotter" + title: qsTr("untitled") SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active } SystemPalette { id: sysPaletteIn; colorGroup: SystemPalette.Disabled } @@ -50,9 +50,7 @@ ApplicationWindow { menuBar: appMenu.trueItem AppMenuBar {id: appMenu} - - History { id: history } - + Popup.GreetScreen {} Popup.Preferences {id: preferences} @@ -185,7 +183,7 @@ ApplicationWindow { } onClosing: function(close) { - if(!history.saved) { + if(!Modules.History.saved) { close.accepted = false appMenu.openSaveUnsavedChangesDialog() } @@ -254,8 +252,20 @@ ApplicationWindow { if(evt.property === "saveFilename") { const fileName = evt.newValue.split('/').pop().split('\\').pop() if(fileName !== "") - title = `${fileName}` + title = fileName } }) + Modules.IO.on("saved loaded", (evt) => { + // Refreshing sidebar + console.log(evt.name) + updateObjectsLists() + if(title.endsWith("*")) + title = title.substring(0, title.length-1) + }) + Modules.IO.on("modified", () => { + console.log("modified") + if(!title.endsWith("*")) + title = title+"*" + }) } } diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml index 57ea4ae..1ca75e4 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml @@ -80,7 +80,7 @@ Repeater { variables: propertyType.variables onChanged: function(newExpr) { if(obj[propertyName].toString() != newExpr.toString()) { - history.addToHistory(new JS.HistoryLib.EditedProperty( + Modules.History.addToHistory(new JS.HistoryLib.EditedProperty( obj.name, objType, propertyName, obj[propertyName], newExpr )) @@ -123,7 +123,7 @@ Repeater { // Ensuring old and new values are different to prevent useless adding to history. if(obj[propertyName] != newValueParsed) { - history.addToHistory(new JS.HistoryLib.EditedProperty( + Modules.History.addToHistory(new JS.HistoryLib.EditedProperty( obj.name, objType, propertyName, obj[propertyName], newValueParsed )) @@ -168,7 +168,7 @@ Repeater { return obj[propertyName] } onClicked: { - history.addToHistory(new JS.HistoryLib.EditedProperty( + Modules.History.addToHistory(new JS.HistoryLib.EditedProperty( obj.name, objType, propertyName, obj[propertyName], this.checked )) @@ -209,7 +209,9 @@ Repeater { if(selectedObj == null) { // Creating new object. selectedObj = Modules.Objects.createNewRegisteredObject(propertyType.objType) - history.addToHistory(new JS.HistoryLib.CreateNewObject(selectedObj.name, propertyType.objType, selectedObj.export())) + Modules.History.addToHistory( + new JS.HistoryLib.CreateNewObject(selectedObj.name, propertyType.objType, selectedObj.export()) + ) baseModel = Modules.Objects.getObjectsName(propertyType.objType).concat( isRealObject ? [qsTr("+ Create new %1").arg(Modules.Objects.types[propertyType.objType].displayType())] : []) @@ -219,14 +221,14 @@ Repeater { //Modules.Objects.currentObjects[objType][objIndex].requiredBy = obj[propertyName].filter((obj) => obj.name != obj.name) } obj.requiredBy = obj.requiredBy.filter((obj) => obj.name != obj.name) - history.addToHistory(new JS.HistoryLib.EditedProperty( + Modules.History.addToHistory(new JS.HistoryLib.EditedProperty( obj.name, objType, propertyName, obj[propertyName], selectedObj )) obj[propertyName] = selectedObj } else if(baseModel[newIndex] != obj[propertyName]) { // Ensuring new property is different to not add useless history entries. - history.addToHistory(new JS.HistoryLib.EditedProperty( + Modules.History.addToHistory(new JS.HistoryLib.EditedProperty( obj.name, objType, propertyName, obj[propertyName], baseModel[newIndex] )) @@ -256,7 +258,7 @@ Repeater { onChanged: { var exported = exportModel() - history.addToHistory(new JS.HistoryLib.EditedProperty( + Modules.History.addToHistory(new JS.HistoryLib.EditedProperty( obj.name, objType, propertyName, obj[propertyName], exported )) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml index e2b149b..715602a 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml @@ -112,7 +112,7 @@ Popup.BaseDialog { if(newName in Modules.Objects.currentObjectsByName) { invalidNameDialog.showDialog(newName) } else { - history.addToHistory(new JS.HistoryLib.NameChanged( + Modules.History.addToHistory(new JS.HistoryLib.NameChanged( objEditor.obj.name, objEditor.objType, newName )) Modules.Objects.renameObject(obj.name, newName) @@ -127,13 +127,17 @@ Popup.BaseDialog { id: labelContentProperty height: 30 width: dlgProperties.width - label: qsTr("Label content") + label: qsTranslate("prop", "labelContent") model: [qsTr("null"), qsTr("name"), qsTr("name + value")] property var idModel: ["null", "name", "name + value"] icon: "common/label.svg" currentIndex: idModel.indexOf(objEditor.obj.labelContent) onActivated: function(newIndex) { if(idModel[newIndex] != objEditor.obj.labelContent) { + Modules.History.addToHistory(new JS.HistoryLib.EditedProperty( + obj.name, objType, "labelContent", + objEditor.obj.labelContent, idModel[newIndex] + )) objEditor.obj.labelContent = idModel[newIndex] objEditor.obj.update() objectListList.update() diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectCreationGrid.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectCreationGrid.qml index 7aa9574..e8d4912 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectCreationGrid.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectCreationGrid.qml @@ -104,7 +104,9 @@ Column { onClicked: { let newObj = Modules.Objects.createNewRegisteredObject(modelData) - history.addToHistory(new JS.HistoryLib.CreateNewObject(newObj.name, modelData, newObj.export())) + Modules.History.addToHistory(new JS.HistoryLib.CreateNewObject( + newObj.name, modelData, newObj.export() + )) objectLists.update() let hasXProp = newObj.constructor.properties().hasOwnProperty('x') diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml index 5018e5e..9624d23 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml @@ -72,7 +72,7 @@ Item { anchors.left: parent.left anchors.leftMargin: 5 onClicked: { - history.addToHistory(new JS.HistoryLib.EditedVisibility( + Modules.History.addToHistory(new JS.HistoryLib.EditedVisibility( obj.name, obj.type, this.checked )) obj.visible = this.checked @@ -212,7 +212,7 @@ Item { selectedColor: obj.color title: qsTr("Pick new color for %1 %2").arg(obj.constructor.displayType()).arg(obj.name) onAccepted: { - history.addToHistory(new JS.HistoryLib.ColorChanged( + Modules.History.addToHistory(new JS.HistoryLib.ColorChanged( obj.name, obj.type, obj.color, selectedColor.toString() )) obj.color = selectedColor.toString() @@ -231,7 +231,7 @@ Item { // Object still exists // Temporary fix for objects require not being propertly updated. object.requiredBy = [] - history.addToHistory(new JS.HistoryLib.DeleteObject( + Modules.History.addToHistory(new JS.HistoryLib.DeleteObject( object.name, object.type, object.export() )) Modules.Objects.deleteObject(object.name) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml index 680c310..b364e73 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml @@ -115,7 +115,7 @@ Item { let obj = Modules.Objects.currentObjectsByName[objName] // Set values if(parent.userPickX && parent.userPickY) { - history.addToHistory(new JS.HistoryLib.EditedPosition( + Modules.History.addToHistory(new JS.HistoryLib.EditedPosition( objName, objType, obj[propertyX], newValueX, obj[propertyY], newValueY )) obj[propertyX] = newValueX @@ -124,7 +124,7 @@ Item { objectLists.update() pickerRoot.picked(obj) } else if(parent.userPickX) { - history.addToHistory(new JS.HistoryLib.EditedProperty( + Modules.History.addToHistory(new JS.HistoryLib.EditedProperty( objName, objType, propertyX, obj[propertyX], newValueX )) obj[propertyX] = newValueX @@ -132,7 +132,7 @@ Item { objectLists.update() pickerRoot.picked(obj) } else if(parent.userPickY) { - history.addToHistory(new JS.HistoryLib.EditedProperty( + Modules.History.addToHistory(new JS.HistoryLib.EditedProperty( objName, objType, propertyY, obj[propertyY], newValueY )) obj[propertyY] = newValueY From b91dbfb31100e221553d61657a5b2b1a3835dfc4 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 02:14:42 +0200 Subject: [PATCH 021/104] Finishing touches on putting History off QML. --- common/src/events.mjs | 1 - common/src/module/history.mjs | 10 +- common/src/module/io.mjs | 3 +- .../LogarithmPlotter/History/History.qml | 112 ------------------ .../History/HistoryBrowser.qml | 2 +- .../eu/ad5001/LogarithmPlotter/History/qmldir | 1 - .../LogarithmPlotter/LogarithmPlotter.qml | 2 +- 7 files changed, 12 insertions(+), 119 deletions(-) delete mode 100644 runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/History.qml diff --git a/common/src/events.mjs b/common/src/events.mjs index fbc8228..dbdd00f 100644 --- a/common/src/events.mjs +++ b/common/src/events.mjs @@ -58,7 +58,6 @@ export class BaseEventEmitter { for(const type of eventType.split(" ")) this.on(type, eventListener) else { - console.log("Listening to", eventType) if(!this.constructor.emits.includes(eventType)) { const className = this.constructor.name const eventTypes = this.constructor.emits.join(", ") diff --git a/common/src/module/history.mjs b/common/src/module/history.mjs index 2a38730..6e32fed 100644 --- a/common/src/module/history.mjs +++ b/common/src/module/history.mjs @@ -29,6 +29,12 @@ class ClearedEvent extends BaseEvent { } } +class LoadedEvent extends BaseEvent { + constructor() { + super("loaded") + } +} + class AddedEvent extends BaseEvent { constructor(action) { super("added") @@ -51,7 +57,7 @@ class RedoneEvent extends BaseEvent { } class HistoryAPI extends Module { - static emits = ["cleared", "added", "undone", "redone"] + static emits = ["cleared", "loaded", "added", "undone", "redone"] #helper @@ -154,7 +160,7 @@ class HistoryAPI extends Module { this.redoStack.push( new Actions[name](...args) ) - this.emit(new UpdatedEvent()) + this.emit(new LoadedEvent()) } /** diff --git a/common/src/module/io.mjs b/common/src/module/io.mjs index 360a8fc..472b061 100644 --- a/common/src/module/io.mjs +++ b/common/src/module/io.mjs @@ -59,7 +59,6 @@ class IOAPI extends Module { }) // Settings.on("changed", this.__emitModified.bind(this)) - console.log("Init IO", this) History.on("added undone redone", this.__emitModified.bind(this)) } @@ -125,6 +124,7 @@ class IOAPI extends Module { } Helper.write(filename, JSON.stringify(settings)) this.#alert.show(qsTranslate("io", "Saved plot to '%1'.").arg(filename.split("/").pop())) + this.#saved = true this.emit(new SavedEvent()) } @@ -203,6 +203,7 @@ class IOAPI extends Module { } Canvas.redraw() this.#alert.show(qsTranslate("io", "Loaded file '%1'.").arg(basename)) + this.#saved = true this.emit(new LoadedEvent()) } diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/History.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/History.qml deleted file mode 100644 index 88579e7..0000000 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/History.qml +++ /dev/null @@ -1,112 +0,0 @@ -/** - * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import QtQuick -import QtQml -import QtQuick.Window -import "../js/index.mjs" as JS - -/*! - \qmltype History - \inqmlmodule eu.ad5001.LogarithmPlotter.History - \brief QObject holding persistantly for undo & redo stacks. - - \sa HistoryBrowser, HistoryLib -*/ -Item { - // Using a QtObject is necessary in order to have proper property propagation in QML - id: historyObj - - /*! - \qmlproperty int History::undoCount - Count of undo actions. - */ - property int undoCount: 0 - /*! - \qmlproperty int History::redoCount - Count of redo actions. - */ - property int redoCount: 0 - /*! - \qmlproperty var History::undoStack - Stack of undo actions. - */ - property var undoStack: [] - /*! - \qmlproperty var History::redoStack - Stack of redo actions. - */ - property var redoStack: [] - /*! - \qmlproperty bool History::saved - true when no modification was done to the current working file, false otherwise. - */ - property bool saved: true - - - /*! - \qmlmethod void History::clear() - Clears both undo and redo stacks completly. - */ - function clear() { - Modules.History.clear() - } - - - /*! - \qmlmethod var History::serialize() - Serializes history into JSON-able content. - */ - function serialize() { - return Modules.History.serialize() - } - - /*! - \qmlmethod void History::unserialize(var undoSt, var redoSt) - Unserializes both \c undoSt stack and \c redoSt stack from serialized content. - */ - function unserialize(undoSt, redoSt) { - Modules.History.unserialize(undoSt, redoSt) - } - - /*! - \qmlmethod void History::addToHistory(var action) - Adds an instance of HistoryLib.Action to history. - */ - function addToHistory(action) { - Modules.History.addToHistory(action) - } - - /*! - \qmlmethod void History::undo(bool updateObjectList = true) - Undoes the HistoryLib.Action at the top of the undo stack and pushes it to the top of the redo stack. - By default, will update the graph and the object list. This behavior can be disabled by setting the \c updateObjectList to false. - */ - function undo(updateObjectList = true) { - Modules.History.undo() - } - - /*! - \qmlmethod void History::redo(bool updateObjectList = true) - Redoes the HistoryLib.Action at the top of the redo stack and pushes it to the top of the undo stack. - By default, will update the graph and the object list. This behavior can be disabled by setting the \c updateObjectList to false. - */ - function redo(updateObjectList = true) { - Modules.History.redo() - } -} diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml index aca7943..eb84340 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml @@ -225,7 +225,7 @@ Item { imageDepth: Screen.devicePixelRatio, fontSize: 14 }) - Modules.History.on("cleared added undone redone", () => { + Modules.History.on("cleared loaded added undone redone", () => { undoCount = Modules.History.undoStack.length redoCount = Modules.History.redoStack.length }) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/qmldir b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/qmldir index 4f011a5..7f8a628 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/qmldir +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/qmldir @@ -1,5 +1,4 @@ module eu.ad5001.LogarithmPlotter.History -History 1.0 History.qml HistoryBrowser 1.0 HistoryBrowser.qml HistoryItem 1.0 HistoryItem.qml diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml index 33967aa..e7cfc1a 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml @@ -183,7 +183,7 @@ ApplicationWindow { } onClosing: function(close) { - if(!Modules.History.saved) { + if(!Modules.IO.saved) { close.accepted = false appMenu.openSaveUnsavedChangesDialog() } From 82e6d2ffe3524efb51061a502521e6c2c8a229d1 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 02:35:13 +0200 Subject: [PATCH 022/104] Removing HistoryInterface (no longer needed) --- common/src/module/history.mjs | 2 +- common/src/module/interface.mjs | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/common/src/module/history.mjs b/common/src/module/history.mjs index 6e32fed..be70f87 100644 --- a/common/src/module/history.mjs +++ b/common/src/module/history.mjs @@ -17,7 +17,7 @@ */ import { Module } from "./common.mjs" -import { HelperInterface, HistoryInterface, NUMBER, STRING } from "./interface.mjs" +import { HelperInterface, NUMBER, STRING } from "./interface.mjs" import { BaseEvent } from "../events.mjs" import { Action, Actions } from "../history/index.mjs" diff --git a/common/src/module/interface.mjs b/common/src/module/interface.mjs index db65ea2..2886f73 100644 --- a/common/src/module/interface.mjs +++ b/common/src/module/interface.mjs @@ -85,15 +85,6 @@ export class DialogInterface extends Interface { show = FUNCTION } -export class HistoryInterface extends Interface { - undo = FUNCTION - redo = FUNCTION - clear = FUNCTION - addToHistory = FUNCTION - unserialize = FUNCTION - serialize = FUNCTION -} - export class LatexInterface extends Interface { /** * @param {string} markup - LaTeX markup to render From 00ab895b21212328ab74025e717d932fc175be72 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 02:38:11 +0200 Subject: [PATCH 023/104] Adding x value as argument for derivative objects. --- common/src/module/latex.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/module/latex.mjs b/common/src/module/latex.mjs index a0e8401..8ccbeb5 100644 --- a/common/src/module/latex.mjs +++ b/common/src/module/latex.mjs @@ -157,7 +157,7 @@ class LatexAPI extends Module { if(args.length === 3) return `\\frac{d${args[0].removeEnclosure().replaceAll(args[1].removeEnclosure(), "x")}}{dx}` else - return `\\frac{d${args[0]}}{dx}(x)` + return `\\frac{d${args[0]}}{dx}(${args[1]})` case "integral": if(args.length === 4) return `\\int\\limits_{${args[0]}}^{${args[1]}}${args[2].removeEnclosure()} d${args[3].removeEnclosure()}` From 9017f84c0684399a3e8239d7bfa7c4a7c8a0ad30 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 18:21:03 +0200 Subject: [PATCH 024/104] Updating metadata and python package lock. --- README.md | 2 +- .../eu.ad5001.LogarithmPlotter.metainfo.xml | 38 ++-- runtime-pyside6/poetry.lock | 184 +++++++++--------- runtime-pyside6/pyproject.toml | 4 +- runtime-pyside6/setup.py | 42 ++-- 5 files changed, 132 insertions(+), 138 deletions(-) diff --git a/README.md b/README.md index 8002fe0..ae252fe 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ![icon](https://git.ad5001.eu/Ad5001/LogarithmPlotter/raw/branch/master/LogarithmPlotter/logarithmplotter.svg) LogarithmPlotter +# ![icon](https://apps.ad5001.eu/icons/apps/svg/logarithmplotter.svg) LogarithmPlotter [![Build Status](https://ci.ad5001.eu/api/badges/Ad5001/LogarithmPlotter/status.svg)](https://ci.ad5001.eu/Ad5001/LogarithmPlotter) [![Translation status](https://hosted.weblate.org/widgets/logarithmplotter/-/logarithmplotter/svg-badge.svg)](https://hosted.weblate.org/engage/logarithmplotter/) diff --git a/assets/native/linux/eu.ad5001.LogarithmPlotter.metainfo.xml b/assets/native/linux/eu.ad5001.LogarithmPlotter.metainfo.xml index 6f90a1f..a9dbded 100644 --- a/assets/native/linux/eu.ad5001.LogarithmPlotter.metainfo.xml +++ b/assets/native/linux/eu.ad5001.LogarithmPlotter.metainfo.xml @@ -66,50 +66,54 @@ Science Education - Qt https://apps.ad5001.eu/logarithmplotter/ https://git.ad5001.eu/Ad5001/LogarithmPlotter/issues/ https://git.ad5001.eu/Ad5001/LogarithmPlotter/wiki/ https://hosted.weblate.org/engage/logarithmplotter/ - - https://apps.ad5001.eu/img/en/logarithmplotter/gain.png?v=0.5 - https://apps.ad5001.eu/img/de/logarithmplotter/gain.png?v=0.5 - https://apps.ad5001.eu/img/fr/logarithmplotter/gain.png?v=0.5 - https://apps.ad5001.eu/img/hu/logarithmplotter/gain.png?v=0.5 - https://apps.ad5001.eu/img/no/logarithmplotter/gain.png?v=0.5 + https://apps.ad5001.eu/img/en/logarithmplotter/gain.png?v=0.6 + https://apps.ad5001.eu/img/de/logarithmplotter/gain.png?v=0.6 + https://apps.ad5001.eu/img/fr/logarithmplotter/gain.png?v=0.6 + https://apps.ad5001.eu/img/hu/logarithmplotter/gain.png?v=0.6 + https://apps.ad5001.eu/img/no/logarithmplotter/gain.png?v=0.6 + https://apps.ad5001.eu/img/es/logarithmplotter/gain.png?v=0.6 Main view of LogarithmPlotter showing an asymptotic Bode magnitude plot. Die Hauptansicht des LogarithmPlotters zeigt eine asymptotische Bode-Magnitude-Darstellung. Vue principale de LogarithmPlotter montrant un tracé asymptotique d'une magnitude de Bode. A LogarithmPlotter fő nézete, amely egy aszimptotikus Bode-magnitúdó ábrát mutat. Hovedvisning av LogarithmPlotter som viser et asymptotisk Bode-størrelsesplott. + Vista principal de LogarithmPlotter mostrando un gráfico asintótico de una magnitud de Bode. - https://apps.ad5001.eu/img/en/logarithmplotter/phase.png?v=0.5 - https://apps.ad5001.eu/img/de/logarithmplotter/phase.png?v=0.5 - https://apps.ad5001.eu/img/fr/logarithmplotter/phase.png?v=0.5 - https://apps.ad5001.eu/img/hu/logarithmplotter/phase.png?v=0.5 - https://apps.ad5001.eu/img/no/logarithmplotter/phase.png?v=0.5 + https://apps.ad5001.eu/img/en/logarithmplotter/phase.png?v=0.6 + https://apps.ad5001.eu/img/de/logarithmplotter/phase.png?v=0.6 + https://apps.ad5001.eu/img/fr/logarithmplotter/phase.png?v=0.6 + https://apps.ad5001.eu/img/hu/logarithmplotter/phase.png?v=0.6 + https://apps.ad5001.eu/img/no/logarithmplotter/phase.png?v=0.6 + https://apps.ad5001.eu/img/es/logarithmplotter/phase.png?v=0.6 Main view of LogarithmPlotter showing an asymptotic Bode phase plot. Hauptansicht des LogarithmPlotters mit einer asymptotischen Bode-Phasendarstellung. Vue principale de LogarithmPlotter montrant un tracé asymptotique d'une phase de Bode. A LogarithmPlotter fő nézete, amely egy aszimptotikus Bode-fázis ábrát mutat. Hovedvisning av LogarithmPlotter som viser et asymptotisk Bode-fasediagram. + Vista principal de LogarithmPlotter mostrando un gráfico asintótico de una fase de Bode. - https://apps.ad5001.eu/img/en/logarithmplotter/welcome.png?v=0.5 - https://apps.ad5001.eu/img/de/logarithmplotter/welcome.png?v=0.5 - https://apps.ad5001.eu/img/fr/logarithmplotter/welcome.png?v=0.5 - https://apps.ad5001.eu/img/hu/logarithmplotter/welcome.png?v=0.5 - https://apps.ad5001.eu/img/no/logarithmplotter/welcome.png?v=0.5 + https://apps.ad5001.eu/img/en/logarithmplotter/welcome.png?v=0.6 + https://apps.ad5001.eu/img/de/logarithmplotter/welcome.png?v=0.6 + https://apps.ad5001.eu/img/fr/logarithmplotter/welcome.png?v=0.6 + https://apps.ad5001.eu/img/hu/logarithmplotter/welcome.png?v=0.6 + https://apps.ad5001.eu/img/no/logarithmplotter/welcome.png?v=0.6 + https://apps.ad5001.eu/img/es/logarithmplotter/welcome.png?v=0.6 LogarithmPlotter's welcome page. LogarithmPlotter's Willkommensseite. Page d'accueil de LogarithmPlotter. LogarithmPlotter üdvözlő oldala. LogarithmPlotters velkomstside. + Página de bienvenida de LogarithmPlotter. diff --git a/runtime-pyside6/poetry.lock b/runtime-pyside6/poetry.lock index a4727e1..07252a5 100644 --- a/runtime-pyside6/poetry.lock +++ b/runtime-pyside6/poetry.lock @@ -24,83 +24,73 @@ files = [ [[package]] name = "coverage" -version = "7.6.1" +version = "7.6.2" description = "Code coverage measurement for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16"}, - {file = "coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36"}, - {file = "coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02"}, - {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc"}, - {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23"}, - {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34"}, - {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c"}, - {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959"}, - {file = "coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232"}, - {file = "coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0"}, - {file = "coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93"}, - {file = "coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3"}, - {file = "coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff"}, - {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d"}, - {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6"}, - {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56"}, - {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234"}, - {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133"}, - {file = "coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c"}, - {file = "coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6"}, - {file = "coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778"}, - {file = "coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391"}, - {file = "coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8"}, - {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d"}, - {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca"}, - {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163"}, - {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a"}, - {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d"}, - {file = "coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5"}, - {file = "coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb"}, - {file = "coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106"}, - {file = "coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9"}, - {file = "coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c"}, - {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a"}, - {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060"}, - {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862"}, - {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388"}, - {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155"}, - {file = "coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a"}, - {file = "coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129"}, - {file = "coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e"}, - {file = "coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962"}, - {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb"}, - {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704"}, - {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b"}, - {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f"}, - {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223"}, - {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3"}, - {file = "coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f"}, - {file = "coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657"}, - {file = "coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0"}, - {file = "coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a"}, - {file = "coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b"}, - {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3"}, - {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de"}, - {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6"}, - {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569"}, - {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989"}, - {file = "coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7"}, - {file = "coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8"}, - {file = "coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255"}, - {file = "coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8"}, - {file = "coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2"}, - {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a"}, - {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc"}, - {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004"}, - {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb"}, - {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36"}, - {file = "coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c"}, - {file = "coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca"}, - {file = "coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df"}, - {file = "coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d"}, + {file = "coverage-7.6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c9df1950fb92d49970cce38100d7e7293c84ed3606eaa16ea0b6bc27175bb667"}, + {file = "coverage-7.6.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:24500f4b0e03aab60ce575c85365beab64b44d4db837021e08339f61d1fbfe52"}, + {file = "coverage-7.6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a663b180b6669c400b4630a24cc776f23a992d38ce7ae72ede2a397ce6b0f170"}, + {file = "coverage-7.6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfde025e2793a22efe8c21f807d276bd1d6a4bcc5ba6f19dbdfc4e7a12160909"}, + {file = "coverage-7.6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:087932079c065d7b8ebadd3a0160656c55954144af6439886c8bcf78bbbcde7f"}, + {file = "coverage-7.6.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9c6b0c1cafd96213a0327cf680acb39f70e452caf8e9a25aeb05316db9c07f89"}, + {file = "coverage-7.6.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6e85830eed5b5263ffa0c62428e43cb844296f3b4461f09e4bdb0d44ec190bc2"}, + {file = "coverage-7.6.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:62ab4231c01e156ece1b3a187c87173f31cbeee83a5e1f6dff17f288dca93345"}, + {file = "coverage-7.6.2-cp310-cp310-win32.whl", hash = "sha256:7b80fbb0da3aebde102a37ef0138aeedff45997e22f8962e5f16ae1742852676"}, + {file = "coverage-7.6.2-cp310-cp310-win_amd64.whl", hash = "sha256:d20c3d1f31f14d6962a4e2f549c21d31e670b90f777ef4171be540fb7fb70f02"}, + {file = "coverage-7.6.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bb21bac7783c1bf6f4bbe68b1e0ff0d20e7e7732cfb7995bc8d96e23aa90fc7b"}, + {file = "coverage-7.6.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a7b2e437fbd8fae5bc7716b9c7ff97aecc95f0b4d56e4ca08b3c8d8adcaadb84"}, + {file = "coverage-7.6.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:536f77f2bf5797983652d1d55f1a7272a29afcc89e3ae51caa99b2db4e89d658"}, + {file = "coverage-7.6.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f361296ca7054f0936b02525646b2731b32c8074ba6defab524b79b2b7eeac72"}, + {file = "coverage-7.6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7926d8d034e06b479797c199747dd774d5e86179f2ce44294423327a88d66ca7"}, + {file = "coverage-7.6.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0bbae11c138585c89fb4e991faefb174a80112e1a7557d507aaa07675c62e66b"}, + {file = "coverage-7.6.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fcad7d5d2bbfeae1026b395036a8aa5abf67e8038ae7e6a25c7d0f88b10a8e6a"}, + {file = "coverage-7.6.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f01e53575f27097d75d42de33b1b289c74b16891ce576d767ad8c48d17aeb5e0"}, + {file = "coverage-7.6.2-cp311-cp311-win32.whl", hash = "sha256:7781f4f70c9b0b39e1b129b10c7d43a4e0c91f90c60435e6da8288efc2b73438"}, + {file = "coverage-7.6.2-cp311-cp311-win_amd64.whl", hash = "sha256:9bcd51eeca35a80e76dc5794a9dd7cb04b97f0e8af620d54711793bfc1fbba4b"}, + {file = "coverage-7.6.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ebc94fadbd4a3f4215993326a6a00e47d79889391f5659bf310f55fe5d9f581c"}, + {file = "coverage-7.6.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9681516288e3dcf0aa7c26231178cc0be6cac9705cac06709f2353c5b406cfea"}, + {file = "coverage-7.6.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d9c5d13927d77af4fbe453953810db766f75401e764727e73a6ee4f82527b3e"}, + {file = "coverage-7.6.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b92f9ca04b3e719d69b02dc4a69debb795af84cb7afd09c5eb5d54b4a1ae2191"}, + {file = "coverage-7.6.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ff2ef83d6d0b527b5c9dad73819b24a2f76fdddcfd6c4e7a4d7e73ecb0656b4"}, + {file = "coverage-7.6.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:47ccb6e99a3031ffbbd6e7cc041e70770b4fe405370c66a54dbf26a500ded80b"}, + {file = "coverage-7.6.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a867d26f06bcd047ef716175b2696b315cb7571ccb951006d61ca80bbc356e9e"}, + {file = "coverage-7.6.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cdfcf2e914e2ba653101157458afd0ad92a16731eeba9a611b5cbb3e7124e74b"}, + {file = "coverage-7.6.2-cp312-cp312-win32.whl", hash = "sha256:f9035695dadfb397bee9eeaf1dc7fbeda483bf7664a7397a629846800ce6e276"}, + {file = "coverage-7.6.2-cp312-cp312-win_amd64.whl", hash = "sha256:5ed69befa9a9fc796fe015a7040c9398722d6b97df73a6b608e9e275fa0932b0"}, + {file = "coverage-7.6.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4eea60c79d36a8f39475b1af887663bc3ae4f31289cd216f514ce18d5938df40"}, + {file = "coverage-7.6.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa68a6cdbe1bc6793a9dbfc38302c11599bbe1837392ae9b1d238b9ef3dafcf1"}, + {file = "coverage-7.6.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ec528ae69f0a139690fad6deac8a7d33629fa61ccce693fdd07ddf7e9931fba"}, + {file = "coverage-7.6.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed5ac02126f74d190fa2cc14a9eb2a5d9837d5863920fa472b02eb1595cdc925"}, + {file = "coverage-7.6.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21c0ea0d4db8a36b275cb6fb2437a3715697a4ba3cb7b918d3525cc75f726304"}, + {file = "coverage-7.6.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:35a51598f29b2a19e26d0908bd196f771a9b1c5d9a07bf20be0adf28f1ad4f77"}, + {file = "coverage-7.6.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c9192925acc33e146864b8cf037e2ed32a91fdf7644ae875f5d46cd2ef086a5f"}, + {file = "coverage-7.6.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf4eeecc9e10f5403ec06138978235af79c9a79af494eb6b1d60a50b49ed2869"}, + {file = "coverage-7.6.2-cp313-cp313-win32.whl", hash = "sha256:e4ee15b267d2dad3e8759ca441ad450c334f3733304c55210c2a44516e8d5530"}, + {file = "coverage-7.6.2-cp313-cp313-win_amd64.whl", hash = "sha256:c71965d1ced48bf97aab79fad56df82c566b4c498ffc09c2094605727c4b7e36"}, + {file = "coverage-7.6.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7571e8bbecc6ac066256f9de40365ff833553e2e0c0c004f4482facb131820ef"}, + {file = "coverage-7.6.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:078a87519057dacb5d77e333f740708ec2a8f768655f1db07f8dfd28d7a005f0"}, + {file = "coverage-7.6.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5e92e3e84a8718d2de36cd8387459cba9a4508337b8c5f450ce42b87a9e760"}, + {file = "coverage-7.6.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebabdf1c76593a09ee18c1a06cd3022919861365219ea3aca0247ededf6facd6"}, + {file = "coverage-7.6.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12179eb0575b8900912711688e45474f04ab3934aaa7b624dea7b3c511ecc90f"}, + {file = "coverage-7.6.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:39d3b964abfe1519b9d313ab28abf1d02faea26cd14b27f5283849bf59479ff5"}, + {file = "coverage-7.6.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:84c4315577f7cd511d6250ffd0f695c825efe729f4205c0340f7004eda51191f"}, + {file = "coverage-7.6.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ff797320dcbff57caa6b2301c3913784a010e13b1f6cf4ab3f563f3c5e7919db"}, + {file = "coverage-7.6.2-cp313-cp313t-win32.whl", hash = "sha256:2b636a301e53964550e2f3094484fa5a96e699db318d65398cfba438c5c92171"}, + {file = "coverage-7.6.2-cp313-cp313t-win_amd64.whl", hash = "sha256:d03a060ac1a08e10589c27d509bbdb35b65f2d7f3f8d81cf2fa199877c7bc58a"}, + {file = "coverage-7.6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c37faddc8acd826cfc5e2392531aba734b229741d3daec7f4c777a8f0d4993e5"}, + {file = "coverage-7.6.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab31fdd643f162c467cfe6a86e9cb5f1965b632e5e65c072d90854ff486d02cf"}, + {file = "coverage-7.6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97df87e1a20deb75ac7d920c812e9326096aa00a9a4b6d07679b4f1f14b06c90"}, + {file = "coverage-7.6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:343056c5e0737487a5291f5691f4dfeb25b3e3c8699b4d36b92bb0e586219d14"}, + {file = "coverage-7.6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4ef1c56b47b6b9024b939d503ab487231df1f722065a48f4fc61832130b90e"}, + {file = "coverage-7.6.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7fca4a92c8a7a73dee6946471bce6d1443d94155694b893b79e19ca2a540d86e"}, + {file = "coverage-7.6.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:69f251804e052fc46d29d0e7348cdc5fcbfc4861dc4a1ebedef7e78d241ad39e"}, + {file = "coverage-7.6.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e8ea055b3ea046c0f66217af65bc193bbbeca1c8661dc5fd42698db5795d2627"}, + {file = "coverage-7.6.2-cp39-cp39-win32.whl", hash = "sha256:6c2ba1e0c24d8fae8f2cf0aeb2fc0a2a7f69b6d20bd8d3749fd6b36ecef5edf0"}, + {file = "coverage-7.6.2-cp39-cp39-win_amd64.whl", hash = "sha256:2186369a654a15628e9c1c9921409a6b3eda833e4b91f3ca2a7d9f77abb4987c"}, + {file = "coverage-7.6.2-pp39.pp310-none-any.whl", hash = "sha256:667952739daafe9616db19fbedbdb87917eee253ac4f31d70c7587f7ab531b4e"}, + {file = "coverage-7.6.2.tar.gz", hash = "sha256:a5f81e68aa62bc0cfca04f7b19eaa8f9c826b53fc82ab9e2121976dc74f131f3"}, ] [package.dependencies] @@ -261,36 +251,36 @@ setuptools = ">=42.0.0" [[package]] name = "pyside6-addons" -version = "6.7.3" +version = "6.8.0" description = "Python bindings for the Qt cross-platform application and UI framework (Addons)" optional = false python-versions = "<3.13,>=3.9" files = [ - {file = "PySide6_Addons-6.7.3-cp39-abi3-macosx_11_0_universal2.whl", hash = "sha256:3174cb3a373c09c98740b452e8e8f4945d64cfa18ed8d43964111d570f0dc647"}, - {file = "PySide6_Addons-6.7.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:bde1eb03dbffd089b50cd445847aaecaf4056cea84c49ea592d00f84f247251e"}, - {file = "PySide6_Addons-6.7.3-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:5a9e0df31345fe6caea677d916ea48b53ba86f95cc6499c57f89e392447ad6db"}, - {file = "PySide6_Addons-6.7.3-cp39-abi3-win_amd64.whl", hash = "sha256:d8a19c2b2446407724c81c33ebf3217eaabd092f0f72da8130c17079e04a7813"}, + {file = "PySide6_Addons-6.8.0-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:aebab1e4fe63ebceccae4068768bf20959ab78f7fe01af832458837241334b5c"}, + {file = "PySide6_Addons-6.8.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:4b3be260f9cc415d1a12b77a703ced18b8854f56985f4708cab5618a9554bbd6"}, + {file = "PySide6_Addons-6.8.0-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:7c153a685341683fac82d32926e2204747a83c13ef7b203db8ae9efe27f26a0f"}, + {file = "PySide6_Addons-6.8.0-cp39-abi3-win_amd64.whl", hash = "sha256:8f7f20fb3758995580f1fb8342df3479be51958eca36db2d6f6a3304f31471de"}, ] [package.dependencies] -PySide6-Essentials = "6.7.3" -shiboken6 = "6.7.3" +PySide6-Essentials = "6.8.0" +shiboken6 = "6.8.0" [[package]] name = "pyside6-essentials" -version = "6.7.3" +version = "6.8.0" description = "Python bindings for the Qt cross-platform application and UI framework (Essentials)" optional = false python-versions = "<3.13,>=3.9" files = [ - {file = "PySide6_Essentials-6.7.3-cp39-abi3-macosx_11_0_universal2.whl", hash = "sha256:f9e08a4e9e7dc7b5ab72fde20abce8c97df7af1b802d9743f098f577dfe1f649"}, - {file = "PySide6_Essentials-6.7.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cda6fd26aead48f32e57f044d18aa75dc39265b49d7957f515ce7ac3989e7029"}, - {file = "PySide6_Essentials-6.7.3-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:acdde06b74f26e7d26b4ae1461081b32a6cb17fcaa2a580050b5e0f0f12236c9"}, - {file = "PySide6_Essentials-6.7.3-cp39-abi3-win_amd64.whl", hash = "sha256:f0950fcdcbcd4f2443336dc6a5fe692172adc225f876839583503ded0ab2f2a7"}, + {file = "PySide6_Essentials-6.8.0-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:c2ad37de574ed911ac2dd392e95888ee7354c4bc475259dafc31978efb710a6a"}, + {file = "PySide6_Essentials-6.8.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:da99a94806416ec1e386426a474e7d1e514c1cdf8ad171c005376f4f633e7216"}, + {file = "PySide6_Essentials-6.8.0-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:ae0732228e93eb882c9a93fd510819fb64b7d09d8e500912b485a604537215d6"}, + {file = "PySide6_Essentials-6.8.0-cp39-abi3-win_amd64.whl", hash = "sha256:2ef7138dc7efb9f1153c1dda7a7bd6ac02badad1aa1971cc140d0b9bf962c3dc"}, ] [package.dependencies] -shiboken6 = "6.7.3" +shiboken6 = "6.8.0" [[package]] name = "pytest" @@ -384,15 +374,15 @@ type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11 [[package]] name = "shiboken6" -version = "6.7.3" +version = "6.8.0" description = "Python/C++ bindings helper module" optional = false python-versions = "<3.13,>=3.9" files = [ - {file = "shiboken6-6.7.3-cp39-abi3-macosx_11_0_universal2.whl", hash = "sha256:285fe3cf79be3135fe1ad1e2b9ff6db3a48698887425af6aa6ed7a05a9abc3d6"}, - {file = "shiboken6-6.7.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f0852e5781de78be5b13c140ec4c7fb9734e2aaf2986eb2d6a224363e03efccc"}, - {file = "shiboken6-6.7.3-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:f0dd635178e64a45be2f84c9f33dd79ac30328da87f834f21a0baf69ae210e6e"}, - {file = "shiboken6-6.7.3-cp39-abi3-win_amd64.whl", hash = "sha256:5f29325dfa86fde0274240f1f38e421303749d3174ce3ada178715b5f4719db9"}, + {file = "shiboken6-6.8.0-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:0d3171c496e7474ad29d73686e46e741317a9b29ae9fa30c421fa0360bc10af0"}, + {file = "shiboken6-6.8.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:ad88c0e73c9e4de3723c6e6b846e651729433ff9d9086bb2b4e6d49965477d97"}, + {file = "shiboken6-6.8.0-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:0f62ee7c34337e2c39fff0985694224f7503328c450245c399846b72cd71c410"}, + {file = "shiboken6-6.8.0-cp39-abi3-win_amd64.whl", hash = "sha256:cb98424a1f0c2d6ebf7f6be99660a121b9b22601a058e6b7efeadbc60bcd2182"}, ] [[package]] @@ -418,13 +408,13 @@ files = [ [[package]] name = "tomli" -version = "2.0.1" +version = "2.0.2" description = "A lil' TOML parser" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"}, + {file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"}, ] [[package]] @@ -449,4 +439,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.13" -content-hash = "5636605737f21954e102a0110972e6bd3df07f2d5929f41fe541c7347c3ecf08" +content-hash = "fad810a5ba9b4cb5ab759c9b5641ccba2b735e12064e510c0bfe0f4766c576f1" diff --git a/runtime-pyside6/pyproject.toml b/runtime-pyside6/pyproject.toml index 5293365..cafc0cb 100644 --- a/runtime-pyside6/pyproject.toml +++ b/runtime-pyside6/pyproject.toml @@ -9,8 +9,8 @@ package-mode = false [tool.poetry.dependencies] python = ">=3.9,<3.13" -PySide6-Essentials = "^6.7" -PySide6-Addons = "^6.7" +PySide6-Essentials = "^6.8" +PySide6-Addons = "^6.8" [tool.poetry.group.packaging.dependencies] pyinstaller = "^6.10.0" diff --git a/runtime-pyside6/setup.py b/runtime-pyside6/setup.py index 08769a6..f76f1d7 100644 --- a/runtime-pyside6/setup.py +++ b/runtime-pyside6/setup.py @@ -26,27 +26,27 @@ print(sys.argv) current_dir = os.path.realpath(os.path.dirname(os.path.realpath(__file__))) # Check where to install by default -if "PREFIX" not in os.environ and sys.platform == 'linux': - from getopt import getopt - optlist, args = getopt(sys.argv, '', ['prefix=', 'root=']) - for arg,value in optlist: - if arg == "prefix" or arg == "root": - os.environ["PREFIX"] = value - if "PREFIX" not in os.environ and sys.platform == 'linux': - if "XDG_DATA_HOME" in os.environ: - os.environ["PREFIX"] = os.environ["XDG_DATA_HOME"] - else: - try: - # Checking if we have permission to write to root. - from os import makedirs, rmdir - makedirs("/usr/share/applications/test") - rmdir("/usr/share/applications/test") - os.environ["PREFIX"] = "/usr/share" - except: - if ".pybuild" in os.environ["HOME"]: # Launchpad building. - os.environ["PREFIX"] = "share" - else: - os.environ["PREFIX"] = os.environ["HOME"] + "/.local/share" +# if "PREFIX" not in os.environ and sys.platform == 'linux': +# from getopt import getopt +# optlist, args = getopt(sys.argv, '', ['prefix=', 'root=']) +# for arg,value in optlist: +# if arg == "prefix" or arg == "root": +# os.environ["PREFIX"] = value +# if "PREFIX" not in os.environ and sys.platform == 'linux': +# if "XDG_DATA_HOME" in os.environ: +# os.environ["PREFIX"] = os.environ["XDG_DATA_HOME"] +# else: +# try: +# # Checking if we have permission to write to root. +# from os import makedirs, rmdir +# makedirs("/usr/share/applications/test") +# rmdir("/usr/share/applications/test") +# os.environ["PREFIX"] = "/usr/share" +# except: +# if ".pybuild" in os.environ["HOME"]: # Launchpad building. +# os.environ["PREFIX"] = "share" +# else: +# os.environ["PREFIX"] = os.environ["HOME"] + "/.local/share" from LogarithmPlotter import __VERSION__ as pkg_version From f3307b47d98c17a95906aee5eae168400e623cd3 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 19:05:34 +0200 Subject: [PATCH 025/104] Fixing bug with saving files --- common/src/module/settings.mjs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/src/module/settings.mjs b/common/src/module/settings.mjs index 1530839..e6313c7 100644 --- a/common/src/module/settings.mjs +++ b/common/src/module/settings.mjs @@ -118,6 +118,12 @@ class SettingsAPI extends Module { this.emit(new ChangedEvent(property, oldValue, value, byUser === true)) } + /** + * Name of the currently opened file. + * @returns {string} + */ + get saveFilename() { return this.#properties.get("saveFilename") } + /** * Zoom on the x axis of the diagram. * @returns {number} From 84adc787e5aaa1d25118da82fba00c304045712b Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 19:05:53 +0200 Subject: [PATCH 026/104] Fixing typo in Spanish translation --- assets/i18n/lp_es.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/i18n/lp_es.ts b/assets/i18n/lp_es.ts index 7a736b5..f365aef 100644 --- a/assets/i18n/lp_es.ts +++ b/assets/i18n/lp_es.ts @@ -335,7 +335,7 @@ Welcome to LogarithmPlotter - Bienvenid@ a LogarithmPlotter + Bienvenido a LogarithmPlotter From 5745587c728977be51c3a90082efd944794e1922 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 19:06:15 +0200 Subject: [PATCH 027/104] Fixing git version detection. --- runtime-pyside6/LogarithmPlotter/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime-pyside6/LogarithmPlotter/__init__.py b/runtime-pyside6/LogarithmPlotter/__init__.py index 2bd4967..0c5cbbb 100644 --- a/runtime-pyside6/LogarithmPlotter/__init__.py +++ b/runtime-pyside6/LogarithmPlotter/__init__.py @@ -29,7 +29,7 @@ if not is_release and which('git') is not None: # Command to check date of latest git commit cmd = ['git', 'log', '--format=%ci', '-n 1'] - cwd = realpath(join(dirname(__file__), '..')) # Root AccountFree directory. + cwd = realpath(join(dirname(__file__), '..', '..', '..')) # Root LogarithmPlotter directory. if exists(join(cwd, '.git')): date_str = check_output(cmd, cwd=cwd).decode('utf-8').split(' ')[0] try: From 7935d0134d89050111c5a14010371e22c04095de Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 19:06:33 +0200 Subject: [PATCH 028/104] Fixing wrap on Greet Screen buttons in certain locales. --- .../qml/eu/ad5001/LogarithmPlotter/Popup/GreetScreen.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/GreetScreen.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/GreetScreen.qml index 09e16e5..5a1ff21 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/GreetScreen.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/GreetScreen.qml @@ -141,7 +141,7 @@ Popup { horizontalAlignment: Text.AlignHCenter font.pixelSize: 14 text: modelData.name - wrapMode: Text.WordWrap + wrapMode: Text.Wrap clip: true } } From c592b9221298de9565155f831e6bf1a0b837e4a8 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 17:18:21 +0000 Subject: [PATCH 029/104] Translated using Weblate (Spanish) Currently translated at 100.0% (265 of 265 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/ --- assets/i18n/lp_es.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/i18n/lp_es.ts b/assets/i18n/lp_es.ts index f365aef..7a736b5 100644 --- a/assets/i18n/lp_es.ts +++ b/assets/i18n/lp_es.ts @@ -335,7 +335,7 @@ Welcome to LogarithmPlotter - Bienvenido a LogarithmPlotter + Bienvenid@ a LogarithmPlotter From 07e58a3a55e60d360be9f84041816bf74065151b Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 19:59:13 +0000 Subject: [PATCH 030/104] Translated using Weblate (French) Currently translated at 100.0% (265 of 265 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/ --- assets/i18n/lp_fr.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/i18n/lp_fr.ts b/assets/i18n/lp_fr.ts index b693568..42f084f 100644 --- a/assets/i18n/lp_fr.ts +++ b/assets/i18n/lp_fr.ts @@ -146,7 +146,7 @@ &Changelog - &Historique des modifications + &Notes de version @@ -194,7 +194,7 @@ Fetching changelog... - Récupération de l'historique des modifications… + Récupération des notes de version… @@ -341,7 +341,7 @@ Welcome to LogarithmPlotter - Bienvenue sur LogarithmPlotter + Bienvenu•e sur LogarithmPlotter @@ -382,7 +382,7 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Changelog - Historique des modifications + Notes de version @@ -879,12 +879,12 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Could not fetch changelog: Server error {}. - Impossible de récupérer l'historique des modifications : Erreur de serveur {}. + Impossible de récupérer les notes de version : Erreur de serveur {}. Could not fetch update: {}. - Impossible de récupérer l'historique des modifications : {}. + Impossible de récupérer les notes de version : {}. From 8a878b4cc12bd13a9546265dddc486cb9bc93c1a Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 22:04:12 +0200 Subject: [PATCH 031/104] Storing LaTeX renders in cache directory instead of temporary to store them for later use. + Makes reponening files instantaneous. + Improves performance of 'base state' objects (e.g. A = (1, 0) or f(x) = x). --- .../LogarithmPlotter/logarithmplotter.py | 2 +- .../LogarithmPlotter/util/helper.py | 2 +- .../LogarithmPlotter/util/latex.py | 27 +++++++++++++------ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/runtime-pyside6/LogarithmPlotter/logarithmplotter.py b/runtime-pyside6/LogarithmPlotter/logarithmplotter.py index 3264097..d620da8 100644 --- a/runtime-pyside6/LogarithmPlotter/logarithmplotter.py +++ b/runtime-pyside6/LogarithmPlotter/logarithmplotter.py @@ -164,7 +164,7 @@ def run(): app.installEventFilter(macos_file_open_handler) helper = Helper(pwd, tmpfile) - latex = Latex(tempdir) + latex = Latex() engine, js_globals = create_engine(helper, latex, dep_time) if len(engine.rootObjects()) == 0: # No root objects loaded diff --git a/runtime-pyside6/LogarithmPlotter/util/helper.py b/runtime-pyside6/LogarithmPlotter/util/helper.py index d2fe631..6db4570 100644 --- a/runtime-pyside6/LogarithmPlotter/util/helper.py +++ b/runtime-pyside6/LogarithmPlotter/util/helper.py @@ -42,7 +42,7 @@ def show_message(msg: str) -> None: Shows a GUI message if GUI messages are enabled """ if SHOW_GUI_MESSAGES: - QMessageBox.warning(None, "LogarithmPlotter", msg, QMessageBox.OK) + QMessageBox.warning(None, "LogarithmPlotter", msg) else: raise InvalidFileException(msg) diff --git a/runtime-pyside6/LogarithmPlotter/util/latex.py b/runtime-pyside6/LogarithmPlotter/util/latex.py index 2c650ce..8f75aa8 100644 --- a/runtime-pyside6/LogarithmPlotter/util/latex.py +++ b/runtime-pyside6/LogarithmPlotter/util/latex.py @@ -20,13 +20,23 @@ from PySide6.QtCore import QObject, Slot, Property, QCoreApplication from PySide6.QtGui import QImage, QColor from PySide6.QtWidgets import QMessageBox -from os import path, remove +from os import path, remove, environ, makedirs from string import Template -from tempfile import TemporaryDirectory from subprocess import Popen, TimeoutExpired, PIPE +from platform import system +from hashlib import sha512 from shutil import which from sys import argv +CACHE_PATH = { + "Linux": path.join(environ["XDG_CONFIG_HOME"], "LogarithmPlotter") + if "XDG_CONFIG_HOME" in environ else + path.join(path.expanduser("~"), ".cache", "LogarithmPlotter"), + "Windows": path.join(path.expandvars('%APPDATA%'), "LogarithmPlotter", "cache"), + "Darwin": path.join(path.expanduser("~"), "Library", "Caches", "LogarithmPlotter"), +}[system()] + + """ Searches for a valid Latex and DVIPNG (http://savannah.nongnu.org/projects/dvipng/) installation and collects the binary path in the DVIPNG_PATH variable. @@ -75,9 +85,10 @@ class Latex(QObject): dvipng to be installed on the system. """ - def __init__(self, tempdir: TemporaryDirectory): + def __init__(self): QObject.__init__(self) - self.tempdir = tempdir + self.tempdir = path.join(CACHE_PATH, "latex") + makedirs(self.tempdir, exist_ok=True) @Property(bool) def latexSupported(self) -> bool: @@ -117,7 +128,7 @@ class Latex(QObject): if self.latexSupported and not path.exists(export_path + ".png"): print("Rendering", latex_markup, export_path) # Generating file - latex_path = path.join(self.tempdir.name, str(markup_hash)) + latex_path = path.join(self.tempdir, str(markup_hash)) # If the formula is just recolored or the font is just changed, no need to recreate the DVI. if not path.exists(latex_path + ".dvi"): self.create_latex_doc(latex_path, latex_markup) @@ -148,8 +159,8 @@ class Latex(QObject): """ Standardizes export path for renders. """ - markup_hash = "render" + str(hash(latex_markup)) - export_path = path.join(self.tempdir.name, f'{markup_hash}_{int(font_size)}_{color.rgb()}') + markup_hash = "render" + str(sha512(latex_markup.encode()).hexdigest()) + export_path = path.join(self.tempdir, f'{markup_hash}_{int(font_size)}_{color.rgb()}') return markup_hash, export_path def create_latex_doc(self, export_path: str, latex_markup: str): @@ -193,7 +204,7 @@ class Latex(QObject): Runs a subprocess and handles exceptions and messages them to the user. """ cmd = " ".join(process) - proc = Popen(process, stdout=PIPE, stderr=PIPE, cwd=self.tempdir.name) + proc = Popen(process, stdout=PIPE, stderr=PIPE, cwd=self.tempdir) try: out, err = proc.communicate(timeout=2) # 2 seconds is already FAR too long. if proc.returncode != 0: From e2d259f8669e74a1a5897d3264a066d5a6f71000 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 22:18:35 +0200 Subject: [PATCH 032/104] Fixing French localization. --- assets/i18n/lp_fr.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/i18n/lp_fr.ts b/assets/i18n/lp_fr.ts index 42f084f..fd806a2 100644 --- a/assets/i18n/lp_fr.ts +++ b/assets/i18n/lp_fr.ts @@ -341,7 +341,7 @@ Welcome to LogarithmPlotter - Bienvenu•e sur LogarithmPlotter + Bienvenu·e sur LogarithmPlotter From 42d5add810932625335b9f675eb4e5a48c81560d Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 11 Oct 2024 22:33:57 +0200 Subject: [PATCH 033/104] Fixing tests and LaTeX --- .../LogarithmPlotter/logarithmplotter.py | 33 ++++++++++++------- .../LogarithmPlotter/util/latex.py | 13 ++------ .../LogarithmPlotter/util/native.py | 4 +++ runtime-pyside6/tests/test_latex.py | 2 +- runtime-pyside6/tests/test_main.py | 11 +++---- runtime-pyside6/tests/test_update.py | 2 +- 6 files changed, 35 insertions(+), 30 deletions(-) diff --git a/runtime-pyside6/LogarithmPlotter/logarithmplotter.py b/runtime-pyside6/LogarithmPlotter/logarithmplotter.py index d620da8..115083a 100644 --- a/runtime-pyside6/LogarithmPlotter/logarithmplotter.py +++ b/runtime-pyside6/LogarithmPlotter/logarithmplotter.py @@ -17,9 +17,9 @@ """ from os import getcwd, chdir, environ, path -from platform import release as os_release +from platform import system as os_name, release as OS_RELEASE from sys import path as sys_path -from sys import platform, argv, exit +from sys import argv, exit from tempfile import TemporaryDirectory from time import time @@ -49,6 +49,18 @@ from LogarithmPlotter.util.helper import Helper from LogarithmPlotter.util.latex import Latex from LogarithmPlotter.util.js import PyJSValue +OS_NAME = os_name() + + +CACHE_PATH = { + "Linux": path.join(environ["XDG_CONFIG_HOME"], "LogarithmPlotter") + if "XDG_CONFIG_HOME" in environ else + path.join(path.expanduser("~"), ".cache", "LogarithmPlotter"), + "Windows": path.join(path.expandvars('%APPDATA%'), "LogarithmPlotter", "cache"), + "Darwin": path.join(path.expanduser("~"), "Library", "Caches", "LogarithmPlotter"), +}[OS_NAME] + + LINUX_THEMES = { # See https://specifications.freedesktop.org/menu-spec/latest/onlyshowin-registry.html "COSMIC": "Basic", "GNOME": "Basic", @@ -82,11 +94,10 @@ def get_linux_theme() -> str: def get_platform_qt_style(os) -> str: return { - "linux": get_linux_theme(), - "freebsd": get_linux_theme(), - "win32": "Universal" if os_release() in ["10", "11", "12", "13", "14"] else "Windows", - "cygwin": "Fusion", - "darwin": "macOS" + "Linux": get_linux_theme(), + "Windows": "Universal" if OS_RELEASE() in ["10", "11", "12", "13", "14"] else "Windows", + "Darwin": "macOS", + "Android": "Material" }[os] @@ -147,7 +158,7 @@ def run(): config.init() if not 'QT_QUICK_CONTROLS_STYLE' in environ: - QQuickStyle.setStyle(get_platform_qt_style(platform)) + QQuickStyle.setStyle(get_platform_qt_style(OS_NAME)) dep_time = time() print("Loaded dependencies in " + str((dep_time - start_time) * 1000) + "ms.") @@ -159,12 +170,12 @@ def run(): # Installing macOS file handler. macos_file_open_handler = None - if platform == "darwin": + if OS_NAME == "Darwin": macos_file_open_handler = native.MacOSFileOpenHandler() app.installEventFilter(macos_file_open_handler) helper = Helper(pwd, tmpfile) - latex = Latex() + latex = Latex(CACHE_PATH) engine, js_globals = create_engine(helper, latex, dep_time) if len(engine.rootObjects()) == 0: # No root objects loaded @@ -177,7 +188,7 @@ def run(): js_globals.Modules.IO.loadDiagram(argv[-1]) chdir(path.dirname(path.realpath(__file__))) - if platform == "darwin": + if OS_NAME == "Darwin": macos_file_open_handler.init_io(js_globals.Modules.IO) # Check for LaTeX installation if LaTeX support is enabled diff --git a/runtime-pyside6/LogarithmPlotter/util/latex.py b/runtime-pyside6/LogarithmPlotter/util/latex.py index 8f75aa8..df32d46 100644 --- a/runtime-pyside6/LogarithmPlotter/util/latex.py +++ b/runtime-pyside6/LogarithmPlotter/util/latex.py @@ -23,19 +23,10 @@ from PySide6.QtWidgets import QMessageBox from os import path, remove, environ, makedirs from string import Template from subprocess import Popen, TimeoutExpired, PIPE -from platform import system from hashlib import sha512 from shutil import which from sys import argv -CACHE_PATH = { - "Linux": path.join(environ["XDG_CONFIG_HOME"], "LogarithmPlotter") - if "XDG_CONFIG_HOME" in environ else - path.join(path.expanduser("~"), ".cache", "LogarithmPlotter"), - "Windows": path.join(path.expandvars('%APPDATA%'), "LogarithmPlotter", "cache"), - "Darwin": path.join(path.expanduser("~"), "Library", "Caches", "LogarithmPlotter"), -}[system()] - """ Searches for a valid Latex and DVIPNG (http://savannah.nongnu.org/projects/dvipng/) @@ -85,9 +76,9 @@ class Latex(QObject): dvipng to be installed on the system. """ - def __init__(self): + def __init__(self, cache_path): QObject.__init__(self) - self.tempdir = path.join(CACHE_PATH, "latex") + self.tempdir = path.join(cache_path, "latex") makedirs(self.tempdir, exist_ok=True) @Property(bool) diff --git a/runtime-pyside6/LogarithmPlotter/util/native.py b/runtime-pyside6/LogarithmPlotter/util/native.py index 7e32119..aefc310 100644 --- a/runtime-pyside6/LogarithmPlotter/util/native.py +++ b/runtime-pyside6/LogarithmPlotter/util/native.py @@ -49,3 +49,7 @@ class MacOSFileOpenHandler(QObject): else: # standard event processing return QObject.eventFilter(self, obj, event) + + + + diff --git a/runtime-pyside6/tests/test_latex.py b/runtime-pyside6/tests/test_latex.py index f02832e..d74f9f1 100644 --- a/runtime-pyside6/tests/test_latex.py +++ b/runtime-pyside6/tests/test_latex.py @@ -31,7 +31,7 @@ latex.SHOW_GUI_MESSAGES = False @pytest.fixture() def latex_obj(): directory = TemporaryDirectory() - obj = latex.Latex(directory) + obj = latex.Latex(directory.name) if not obj.checkLatexInstallation(): raise Exception("Cannot run LaTeX tests without a proper LaTeX installation. Make sure to install a LaTeX distribution, DVIPNG, and the calligra package, and run the tests again.") yield obj diff --git a/runtime-pyside6/tests/test_main.py b/runtime-pyside6/tests/test_main.py index d8a56b6..047e21f 100644 --- a/runtime-pyside6/tests/test_main.py +++ b/runtime-pyside6/tests/test_main.py @@ -39,11 +39,10 @@ THEMES = [ ] OS_PLATFORMS = [ - "linux", - "freebsd", - "win32", - "cygwin", - "darwin" + "Linux", + "Windows", + "Darwin", + "Android" ] @pytest.fixture() @@ -91,7 +90,7 @@ class TestMain: # Engine tmpfile, tempdir = temporary helper = Helper(".", tmpfile) - latex = Latex(tempdir) + latex = Latex(tempdir.name) engine, js_globals = create_engine(helper, latex, 0) assert len(engine.rootObjects()) > 0 # QML File loaded. assert type(engine.rootContext().contextProperty("TestBuild")) is bool diff --git a/runtime-pyside6/tests/test_update.py b/runtime-pyside6/tests/test_update.py index 9f65597..5e1a705 100644 --- a/runtime-pyside6/tests/test_update.py +++ b/runtime-pyside6/tests/test_update.py @@ -60,7 +60,7 @@ def test_update(qtbot): def test_update_checker(qtbot): update_info = check_for_updates('0.6.0', MockWindow()) - assert QThreadPool.globalInstance().activeThreadCount() == 1 + assert QThreadPool.globalInstance().activeThreadCount() >= 1 qtbot.waitSignal(update_info.got_update_info, timeout=10000) argv.append("--no-check-for-updates") update_info = check_for_updates('0.6.0', MockWindow()) From 0abb22130f4dca37a310afe9c7a09427ee068f47 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sat, 12 Oct 2024 00:40:46 +0200 Subject: [PATCH 034/104] Disable domain tests, started base tests. --- common/package-lock.json | 25 +++++++ common/package.json | 2 + common/src/events.mjs | 3 +- common/test/general/events.mjs | 122 +++++++++++++++++++++++++++++++++ common/test/hooks.mjs | 2 - common/test/math/domain.mjs | 86 +++++++++++------------ 6 files changed, 194 insertions(+), 46 deletions(-) create mode 100644 common/test/general/events.mjs diff --git a/common/package-lock.json b/common/package-lock.json index b90e4f5..ee15bf5 100644 --- a/common/package-lock.json +++ b/common/package-lock.json @@ -19,9 +19,11 @@ }, "devDependencies": { "@types/chai": "^5.0.0", + "@types/chai-spies": "^1.0.6", "@types/mocha": "^10.0.8", "chai": "^5.1.1", "chai-as-promised": "^8.0.0", + "chai-spies": "^1.1.0", "esm": "^3.2.25", "mocha": "^10.7.3" } @@ -2199,6 +2201,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/chai-spies": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/chai-spies/-/chai-spies-1.0.6.tgz", + "integrity": "sha512-xkk4HmhBB9OQeTAifa9MJ+6R5/Rq9+ungDe4JidZD+vqZVeiWZwc2i7/pd1ZKjyGlSBIQePoWdyUyFUGT0rv5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -2514,6 +2526,19 @@ "chai": ">= 2.1.2 < 6" } }, + "node_modules/chai-spies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/chai-spies/-/chai-spies-1.1.0.tgz", + "integrity": "sha512-ikaUhQvQWchRYj2K54itFp3nrcxaFRpSDQxDlRzSn9aWgu9Pi7lD8yFxTso4WnQ39+WZ69oB/qOvqp+isJIIWA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + }, + "peerDependencies": { + "chai": "*" + } + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", diff --git a/common/package.json b/common/package.json index 9ef203c..6940d87 100644 --- a/common/package.json +++ b/common/package.json @@ -24,9 +24,11 @@ }, "devDependencies": { "@types/chai": "^5.0.0", + "@types/chai-spies": "^1.0.6", "@types/mocha": "^10.0.8", "chai": "^5.1.1", "chai-as-promised": "^8.0.0", + "chai-spies": "^1.1.0", "esm": "^3.2.25", "mocha": "^10.7.3" } diff --git a/common/src/events.mjs b/common/src/events.mjs index dbdd00f..702fc7d 100644 --- a/common/src/events.mjs +++ b/common/src/events.mjs @@ -79,7 +79,8 @@ export class BaseEventEmitter { if(eventType.includes(" ")) { // Unlisten to several different events with the same listener. let found = false for(const type of eventType.split(" ")) - found ||= this.off(eventType, eventListener) + found ||= this.off(type, eventListener) + return found } else { if(!this.constructor.emits.includes(eventType)) { const className = this.constructor.name diff --git a/common/test/general/events.mjs b/common/test/general/events.mjs new file mode 100644 index 0000000..f82875f --- /dev/null +++ b/common/test/general/events.mjs @@ -0,0 +1,122 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import { BaseEventEmitter, BaseEvent } from "../../src/events.mjs" + +import { describe, it } from "mocha" +import { expect, use } from "chai" +import spies from "chai-spies" + +// Setting up modules +const { spy } = use(spies) + + +class MockEmitter extends BaseEventEmitter { + static emits = ["example1", "example2"] +} + +class MockEvent1 extends BaseEvent { + constructor() { + super("example1") + } +} + +class MockEvent2 extends BaseEvent { + constructor(parameter) { + super("example2") + this.parameter = parameter + } +} + +const sandbox = spy.sandbox() + +describe("Events", function() { + + afterEach(() => { + sandbox.restore() + }) + + it("should forward events to all of its listeners", function() { + const emitter = new MockEmitter() + const listener1 = spy() + const listener2 = spy() + emitter.on("example1", listener1) + emitter.on("example1", listener2) + emitter.emit(new MockEvent1()) + expect(listener1).to.have.been.called.once + expect(listener2).to.have.been.called.once + }) + + it("should forward multiple events to a singular listener", function() { + const emitter = new MockEmitter() + const listener = spy() + const mockEvent1 = new MockEvent1() + const mockEvent2 = new MockEvent2(3) + emitter.on("example1 example2", listener) + emitter.emit(mockEvent1) + emitter.emit(mockEvent2) + expect(listener).to.have.been.called.twice + expect(listener).to.have.been.called.with.exactly(mockEvent1) + expect(listener).to.have.been.called.with.exactly(mockEvent2) + }) + + it("should be able to remove listeners", function() { + const emitter = new MockEmitter() + const listener = spy() + emitter.on("example1", listener) + const removedFromEventItDoesntListenTo = emitter.off("example2", listener) + const removedFromEventItListensTo = emitter.off("example1", listener) + const removedFromEventASecondTime = emitter.off("example1", listener) + expect(removedFromEventItDoesntListenTo).to.be.false + expect(removedFromEventItListensTo).to.be.true + expect(removedFromEventASecondTime).to.be.false + emitter.on("example1 example2", listener) + const removedFromBothEvents = emitter.off("example1 example2", listener) + expect(removedFromBothEvents).to.be.true + emitter.on("example1", listener) + const removedFromOneOfTheEvents = emitter.off("example1 example2", listener) + expect(removedFromOneOfTheEvents).to.be.true + }) + + it("should be able to remove listening to one event when listener listens to multiple", function() { + const emitter = new MockEmitter() + const listener = spy() + const mockEvent1 = new MockEvent1() + const mockEvent2 = new MockEvent2(3) + emitter.on("example1 example2", listener) + // Disable listener for example1 + emitter.off("example1", listener) + emitter.emit(mockEvent1) + emitter.emit(mockEvent2) + expect(listener).to.have.been.called.once + expect(listener).to.have.been.called.with.exactly(mockEvent2) + }) + + it("shouldn't be able to listen/unlisten/emit inexistant events", function() { + const emitter = new MockEmitter() + const listener = spy() + expect(() => emitter.on("inexistant", listener)).to.throw(Error) + expect(() => emitter.off("inexistant", listener)).to.throw(Error) + expect(() => emitter.emit(new BaseEvent("inexistant"))).to.throw(Error) + }) + + it("shouldn't be able to emit non-events", function() { + const emitter = new MockEmitter() + expect(() => emitter.emit("not-an-event")).to.throw(Error) + }) +}) \ No newline at end of file diff --git a/common/test/hooks.mjs b/common/test/hooks.mjs index e48525e..0f3ebda 100644 --- a/common/test/hooks.mjs +++ b/common/test/hooks.mjs @@ -19,12 +19,10 @@ import * as fs from "./mock/fs.mjs"; import Qt from "./mock/qt.mjs"; import { MockHelper } from "./mock/helper.mjs"; import { MockLatex } from "./mock/latex.mjs"; -import Modules from "../src/module/index.mjs"; function setup() { globalThis.Helper = new MockHelper() globalThis.Latex = new MockLatex() - Modules.Latex.initialize({ latex: Latex, helper: Helper }) } setup() diff --git a/common/test/math/domain.mjs b/common/test/math/domain.mjs index c00384f..e32dbd1 100644 --- a/common/test/math/domain.mjs +++ b/common/test/math/domain.mjs @@ -19,46 +19,46 @@ import { describe, it } from "mocha" import { expect } from "chai" -import { Domain, parseDomainSimple } from "../../src/math/domain.mjs" - -describe("math.domain", function() { - describe("#parseDomainSimple", function() { - it("returns predefined domains", function() { - const predefinedToCheck = [ - // Real domains - { domain: Domain.R, shortcuts: ["R", "ℝ"] }, - // Zero exclusive real domains - { domain: Domain.RE, shortcuts: ["RE", "R*", "ℝ*"] }, - // Real positive domains - { domain: Domain.RP, shortcuts: ["RP", "R+", "ℝ⁺", "ℝ+"] }, - // Zero-exclusive real positive domains - { domain: Domain.RPE, shortcuts: ["RPE", "REP", "R+*", "R*+", "ℝ*⁺", "ℝ⁺*", "ℝ*+", "ℝ+*"] }, - // Real negative domain - { domain: Domain.RM, shortcuts: ["RM", "R-", "ℝ⁻", "ℝ-"] }, - // Zero-exclusive real negative domains - { domain: Domain.RME, shortcuts: ["RME", "REM", "R-*", "R*-", "ℝ⁻*", "ℝ*⁻", "ℝ-*", "ℝ*-"] }, - // Natural integers domain - { domain: Domain.N, shortcuts: ["ℕ", "N", "ZP", "Z+", "ℤ⁺", "ℤ+"] }, - // Zero-exclusive natural integers domain - { domain: Domain.NE, shortcuts: ["NE", "NP", "N*", "N+", "ℕ*", "ℕ⁺", "ℕ+", "ZPE", "ZEP", "Z+*", "Z*+", "ℤ⁺*", "ℤ*⁺", "ℤ+*", "ℤ*+"] }, - // Logarithmic natural domains - { domain: Domain.NLog, shortcuts: ["NLOG", "ℕˡᵒᵍ", "ℕLOG"] }, - // All integers domains - { domain: Domain.Z, shortcuts: ["Z", "ℤ"] }, - // Zero-exclusive all integers domain - { domain: Domain.ZE, shortcuts: ["ZE", "Z*", "ℤ*"] }, - // Negative integers domain - { domain: Domain.ZM, shortcuts: ["ZM", "Z-", "ℤ⁻", "ℤ-"] }, - // Zero-exclusive negative integers domain - { domain: Domain.ZME, shortcuts: ["ZME", "ZEM", "Z-*", "Z*-", "ℤ⁻*", "ℤ*⁻", "ℤ-*", "ℤ*-"] }, - ] - - // Real domains - for(const { domain, shortcuts } of predefinedToCheck) - for(const shortcut of shortcuts) - expect(parseDomainSimple(shortcut)).to.be.equal(domain) - }) - - it("") - }) -}) +// import { Domain, parseDomainSimple } from "../../src/math/domain.mjs" +// +// describe("math.domain", function() { +// describe("#parseDomainSimple", function() { +// it("returns predefined domains", function() { +// const predefinedToCheck = [ +// // Real domains +// { domain: Domain.R, shortcuts: ["R", "ℝ"] }, +// // Zero exclusive real domains +// { domain: Domain.RE, shortcuts: ["RE", "R*", "ℝ*"] }, +// // Real positive domains +// { domain: Domain.RP, shortcuts: ["RP", "R+", "ℝ⁺", "ℝ+"] }, +// // Zero-exclusive real positive domains +// { domain: Domain.RPE, shortcuts: ["RPE", "REP", "R+*", "R*+", "ℝ*⁺", "ℝ⁺*", "ℝ*+", "ℝ+*"] }, +// // Real negative domain +// { domain: Domain.RM, shortcuts: ["RM", "R-", "ℝ⁻", "ℝ-"] }, +// // Zero-exclusive real negative domains +// { domain: Domain.RME, shortcuts: ["RME", "REM", "R-*", "R*-", "ℝ⁻*", "ℝ*⁻", "ℝ-*", "ℝ*-"] }, +// // Natural integers domain +// { domain: Domain.N, shortcuts: ["ℕ", "N", "ZP", "Z+", "ℤ⁺", "ℤ+"] }, +// // Zero-exclusive natural integers domain +// { domain: Domain.NE, shortcuts: ["NE", "NP", "N*", "N+", "ℕ*", "ℕ⁺", "ℕ+", "ZPE", "ZEP", "Z+*", "Z*+", "ℤ⁺*", "ℤ*⁺", "ℤ+*", "ℤ*+"] }, +// // Logarithmic natural domains +// { domain: Domain.NLog, shortcuts: ["NLOG", "ℕˡᵒᵍ", "ℕLOG"] }, +// // All integers domains +// { domain: Domain.Z, shortcuts: ["Z", "ℤ"] }, +// // Zero-exclusive all integers domain +// { domain: Domain.ZE, shortcuts: ["ZE", "Z*", "ℤ*"] }, +// // Negative integers domain +// { domain: Domain.ZM, shortcuts: ["ZM", "Z-", "ℤ⁻", "ℤ-"] }, +// // Zero-exclusive negative integers domain +// { domain: Domain.ZME, shortcuts: ["ZME", "ZEM", "Z-*", "Z*-", "ℤ⁻*", "ℤ*⁻", "ℤ-*", "ℤ*-"] }, +// ] +// +// // Real domains +// for(const { domain, shortcuts } of predefinedToCheck) +// for(const shortcut of shortcuts) +// expect(parseDomainSimple(shortcut)).to.be.equal(domain) +// }) +// +// it("") +// }) +// }) From 885d1f5dc321f31b0e655617d2f55dd659b96c9c Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sat, 12 Oct 2024 03:22:49 +0200 Subject: [PATCH 035/104] Adding test for Utils --- common/src/module/latex.mjs | 4 +- common/src/utils.mjs | 405 +++++++++++++++++---------------- common/test/general/events.mjs | 14 +- common/test/general/utils.mjs | 183 +++++++++++++++ 4 files changed, 404 insertions(+), 202 deletions(-) create mode 100644 common/test/general/utils.mjs diff --git a/common/src/module/latex.mjs b/common/src/module/latex.mjs index 8ccbeb5..4ff81cb 100644 --- a/common/src/module/latex.mjs +++ b/common/src/module/latex.mjs @@ -137,9 +137,9 @@ class LatexAPI extends Module { */ parif(elem, contents) { elem = elem.toString() - if(elem[0] !== "(" && elem[elem.length - 1] !== ")" && contents.some(x => elem.indexOf(x) > 0)) + if(elem[0] !== "(" && elem.at(-1) !== ")" && contents.some(x => elem.indexOf(x) > 0)) return this.par(elem) - if(elem[0] === "(" && elem[elem.length - 1] === ")") + if(elem[0] === "(" && elem.at(-1) === ")") return elem.removeEnclosure() return elem } diff --git a/common/src/utils.mjs b/common/src/utils.mjs index 094147d..0e451f4 100644 --- a/common/src/utils.mjs +++ b/common/src/utils.mjs @@ -21,14 +21,16 @@ * Replaces latin characters with their uppercase versions. * @return {string} */ -String.prototype.toLatinUppercase = String.prototype.toLatinUppercase || function() { +String.prototype.toLatinUppercase = function() { return this.replace(/[a-z]/g, function(match) { return match.toUpperCase() }) } /** - * Removes the 'enclosers' of a string (e.g. quotes, parentheses, brackets...) + * Removes the first and last character of a string + * Used to remove enclosing characters like quotes, parentheses, brackets... + * @note Does NOT check for their existence ahead of time. * @return {string} */ String.prototype.removeEnclosure = function() { @@ -43,126 +45,126 @@ String.prototype.removeEnclosure = function() { * @return {number} */ Number.prototype.toDecimalPrecision = function(decimalPlaces = 0) { - const p = Math.pow(10, decimalPlaces); - const n = (this * p) * (1 + Number.EPSILON); - return Math.round(n) / p; + const p = Math.pow(10, decimalPlaces) + const n = (this * p) * (1 + Number.EPSILON) + return Math.round(n) / p } -const powerpos = { - "-": "⁻", - "+": "⁺", - "=": "⁼", - " ": " ", - "(": "⁽", - ")": "⁾", - "0": "⁰", - "1": "¹", - "2": "²", - "3": "³", - "4": "⁴", - "5": "⁵", - "6": "⁶", - "7": "⁷", - "8": "⁸", - "9": "⁹", - "a": "ᵃ", - "b": "ᵇ", - "c": "ᶜ", - "d": "ᵈ", - "e": "ᵉ", - "f": "ᶠ", - "g": "ᵍ", - "h": "ʰ", - "i": "ⁱ", - "j": "ʲ", - "k": "ᵏ", - "l": "ˡ", - "m": "ᵐ", - "n": "ⁿ", - "o": "ᵒ", - "p": "ᵖ", - "r": "ʳ", - "s": "ˢ", - "t": "ᵗ", - "u": "ᵘ", - "v": "ᵛ", - "w": "ʷ", - "x": "ˣ", - "y": "ʸ", - "z": "ᶻ" -} +const CHARACTER_TO_POWER = new Map([ + ["-", "⁻"], + ["+", "⁺"], + ["=", "⁼"], + [" ", " "], + ["(", "⁽"], + [")", "⁾"], + ["0", "⁰"], + ["1", "¹"], + ["2", "²"], + ["3", "³"], + ["4", "⁴"], + ["5", "⁵"], + ["6", "⁶"], + ["7", "⁷"], + ["8", "⁸"], + ["9", "⁹"], + ["a", "ᵃ"], + ["b", "ᵇ"], + ["c", "ᶜ"], + ["d", "ᵈ"], + ["e", "ᵉ"], + ["f", "ᶠ"], + ["g", "ᵍ"], + ["h", "ʰ"], + ["i", "ⁱ"], + ["j", "ʲ"], + ["k", "ᵏ"], + ["l", "ˡ"], + ["m", "ᵐ"], + ["n", "ⁿ"], + ["o", "ᵒ"], + ["p", "ᵖ"], + ["r", "ʳ"], + ["s", "ˢ"], + ["t", "ᵗ"], + ["u", "ᵘ"], + ["v", "ᵛ"], + ["w", "ʷ"], + ["x", "ˣ"], + ["y", "ʸ"], + ["z", "ᶻ"] +]) -const exponents = [ - "⁰","¹","²","³","⁴","⁵","⁶","⁷","⁸","⁹" +const CHARACTER_TO_INDICE = new Map([ + ["-", "₋"], + ["+", "₊"], + ["=", "₌"], + ["(", "₍"], + [")", "₎"], + [" ", " "], + ["0", "₀"], + ["1", "₁"], + ["2", "₂"], + ["3", "₃"], + ["4", "₄"], + ["5", "₅"], + ["6", "₆"], + ["7", "₇"], + ["8", "₈"], + ["9", "₉"], + ["a", "ₐ"], + ["e", "ₑ"], + ["h", "ₕ"], + ["i", "ᵢ"], + ["j", "ⱼ"], + ["k", "ₖ"], + ["l", "ₗ"], + ["m", "ₘ"], + ["n", "ₙ"], + ["o", "ₒ"], + ["p", "ₚ"], + ["r", "ᵣ"], + ["s", "ₛ"], + ["t", "ₜ"], + ["u", "ᵤ"], + ["v", "ᵥ"], + ["x", "ₓ"] +]) + +const EXPONENTS = [ + "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹" ] -const exponentReg = new RegExp('(['+exponents.join('')+']+)', 'g') +const EXPONENTS_REG = new RegExp("([" + EXPONENTS.join("") + "]+)", "g") -const indicepos = { - "-": "₋", - "+": "₊", - "=": "₌", - "(": "₍", - ")": "₎", - " ": " ", - "0": "₀", - "1": "₁", - "2": "₂", - "3": "₃", - "4": "₄", - "5": "₅", - "6": "₆", - "7": "₇", - "8": "₈", - "9": "₉", - "a": "ₐ", - "e": "ₑ", - "h": "ₕ", - "i": "ᵢ", - "j": "ⱼ", - "k": "ₖ", - "l": "ₗ", - "m": "ₘ", - "n": "ₙ", - "o": "ₒ", - "p": "ₚ", - "r": "ᵣ", - "s": "ₛ", - "t": "ₜ", - "u": "ᵤ", - "v": "ᵥ", - "x": "ₓ", -} -// Put a text in sup position +/** + * Put a text in sup position + * @param {string} text + * @return {string} + */ export function textsup(text) { let ret = "" text = text.toString() - for (let i = 0; i < text.length; i++) { - if(Object.keys(powerpos).indexOf(text[i]) >= 0) { - ret += powerpos[text[i]] - } else { - ret += text[i] - } - } + for(let letter of text) + ret += CHARACTER_TO_POWER.has(letter) ? CHARACTER_TO_POWER.get(letter) : letter return ret } -// Put a text in sub position +/** + * Put a text in sub position + * @param {string} text + * @return {string} + */ export function textsub(text) { let ret = "" text = text.toString() - for (let i = 0; i < text.length; i++) { - if(Object.keys(indicepos).indexOf(text[i]) >= 0) { - ret += indicepos[text[i]] - } else { - ret += text[i] - } - } + for(let letter of text) + ret += CHARACTER_TO_INDICE.has(letter) ? CHARACTER_TO_INDICE.get(letter) : letter return ret } /** * Simplifies (mathematically) a mathematical expression. + * @deprecated * @param {string} str - Expression to parse * @returns {string} */ @@ -185,37 +187,43 @@ export function simplifyExpression(str) { // n1 & n3 are multiplied, opeM is the main operation (- or +). // Putting all n in form of number //n2 = n2 == undefined ? 1 : parseFloat(n) - n1 = m1 === undefined ? 1 : eval(m1 + '1') - n2 = m2 === undefined ? 1 : eval('1' + m2) - n3 = m3 === undefined ? 1 : eval(m3 + '1') - n4 = m4 === undefined ? 1 : eval('1' + m4) - //let [n1, n2, n3, n4] = [n1, n2, n3, n4].map(n => n == undefined ? 1 : parseFloat(n)) - // Falling back to * in case it does not exist (the corresponding n would be 1) - [ope2, ope4] = [ope2, ope4].map(ope => ope === '/' ? '/' : '*') - let coeff1 = n1*n2 - let coeff2 = n3*n4 - let coefficient = coeff1+coeff2-(opeM === '-' ? 2*coeff2 : 0) - + n1 = m1 === undefined ? 1 : eval(m1 + "1") + n2 = m2 === undefined ? 1 : eval("1" + m2) + n3 = m3 === undefined ? 1 : eval(m3 + "1") + n4 = m4 === undefined ? 1 : eval("1" + m4) + //let [n1, n2, n3, n4] = [n1, n2, n3, n4].map(n => n == undefined ? 1 : parseFloat(n)) + // Falling back to * in case it does not exist (the corresponding n would be 1) + [ope2, ope4] = [ope2, ope4].map(ope => ope === "/" ? "/" : "*") + let coeff1 = n1 * n2 + let coeff2 = n3 * n4 + let coefficient = coeff1 + coeff2 - (opeM === "-" ? 2 * coeff2 : 0) + return `${coefficient} * π` } ], [ // Removing parenthesis when content is only added from both sides. /(^|[+-] |\()\(([^)(]+)\)($| [+-]|\))/g, - function(match, b4, middle, after) {return `${b4}${middle}${after}`} + function(match, b4, middle, after) { + return `${b4}${middle}${after}` + } ], [ // Removing parenthesis when content is only multiplied. /(^|[*\/] |\()\(([^)(+-]+)\)($| [*\/+-]|\))/g, - function(match, b4, middle, after) {return `${b4}${middle}${after}`} + function(match, b4, middle, after) { + return `${b4}${middle}${after}` + } ], [ // Removing parenthesis when content is only multiplied. /(^|[*\/+-] |\()\(([^)(+-]+)\)($| [*\/]|\))/g, - function(match, b4, middle, after) {return `${b4}${middle}${after}`} + function(match, b4, middle, after) { + return `${b4}${middle}${after}` + } ], [// Simplification additions/subtractions. /(^|[^*\/] |\()([-.\d]+) [+-] (\([^)(]+\)|[^)(]+) [+-] ([-.\d]+)($| [^*\/]|\))/g, function(match, b4, n1, op1, middle, op2, n2, after) { let total - if(op2 === '+') { + if(op2 === "+") { total = parseFloat(n1) + parseFloat(n2) } else { total = parseFloat(n1) - parseFloat(n2) @@ -224,14 +232,14 @@ export function simplifyExpression(str) { } ], [// Simplification multiplications/divisions. - /([-.\d]+) [*\/] (\([^)(]+\)|[^)(+-]+) [*\/] ([-.\d]+)/g, + /([-.\d]+) [*\/] (\([^)(]+\)|[^)(+-]+) [*\/] ([-.\d]+)/g, function(match, n1, op1, middle, op2, n2) { - if(parseInt(n1) === n1 && parseInt(n2) === n2 && op2 === '/' && - (parseInt(n1) / parseInt(n2)) % 1 !== 0) { + if(parseInt(n1) === n1 && parseInt(n2) === n2 && op2 === "/" && + (parseInt(n1) / parseInt(n2)) % 1 !== 0) { // Non int result for int division. return `(${n1} / ${n2}) ${op1} ${middle}` } else { - if(op2 === '*') { + if(op2 === "*") { return `${parseFloat(n1) * parseFloat(n2)} ${op1} ${middle}` } else { return `${parseFloat(n1) / parseFloat(n2)} ${op1} ${middle}` @@ -245,17 +253,17 @@ export function simplifyExpression(str) { let str = middle // Replace all groups while(/\([^)(]+\)/g.test(str)) - str = str.replace(/\([^)(]+\)/g, '') + str = str.replace(/\([^)(]+\)/g, "") // There shouldn't be any more parenthesis // If there is, that means the 2 parenthesis are needed. - if(!str.includes(')') && !str.includes('(')) { + if(!str.includes(")") && !str.includes("(")) { return middle } else { return `(${middle})` } - + } - ], + ] // Simple simplifications // [/(\s|^|\()0(\.0+)? \* (\([^)(]+\))/g, '$10'], // [/(\s|^|\()0(\.0+)? \* ([^)(+-]+)/g, '$10'], @@ -268,7 +276,7 @@ export function simplifyExpression(str) { // [/(^| |\() /g, '$1'], // [/ ($|\))/g, '$1'], ] - + // Replacements let found do { @@ -286,24 +294,35 @@ export function simplifyExpression(str) { /** * Transforms a mathematical expression to make it readable by humans. * NOTE: Will break parsing of expression. + * @deprecated * @param {string} str - Expression to parse. * @returns {string} */ export function makeExpressionReadable(str) { let replacements = [ // letiables - [/pi/g, 'π'], - [/Infinity/g, '∞'], - [/inf/g, '∞'], + [/pi/g, "π"], + [/Infinity/g, "∞"], + [/inf/g, "∞"], // Other - [/ \* /g, '×'], - [/ \^ /g, '^'], - [/\^\(([\d\w+-]+)\)/g, function(match, p1) { return textsup(p1) }], - [/\^([\d\w+-]+)/g, function(match, p1) { return textsup(p1) }], - [/_\(([\d\w+-]+)\)/g, function(match, p1) { return textsub(p1) }], - [/_([\d\w+-]+)/g, function(match, p1) { return textsub(p1) }], - [/\[([^\[\]]+)\]/g, function(match, p1) { return textsub(p1) }], - [/(\d|\))×/g, '$1'], + [/ \* /g, "×"], + [/ \^ /g, "^"], + [/\^\(([\d\w+-]+)\)/g, function(match, p1) { + return textsup(p1) + }], + [/\^([\d\w+-]+)/g, function(match, p1) { + return textsup(p1) + }], + [/_\(([\d\w+-]+)\)/g, function(match, p1) { + return textsub(p1) + }], + [/_([\d\w+-]+)/g, function(match, p1) { + return textsub(p1) + }], + [/\[([^\[\]]+)\]/g, function(match, p1) { + return textsub(p1) + }], + [/(\d|\))×/g, "$1"], [/integral\((.+),\s?(.+),\s?["'](.+)["'],\s?["'](.+)["']\)/g, function(match, a, b, p1, body, p2, p3, by, p4) { if(a.length < b.length) { return `∫${textsub(a)}${textsup(b)} ${body} d${by}` @@ -312,10 +331,10 @@ export function makeExpressionReadable(str) { } }], [/derivative\(?["'](.+)["'], ?["'](.+)["'], ?(.+)\)?/g, function(match, p1, body, p2, p3, by, p4, x) { - return `d(${body.replace(new RegExp(by, 'g'), 'x')})/dx` + return `d(${body.replace(new RegExp(by, "g"), "x")})/dx` }] ] - + // str = simplifyExpression(str) // Replacements for(let replacement of replacements) @@ -324,6 +343,48 @@ export function makeExpressionReadable(str) { return str } +/** @type {[RegExp, string][]} */ +const replacements = [ + // Greek letters + [/(\W|^)al(pha)?(\W|$)/g, "$1α$3"], + [/(\W|^)be(ta)?(\W|$)/g, "$1β$3"], + [/(\W|^)ga(mma)?(\W|$)/g, "$1γ$3"], + [/(\W|^)de(lta)?(\W|$)/g, "$1δ$3"], + [/(\W|^)ep(silon)?(\W|$)/g, "$1ε$3"], + [/(\W|^)ze(ta)?(\W|$)/g, "$1ζ$3"], + [/(\W|^)et(a)?(\W|$)/g, "$1η$3"], + [/(\W|^)th(eta)?(\W|$)/g, "$1θ$3"], + [/(\W|^)io(ta)?(\W|$)/g, "$1ι$3"], + [/(\W|^)ka(ppa)?(\W|$)/g, "$1κ$3"], + [/(\W|^)la(mbda)?(\W|$)/g, "$1λ$3"], + [/(\W|^)mu(\W|$)/g, "$1μ$2"], + [/(\W|^)nu(\W|$)/g, "$1ν$2"], + [/(\W|^)xi(\W|$)/g, "$1ξ$2"], + [/(\W|^)rh(o)?(\W|$)/g, "$1ρ$3"], + [/(\W|^)si(gma)?(\W|$)/g, "$1σ$3"], + [/(\W|^)ta(u)?(\W|$)/g, "$1τ$3"], + [/(\W|^)up(silon)?(\W|$)/g, "$1υ$3"], + [/(\W|^)ph(i)?(\W|$)/g, "$1φ$3"], + [/(\W|^)ch(i)?(\W|$)/g, "$1χ$3"], + [/(\W|^)ps(i)?(\W|$)/g, "$1ψ$3"], + [/(\W|^)om(ega)?(\W|$)/g, "$1ω$3"], + // Capital greek letters + [/(\W|^)gga(mma)?(\W|$)/g, "$1Γ$3"], + [/(\W|^)gde(lta)?(\W|$)/g, "$1Δ$3"], + [/(\W|^)gth(eta)?(\W|$)/g, "$1Θ$3"], + [/(\W|^)gla(mbda)?(\W|$)/g, "$1Λ$3"], + [/(\W|^)gxi(\W|$)/g, "$1Ξ$2"], + [/(\W|^)gpi(\W|$)/g, "$1Π$2"], + [/(\W|^)gsi(gma)?(\W|$)/g, "$1Σ$3"], + [/(\W|^)gph(i)?(\W|$)/g, "$1Φ$3"], + [/(\W|^)gps(i)?(\W|$)/g, "$1Ψ$3"], + [/(\W|^)gom(ega)?(\W|$)/g, "$1Ω$3"], + // Array elements + [/\[([^\]\[]+)\]/g, function(match, p1) { + return textsub(p1) + }] +] + /** * Parses a variable name to make it readable by humans. * @@ -332,65 +393,24 @@ export function makeExpressionReadable(str) { * @returns {string} - The parsed name */ export function parseName(str, removeUnallowed = true) { - let replacements = [ - // Greek letters - [/([^a-z]|^)al(pha)?([^a-z]|$)/g, '$1α$3'], - [/([^a-z]|^)be(ta)?([^a-z]|$)/g, '$1β$3'], - [/([^a-z]|^)ga(mma)?([^a-z]|$)/g, '$1γ$3'], - [/([^a-z]|^)de(lta)?([^a-z]|$)/g, '$1δ$3'], - [/([^a-z]|^)ep(silon)?([^a-z]|$)/g, '$1ε$3'], - [/([^a-z]|^)ze(ta)?([^a-z]|$)/g, '$1ζ$3'], - [/([^a-z]|^)et(a)?([^a-z]|$)/g, '$1η$3'], - [/([^a-z]|^)th(eta)?([^a-z]|$)/g, '$1θ$3'], - [/([^a-z]|^)io(ta)?([^a-z]|$)/g, '$1ι$3'], - [/([^a-z]|^)ka(ppa)([^a-z]|$)?/g, '$1κ$3'], - [/([^a-z]|^)la(mbda)?([^a-z]|$)/g, '$1λ$3'], - [/([^a-z]|^)mu([^a-z]|$)/g, '$1μ$2'], - [/([^a-z]|^)nu([^a-z]|$)/g, '$1ν$2'], - [/([^a-z]|^)xi([^a-z]|$)/g, '$1ξ$2'], - [/([^a-z]|^)rh(o)?([^a-z]|$)/g, '$1ρ$3'], - [/([^a-z]|^)si(gma)?([^a-z]|$)/g, '$1σ$3'], - [/([^a-z]|^)ta(u)?([^a-z]|$)/g, '$1τ$3'], - [/([^a-z]|^)up(silon)?([^a-z]|$)/g, '$1υ$3'], - [/([^a-z]|^)ph(i)?([^a-z]|$)/g, '$1φ$3'], - [/([^a-z]|^)ch(i)?([^a-z]|$)/g, '$1χ$3'], - [/([^a-z]|^)ps(i)?([^a-z]|$)/g, '$1ψ$3'], - [/([^a-z]|^)om(ega)?([^a-z]|$)/g, '$1ω$3'], - // Capital greek letters - [/([^a-z]|^)gga(mma)?([^a-z]|$)/g, '$1Γ$3'], - [/([^a-z]|^)gde(lta)?([^a-z]|$)/g, '$1Δ$3'], - [/([^a-z]|^)gth(eta)?([^a-z]|$)/g, '$1Θ$3'], - [/([^a-z]|^)gla(mbda)?([^a-z]|$)/g, '$1Λ$3'], - [/([^a-z]|^)gxi([^a-z]|$)/g, '$1Ξ$2'], - [/([^a-z]|^)gpi([^a-z]|$)/g, '$1Π$2'], - [/([^a-z]|^)gsi(gma)([^a-z]|$)?/g, '$1Σ$3'], - [/([^a-z]|^)gph(i)?([^a-z]|$)/g, '$1Φ$3'], - [/([^a-z]|^)gps(i)?([^a-z]|$)/g, '$1Ψ$3'], - [/([^a-z]|^)gom(ega)?([^a-z]|$)/g, '$1Ω$3'], - // Underscores - // [/_\(([^_]+)\)/g, function(match, p1) { return textsub(p1) }], - // [/_([^" ]+)/g, function(match, p1) { return textsub(p1) }], - // Array elements - [/\[([^\]\[]+)\]/g, function(match, p1) { return textsub(p1) }], - // Removing - [/[xπℝℕ\\∪∩\]\[ ()^/÷*×+=\d-]/g , ''], - ] - if(!removeUnallowed) replacements.pop() - // Replacements - for(let replacement of replacements) + for(const replacement of replacements) str = str.replace(replacement[0], replacement[1]) + if(removeUnallowed) + str = str.replace(/[xnπℝℕ\\∪∩\]\[ ()^/÷*×+=\d¹²³⁴⁵⁶⁷⁸⁹⁰-]/g, "") + return str } /** * Transforms camel case strings to a space separated one. * + * @deprecated * @param {string} label - Camel case to parse * @returns {string} Parsed label. */ export function camelCase2readable(label) { let parsed = parseName(label, false) - return parsed.charAt(0).toLatinUppercase() + parsed.slice(1).replace(/([A-Z])/g," $1") + return parsed.charAt(0).toLatinUppercase() + parsed.slice(1).replace(/([A-Z])/g, " $1") } /** @@ -398,12 +418,12 @@ export function camelCase2readable(label) { * @returns {string} */ export function getRandomColor() { - let clrs = '0123456789ABCDEF'; - let color = '#'; + let clrs = "0123456789ABCDEF" + let color = "#" for(let i = 0; i < 6; i++) { - color += clrs[Math.floor(Math.random() * (16-5*(i%2===0)))]; + color += clrs[Math.floor(Math.random() * (16 - 5 * (i % 2 === 0)))] } - return color; + return color } /** @@ -412,16 +432,15 @@ export function getRandomColor() { * @returns {string} */ export function escapeHTML(str) { - return str.replace(/&/g,'&').replace(//g,'>') ; + return str.replace(/&/g, "&").replace(//g, ">") } - /** * Parses exponents and replaces them with expression values * @param {string} expression - The expression to replace in. * @return {string} The parsed expression */ export function exponentsToExpression(expression) { - return expression.replace(exponentReg, (m, exp) => '^' + exp.split('').map((x) => exponents.indexOf(x)).join('')) + return expression.replace(EXPONENTS_REG, (m, exp) => "^" + exp.split("").map((x) => EXPONENTS.indexOf(x)).join("")) } diff --git a/common/test/general/events.mjs b/common/test/general/events.mjs index f82875f..15d44aa 100644 --- a/common/test/general/events.mjs +++ b/common/test/general/events.mjs @@ -45,7 +45,7 @@ class MockEvent2 extends BaseEvent { const sandbox = spy.sandbox() -describe("Events", function() { +describe("EventsEmitters", function() { afterEach(() => { sandbox.restore() @@ -71,11 +71,11 @@ describe("Events", function() { emitter.emit(mockEvent1) emitter.emit(mockEvent2) expect(listener).to.have.been.called.twice - expect(listener).to.have.been.called.with.exactly(mockEvent1) - expect(listener).to.have.been.called.with.exactly(mockEvent2) + expect(listener).to.also.have.been.called.with.exactly(mockEvent1) + expect(listener).to.also.have.been.called.with.exactly(mockEvent2) }) - it("should be able to remove listeners", function() { + it("should be able to have listeners remvoed", function() { const emitter = new MockEmitter() const listener = spy() emitter.on("example1", listener) @@ -93,7 +93,7 @@ describe("Events", function() { expect(removedFromOneOfTheEvents).to.be.true }) - it("should be able to remove listening to one event when listener listens to multiple", function() { + it("should be able to remove one listener listening to one event when said listener listens to multiple", function() { const emitter = new MockEmitter() const listener = spy() const mockEvent1 = new MockEvent1() @@ -104,10 +104,10 @@ describe("Events", function() { emitter.emit(mockEvent1) emitter.emit(mockEvent2) expect(listener).to.have.been.called.once - expect(listener).to.have.been.called.with.exactly(mockEvent2) + expect(listener).to.also.have.been.called.with.exactly(mockEvent2) }) - it("shouldn't be able to listen/unlisten/emit inexistant events", function() { + it("shouldn't be able to add listen/unlisten to, or emit inexistant events", function() { const emitter = new MockEmitter() const listener = spy() expect(() => emitter.on("inexistant", listener)).to.throw(Error) diff --git a/common/test/general/utils.mjs b/common/test/general/utils.mjs new file mode 100644 index 0000000..8078645 --- /dev/null +++ b/common/test/general/utils.mjs @@ -0,0 +1,183 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import { textsup, textsub, parseName, getRandomColor, escapeHTML, exponentsToExpression } from "../../src/utils.mjs" + + +import { describe, it } from "mocha" +import { expect } from "chai" + +describe("Extensions", function() { + describe("#String.toLatinUppercase", function() { + it("should be able to transform latin characters from strings to their uppercase version", function() { + expect("abc".toLatinUppercase()).to.equal("ABC") + expect("abCd".toLatinUppercase()).to.equal("ABCD") + expect("ab123cd456".toLatinUppercase()).to.equal("AB123CD456") + expect("ABC".toLatinUppercase()).to.equal("ABC") + }) + + it("shouldn't transform non latin characters to their uppercase version", function() { + expect("abαπ".toLatinUppercase()).to.equal("ABαπ") + expect("abαπ".toLatinUppercase()).to.not.equal("abαπ".toUpperCase()) + }) + }) + + describe("#String.removeEnclosure", function() { + it("should be able to remove the first and last characters", function() { + expect("[1+t]".removeEnclosure()).to.equal("1+t") + expect('"a+b+c*d"'.removeEnclosure()).to.equal("a+b+c*d") + expect("(pi/2)".removeEnclosure()).to.equal("pi/2") + }) + }) + + describe("#Number.toDecimalPrecision", function() { + it("should be able to round a number to a fixed decimal precision", function() { + expect(123.456789.toDecimalPrecision()).to.equal(123) + expect(123.456789.toDecimalPrecision(1)).to.equal(123.5) + expect(123.456789.toDecimalPrecision(2)).to.equal(123.46) + expect(123.456789.toDecimalPrecision(3)).to.equal(123.457) + expect(123.456789.toDecimalPrecision(4)).to.equal(123.4568) + expect(123.456789.toDecimalPrecision(5)).to.equal(123.45679) + expect(123.456789.toDecimalPrecision(6)).to.equal(123.456789) + expect(123.111111.toDecimalPrecision(5)).to.equal(123.11111) + }) + }) +}) + +describe("Utils", function() { + describe("#textsup", function() { + it("should transform characters which have a sup unicode equivalent", function() { + expect(textsup("-+=()")).to.equal("⁻⁺⁼⁽⁾") + expect(textsup("0123456789")).to.equal("⁰¹²³⁴⁵⁶⁷⁸⁹") + expect(textsup("abcdefghijklmnoprstuvwxyz")).to.equal("ᵃᵇᶜᵈᵉᶠᵍʰⁱʲᵏˡᵐⁿᵒᵖʳˢᵗᵘᵛʷˣʸᶻ") + }) + + it("shouldn't transform characters without a sup equivalent", function() { + expect(textsup("ABCDEFGHIJKLMNOPQRSTUVWXYZq")).to.equal("ABCDEFGHIJKLMNOPQRSTUVWXYZq") + }) + + it("should partially transform strings which only have a few characters with a sup equivalent", function() { + expect(textsup("ABCabcABC")).to.equal("ABCᵃᵇᶜABC") + }) + }) + + describe("#textsub", function() { + it("should transform characters which have a sub unicode equivalent", function() { + expect(textsub("-+=()")).to.equal("₋₊₌₍₎") + expect(textsub("0123456789")).to.equal("₀₁₂₃₄₅₆₇₈₉") + expect(textsub("aehijklmnoprstuvx")).to.equal("ₐₑₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓ") + }) + + it("shouldn't transform characters without a sub equivalent", function() { + expect(textsub("ABCDEFGHIJKLMNOPQRSTUVWXYZ")).to.equal("ABCDEFGHIJKLMNOPQRSTUVWXYZ") + expect(textsub("bcdfgqyz")).to.equal("bcdfgqyz") + }) + + it("should partially transform strings which only have a few characters with a sub equivalent", function() { + expect(textsub("ABC123ABC")).to.equal("ABC₁₂₃ABC") + }) + }) + + describe("#parseName", function() { + it("should parse greek letter names", function() { + const shorthands = { + "α": ["al", "alpha"], + "β": ["be", "beta"], + "γ": ["ga", "gamma"], + "δ": ["de", "delta"], + "ε": ["ep", "epsilon"], + "ζ": ["ze", "zeta"], + "η": ["et", "eta"], + "θ": ["th", "theta"], + "κ": ["ka", "kappa"], + "λ": ["la", "lambda"], + "μ": ["mu"], + "ν": ["nu"], + "ξ": ["xi"], + "ρ": ["rh", "rho"], + "σ": ["si", "sigma"], + "τ": ["ta", "tau"], + "υ": ["up", "upsilon"], + "φ": ["ph", "phi"], + "χ": ["ch", "chi"], + "ψ": ["ps", "psi"], + "ω": ["om", "omega"], + "Γ": ["gga", "ggamma"], + "Δ": ["gde", "gdelta"], + "Θ": ["gth", "gtheta"], + "Λ": ["gla", "glambda"], + "Ξ": ["gxi"], + "Π": ["gpi"], + "Σ": ["gsi", "gsigma"], + "Φ": ["gph", "gphi"], + "Ψ": ["gps", "gpsi"], + "Ω": ["gom", "gomega"], + } + for(const [char, shorts] of Object.entries(shorthands)) { + expect(parseName(char)).to.equal(char) + for(const short of shorts) + expect(parseName(short)).to.equal(char) + } + }) + + it("should parse array elements into sub", function() { + expect(parseName("u[n+1]")).to.equal("uₙ₊₁") + expect(parseName("u[(n+x)]")).to.equal("u₍ₙ₊ₓ₎") + expect(parseName("u[A]")).to.equal("uA") + }) + + it("should remove disallowed characters when indicated", function() { + const disallowed = "xnπℝℕ\\∪∩[] ()^/^/÷*×+=1234567890¹²³⁴⁵⁶⁷⁸⁹⁰-" + expect(parseName(disallowed)).to.equal("") + expect(parseName("AA" + disallowed)).to.equal("AA") + expect(parseName(disallowed, false)).to.equal(disallowed) + }) + + it("should be able to do all three at once", function() { + expect(parseName("al[n+1]+n")).to.equal("αₙ₊₁") + expect(parseName("al[n+1]+n", false)).to.equal("αₙ₊₁+n") + }) + }) + + describe("#getRandomColor", function() { + it("should provide a valid color", function() { + const colorReg = /^#[A-F\d]{6}$/ + for(let i = 0; i < 50; i++) + expect(getRandomColor()).to.match(colorReg) + }) + }) + + describe("#escapeHTML", function() { + it("should should escape ampersands", function() { + expect(escapeHTML("&")).to.equal("&") + expect(escapeHTML("High & Mighty")).to.equal("High & Mighty") + }) + + it("should escape injected HTML tags", function() { + expect(escapeHTML("")).to.equal("<script>alert('Injected!')</script>") + expect(escapeHTML('Link')).to.equal('<a href="javascript:alert()">Link</a>') + }) + }) + + describe("#exponentsToExpression", function() { + it("should transform exponents to power expression", function() { + expect(exponentsToExpression("x¹²³⁴⁵⁶⁷⁸⁹⁰")).to.equal("x^1234567890") + expect(exponentsToExpression("x¹²+y³⁴")).to.equal("x^12+y^34") + }) + }) +}) From 4c1b7052404e138bbe6bc366c7f14caaad26cd66 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sat, 12 Oct 2024 04:57:07 +0200 Subject: [PATCH 036/104] Mocking interfaces (+adding new method to canvas to make it more JS-like) --- common/src/module/canvas.mjs | 5 +- common/src/module/common.mjs | 2 +- common/src/module/interface.mjs | 10 ++- common/test/{general => basics}/events.mjs | 0 common/test/basics/interface.mjs | 51 ++++++++++++++++ common/test/{general => basics}/utils.mjs | 0 common/test/mock/canvas.mjs | 59 ++++++++++++++++++ common/test/mock/dialog.mjs | 23 +++++++ common/test/mock/root.mjs | 61 +++++++++++++++++++ .../LogarithmPlotter/LogGraphCanvas.qml | 16 ++++- .../LogarithmPlotter/LogarithmPlotter.qml | 2 - 11 files changed, 216 insertions(+), 13 deletions(-) rename common/test/{general => basics}/events.mjs (100%) create mode 100644 common/test/basics/interface.mjs rename common/test/{general => basics}/utils.mjs (100%) create mode 100644 common/test/mock/canvas.mjs create mode 100644 common/test/mock/dialog.mjs create mode 100644 common/test/mock/root.mjs diff --git a/common/src/module/canvas.mjs b/common/src/module/canvas.mjs index 5d42f5e..c46c9a1 100644 --- a/common/src/module/canvas.mjs +++ b/common/src/module/canvas.mjs @@ -522,8 +522,9 @@ class CanvasAPI extends Module { const onRendered = (imgData) => { if(!this.#canvas.isImageLoaded(imgData.source) && !this.#canvas.isImageLoading(imgData.source)) { // Wait until the image is loaded to callback. - this.#canvas.loadImage(imgData.source) - this.#canvas.imageLoaders[imgData.source] = [callback, imgData] + this.#canvas.loadImageAsync(imgData.source).then(() => { + callback(imgData) + }) } else { // Callback directly callback(imgData) diff --git a/common/src/module/common.mjs b/common/src/module/common.mjs index bdca62f..243fed2 100644 --- a/common/src/module/common.mjs +++ b/common/src/module/common.mjs @@ -57,7 +57,7 @@ export class Module extends BaseEventEmitter { if(!options.hasOwnProperty(name)) throw new Error(`Option '${name}' of initialize of module ${this.#name} does not exist.`) if(typeof value === "function" && value.prototype instanceof Interface) - Interface.check_implementation(value, options[name]) + Interface.checkImplementation(value, options[name]) else if(typeof value !== typeof options[name]) throw new Error(`Option '${name}' of initialize of module ${this.#name} is not a '${value}' (${typeof options[name]}).`) } diff --git a/common/src/module/interface.mjs b/common/src/module/interface.mjs index 2886f73..27fb7eb 100644 --- a/common/src/module/interface.mjs +++ b/common/src/module/interface.mjs @@ -35,9 +35,8 @@ export class Interface { * Throws an error if the implementation does not conform to the interface. * @param {typeof Interface} interface_ * @param {object} classToCheck - * @return {boolean} */ - static check_implementation(interface_, classToCheck) { + static checkImplementation(interface_, classToCheck) { const properties = new interface_() const interfaceName = interface_.name const toCheckName = classToCheck.constructor.name @@ -52,7 +51,7 @@ export class Interface { else if((typeof value) === "object") // Test type of object. if(value instanceof Interface) - Interface.check_implementation(value, classToCheck[property]) + Interface.checkImplementation(value, classToCheck[property]) else if(value.prototype && !(classToCheck[property] instanceof value)) throw new Error(`Property '${property}' of ${interfaceName} implementation ${toCheckName} is not '${value.constructor.name}'.`) } @@ -61,13 +60,12 @@ export class Interface { export class CanvasInterface extends Interface { - imageLoaders = OBJECT /** @type {function(string): CanvasRenderingContext2D} */ getContext = FUNCTION /** @type {function(rect)} */ markDirty = FUNCTION - /** @type {function(string)} */ - loadImage = FUNCTION + /** @type {function(string): Promise} */ + loadImageAsync = FUNCTION /** @type {function(string)} */ isImageLoading = FUNCTION /** @type {function(string)} */ diff --git a/common/test/general/events.mjs b/common/test/basics/events.mjs similarity index 100% rename from common/test/general/events.mjs rename to common/test/basics/events.mjs diff --git a/common/test/basics/interface.mjs b/common/test/basics/interface.mjs new file mode 100644 index 0000000..a8d8d32 --- /dev/null +++ b/common/test/basics/interface.mjs @@ -0,0 +1,51 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import { describe, it } from "mocha" +import { expect } from "chai" + +import { MockLatex } from "../mock/latex.mjs" +import { MockHelper } from "../mock/helper.mjs" +import { + CanvasInterface, + DialogInterface, + HelperInterface, + Interface, + LatexInterface, + RootInterface +} from "../../src/module/interface.mjs" +import { MockDialog } from "../mock/dialog.mjs" +import { MockRootElement } from "../mock/root.mjs" +import { MockCanvas } from "../mock/canvas.mjs" + +describe("Interface", function() { + describe("#checkImplementation", function() { + it("should validate the implementation of mocks", function() { + const checkMockLatex = () => Interface.checkImplementation(LatexInterface, new MockLatex()) + const checkMockHelper = () => Interface.checkImplementation(HelperInterface, new MockHelper()) + const checkMockDialog = () => Interface.checkImplementation(DialogInterface, new MockDialog()) + const checkMockRoot = () => Interface.checkImplementation(RootInterface, new MockRootElement()) + const checkMockCanvas = () => Interface.checkImplementation(CanvasInterface, new MockCanvas()) + expect(checkMockLatex).to.not.throw() + expect(checkMockHelper).to.not.throw() + expect(checkMockDialog).to.not.throw() + expect(checkMockRoot).to.not.throw() + expect(checkMockCanvas).to.not.throw() + }) + }) +}) \ No newline at end of file diff --git a/common/test/general/utils.mjs b/common/test/basics/utils.mjs similarity index 100% rename from common/test/general/utils.mjs rename to common/test/basics/utils.mjs diff --git a/common/test/mock/canvas.mjs b/common/test/mock/canvas.mjs new file mode 100644 index 0000000..e770e10 --- /dev/null +++ b/common/test/mock/canvas.mjs @@ -0,0 +1,59 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +export class MockCanvas { + constructor(mockLoading = false) { + this.mockLoading = mockLoading + } + + getContext(context) { + throw new Error("MockCanvas.getContext not implemented") + } + + markDirty(rect) { + this.requestPaint() + } + + loadImageAsync(image) { + return new Promise((resolve, reject) => { + resolve() + }) + } + + /** + * Image loading is instantaneous. + * @param {string} image + * @return {boolean} + */ + isImageLoading(image) { + return this.mockLoading + } + + /** + * Image loading is instantaneous. + * @param {string} image + * @return {boolean} + */ + isImageLoaded(image) { + return !this.mockLoading + } + + requestPaint() { + } +} \ No newline at end of file diff --git a/common/test/mock/dialog.mjs b/common/test/mock/dialog.mjs new file mode 100644 index 0000000..3ff118f --- /dev/null +++ b/common/test/mock/dialog.mjs @@ -0,0 +1,23 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export class MockDialog { + constructor() {} + + show() {} +} \ No newline at end of file diff --git a/common/test/mock/root.mjs b/common/test/mock/root.mjs new file mode 100644 index 0000000..51807e2 --- /dev/null +++ b/common/test/mock/root.mjs @@ -0,0 +1,61 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * Mock for root element with width and height property. + * setWidth, setHeight, getWidth, and getHeight methods can be spied on to check + * when the accessor is called. + */ +export class MockRootElement { + #width = 0 + #height = 0 + + constructor() {} + + setWidth(width) { + this.#width = width; + } + + getWidth() { + return this.#width + } + + setHeight(height) { + this.#height = height; + } + + getHeight() { + return this.#height + } + + get width() { + return this.getWidth() + } + + set width(value) { + this.setWidth(value) + } + + get height() { + return this.getHeight() + } + + set height(value) { + this.setHeight(value) + } +} \ No newline at end of file diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml index 07b6002..e1583f6 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml @@ -36,7 +36,7 @@ Canvas { width: parent.width /*! \qmlproperty var LogGraphCanvas::imageLoaders - Dictionary of format {image: [callback.image data]} containing data for defered image loading. + Dictionary of format {image: callback} containing data for deferred image loading. */ property var imageLoaders: {} @@ -66,9 +66,21 @@ Canvas { Object.keys(imageLoaders).forEach((key) => { if(isImageLoaded(key)) { // Calling callback - imageLoaders[key][0](imageLoaders[key][1]) + imageLoaders[key]() delete imageLoaders[key] } }) } + + /*! + \qmlmethod void LogGraphCanvas::loadImageAsync(string imageSource) + Loads an image data onto the canvas asynchronously. + Returns a Promise that is resolved when the image is loaded. + */ + function loadImageAsync(imageSource) { + return new Promise((resolve) => { + this.loadImage(imageSource) + this.imageLoaders[imageSource] = resolve + }) + } } diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml index e7cfc1a..d541a0c 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml @@ -257,13 +257,11 @@ ApplicationWindow { }) Modules.IO.on("saved loaded", (evt) => { // Refreshing sidebar - console.log(evt.name) updateObjectsLists() if(title.endsWith("*")) title = title.substring(0, title.length-1) }) Modules.IO.on("modified", () => { - console.log("modified") if(!title.endsWith("*")) title = title+"*" }) From 974baa6cc294dcc04a4e4dd0ef98979fb286ec13 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sat, 12 Oct 2024 05:31:42 +0200 Subject: [PATCH 037/104] Adding base module tests --- common/src/module/common.mjs | 14 +++-- common/test/basics/events.mjs | 14 ++--- common/test/basics/interface.mjs | 11 +++- common/test/basics/module.mjs | 89 ++++++++++++++++++++++++++++++++ common/test/basics/utils.mjs | 40 +++++++------- 5 files changed, 136 insertions(+), 32 deletions(-) create mode 100644 common/test/basics/module.mjs diff --git a/common/src/module/common.mjs b/common/src/module/common.mjs index 243fed2..4cd7993 100644 --- a/common/src/module/common.mjs +++ b/common/src/module/common.mjs @@ -30,6 +30,8 @@ export class Module extends BaseEventEmitter { #name /** @type {Object.} */ #initializationParameters + /** @type {boolean} */ + #initialized = false /** * @@ -41,8 +43,14 @@ export class Module extends BaseEventEmitter { console.log(`Loading module ${name}...`) this.#name = name this.#initializationParameters = initializationParameters - this.initialized = false + } + get name() { + return this.#name; + } + + get initialized() { + return this.#initialized } /** @@ -50,7 +58,7 @@ export class Module extends BaseEventEmitter { * @param {Object.} options */ initialize(options) { - if(this.initialized) + if(this.#initialized) throw new Error(`Cannot reinitialize module ${this.#name}.`) console.log(`Initializing ${this.#name}...`) for(const [name, value] of Object.entries(this.#initializationParameters)) { @@ -61,6 +69,6 @@ export class Module extends BaseEventEmitter { else if(typeof value !== typeof options[name]) throw new Error(`Option '${name}' of initialize of module ${this.#name} is not a '${value}' (${typeof options[name]}).`) } - this.initialized = true + this.#initialized = true } } diff --git a/common/test/basics/events.mjs b/common/test/basics/events.mjs index 15d44aa..8261ff1 100644 --- a/common/test/basics/events.mjs +++ b/common/test/basics/events.mjs @@ -45,13 +45,13 @@ class MockEvent2 extends BaseEvent { const sandbox = spy.sandbox() -describe("EventsEmitters", function() { +describe("Lib/EventsEmitters", function() { afterEach(() => { sandbox.restore() }) - it("should forward events to all of its listeners", function() { + it("forwards events to all of its listeners", function() { const emitter = new MockEmitter() const listener1 = spy() const listener2 = spy() @@ -62,7 +62,7 @@ describe("EventsEmitters", function() { expect(listener2).to.have.been.called.once }) - it("should forward multiple events to a singular listener", function() { + it("forwards multiple events to a singular listener", function() { const emitter = new MockEmitter() const listener = spy() const mockEvent1 = new MockEvent1() @@ -75,7 +75,7 @@ describe("EventsEmitters", function() { expect(listener).to.also.have.been.called.with.exactly(mockEvent2) }) - it("should be able to have listeners remvoed", function() { + it("is able to have listeners removed", function() { const emitter = new MockEmitter() const listener = spy() emitter.on("example1", listener) @@ -93,7 +93,7 @@ describe("EventsEmitters", function() { expect(removedFromOneOfTheEvents).to.be.true }) - it("should be able to remove one listener listening to one event when said listener listens to multiple", function() { + it("is able to have one listener's listening to a single event removed when said listener listens to multiple", function() { const emitter = new MockEmitter() const listener = spy() const mockEvent1 = new MockEvent1() @@ -107,7 +107,7 @@ describe("EventsEmitters", function() { expect(listener).to.also.have.been.called.with.exactly(mockEvent2) }) - it("shouldn't be able to add listen/unlisten to, or emit inexistant events", function() { + it("is not able to emit or add/remove listeners for inexistant events", function() { const emitter = new MockEmitter() const listener = spy() expect(() => emitter.on("inexistant", listener)).to.throw(Error) @@ -115,7 +115,7 @@ describe("EventsEmitters", function() { expect(() => emitter.emit(new BaseEvent("inexistant"))).to.throw(Error) }) - it("shouldn't be able to emit non-events", function() { + it("isn't able to emit non-events", function() { const emitter = new MockEmitter() expect(() => emitter.emit("not-an-event")).to.throw(Error) }) diff --git a/common/test/basics/interface.mjs b/common/test/basics/interface.mjs index a8d8d32..aaf512e 100644 --- a/common/test/basics/interface.mjs +++ b/common/test/basics/interface.mjs @@ -33,9 +33,16 @@ import { MockDialog } from "../mock/dialog.mjs" import { MockRootElement } from "../mock/root.mjs" import { MockCanvas } from "../mock/canvas.mjs" -describe("Interface", function() { +describe("Interfaces", function() { + describe("#interface methods", function() { + it("throws an error when called directly", function() { + const obj = new CanvasInterface() + expect(() => obj.markDirty()).to.throw(Error) + }) + }) + describe("#checkImplementation", function() { - it("should validate the implementation of mocks", function() { + it("validates the implementation of mocks", function() { const checkMockLatex = () => Interface.checkImplementation(LatexInterface, new MockLatex()) const checkMockHelper = () => Interface.checkImplementation(HelperInterface, new MockHelper()) const checkMockDialog = () => Interface.checkImplementation(DialogInterface, new MockDialog()) diff --git a/common/test/basics/module.mjs b/common/test/basics/module.mjs new file mode 100644 index 0000000..5093096 --- /dev/null +++ b/common/test/basics/module.mjs @@ -0,0 +1,89 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// Load prior events +import "./events.mjs" +import "./interface.mjs" + +import { describe, it } from "mocha" +import { expect } from "chai" +import { BOOLEAN, DialogInterface, FUNCTION, NUMBER, STRING } from "../../src/module/interface.mjs" +import { Module } from "../../src/module/common.mjs" +import { MockDialog } from "../mock/dialog.mjs" + +class MockModule extends Module { + constructor() { + super("mock", { + number: NUMBER, + bool: BOOLEAN, + str: STRING, + func: FUNCTION, + dialog: DialogInterface + }) + } +} + +describe("Modules/Base", function() { + it("defined a Modules global", function() { + expect(globalThis.Modules).to.not.be.undefined + }) + + it("is not be initialized upon construction", function() { + const module = new MockModule() + expect(module.name).to.equal("mock") + expect(module.initialized).to.be.false + }) + + it("is only be initialized with the right arguments", function() { + const module = new MockModule() + const initializeWithNoArg = () => module.initialize({}) + const initializeWithSomeArg = () => module.initialize({ number: 0, str: "" }) + const initializeWithWrongType = () => module.initialize({ + number: () => {}, + str: 0, + bool: "", + func: false, + dialog: null + }) + const initializeProperly = () => module.initialize({ + number: 0, + str: "", + bool: true, + func: FUNCTION, + dialog: new MockDialog() + }) + expect(initializeWithNoArg).to.throw(Error) + expect(initializeWithSomeArg).to.throw(Error) + expect(initializeWithWrongType).to.throw(Error) + expect(initializeProperly).to.not.throw(Error) + expect(module.initialized).to.be.true + }) + + it("cannot be initialized twice", function() { + const module = new MockModule() + const initialize = () => module.initialize({ + number: 0, + str: "", + bool: true, + func: FUNCTION, + dialog: new MockDialog() + }) + expect(initialize).to.not.throw(Error) + expect(initialize).to.throw(Error) + }) +}) \ No newline at end of file diff --git a/common/test/basics/utils.mjs b/common/test/basics/utils.mjs index 8078645..aab2cf5 100644 --- a/common/test/basics/utils.mjs +++ b/common/test/basics/utils.mjs @@ -22,23 +22,23 @@ import { textsup, textsub, parseName, getRandomColor, escapeHTML, exponentsToExp import { describe, it } from "mocha" import { expect } from "chai" -describe("Extensions", function() { +describe("Lib/PrototypeExtensions", function() { describe("#String.toLatinUppercase", function() { - it("should be able to transform latin characters from strings to their uppercase version", function() { + it("transforms latin characters from strings to their uppercase version", function() { expect("abc".toLatinUppercase()).to.equal("ABC") expect("abCd".toLatinUppercase()).to.equal("ABCD") expect("ab123cd456".toLatinUppercase()).to.equal("AB123CD456") expect("ABC".toLatinUppercase()).to.equal("ABC") }) - it("shouldn't transform non latin characters to their uppercase version", function() { + it("does not transform non latin characters to their uppercase version", function() { expect("abαπ".toLatinUppercase()).to.equal("ABαπ") expect("abαπ".toLatinUppercase()).to.not.equal("abαπ".toUpperCase()) }) }) describe("#String.removeEnclosure", function() { - it("should be able to remove the first and last characters", function() { + it("is able to remove the first and last characters", function() { expect("[1+t]".removeEnclosure()).to.equal("1+t") expect('"a+b+c*d"'.removeEnclosure()).to.equal("a+b+c*d") expect("(pi/2)".removeEnclosure()).to.equal("pi/2") @@ -46,7 +46,7 @@ describe("Extensions", function() { }) describe("#Number.toDecimalPrecision", function() { - it("should be able to round a number to a fixed decimal precision", function() { + it("rounds a number to a fixed decimal precision", function() { expect(123.456789.toDecimalPrecision()).to.equal(123) expect(123.456789.toDecimalPrecision(1)).to.equal(123.5) expect(123.456789.toDecimalPrecision(2)).to.equal(123.46) @@ -59,42 +59,42 @@ describe("Extensions", function() { }) }) -describe("Utils", function() { +describe("Lib/Utils", function() { describe("#textsup", function() { - it("should transform characters which have a sup unicode equivalent", function() { + it("transforms characters which have a sup unicode equivalent", function() { expect(textsup("-+=()")).to.equal("⁻⁺⁼⁽⁾") expect(textsup("0123456789")).to.equal("⁰¹²³⁴⁵⁶⁷⁸⁹") expect(textsup("abcdefghijklmnoprstuvwxyz")).to.equal("ᵃᵇᶜᵈᵉᶠᵍʰⁱʲᵏˡᵐⁿᵒᵖʳˢᵗᵘᵛʷˣʸᶻ") }) - it("shouldn't transform characters without a sup equivalent", function() { + it("does not transform characters without a sup equivalent", function() { expect(textsup("ABCDEFGHIJKLMNOPQRSTUVWXYZq")).to.equal("ABCDEFGHIJKLMNOPQRSTUVWXYZq") }) - it("should partially transform strings which only have a few characters with a sup equivalent", function() { + it("partially transforms strings which only have a few characters with a sup equivalent", function() { expect(textsup("ABCabcABC")).to.equal("ABCᵃᵇᶜABC") }) }) describe("#textsub", function() { - it("should transform characters which have a sub unicode equivalent", function() { + it("transforms characters which have a sub unicode equivalent", function() { expect(textsub("-+=()")).to.equal("₋₊₌₍₎") expect(textsub("0123456789")).to.equal("₀₁₂₃₄₅₆₇₈₉") expect(textsub("aehijklmnoprstuvx")).to.equal("ₐₑₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓ") }) - it("shouldn't transform characters without a sub equivalent", function() { + it("does not transform characters without a sub equivalent", function() { expect(textsub("ABCDEFGHIJKLMNOPQRSTUVWXYZ")).to.equal("ABCDEFGHIJKLMNOPQRSTUVWXYZ") expect(textsub("bcdfgqyz")).to.equal("bcdfgqyz") }) - it("should partially transform strings which only have a few characters with a sub equivalent", function() { + it("partially transforms strings which only have a few characters with a sub equivalent", function() { expect(textsub("ABC123ABC")).to.equal("ABC₁₂₃ABC") }) }) describe("#parseName", function() { - it("should parse greek letter names", function() { + it("parses greek letter names", function() { const shorthands = { "α": ["al", "alpha"], "β": ["be", "beta"], @@ -135,27 +135,27 @@ describe("Utils", function() { } }) - it("should parse array elements into sub", function() { + it("parses array elements into sub", function() { expect(parseName("u[n+1]")).to.equal("uₙ₊₁") expect(parseName("u[(n+x)]")).to.equal("u₍ₙ₊ₓ₎") expect(parseName("u[A]")).to.equal("uA") }) - it("should remove disallowed characters when indicated", function() { + it("removes disallowed characters when indicated", function() { const disallowed = "xnπℝℕ\\∪∩[] ()^/^/÷*×+=1234567890¹²³⁴⁵⁶⁷⁸⁹⁰-" expect(parseName(disallowed)).to.equal("") expect(parseName("AA" + disallowed)).to.equal("AA") expect(parseName(disallowed, false)).to.equal(disallowed) }) - it("should be able to do all three at once", function() { + it("is able to do all three at once", function() { expect(parseName("al[n+1]+n")).to.equal("αₙ₊₁") expect(parseName("al[n+1]+n", false)).to.equal("αₙ₊₁+n") }) }) describe("#getRandomColor", function() { - it("should provide a valid color", function() { + it("provides a valid color", function() { const colorReg = /^#[A-F\d]{6}$/ for(let i = 0; i < 50; i++) expect(getRandomColor()).to.match(colorReg) @@ -163,19 +163,19 @@ describe("Utils", function() { }) describe("#escapeHTML", function() { - it("should should escape ampersands", function() { + it("escapes ampersands", function() { expect(escapeHTML("&")).to.equal("&") expect(escapeHTML("High & Mighty")).to.equal("High & Mighty") }) - it("should escape injected HTML tags", function() { + it("escapes injected HTML tags", function() { expect(escapeHTML("")).to.equal("<script>alert('Injected!')</script>") expect(escapeHTML('Link')).to.equal('<a href="javascript:alert()">Link</a>') }) }) describe("#exponentsToExpression", function() { - it("should transform exponents to power expression", function() { + it("transforms exponents to power expression", function() { expect(exponentsToExpression("x¹²³⁴⁵⁶⁷⁸⁹⁰")).to.equal("x^1234567890") expect(exponentsToExpression("x¹²+y³⁴")).to.equal("x^12+y^34") }) From 345458f45372be27e1433a63b14687e55ff3d356 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sat, 12 Oct 2024 06:19:30 +0200 Subject: [PATCH 038/104] Adding new test for Settings Module --- common/src/events.mjs | 8 +- common/src/module/objects.mjs | 8 +- common/src/module/settings.mjs | 6 +- common/test/basics/events.mjs | 22 ++-- .../basics/{module.mjs => module-base.mjs} | 6 +- common/test/basics/module-objects.mjs | 30 ++++++ common/test/basics/module-settings.mjs | 101 ++++++++++++++++++ common/test/hooks.mjs | 14 ++- 8 files changed, 169 insertions(+), 26 deletions(-) rename common/test/basics/{module.mjs => module-base.mjs} (98%) create mode 100644 common/test/basics/module-objects.mjs create mode 100644 common/test/basics/module-settings.mjs diff --git a/common/src/events.mjs b/common/src/events.mjs index 702fc7d..25f5bf3 100644 --- a/common/src/events.mjs +++ b/common/src/events.mjs @@ -23,11 +23,17 @@ export class BaseEvent { + #name + /** * @property {string} name - Name of the event. */ constructor(name) { - this.name = name + this.#name = name + } + + get name() { + return this.#name } } diff --git a/common/src/module/objects.mjs b/common/src/module/objects.mjs index a95dc89..23801be 100644 --- a/common/src/module/objects.mjs +++ b/common/src/module/objects.mjs @@ -24,6 +24,10 @@ class ObjectsAPI extends Module { constructor() { super("Objects") + /** + * List of object constructors. + * @type {Object.} + */ this.types = {} /** * List of objects for each type of object. @@ -65,7 +69,7 @@ class ObjectsAPI extends Module { * @param {string} newName - Name to rename the object to. */ renameObject(oldName, newName) { - let obj = this.currentObjectsByName[oldName] + const obj = this.currentObjectsByName[oldName] delete this.currentObjectsByName[oldName] this.currentObjectsByName[newName] = obj obj.name = newName @@ -76,7 +80,7 @@ class ObjectsAPI extends Module { * @param {string} objName - Current name of the object. */ deleteObject(objName) { - let obj = this.currentObjectsByName[objName] + const obj = this.currentObjectsByName[objName] if(obj !== undefined) { this.currentObjects[obj.type].splice(this.currentObjects[obj.type].indexOf(obj), 1) obj.delete() diff --git a/common/src/module/settings.mjs b/common/src/module/settings.mjs index e6313c7..64c39c2 100644 --- a/common/src/module/settings.mjs +++ b/common/src/module/settings.mjs @@ -49,7 +49,8 @@ class SettingsAPI extends Module { static emits = ["changed"] #nonConfigurable = ["saveFilename"] - + + /** @type {Map} */ #properties = new Map([ ["saveFilename", ""], ["xzoom", 100], @@ -105,9 +106,8 @@ class SettingsAPI extends Module { * @param {boolean} byUser - Set to true if the user is at the origin of this change. */ set(property, value, byUser) { - if(!this.#properties.has(property)) { + if(!this.#properties.has(property)) throw new Error(`Property ${property} is not a setting.`) - } const oldValue = this.#properties.get(property) const propType = typeof oldValue if(byUser) diff --git a/common/test/basics/events.mjs b/common/test/basics/events.mjs index 8261ff1..092f037 100644 --- a/common/test/basics/events.mjs +++ b/common/test/basics/events.mjs @@ -16,15 +16,12 @@ * along with this program. If not, see . */ -import { BaseEventEmitter, BaseEvent } from "../../src/events.mjs" - import { describe, it } from "mocha" -import { expect, use } from "chai" -import spies from "chai-spies" +import { expect } from "chai" -// Setting up modules -const { spy } = use(spies) +const { spy } = chaiPlugins +import { BaseEventEmitter, BaseEvent } from "../../src/events.mjs" class MockEmitter extends BaseEventEmitter { static emits = ["example1", "example2"] @@ -43,12 +40,11 @@ class MockEvent2 extends BaseEvent { } } -const sandbox = spy.sandbox() - describe("Lib/EventsEmitters", function() { - - afterEach(() => { - sandbox.restore() + it("sends events with unique and readonly names", function() { + const event = new MockEvent1() + expect(event.name).to.equal("example1") + expect(() => event.name = "not").to.throw() }) it("forwards events to all of its listeners", function() { @@ -71,8 +67,8 @@ describe("Lib/EventsEmitters", function() { emitter.emit(mockEvent1) emitter.emit(mockEvent2) expect(listener).to.have.been.called.twice - expect(listener).to.also.have.been.called.with.exactly(mockEvent1) - expect(listener).to.also.have.been.called.with.exactly(mockEvent2) + expect(listener).to.have.been.first.called.with.exactly(mockEvent1) + expect(listener).to.have.been.second.called.with.exactly(mockEvent2) }) it("is able to have listeners removed", function() { diff --git a/common/test/basics/module.mjs b/common/test/basics/module-base.mjs similarity index 98% rename from common/test/basics/module.mjs rename to common/test/basics/module-base.mjs index 5093096..9a38109 100644 --- a/common/test/basics/module.mjs +++ b/common/test/basics/module-base.mjs @@ -16,15 +16,15 @@ * along with this program. If not, see . */ -// Load prior events +// Load prior tests import "./events.mjs" import "./interface.mjs" import { describe, it } from "mocha" import { expect } from "chai" +import { MockDialog } from "../mock/dialog.mjs" import { BOOLEAN, DialogInterface, FUNCTION, NUMBER, STRING } from "../../src/module/interface.mjs" import { Module } from "../../src/module/common.mjs" -import { MockDialog } from "../mock/dialog.mjs" class MockModule extends Module { constructor() { @@ -38,7 +38,7 @@ class MockModule extends Module { } } -describe("Modules/Base", function() { +describe("Module/Base", function() { it("defined a Modules global", function() { expect(globalThis.Modules).to.not.be.undefined }) diff --git a/common/test/basics/module-objects.mjs b/common/test/basics/module-objects.mjs new file mode 100644 index 0000000..ffc8076 --- /dev/null +++ b/common/test/basics/module-objects.mjs @@ -0,0 +1,30 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// Load prior tests +import "./module-base.mjs" +import "./utils.mjs" + +import { describe, it } from "mocha" +import { expect } from "chai" + +import Objects from "../../src/module/objects.mjs" + +describe("Module/Objects", function() { + +}) \ No newline at end of file diff --git a/common/test/basics/module-settings.mjs b/common/test/basics/module-settings.mjs new file mode 100644 index 0000000..ea26556 --- /dev/null +++ b/common/test/basics/module-settings.mjs @@ -0,0 +1,101 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// Load prior tests +import "./module-base.mjs" +import "./utils.mjs" + +import { describe, it } from "mocha" +import { expect } from "chai" + +const { spy } = chaiPlugins + +import Settings from "../../src/module/settings.mjs" +import { BaseEvent } from "../../src/events.mjs" + +describe("Module/Settings", function() { + it("is defined as a global", function() { + expect(globalThis.Modules.Settings).to.equal(Settings) + }) + + it("has base defined properties even before initialization", function() { + expect(Settings.saveFilename).to.be.a("string") + expect(Settings.xzoom).to.be.a("number") + expect(Settings.yzoom).to.be.a("number") + expect(Settings.xmin).to.be.a("number") + expect(Settings.ymax).to.be.a("number") + expect(Settings.xaxisstep).to.be.a("string") + expect(Settings.yaxisstep).to.be.a("string") + expect(Settings.xlabel).to.be.a("string") + expect(Settings.ylabel).to.be.a("string") + expect(Settings.linewidth).to.be.a("number") + expect(Settings.textsize).to.be.a("number") + expect(Settings.logscalex).to.be.a("boolean") + expect(Settings.showxgrad).to.be.a("boolean") + expect(Settings.showygrad).to.be.a("boolean") + }) + + it("can be set values, but only of the right type", function() { + expect(() => Settings.set("xzoom", "", false)).to.throw() + expect(() => Settings.set("xlabel", true, false)).to.throw() + expect(() => Settings.set("showxgrad", 2, false)).to.throw() + + expect(() => Settings.set("xzoom", 200, false)).to.not.throw() + expect(() => Settings.set("xlabel", "x", false)).to.not.throw() + expect(() => Settings.set("showxgrad", false, false)).to.not.throw() + }) + + it("cannot be set unknown settings", function() { + expect(() => Settings.set("unknown", "", false)).to.throw() + }) + + it("sends an event when a value is set", function() { + const listener = spy((e) => { + expect(e).to.be.an.instanceof(BaseEvent) + expect(e.name).to.equal("changed") + expect(e.property).to.equal("xzoom") + expect(e.newValue).to.equal(300) + expect(e.byUser).to.be.true + }) + Settings.on("changed", listener) + Settings.set("xzoom", 300, true) + expect(listener).to.have.been.called.once + Settings.off("changed", listener) + }) + + it("requires a helper to set default values", function() { + spy.on(Settings, "set") + expect(() => Settings.initialize({})).to.throw() + expect(() => Settings.initialize({ helper: globalThis.Helper })).to.not.throw() + expect(Settings.set).to.have.been.called.exactly(13) + expect(Settings.set).to.not.have.been.called.with("saveFilename") + expect(Settings.set).to.have.been.called.with("xzoom") + expect(Settings.set).to.have.been.called.with("yzoom") + expect(Settings.set).to.have.been.called.with("xmin") + expect(Settings.set).to.have.been.called.with("ymax") + expect(Settings.set).to.have.been.called.with("xaxisstep") + expect(Settings.set).to.have.been.called.with("yaxisstep") + expect(Settings.set).to.have.been.called.with("xlabel") + expect(Settings.set).to.have.been.called.with("ylabel") + expect(Settings.set).to.have.been.called.with("linewidth") + expect(Settings.set).to.have.been.called.with("textsize") + expect(Settings.set).to.have.been.called.with("logscalex") + expect(Settings.set).to.have.been.called.with("showxgrad") + expect(Settings.set).to.have.been.called.with("showygrad") + }) +}) \ No newline at end of file diff --git a/common/test/hooks.mjs b/common/test/hooks.mjs index 0f3ebda..abe468f 100644 --- a/common/test/hooks.mjs +++ b/common/test/hooks.mjs @@ -15,14 +15,20 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -import * as fs from "./mock/fs.mjs"; -import Qt from "./mock/qt.mjs"; -import { MockHelper } from "./mock/helper.mjs"; -import { MockLatex } from "./mock/latex.mjs"; +import * as fs from "./mock/fs.mjs" +import Qt from "./mock/qt.mjs" +import { MockHelper } from "./mock/helper.mjs" +import { MockLatex } from "./mock/latex.mjs" + +import { use } from "chai" +import spies from "chai-spies" function setup() { + const { spy } = use(spies) + globalThis.Helper = new MockHelper() globalThis.Latex = new MockLatex() + globalThis.chaiPlugins = { spy } } setup() From edf45184942f6c1a25f46157fc4727ea70284f15 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sat, 12 Oct 2024 20:37:16 +0200 Subject: [PATCH 039/104] Starting expr-eval's tests. --- common/src/lib/expr-eval/expression.mjs | 3 - common/src/lib/expr-eval/parser.mjs | 3 - common/src/lib/expr-eval/tokens.mjs | 2 +- common/src/module/expreval.mjs | 8 +- .../module-base.mjs => module/base.mjs} | 4 +- common/test/module/expreval.mjs | 187 ++++++++++++++++++ .../module-objects.mjs => module/objects.mjs} | 14 +- .../settings.mjs} | 4 +- 8 files changed, 203 insertions(+), 22 deletions(-) rename common/test/{basics/module-base.mjs => module/base.mjs} (97%) create mode 100644 common/test/module/expreval.mjs rename common/test/{basics/module-objects.mjs => module/objects.mjs} (85%) rename common/test/{basics/module-settings.mjs => module/settings.mjs} (98%) diff --git a/common/src/lib/expr-eval/expression.mjs b/common/src/lib/expr-eval/expression.mjs index 89831c7..d89d67e 100644 --- a/common/src/lib/expr-eval/expression.mjs +++ b/common/src/lib/expr-eval/expression.mjs @@ -171,9 +171,6 @@ function evaluate(tokens, expr, values) { nstack.push(n1 ? !!evaluate(n2, expr, values) : false) } else if(item.value === "or") { nstack.push(n1 ? true : !!evaluate(n2, expr, values)) - } else if(item.value === "=") { - f = expr.binaryOps[item.value] - nstack.push(f(n1, evaluate(n2, expr, values), values)) } else { f = expr.binaryOps[item.value] nstack.push(f(resolveExpression(n1, values), resolveExpression(n2, values))) diff --git a/common/src/lib/expr-eval/parser.mjs b/common/src/lib/expr-eval/parser.mjs index 71a1c95..ba920c6 100644 --- a/common/src/lib/expr-eval/parser.mjs +++ b/common/src/lib/expr-eval/parser.mjs @@ -47,9 +47,7 @@ const optionNameMap = { "not": "logical", "?": "conditional", ":": "conditional", - //'=': 'assignment', // Disable assignment "[": "array" - //'()=': 'fndef' // Diable function definition } export class Parser { @@ -109,7 +107,6 @@ export class Parser { and: Polyfill.andOperator, or: Polyfill.orOperator, "in": Polyfill.inOperator, - "=": Polyfill.setVar, "[": Polyfill.arrayIndex } diff --git a/common/src/lib/expr-eval/tokens.mjs b/common/src/lib/expr-eval/tokens.mjs index 919433c..bfaad39 100644 --- a/common/src/lib/expr-eval/tokens.mjs +++ b/common/src/lib/expr-eval/tokens.mjs @@ -472,7 +472,7 @@ export class TokenStream { this.current = this.newToken(TOP, "==") this.pos++ } else { - this.current = this.newToken(TOP, c) + return false } } else if(c === "!") { if(this.expression.charAt(this.pos + 1) === "=") { diff --git a/common/src/module/expreval.mjs b/common/src/module/expreval.mjs index 964177c..7b40b2f 100644 --- a/common/src/module/expreval.mjs +++ b/common/src/module/expreval.mjs @@ -84,11 +84,11 @@ class ExprParserAPI extends Module { return this.#parser.parse(expression) } - integral(a, b, ...args) { + integral(a = null, b = null, ...args) { let usage1 = qsTranslate("usage", "integral(, , )") let usage2 = qsTranslate("usage", "integral(, , , )") let f = this.parseArgumentsForFunction(args, usage1, usage2) - if(a == null || b == null) + if(typeof a !== "number" || typeof b !== "number") throw EvalError(qsTranslate("usage", "Usage:\n%1\n%2").arg(usage1).arg(usage2)) // https://en.wikipedia.org/wiki/Simpson%27s_rule @@ -101,10 +101,10 @@ class ExprParserAPI extends Module { let usage2 = qsTranslate("usage", "derivative(, , )") let x = args.pop() let f = this.parseArgumentsForFunction(args, usage1, usage2) - if(x == null) + if(typeof x !== "number") throw EvalError(qsTranslate("usage", "Usage:\n%1\n%2").arg(usage1).arg(usage2)) - let derivative_precision = x / 10 + let derivative_precision = 1e-8 return (f(x + derivative_precision / 2) - f(x - derivative_precision / 2)) / derivative_precision } } diff --git a/common/test/basics/module-base.mjs b/common/test/module/base.mjs similarity index 97% rename from common/test/basics/module-base.mjs rename to common/test/module/base.mjs index 9a38109..be035c0 100644 --- a/common/test/basics/module-base.mjs +++ b/common/test/module/base.mjs @@ -17,8 +17,8 @@ */ // Load prior tests -import "./events.mjs" -import "./interface.mjs" +import "../basics/events.mjs" +import "../basics/interface.mjs" import { describe, it } from "mocha" import { expect } from "chai" diff --git a/common/test/module/expreval.mjs b/common/test/module/expreval.mjs new file mode 100644 index 0000000..c9361f0 --- /dev/null +++ b/common/test/module/expreval.mjs @@ -0,0 +1,187 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// Load prior tests +import "./base.mjs" + +import { describe, it } from "mocha" +import { expect } from "chai" + +import ExprEval from "../../src/module/expreval.mjs" + +describe("Module/ExprEval", function() { + describe("#parse", function() { + const evaluate = (expr, vals) => ExprEval.parse(expr).evaluate(vals) + it("parses simple mathematical expressions", function() { + expect(evaluate("1", {})).to.equal(1) + expect(evaluate("-1", {})).to.equal(-1) + expect(evaluate("-(-1)", {})).to.equal(1) + expect(evaluate("+(-1)", {})).to.equal(-1) + expect(evaluate("3!", {})).to.equal(6) + expect(evaluate("1+1", {})).to.equal(2) + expect(evaluate("4*3", {})).to.equal(12) + expect(evaluate("64/4", {})).to.equal(16) + expect(evaluate("2^10", {})).to.equal(1024) + expect(evaluate("10%3", {})).to.equal(1) + expect(evaluate("10%3", {})).to.equal(1) + // Test priorities + expect(evaluate("10*10+10*10", {})).to.equal(200) + expect(evaluate("10/10+10/10", {})).to.equal(2) + expect(evaluate("10/10+10/10", {})).to.equal(2) + expect(evaluate("2^2-2^2", {})).to.equal(0) + expect(evaluate("(2^2-2)^2", {})).to.equal(4) + }) + + it("parses equality and test statements", function() { + expect(evaluate("10%3 == 1 ? 2 : 1", {})).to.equal(2) + expect(evaluate("10%3 != 1 ? 2 : 1", {})).to.equal(1) + expect(evaluate("10 < 3 ? 2 : 1", {})).to.equal(1) + expect(evaluate("10 > 3 ? (2+1) : 1", {})).to.equal(3) + expect(evaluate("10 <= 3 ? 4 : 1", {})).to.equal(1) + expect(evaluate("10 >= 3 ? 4 : 1", {})).to.equal(4) + // Check equality + expect(evaluate("10 < 10 ? 2 : 1", {})).to.equal(1) + expect(evaluate("10 > 10 ? 2 : 1", {})).to.equal(1) + expect(evaluate("10 <= 10 ? 4 : 1", {})).to.equal(4) + expect(evaluate("10 >= 10 ? 4 : 1", {})).to.equal(4) + // Check 'and' and 'or' + expect(evaluate("10 <= 3 and 10 < 10 ? 4 : 1", {})).to.equal(1) + expect(evaluate("10 <= 10 and 10 < 10 ? 4 : 1", {})).to.equal(1) + expect(evaluate("10 <= 10 and 10 < 20 ? 4 : 1", {})).to.equal(4) + expect(evaluate("10 <= 3 or 10 < 10 ? 4 : 1", {})).to.equal(1) + expect(evaluate("10 <= 10 or 10 < 10 ? 4 : 1", {})).to.equal(4) + expect(evaluate("10 <= 10 or 10 < 20 ? 4 : 1", {})).to.equal(4) + }) + + it("parses singular function operators (functions with one arguments and no parenthesis)", function() { + // Trigonometric functions + expect(evaluate("sin π", { })).to.be.approximately(0, Number.EPSILON) + expect(evaluate("cos π", { })).to.be.approximately(-1, Number.EPSILON) + expect(evaluate("tan π", { })).to.be.approximately(0, Number.EPSILON) + expect(evaluate("asin 1", { })).to.be.approximately(Math.PI/2, Number.EPSILON) + expect(evaluate("acos 1", { })).to.be.approximately(0, Number.EPSILON) + expect(evaluate("atan 1", { })).to.be.approximately(Math.PI/4, Number.EPSILON) + expect(evaluate("sinh 1", { })).to.be.approximately(Math.sinh(1), Number.EPSILON) + expect(evaluate("cosh 1", { })).to.be.approximately(Math.cosh(1), Number.EPSILON) + expect(evaluate("tanh 1", { })).to.be.approximately(Math.tanh(1), Number.EPSILON) + expect(evaluate("asinh 1", { })).to.be.approximately(Math.asinh(1), Number.EPSILON) + expect(evaluate("acosh 1", { })).to.be.approximately(Math.acosh(1), Number.EPSILON) + expect(evaluate("atanh 0.5", { })).to.be.approximately(Math.atanh(0.5), Number.EPSILON) + // Reverse trigonometric + expect(evaluate("asin sin 1", { })).to.be.approximately(1, Number.EPSILON) + expect(evaluate("acos cos 1", { })).to.be.approximately(1, Number.EPSILON) + expect(evaluate("atan tan 1", { })).to.be.approximately(1, Number.EPSILON) + expect(evaluate("asinh sinh 1", { })).to.be.approximately(1, Number.EPSILON) + expect(evaluate("acosh cosh 1", { })).to.be.approximately(1, Number.EPSILON) + expect(evaluate("atanh tanh 1", { })).to.be.approximately(1, Number.EPSILON) + // Other functions + }) + }) + + + describe("#integral", function() { + it("returns the integral value between two integers", function() { + expect(ExprEval.integral(0, 1, "1", "t")).to.be.approximately(1, Number.EPSILON) + expect(ExprEval.integral(0, 1, "t", "t")).to.be.approximately(1 / 2, Number.EPSILON) + expect(ExprEval.integral(0, 1, "t^2", "t")).to.be.approximately(1 / 3, Number.EPSILON) + expect(ExprEval.integral(0, 1, "t^3", "t")).to.be.approximately(1 / 4, 0.01) + expect(ExprEval.integral(0, 1, "t^4", "t")).to.be.approximately(1 / 5, 0.01) + + expect(ExprEval.integral(10, 40, "1", "t")).to.equal(30) + expect(ExprEval.integral(20, 40, "1", "t")).to.equal(20) + + expect(ExprEval.integral(0, 10, { execute: (x) => 1 })).to.equal(10) + expect(ExprEval.integral(0, 10, { execute: (x) => x })).to.equal(50) + expect(ExprEval.integral(0, 1, { execute: (x) => Math.pow(x, 2) })).to.equal(1 / 3) + }) + + + it("throws error when provided with invalid arguments", function() { + const noArg1 = () => ExprEval.integral() + const noArg2 = () => ExprEval.integral(0) + const noFunction = () => ExprEval.integral(0, 1) + const invalidObjectProvided = () => ExprEval.integral(0, 1, { a: 2 }) + const notAnObjectProvided = () => ExprEval.integral(0, 1, "string") + const invalidFromProvided = () => ExprEval.integral("ze", 1, "t^2", "t") + const invalidToProvided = () => ExprEval.integral(0, "ze", "t^2", "t") + const notStringProvided1 = () => ExprEval.integral(0, 1, { a: 2 }, { b: 1 }) + const notStringProvided2 = () => ExprEval.integral(0, 1, { a: 2 }, "t") + const notStringProvided3 = () => ExprEval.integral(0, 1, "t^2", { b: 1 }) + const invalidVariableProvided = () => ExprEval.integral(0, 1, "t^2", "93IO74") + const invalidExpressionProvided = () => ExprEval.integral(0, 1, "t^2t", "t") + const invalidVariableInExpression = () => ExprEval.integral(0, 1, "t^2+x", "t") + expect(noArg1).to.throw() + expect(noArg2).to.throw() + expect(noFunction).to.throw() + expect(invalidObjectProvided).to.throw() + expect(invalidFromProvided).to.throw() + expect(invalidToProvided).to.throw() + expect(notAnObjectProvided).to.throw() + expect(notStringProvided1).to.throw() + expect(notStringProvided2).to.throw() + expect(notStringProvided3).to.throw() + expect(invalidVariableProvided).to.throw() + expect(invalidExpressionProvided).to.throw() + expect(invalidVariableInExpression).to.throw() + }) + }) + + describe("#derivative", function() { + const DELTA = 1e-5 + it("returns the derivative value between two integers", function() { + expect(ExprEval.derivative("1", "t", 2)).to.be.approximately(0, DELTA) + expect(ExprEval.derivative("t", "t", 2)).to.be.approximately(1, DELTA) + expect(ExprEval.derivative("t^2", "t", 2)).to.be.approximately(4, DELTA) + expect(ExprEval.derivative("t^3", "t", 2)).to.be.approximately(12, DELTA) + expect(ExprEval.derivative("t^4", "t", 2)).to.be.approximately(32, DELTA) + + expect(ExprEval.derivative({ execute: (x) => 1 }, 10)).to.equal(0) + expect(ExprEval.derivative({ execute: (x) => x }, 10)).to.be.approximately(1, DELTA) + expect(ExprEval.derivative({ execute: (x) => Math.pow(x, 2) }, 10)).to.be.approximately(20, DELTA) + }) + + it("throws error when provided with invalid arguments", function() { + const noArg1 = () => ExprEval.derivative() + const noArg2 = () => ExprEval.derivative("1") + const noValue1 = () => ExprEval.derivative("0", "1") + const noValue2 = () => ExprEval.derivative({ execute: (x) => 1 }) + const invalidObjectProvided = () => ExprEval.derivative({ a: 2 }, 1) + const notAnObjectProvided = () => ExprEval.derivative("string", 1) + const invalidXProvided = () => ExprEval.derivative("t^2+x", "t", "ze") + const notStringProvided1 = () => ExprEval.derivative({ a: 2 }, { b: 1 }, 1) + const notStringProvided2 = () => ExprEval.derivative({ a: 2 }, "t", 1) + const notStringProvided3 = () => ExprEval.derivative("t^2", { b: 1 }, 1) + const invalidVariableProvided = () => ExprEval.derivative("t^2", "93IO74", 1) + const invalidExpressionProvided = () => ExprEval.derivative("t^2t", "t", 1) + const invalidVariableInExpression = () => ExprEval.derivative("t^2+x", "t", 1) + expect(noArg1).to.throw() + expect(noArg2).to.throw() + expect(noValue1).to.throw() + expect(noValue2).to.throw() + expect(invalidObjectProvided).to.throw() + expect(invalidXProvided).to.throw() + expect(notAnObjectProvided).to.throw() + expect(notStringProvided1).to.throw() + expect(notStringProvided2).to.throw() + expect(notStringProvided3).to.throw() + expect(invalidVariableProvided).to.throw() + expect(invalidExpressionProvided).to.throw() + expect(invalidVariableInExpression).to.throw() + }) + }) +}) \ No newline at end of file diff --git a/common/test/basics/module-objects.mjs b/common/test/module/objects.mjs similarity index 85% rename from common/test/basics/module-objects.mjs rename to common/test/module/objects.mjs index ffc8076..4665232 100644 --- a/common/test/basics/module-objects.mjs +++ b/common/test/module/objects.mjs @@ -17,14 +17,14 @@ */ // Load prior tests -import "./module-base.mjs" -import "./utils.mjs" +import "./base.mjs" +import "../basics/utils.mjs" import { describe, it } from "mocha" import { expect } from "chai" -import Objects from "../../src/module/objects.mjs" - -describe("Module/Objects", function() { - -}) \ No newline at end of file +// import Objects from "../../src/module/objects.mjs" +// +// describe("Module/Objects", function() { +// +// }) \ No newline at end of file diff --git a/common/test/basics/module-settings.mjs b/common/test/module/settings.mjs similarity index 98% rename from common/test/basics/module-settings.mjs rename to common/test/module/settings.mjs index ea26556..7ad439a 100644 --- a/common/test/basics/module-settings.mjs +++ b/common/test/module/settings.mjs @@ -17,8 +17,8 @@ */ // Load prior tests -import "./module-base.mjs" -import "./utils.mjs" +import "./base.mjs" +import "../basics/utils.mjs" import { describe, it } from "mocha" import { expect } from "chai" From 3a81441d0bc37dfb7a1c8aeefba8b523885e2c1e Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sun, 13 Oct 2024 00:33:22 +0200 Subject: [PATCH 040/104] Finished expr-eval testing --- common/src/lib/expr-eval/expression.mjs | 14 +- common/src/lib/expr-eval/parser.mjs | 11 +- common/src/lib/expr-eval/polyfill.mjs | 55 +---- common/src/module/expreval.mjs | 4 +- common/test/module/expreval.mjs | 308 ++++++++++++++++++++---- 5 files changed, 260 insertions(+), 132 deletions(-) diff --git a/common/src/lib/expr-eval/expression.mjs b/common/src/lib/expr-eval/expression.mjs index d89d67e..f782fa3 100644 --- a/common/src/lib/expr-eval/expression.mjs +++ b/common/src/lib/expr-eval/expression.mjs @@ -111,7 +111,7 @@ function simplify(tokens, unaryOps, binaryOps, ternaryOps, values) { * In the given instructions, replaces variable by expr. * @param {Instruction[]} tokens * @param {string} variable - * @param {number} expr + * @param {ExprEvalExpression} expr * @return {Instruction[]} */ function substitute(tokens, variable, expr) { @@ -487,18 +487,6 @@ export class ExprEvalExpression { return evaluate(this.tokens, this, values) } - /** - * Returns a list of symbols (string of characters) in the expressions. - * Can be functions, constants, or variables. - * @returns {string[]} - */ - symbols(options) { - options = options || {} - const vars = [] - getSymbols(this.tokens, vars, options) - return vars - } - toString() { return expressionToString(this.tokens, false) } diff --git a/common/src/lib/expr-eval/parser.mjs b/common/src/lib/expr-eval/parser.mjs index ba920c6..e27d512 100644 --- a/common/src/lib/expr-eval/parser.mjs +++ b/common/src/lib/expr-eval/parser.mjs @@ -120,18 +120,13 @@ export class Parser { min: Polyfill.min, max: Polyfill.max, hypot: Math.hypot || Polyfill.hypot, - pyt: Math.hypot || Polyfill.hypot, // backward compat + pyt: Math.hypot || Polyfill.hypot, pow: Math.pow, atan2: Math.atan2, "if": Polyfill.condition, gamma: Polyfill.gamma, "Γ": Polyfill.gamma, roundTo: Polyfill.roundTo, - map: Polyfill.arrayMap, - fold: Polyfill.arrayFold, - filter: Polyfill.arrayFilter, - indexOf: Polyfill.stringOrArrayIndexOf, - join: Polyfill.arrayJoin } // These constants will automatically be replaced the MOMENT they are parsed. @@ -156,10 +151,6 @@ export class Parser { return new ExprEvalExpression(instr, this) } - evaluate(expr, variables) { - return this.parse(expr).evaluate(variables) - } - isOperatorEnabled(op) { const optionName = optionNameMap.hasOwnProperty(op) ? optionNameMap[op] : op const operators = this.options.operators || {} diff --git a/common/src/lib/expr-eval/polyfill.mjs b/common/src/lib/expr-eval/polyfill.mjs index 9e8e885..c618aaf 100644 --- a/common/src/lib/expr-eval/polyfill.mjs +++ b/common/src/lib/expr-eval/polyfill.mjs @@ -210,9 +210,8 @@ export function gamma(n) { } export function stringOrArrayLength(s) { - if(Array.isArray(s)) { + if(Array.isArray(s)) return s.length - } return String(s).length } @@ -296,58 +295,6 @@ export function min(array) { } } -export function arrayMap(f, a) { - if(typeof f !== "function") { - throw new EvalError(qsTranslate("error", "First argument to map is not a function.")) - } - if(!Array.isArray(a)) { - throw new EvalError(qsTranslate("error", "Second argument to map is not an array.")) - } - return a.map(function(x, i) { - return f(x, i) - }) -} - -export function arrayFold(f, init, a) { - if(typeof f !== "function") { - throw new EvalError(qsTranslate("error", "First argument to fold is not a function.")) - } - if(!Array.isArray(a)) { - throw new EvalError(qsTranslate("error", "Second argument to fold is not an array.")) - } - return a.reduce(function(acc, x, i) { - return f(acc, x, i) - }, init) -} - -export function arrayFilter(f, a) { - if(typeof f !== "function") { - throw new EvalError(qsTranslate("error", "First argument to filter is not a function.")) - } - if(!Array.isArray(a)) { - throw new EvalError(qsTranslate("error", "Second argument to filter is not an array.")) - } - return a.filter(function(x, i) { - return f(x, i) - }) -} - -export function stringOrArrayIndexOf(target, s) { - if(!(Array.isArray(s) || typeof s === "string")) { - throw new Error(qsTranslate("error", "Second argument to indexOf is not a string or array.")) - } - - return s.indexOf(target) -} - -export function arrayJoin(sep, a) { - if(!Array.isArray(a)) { - throw new Error(qsTranslate("error", "Second argument to join is not an array.")) - } - - return a.join(sep) -} - export function sign(x) { return ((x > 0) - (x < 0)) || +x } diff --git a/common/src/module/expreval.mjs b/common/src/module/expreval.mjs index 7b40b2f..8440282 100644 --- a/common/src/module/expreval.mjs +++ b/common/src/module/expreval.mjs @@ -19,7 +19,7 @@ import { Module } from "./common.mjs" import { Parser } from "../lib/expr-eval/parser.mjs" -const evalVariables = { +const EVAL_VARIABLES = { // Variables not provided by expr-eval.js, needs to be provided manually "pi": Math.PI, "PI": Math.PI, @@ -42,7 +42,7 @@ class ExprParserAPI extends Module { this.currentVars = {} this.#parser = new Parser() - this.#parser.consts = Object.assign({}, this.#parser.consts, evalVariables) + this.#parser.consts = Object.assign({}, this.#parser.consts, EVAL_VARIABLES) this.#parser.functions.integral = this.integral.bind(this) this.#parser.functions.derivative = this.derivative.bind(this) diff --git a/common/test/module/expreval.mjs b/common/test/module/expreval.mjs index c9361f0..2d075f6 100644 --- a/common/test/module/expreval.mjs +++ b/common/test/module/expreval.mjs @@ -25,72 +25,274 @@ import { expect } from "chai" import ExprEval from "../../src/module/expreval.mjs" describe("Module/ExprEval", function() { - describe("#parse", function() { - const evaluate = (expr, vals) => ExprEval.parse(expr).evaluate(vals) + describe("#parse.evaluate", function() { + const evaluate = (expr, vals = {}) => ExprEval.parse(expr).evaluate(vals) it("parses simple mathematical expressions", function() { - expect(evaluate("1", {})).to.equal(1) - expect(evaluate("-1", {})).to.equal(-1) - expect(evaluate("-(-1)", {})).to.equal(1) - expect(evaluate("+(-1)", {})).to.equal(-1) - expect(evaluate("3!", {})).to.equal(6) - expect(evaluate("1+1", {})).to.equal(2) - expect(evaluate("4*3", {})).to.equal(12) - expect(evaluate("64/4", {})).to.equal(16) - expect(evaluate("2^10", {})).to.equal(1024) - expect(evaluate("10%3", {})).to.equal(1) - expect(evaluate("10%3", {})).to.equal(1) + expect(evaluate(`"\\'\\"\\\\\\/\\b\\f\\n\\r\\t\\u3509"`)).to.equal(`'"\\/\b\f\n\r\t\u3509`) + expect(evaluate("1")).to.equal(1) + expect(evaluate(" 1 ")).to.equal(1) + expect(evaluate("0xFF")).to.equal(255) + expect(evaluate("0b11")).to.equal(3) + expect(evaluate("-1")).to.equal(-1) + expect(evaluate("-(-1)")).to.equal(1) + expect(evaluate("+(-1)")).to.equal(-1) + expect(evaluate("3!")).to.equal(6) + expect(evaluate("1+1")).to.equal(2) + expect(evaluate("4*3")).to.equal(12) + expect(evaluate("4•3")).to.equal(12) + expect(evaluate("64/4")).to.equal(16) + expect(evaluate("2^10")).to.equal(1024) + expect(evaluate("10%3")).to.equal(1) + expect(evaluate("10%3")).to.equal(1) // Test priorities - expect(evaluate("10*10+10*10", {})).to.equal(200) - expect(evaluate("10/10+10/10", {})).to.equal(2) - expect(evaluate("10/10+10/10", {})).to.equal(2) - expect(evaluate("2^2-2^2", {})).to.equal(0) - expect(evaluate("(2^2-2)^2", {})).to.equal(4) + expect(evaluate("10*10+10*10")).to.equal(200) + expect(evaluate("10/10+10/10")).to.equal(2) + expect(evaluate("10/10+10/10")).to.equal(2) + expect(evaluate("2^2-2^2")).to.equal(0) + expect(evaluate("(2^2-2)^2")).to.equal(4) }) it("parses equality and test statements", function() { - expect(evaluate("10%3 == 1 ? 2 : 1", {})).to.equal(2) - expect(evaluate("10%3 != 1 ? 2 : 1", {})).to.equal(1) - expect(evaluate("10 < 3 ? 2 : 1", {})).to.equal(1) - expect(evaluate("10 > 3 ? (2+1) : 1", {})).to.equal(3) - expect(evaluate("10 <= 3 ? 4 : 1", {})).to.equal(1) - expect(evaluate("10 >= 3 ? 4 : 1", {})).to.equal(4) + expect(evaluate("10%3 == 1 ? 2 : 1")).to.equal(2) + expect(evaluate("not(10%3 == 1) ? 2 : 1")).to.equal(1) + expect(evaluate("10%3 != 1 ? 2 : 1")).to.equal(1) + expect(evaluate("10 < 3 ? 2 : 1")).to.equal(1) + expect(evaluate("10 > 3 ? (2+1) : 1")).to.equal(3) + expect(evaluate("10 <= 3 ? 4 : 1")).to.equal(1) + expect(evaluate("10 >= 3 ? 4 : 1")).to.equal(4) // Check equality - expect(evaluate("10 < 10 ? 2 : 1", {})).to.equal(1) - expect(evaluate("10 > 10 ? 2 : 1", {})).to.equal(1) - expect(evaluate("10 <= 10 ? 4 : 1", {})).to.equal(4) - expect(evaluate("10 >= 10 ? 4 : 1", {})).to.equal(4) + expect(evaluate("10 < 10 ? 2 : 1")).to.equal(1) + expect(evaluate("10 > 10 ? 2 : 1")).to.equal(1) + expect(evaluate("10 <= 10 ? 4 : 1")).to.equal(4) + expect(evaluate("10 >= 10 ? 4 : 1")).to.equal(4) // Check 'and' and 'or' - expect(evaluate("10 <= 3 and 10 < 10 ? 4 : 1", {})).to.equal(1) - expect(evaluate("10 <= 10 and 10 < 10 ? 4 : 1", {})).to.equal(1) - expect(evaluate("10 <= 10 and 10 < 20 ? 4 : 1", {})).to.equal(4) - expect(evaluate("10 <= 3 or 10 < 10 ? 4 : 1", {})).to.equal(1) - expect(evaluate("10 <= 10 or 10 < 10 ? 4 : 1", {})).to.equal(4) - expect(evaluate("10 <= 10 or 10 < 20 ? 4 : 1", {})).to.equal(4) + expect(evaluate("10 <= 3 and 10 < 10 ? 4 : 1")).to.equal(1) + expect(evaluate("10 <= 10 and 10 < 10 ? 4 : 1")).to.equal(1) + expect(evaluate("10 <= 10 and 10 < 20 ? 4 : 1")).to.equal(4) + expect(evaluate("10 <= 3 or 10 < 10 ? 4 : 1")).to.equal(1) + expect(evaluate("10 <= 10 or 10 < 10 ? 4 : 1")).to.equal(4) + expect(evaluate("10 <= 10 or 10 < 20 ? 4 : 1")).to.equal(4) }) it("parses singular function operators (functions with one arguments and no parenthesis)", function() { // Trigonometric functions - expect(evaluate("sin π", { })).to.be.approximately(0, Number.EPSILON) - expect(evaluate("cos π", { })).to.be.approximately(-1, Number.EPSILON) - expect(evaluate("tan π", { })).to.be.approximately(0, Number.EPSILON) - expect(evaluate("asin 1", { })).to.be.approximately(Math.PI/2, Number.EPSILON) - expect(evaluate("acos 1", { })).to.be.approximately(0, Number.EPSILON) - expect(evaluate("atan 1", { })).to.be.approximately(Math.PI/4, Number.EPSILON) - expect(evaluate("sinh 1", { })).to.be.approximately(Math.sinh(1), Number.EPSILON) - expect(evaluate("cosh 1", { })).to.be.approximately(Math.cosh(1), Number.EPSILON) - expect(evaluate("tanh 1", { })).to.be.approximately(Math.tanh(1), Number.EPSILON) - expect(evaluate("asinh 1", { })).to.be.approximately(Math.asinh(1), Number.EPSILON) - expect(evaluate("acosh 1", { })).to.be.approximately(Math.acosh(1), Number.EPSILON) - expect(evaluate("atanh 0.5", { })).to.be.approximately(Math.atanh(0.5), Number.EPSILON) + expect(evaluate("sin 0")).to.be.approximately(0, Number.EPSILON) + expect(evaluate("cos 0")).to.be.approximately(1, Number.EPSILON) + expect(evaluate("tan 0")).to.be.approximately(0, Number.EPSILON) + expect(evaluate("asin 1")).to.be.approximately(Math.PI / 2, Number.EPSILON) + expect(evaluate("acos 1")).to.be.approximately(0, Number.EPSILON) + expect(evaluate("atan 1")).to.be.approximately(Math.PI / 4, Number.EPSILON) + expect(evaluate("sinh 1")).to.be.approximately(Math.sinh(1), Number.EPSILON) + expect(evaluate("cosh 1")).to.be.approximately(Math.cosh(1), Number.EPSILON) + expect(evaluate("tanh 1")).to.be.approximately(Math.tanh(1), Number.EPSILON) + expect(evaluate("asinh 1")).to.be.approximately(Math.asinh(1), Number.EPSILON) + expect(evaluate("acosh 1")).to.be.approximately(Math.acosh(1), Number.EPSILON) + expect(evaluate("atanh 0.5")).to.be.approximately(Math.atanh(0.5), Number.EPSILON) // Reverse trigonometric - expect(evaluate("asin sin 1", { })).to.be.approximately(1, Number.EPSILON) - expect(evaluate("acos cos 1", { })).to.be.approximately(1, Number.EPSILON) - expect(evaluate("atan tan 1", { })).to.be.approximately(1, Number.EPSILON) - expect(evaluate("asinh sinh 1", { })).to.be.approximately(1, Number.EPSILON) - expect(evaluate("acosh cosh 1", { })).to.be.approximately(1, Number.EPSILON) - expect(evaluate("atanh tanh 1", { })).to.be.approximately(1, Number.EPSILON) + expect(evaluate("asin sin 1")).to.be.approximately(1, Number.EPSILON) + expect(evaluate("acos cos 1")).to.be.approximately(1, Number.EPSILON) + expect(evaluate("atan tan 1")).to.be.approximately(1, Number.EPSILON) + expect(evaluate("asinh sinh 1")).to.be.approximately(1, Number.EPSILON) + expect(evaluate("acosh cosh 1")).to.be.approximately(1, Number.EPSILON) + expect(evaluate("atanh tanh 1")).to.be.approximately(1, Number.EPSILON) // Other functions + expect(evaluate("sqrt 4")).to.be.approximately(2, Number.EPSILON) + expect(evaluate("sqrt 2")).to.be.approximately(Math.sqrt(2), Number.EPSILON) + expect(evaluate("cbrt 27")).to.be.approximately(3, Number.EPSILON) + expect(evaluate("cbrt 14")).to.be.approximately(Math.cbrt(14), Number.EPSILON) + expect(evaluate("log 1")).to.be.approximately(Math.log(1), Number.EPSILON) + expect(evaluate("ln 1")).to.be.approximately(Math.log(1), Number.EPSILON) + expect(evaluate("log2 8")).to.be.approximately(3, Number.EPSILON) + expect(evaluate("log10 100")).to.be.approximately(2, Number.EPSILON) + expect(evaluate("lg 100")).to.be.approximately(2, Number.EPSILON) + expect(evaluate("expm1 0")).to.be.approximately(0, Number.EPSILON) + expect(evaluate("expm1 10")).to.be.approximately(Math.expm1(10), Number.EPSILON) + expect(evaluate("log1p 0")).to.be.approximately(0, Number.EPSILON) + expect(evaluate("log1p 10")).to.be.approximately(Math.log1p(10), Number.EPSILON) + // Roundings/Sign transformations + expect(evaluate("abs -12.34")).to.equal(12.34) + expect(evaluate("abs 12.45")).to.equal(12.45) + expect(evaluate("ceil 12.45")).to.equal(13) + expect(evaluate("ceil 12.75")).to.equal(13) + expect(evaluate("ceil 12.0")).to.equal(12) + expect(evaluate("ceil -12.6")).to.equal(-12) + expect(evaluate("floor 12.45")).to.equal(12) + expect(evaluate("floor 12.75")).to.equal(12) + expect(evaluate("floor 12.0")).to.equal(12) + expect(evaluate("floor -12.2")).to.equal(-13) + expect(evaluate("round 12.45")).to.equal(12) + expect(evaluate("round 12.75")).to.equal(13) + expect(evaluate("round 12.0")).to.equal(12) + expect(evaluate("round -12.2")).to.equal(-12) + expect(evaluate("round -12.6")).to.equal(-13) + expect(evaluate("trunc 12.45")).to.equal(12) + expect(evaluate("trunc 12.75")).to.equal(12) + expect(evaluate("trunc 12.0")).to.equal(12) + expect(evaluate("trunc -12.2")).to.equal(-12) + expect(evaluate("exp 1")).to.be.approximately(Math.E, Number.EPSILON) + expect(evaluate("exp 10")).to.be.approximately(Math.pow(Math.E, 10), 1e-8) + expect(evaluate("length \"string\"")).to.equal(6) + expect(evaluate("sign 0")).to.equal(0) + expect(evaluate("sign -0")).to.equal(0) + expect(evaluate("sign -10")).to.equal(-1) + expect(evaluate("sign 80")).to.equal(1) }) + + it("parses regular functions", function() { + for(let i = 0; i < 1000; i++) { + expect(evaluate("random()")).to.be.within(0, 1) + expect(evaluate("random(100)")).to.be.within(0, 100) + } + expect(evaluate("fac(3)")).to.equal(6) + expect(evaluate("fac(10)")).to.equal(3628800) + expect(evaluate("min(10, 20)")).to.equal(10) + expect(evaluate("min(-10, -20)")).to.equal(-20) + expect(evaluate("max(10, 20)")).to.equal(20) + expect(evaluate("max(-10, -20)")).to.equal(-10) + expect(evaluate("hypot(3, 4)")).to.equal(5) + expect(evaluate("pyt(30, 40)")).to.equal(50) + expect(evaluate("atan2(1, 1)")).to.be.approximately(Math.PI / 4, Number.EPSILON) + expect(evaluate("atan2(1, 0)")).to.be.approximately(Math.PI / 2, Number.EPSILON) + expect(evaluate("atan2(0, 1)")).to.be.approximately(0, Number.EPSILON) + expect(evaluate("if(10 == 10, 1, 0)")).to.be.approximately(1, Number.EPSILON) + expect(evaluate("if(10 != 10, 1, 0)")).to.be.approximately(0, Number.EPSILON) + expect(evaluate("gamma(10) == 9!")).to.be.true + expect(evaluate("Γ(30) == 29!")).to.be.true + expect(evaluate("Γ(25) == 23!")).to.be.false + expect(evaluate("roundTo(26.04)")).to.equal(26) + expect(evaluate("roundTo(26.04, 2)")).to.equal(26.04) + expect(evaluate("roundTo(26.04836432123, 5)")).to.equal(26.04836) + expect(evaluate("roundTo(26.04836432123, 5)")).to.equal(26.04836) + }) + + it("parses arrays and access their members", function() { + expect(evaluate("[6, 7, 9]")).to.have.lengthOf(3) + expect(evaluate("[6, 7, 9]")).to.deep.equal([6, 7, 9]) + expect(evaluate("[6, \"8\", 9]")).to.have.lengthOf(3) + expect(evaluate("[6, 7%2]")).to.deep.equal([6, 1]) + // Access array indices + expect(evaluate("[6, 7][1]")).to.equal(7) + expect(evaluate("[6, 7, 8, 9, 10][2*2-1]")).to.equal(9) + }) + + it("can apply functions to arrays", function() { + expect(evaluate("length [6, 7, 9]")).to.equal(3) + expect(evaluate("length [6, 7, 8, 9]")).to.equal(4) + expect(evaluate("[6, 7, 9]||[10,11,12]")).to.deep.equal([6, 7, 9, 10, 11, 12]) + expect(evaluate("6 in [6, 7, 9]")).to.be.true + expect(evaluate("2 in [6, 7, 9]")).to.be.false + expect(evaluate("min([10, 6, 7, 8, 9])")).to.equal(6) + expect(evaluate("max([6, 7, 8, 9, 2])")).to.equal(9) + }) + + it("throws errors when invalid function parameters are provided", function() { + expect(() => evaluate("max()")).to.throw() + expect(() => evaluate("min()")).to.throw() + }) + + it("parses constants", function() { + expect(evaluate("pi")).to.equal(Math.PI) + expect(evaluate("PI")).to.equal(Math.PI) + expect(evaluate("π")).to.equal(Math.PI) + expect(evaluate("e")).to.equal(Math.E) + expect(evaluate("E")).to.equal(Math.E) + expect(evaluate("true")).to.be.true + expect(evaluate("false")).to.be.false + // expect(evaluate("∞")).to.equal(Math.Infinity) + // expect(evaluate("infinity")).to.equal(Math.Infinity) + // expect(evaluate("Infinity")).to.equal(Math.Infinity) + }) + + it("can be provided variables", function() { + const u = [1, 2, 3, 4] + const x = 10 + const s_ = "string" + const f = (x) => x * 2 + expect(evaluate("u", { u })).to.deep.equal([...u]) + expect(evaluate("x", { x })).to.equal(x) + expect(evaluate("s_", { s_ })).to.equal(s_) + expect(evaluate("f", { f })).to.equal(f) + expect(evaluate("b", { b: true })).to.equal(true) + expect(evaluate("u[1]", { u })).to.equal(u[1]) + expect(evaluate("x/2", { x })).to.equal(x / 2) + expect(evaluate("f(2)", { f })).to.equal(f(2)) + expect(evaluate("if(x == f(2), u[0], s_)", { x, u, s_, f })).to.equal(s_) + }) + + it("can be provided objects", function() { + const obj = { execute: (x) => x * 3, x: 10, y: { cached: true, execute: () => 20 } } + expect(evaluate("O(3)+O(2)", { O: obj })).to.equal(9 + 6) + expect(evaluate("O.x+O.y", { O: obj })).to.equal(30) + }) + + it("throws errors when trying to use variables wrongly", function() { + const obj = { execute: (x) => x * 3 } + expect(() => evaluate("O()", { O: obj })).to.throw() + expect(() => evaluate("O.x", { O: obj })).to.throw() + expect(() => evaluate("x()", { x: 10 })).to.throw() + expect(() => evaluate("x")).to.throw() + expect(() => evaluate("n")).to.throw() + }) + + it("can do it all at once", function() { + const obj = { execute: (x) => x * 3, x: 20 } + const u = [1, 2, 3, 4] + const x = 10 + const s = "string" + const expr = "random(e) <= e ? fac(x)+u[2]+O(pi) : O.x+length s" + expect(evaluate(expr, { x, u, s, O: obj })).to.equal(3628803 + obj.execute(Math.PI)) + }) + + it("cannot parse invalid expressions", function() { + expect(() => evaluate("1+")).to.throw() + expect(() => evaluate("@")).to.throw() + expect(() => evaluate("]")).to.throw() + expect(() => evaluate("")).to.throw() + expect(() => evaluate(`"\\u35P2"`)).to.throw() + expect(() => evaluate(`"\\x"`)).to.throw() + }) + }) + + describe("#parse.toString", function() { + it("can be converted back into a string without changes", function() { + const expressions = ["pi+2*(e+2)^4", "sin(1+2!+pi+cos -3)^2", "[2,3,4][(2-1)*2]", "true ? false : true"] + for(const ogString of expressions) { + const expr = ExprEval.parse(ogString) + const convertedString = expr.toString() + expect(ExprEval.parse(convertedString)).to.deep.equal(expr) // Can be reparsed just the same + } + }) + }) + + describe("#parse.substitute", function() { + const parsed = ExprEval.parse("if(x == 0, 1, 2+x)") + it("can substitute a variable for a number", function() { + expect(parsed.substitute("x", 10).evaluate({})).to.equal(12) + expect(parsed.substitute("x", 0).evaluate({})).to.equal(1) + }) + + it("can substitute a variable for another", function() { + expect(parsed.substitute("x", "b").evaluate({ b: 10 })).to.equal(12) + expect(parsed.substitute("x", "b").evaluate({ b: 0 })).to.equal(1) + }) + + it("can substitute a variable for an expression", function() { + expect(parsed.substitute("x", "sin α").evaluate({ "α": Math.PI / 2 })).to.be.approximately(3, Number.EPSILON) + expect(parsed.substitute("x", "sin α").evaluate({ "α": 0 })).to.equal(1) + expect(parsed.substitute("x", "α == 1 ? 0 : 1").evaluate({ "α": 1 })).to.equal(1) + }) + }) + + describe("#parse.variables", function() { + it("can list all parsed undefined variables", function() { + expect(ExprEval.parse("a+b+x+pi+sin(b)").variables()).to.deep.equal(["a", "b", "x"]) + }) + }) + + describe("#parse.toJSFunction", function() { + const func = ExprEval.parse("not(false) ? a+b+x+1/x : x!+random()+A.x+[][0]").toJSFunction("x", { a: "10", b: "0" }) + expect(func(10)).to.equal(20.1) + expect(func(20)).to.equal(30.05) }) @@ -143,7 +345,7 @@ describe("Module/ExprEval", function() { describe("#derivative", function() { const DELTA = 1e-5 - it("returns the derivative value between two integers", function() { + it("returns the derivative value of a function at a given number", function() { expect(ExprEval.derivative("1", "t", 2)).to.be.approximately(0, DELTA) expect(ExprEval.derivative("t", "t", 2)).to.be.approximately(1, DELTA) expect(ExprEval.derivative("t^2", "t", 2)).to.be.approximately(4, DELTA) From c03afdf4eeb490808b9c16f8a1ef211a17b7ee46 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Mon, 14 Oct 2024 17:18:58 +0200 Subject: [PATCH 041/104] Upgrading deb packaging --- README.md | 8 +++++- assets/native/linux/debian/depends | 1 - assets/native/linux/debian/depends.packaged | 1 + assets/native/linux/debian/depends.wheels | 1 + common/package.json | 2 +- scripts/package-deb.sh | 13 ++++++++- scripts/sign-deb.sh | 31 +++++++++++---------- 7 files changed, 39 insertions(+), 18 deletions(-) delete mode 100644 assets/native/linux/debian/depends create mode 100644 assets/native/linux/debian/depends.packaged create mode 100644 assets/native/linux/debian/depends.wheels diff --git a/README.md b/README.md index ae252fe..5d4ba57 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,13 @@ To run LogarithmPlotter's tests, follow these steps: - Python - Install python3 and [poetry](https://python-poetry.org/) - - Run `poetry install --with test` + - Create and activate virtual env (recommended) + - Go into `runtime-pyside6` and run `poetry install --with test` +- ECMAScript + - Install node with npm + - Go into `common` and run `npm install -D` + +Finally, to actually run the tests: - Run `scripts/run-tests.sh` ## Legal notice diff --git a/assets/native/linux/debian/depends b/assets/native/linux/debian/depends deleted file mode 100644 index 5b7d902..0000000 --- a/assets/native/linux/debian/depends +++ /dev/null @@ -1 +0,0 @@ -python3 (>= 3.9), python3-pip, python3-pyside6-essentials (>= 6.7.0), texlive-latex-base, dvipng diff --git a/assets/native/linux/debian/depends.packaged b/assets/native/linux/debian/depends.packaged new file mode 100644 index 0000000..22f3322 --- /dev/null +++ b/assets/native/linux/debian/depends.packaged @@ -0,0 +1 @@ +python3 (>= 3.9), python3-pip, python3-pyside6.qtcore (>= 6), python3-pyside6.qtcore (>= 6), texlive-latex-base, dvipng diff --git a/assets/native/linux/debian/depends.wheels b/assets/native/linux/debian/depends.wheels new file mode 100644 index 0000000..9a874f7 --- /dev/null +++ b/assets/native/linux/debian/depends.wheels @@ -0,0 +1 @@ +python3 (>= 3.9), python3-pip, python3-pyside6-essentials (>= 6.7.0), python3-pyside6-addons (>= 6.7.0), texlive-latex-base, dvipng diff --git a/common/package.json b/common/package.json index 6940d87..e85d3ff 100644 --- a/common/package.json +++ b/common/package.json @@ -2,7 +2,7 @@ "name": "logarithmplotter", "version": "0.6.0", "description": "2D plotter software to make Bode plots, sequences and distribution functions.", - "main": "LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/autoload.mjs", + "main": "src/index.mjs", "scripts": { "build": "rollup --config rollup.config.mjs", "test": "c8 mocha test/**/*.mjs" diff --git a/scripts/package-deb.sh b/scripts/package-deb.sh index 8ed03ee..eea10ba 100755 --- a/scripts/package-deb.sh +++ b/scripts/package-deb.sh @@ -26,7 +26,18 @@ mkdir assets cp -r ../../assets/{native,*.svg} assets/ cp ../../README.md . +# Build for noble python3 setup.py --remove-git-version --command-packages=stdeb.command sdist_dsc \ --package logarithmplotter --copyright-file assets/native/linux/debian/copyright \ - --suite noble --depends3 "$(cat assets/native/linux/debian/depends)" --section science \ + --suite noble --depends3 "$(cat assets/native/linux/debian/depends.wheels)" --section science \ bdist_deb + +mv deb_dist deb_dist.noble + +# Build for oracular (different dependencies) +python3 setup.py --remove-git-version --command-packages=stdeb.command sdist_dsc \ + --package logarithmplotter --copyright-file assets/native/linux/debian/copyright \ + --suite oracular --depends3 "$(cat assets/native/linux/debian/depends.packaged)" --section science \ + bdist_deb + +mv deb_dist deb_dist.oracular diff --git a/scripts/sign-deb.sh b/scripts/sign-deb.sh index f8e0a9a..05bee26 100755 --- a/scripts/sign-deb.sh +++ b/scripts/sign-deb.sh @@ -1,23 +1,26 @@ #!/bin/bash # This script is used to sign the LogarithmPlotter deb directly from it's DSC file. # Adapted from https://github.com/astraw/stdeb/issues/181 -cd "$(dirname "$(readlink -f "$0" || realpath "$0")")/../build/runtime-pyside6/deb_dist" || exit 1 +cd "$(dirname "$(readlink -f "$0" || realpath "$0")")/../build/runtime-pyside6/" || exit 1 PPA_ARCHIVE="ppa:ad5001/logarithmplotter" -# create a temporary folder -mkdir tmp -p -cd tmp -rm -rf * +for dist in `echo noble oracular`; do + echo "Signing $dist deb..." + # create a temporary folder + mkdir "deb_dist.$dist/tmp" -p + cd "deb_dist.$dist/tmp" || exit 1 + rm -rf * -# DSC file variables -dsc_file="$(find ../ -regextype sed -regex ".*/*.dsc" | cut -c 4-)" -source_package_name="$(echo $dsc_file | cut -c -$(expr ${#dsc_file} - 4))" + # DSC file variables + dsc_file="$(find ../ -regextype sed -regex ".*/*.dsc" | cut -c 4-)" + source_package_name="$(echo $dsc_file | cut -c -$(expr ${#dsc_file} - 4))" -# extract and sign the files -dpkg-source -x "../$dsc_file" -cd "$(find . -type d | head -n 2 | tail -n 1 | cut -c 3-)" # go to the (only) directory. -debuild -S -sa -k"mail@ad5001.eu" + # extract and sign the files + dpkg-source -x "../$dsc_file" + cd "$(find . -type d | head -n 2 | tail -n 1 | cut -c 3-)" # go to the (only) directory. + debuild -S -sa -k"mail@ad5001.eu" -# upload package to my PPA -dput $PPA_ARCHIVE "../${source_package_name}_source.changes" + # upload package to my PPA + dput $PPA_ARCHIVE "../${source_package_name}_source.changes" +done From 89e78913de559471474c93d28bc2fc0c19cfd5ad Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Mon, 14 Oct 2024 17:28:43 +0200 Subject: [PATCH 042/104] Adding dependencies for Ubuntu 24.10. --- assets/native/linux/debian/{control => control.bkp} | 0 assets/native/linux/debian/depends.packaged | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename assets/native/linux/debian/{control => control.bkp} (100%) diff --git a/assets/native/linux/debian/control b/assets/native/linux/debian/control.bkp similarity index 100% rename from assets/native/linux/debian/control rename to assets/native/linux/debian/control.bkp diff --git a/assets/native/linux/debian/depends.packaged b/assets/native/linux/debian/depends.packaged index 22f3322..4ec21f5 100644 --- a/assets/native/linux/debian/depends.packaged +++ b/assets/native/linux/debian/depends.packaged @@ -1 +1 @@ -python3 (>= 3.9), python3-pip, python3-pyside6.qtcore (>= 6), python3-pyside6.qtcore (>= 6), texlive-latex-base, dvipng +python3 (>= 3.9), python3-pip, python3-pyside6.qtcore (>= 6), python3-pyside6.qtgui (>= 6), python3-pyside6.qtqml (>= 6), python3-pyside6.qtwidgets (>= 6), python3-pyside6.qtquick (>= 6), python3-pyside6.qtquickcontrols2 (>= 6), qml6-module-qt5compat-graphicaleffects (>= 6), qml6-module-qt-labs-platform (>= 6), qml6-module-qtquick-dialogs (>= 6), texlive-latex-base, dvipng From a26dbc8a0043267a93676aa45ec00aff52902589 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Mon, 14 Oct 2024 17:39:02 +0200 Subject: [PATCH 043/104] Getting rid of Qt5Compat, ridding dependency on PySide6-Addons --- assets/native/linux/debian/depends.packaged | 2 +- assets/native/linux/debian/depends.wheels | 2 +- .../eu/ad5001/LogarithmPlotter/History/HistoryItem.qml | 8 +++----- runtime-pyside6/setup.py | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/assets/native/linux/debian/depends.packaged b/assets/native/linux/debian/depends.packaged index 4ec21f5..0bace27 100644 --- a/assets/native/linux/debian/depends.packaged +++ b/assets/native/linux/debian/depends.packaged @@ -1 +1 @@ -python3 (>= 3.9), python3-pip, python3-pyside6.qtcore (>= 6), python3-pyside6.qtgui (>= 6), python3-pyside6.qtqml (>= 6), python3-pyside6.qtwidgets (>= 6), python3-pyside6.qtquick (>= 6), python3-pyside6.qtquickcontrols2 (>= 6), qml6-module-qt5compat-graphicaleffects (>= 6), qml6-module-qt-labs-platform (>= 6), qml6-module-qtquick-dialogs (>= 6), texlive-latex-base, dvipng +python3 (>= 3.9), python3-pip, python3-pyside6.qtcore (>= 6), python3-pyside6.qtgui (>= 6), python3-pyside6.qtqml (>= 6), python3-pyside6.qtwidgets (>= 6), python3-pyside6.qtquick (>= 6), python3-pyside6.qtquickcontrols2 (>= 6), qml6-module-qt-labs-platform (>= 6), qml6-module-qtquick-dialogs (>= 6), texlive-latex-base, dvipng diff --git a/assets/native/linux/debian/depends.wheels b/assets/native/linux/debian/depends.wheels index 9a874f7..5b7d902 100644 --- a/assets/native/linux/debian/depends.wheels +++ b/assets/native/linux/debian/depends.wheels @@ -1 +1 @@ -python3 (>= 3.9), python3-pip, python3-pyside6-essentials (>= 6.7.0), python3-pyside6-addons (>= 6.7.0), texlive-latex-base, dvipng +python3 (>= 3.9), python3-pip, python3-pyside6-essentials (>= 6.7.0), texlive-latex-base, dvipng diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryItem.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryItem.qml index f37eb3b..6ad6556 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryItem.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryItem.qml @@ -16,9 +16,8 @@ * along with this program. If not, see . */ -import QtQuick.Controls import QtQuick -import Qt5Compat.GraphicalEffects +import QtQuick.Controls import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting @@ -82,12 +81,11 @@ Button { height: hidden ? 8 : Math.max(actionHeight, label.height + 15) - LinearGradient { + Rectangle { anchors.fill: parent //opacity: hidden ? 0.6 : 1 - start: Qt.point(0, 0) - end: Qt.point(parent.width, 0) gradient: Gradient { + orientation: Gradient.Horizontal GradientStop { position: 0.1; color: "transparent" } GradientStop { position: 1.5; color: clr } } diff --git a/runtime-pyside6/setup.py b/runtime-pyside6/setup.py index f76f1d7..524ad29 100644 --- a/runtime-pyside6/setup.py +++ b/runtime-pyside6/setup.py @@ -122,7 +122,7 @@ if sys.platform == 'linux': # os.remove(os.environ["PREFIX"] + '/icons/hicolor/scalable/apps/logplotter.svg') setuptools.setup( - install_requires=([] if "FLATPAK_INSTALL" in os.environ else ["PySide6-Essentials", "PySide6-Addons"]), + install_requires=([] if "FLATPAK_INSTALL" in os.environ else ["PySide6-Essentials"]), python_requires='>=3.9', name='logarithmplotter', From 2995b2271a031aad5197efdc0aba8f96600db7eb Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Mon, 14 Oct 2024 17:55:53 +0200 Subject: [PATCH 044/104] Fixing mind-bogingingly strange issue causing Qt crash when attempting to set WeakSet during mouse move events. --- common/src/events.mjs | 6 +++--- common/src/module/settings.mjs | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/common/src/events.mjs b/common/src/events.mjs index 25f5bf3..75a7a52 100644 --- a/common/src/events.mjs +++ b/common/src/events.mjs @@ -23,17 +23,17 @@ export class BaseEvent { - #name + ___name = "" /** * @property {string} name - Name of the event. */ constructor(name) { - this.#name = name + this.___name = name } get name() { - return this.#name + return this.___name } } diff --git a/common/src/module/settings.mjs b/common/src/module/settings.mjs index 64c39c2..8ea152d 100644 --- a/common/src/module/settings.mjs +++ b/common/src/module/settings.mjs @@ -115,7 +115,8 @@ class SettingsAPI extends Module { if(propType !== typeof value) throw new Error(`Value of ${property} must be a ${propType} (${typeof value} provided).`) this.#properties.set(property, value) - this.emit(new ChangedEvent(property, oldValue, value, byUser === true)) + const evt = new ChangedEvent(property, oldValue, value, byUser === true) + this.emit(evt) } /** From b33e1329dbbfc99a25f1cfeaca8c44514fdde6e8 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Mon, 14 Oct 2024 23:22:57 +0200 Subject: [PATCH 045/104] Removing typed config functions in Helper. --- common/src/module/history.mjs | 2 +- common/src/module/interface.mjs | 28 +------- common/src/module/latex.mjs | 2 +- common/src/module/settings.mjs | 18 +---- common/src/preferences/common.mjs | 14 ++-- common/src/preferences/default.mjs | 2 +- common/test/mock/helper.mjs | 69 ++++--------------- .../Setting/ExpressionEditor.qml | 8 +-- .../eu/ad5001/LogarithmPlotter/Settings.qml | 18 ++--- .../LogarithmPlotter/util/helper.py | 31 ++------- runtime-pyside6/tests/test_helper.py | 10 +-- 11 files changed, 53 insertions(+), 149 deletions(-) diff --git a/common/src/module/history.mjs b/common/src/module/history.mjs index be70f87..4b07095 100644 --- a/common/src/module/history.mjs +++ b/common/src/module/history.mjs @@ -138,7 +138,7 @@ class HistoryAPI extends Module { if(action instanceof Action) { console.log("Added new entry to history: " + action.getReadableString()) this.undoStack.push(action) - if(this.#helper.getSettingBool("reset_redo_stack")) + if(this.#helper.getSetting("reset_redo_stack")) this.redoStack = [] this.emit(new AddedEvent(action)) } diff --git a/common/src/module/interface.mjs b/common/src/module/interface.mjs index 27fb7eb..b6d462f 100644 --- a/common/src/module/interface.mjs +++ b/common/src/module/interface.mjs @@ -109,37 +109,13 @@ export class HelperInterface extends Interface { /** * Gets a setting from the config * @param {string} settingName - Setting (and its dot-separated namespace) to get (e.g. "default_graph.xmin") - * @returns {boolean} Value of the setting - */ - getSettingBool = FUNCTION - /** - * Gets a setting from the config - * @param {string} settingName - Setting (and its dot-separated namespace) to get (e.g. "default_graph.xmin") - * @returns {number} Value of the setting - */ - getSettingInt = FUNCTION - /** - * Gets a setting from the config - * @param {string} settingName - Setting (and its dot-separated namespace) to get (e.g. "default_graph.xmin") - * @returns {string} Value of the setting + * @returns {string|number|boolean} Value of the setting */ getSetting = FUNCTION /** * Sets a setting in the config * @param {string} settingName - Setting (and its dot-separated namespace) to set (e.g. "default_graph.xmin") - * @param {boolean} value - */ - setSettingBool = FUNCTION - /** - * Sets a setting in the config - * @param {string} settingName - Setting (and its dot-separated namespace) to set (e.g. "default_graph.xmin") - * @param {number} value - */ - setSettingInt = FUNCTION - /** - * Sets a setting in the config - * @param {string} settingName - Setting (and its dot-separated namespace) to set (e.g. "default_graph.xmin") - * @param {string} value + * @param {string|number|boolean} value */ setSetting = FUNCTION /** diff --git a/common/src/module/latex.mjs b/common/src/module/latex.mjs index 4ff81cb..a6aa216 100644 --- a/common/src/module/latex.mjs +++ b/common/src/module/latex.mjs @@ -81,7 +81,7 @@ class LatexAPI extends Module { initialize({ latex, helper }) { super.initialize({ latex, helper }) this.#latex = latex - this.enabled = helper.getSettingBool("enable_latex") + this.enabled = helper.getSetting("enable_latex") } /** diff --git a/common/src/module/settings.mjs b/common/src/module/settings.mjs index 8ea152d..d630e7a 100644 --- a/common/src/module/settings.mjs +++ b/common/src/module/settings.mjs @@ -81,21 +81,9 @@ class SettingsAPI extends Module { initialize({ helper }) { super.initialize({ helper }) // Initialize default values. - for(const key of this.#properties.keys()) { - if(!this.#nonConfigurable.includes(key)) { - switch(typeof this.#properties.get(key)) { - case "boolean": - this.set(key, helper.getSettingBool("default_graph."+key), false) - break - case "number": - this.set(key, helper.getSettingInt("default_graph."+key), false) - break - case "string": - this.set(key, helper.getSetting("default_graph."+key), false) - break - } - } - } + for(const key of this.#properties.keys()) + if(!this.#nonConfigurable.includes(key)) + this.set(key, helper.getSetting("default_graph."+key), false) } /** diff --git a/common/src/preferences/common.mjs b/common/src/preferences/common.mjs index e456dc2..812263c 100644 --- a/common/src/preferences/common.mjs +++ b/common/src/preferences/common.mjs @@ -53,11 +53,11 @@ export class BoolSetting extends Setting { } value() { - return Helper.getSettingBool(this.nameInConfig) + return Helper.getSetting(this.nameInConfig) } set(value) { - Helper.setSettingBool(this.nameInConfig, value) + Helper.setSetting(this.nameInConfig, value === true) } } @@ -69,11 +69,11 @@ export class NumberSetting extends Setting { } value() { - return Helper.getSettingInt(this.nameInConfig) + return Helper.getSetting(this.nameInConfig) } set(value) { - Helper.setSettingInt(this.nameInConfig, value) + Helper.setSetting(this.nameInConfig, +value) } } @@ -84,11 +84,11 @@ export class EnumIntSetting extends Setting { } value() { - return Helper.getSettingInt(this.nameInConfig) + return Helper.getSetting(this.nameInConfig) } set(value) { - Helper.setSettingInt(this.nameInConfig, value) + Helper.setSetting(this.nameInConfig, +value) } } @@ -131,6 +131,6 @@ export class StringSetting extends Setting { } set(value) { - Helper.setSetting(this.nameInConfig, value) + Helper.setSetting(this.nameInConfig, ""+value) } } \ No newline at end of file diff --git a/common/src/preferences/default.mjs b/common/src/preferences/default.mjs index 20d62e3..1d7e4bd 100644 --- a/common/src/preferences/default.mjs +++ b/common/src/preferences/default.mjs @@ -37,7 +37,7 @@ const XMIN = new NumberSetting( qsTranslate("Settings", "Min X"), "default_graph.xmin", "xmin", - () => Helper.getSettingBool("default_graph.logscalex") ? 1e-100 : -Infinity + () => Helper.getSetting("default_graph.logscalex") ? 1e-100 : -Infinity ) const YMAX = new NumberSetting( diff --git a/common/test/mock/helper.mjs b/common/test/mock/helper.mjs index 9f74b64..c2b024f 100644 --- a/common/test/mock/helper.mjs +++ b/common/test/mock/helper.mjs @@ -53,7 +53,13 @@ export class MockHelper { this.__settings = { ...DEFAULT_SETTINGS } } - __getSetting(settingName) { + + /** + * Gets a setting from the config + * @param {string} settingName - Setting (and its dot-separated namespace) to get (e.g. "default_graph.xmin") + * @returns {string|number|boolean} Value of the setting + */ + getSetting(settingName) { const namespace = settingName.split(".") let data = this.__settings for(const name of namespace) @@ -64,7 +70,12 @@ export class MockHelper { return data } - __setSetting(settingName, value) { + /** + * Sets a setting in the config + * @param {string} settingName - Setting (and its dot-separated namespace) to set (e.g. "default_graph.xmin") + * @param {string|number|boolean} value + */ + setSetting(settingName, value) { const namespace = settingName.split(".") const finalName = namespace.pop() let data = this.__settings @@ -76,60 +87,6 @@ export class MockHelper { data[finalName] = value } - /** - * Gets a setting from the config - * @param {string} settingName - Setting (and its dot-separated namespace) to get (e.g. "default_graph.xmin") - * @returns {boolean} Value of the setting - */ - getSettingBool(settingName) { - return this.__getSetting(settingName) === true - } - - /** - * Gets a setting from the config - * @param {string} settingName - Setting (and its dot-separated namespace) to get (e.g. "default_graph.xmin") - * @returns {number} Value of the setting - */ - getSettingInt(settingName) { - return +(this.__getSetting(settingName)) - } - - /** - * Gets a setting from the config - * @param {string} settingName - Setting (and its dot-separated namespace) to get (e.g. "default_graph.xmin") - * @returns {string} Value of the setting - */ - getSetting(settingName) { - return this.__getSetting(settingName).toString() - } - - /** - * Sets a setting in the config - * @param {string} settingName - Setting (and its dot-separated namespace) to set (e.g. "default_graph.xmin") - * @param {boolean} value - */ - setSettingBool(settingName, value) { - return this.__setSetting(settingName, value === true) - } - - /** - * Sets a setting in the config - * @param {string} settingName - Setting (and its dot-separated namespace) to set (e.g. "default_graph.xmin") - * @param {number} value - */ - setSettingInt(settingName, value) { - return this.__setSetting(settingName, +(value)) - } - - /** - * Sets a setting in the config - * @param {string} settingName - Setting (and its dot-separated namespace) to set (e.g. "default_graph.xmin") - * @param {string} value - */ - setSetting(settingName, value) { - return this.__setSetting(settingName, value.toString()) - } - /** * Sends data to be written * @param {string} file diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml index a0c030a..bb99f52 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml @@ -221,9 +221,9 @@ Item { focus: true selectByMouse: true - property bool autocompleteEnabled: Helper.getSettingBool("autocompletion.enabled") - property bool syntaxHighlightingEnabled: Helper.getSettingBool("expression_editor.colorize") - property bool autoClosing: Helper.getSettingBool("expression_editor.autoclose") + property bool autocompleteEnabled: Helper.getSetting("autocompletion.enabled") + property bool syntaxHighlightingEnabled: Helper.getSetting("expression_editor.colorize") + property bool autoClosing: Helper.getSetting("expression_editor.autoclose") property var tokens: autocompleteEnabled || syntaxHighlightingEnabled ? parent.tokens(text) : [] Keys.priority: Keys.BeforeItem // Required for knowing which key the user presses. @@ -600,7 +600,7 @@ Item { */ function colorize(tokenList) { let parsedText = "" - let scheme = colorSchemes[Helper.getSettingInt("expression_editor.color_scheme")] + let scheme = colorSchemes[Helper.getSetting("expression_editor.color_scheme")] for(let token of tokenList) { switch(token.type) { case JS.Parsing.TokenType.VARIABLE: diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml index b440d07..992e9b1 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml @@ -44,25 +44,25 @@ ScrollView { Zoom on the x axis of the diagram, provided from settings. \sa Settings */ - property double xzoom: Helper.getSettingInt('default_graph.xzoom') + property double xzoom: Helper.getSetting('default_graph.xzoom') /*! \qmlproperty double Settings::yzoom Zoom on the y axis of the diagram, provided from settings. \sa Settings */ - property double yzoom: Helper.getSettingInt('default_graph.yzoom') + property double yzoom: Helper.getSetting('default_graph.yzoom') /*! \qmlproperty double Settings::xmin Minimum x of the diagram, provided from settings. \sa Settings */ - property double xmin: Helper.getSettingInt('default_graph.xmin') + property double xmin: Helper.getSetting('default_graph.xmin') /*! \qmlproperty double Settings::ymax Maximum y of the diagram, provided from settings. \sa Settings */ - property double ymax: Helper.getSettingInt('default_graph.ymax') + property double ymax: Helper.getSetting('default_graph.ymax') /*! \qmlproperty string Settings::xaxisstep Step of the x axis graduation, provided from settings. @@ -93,34 +93,34 @@ ScrollView { Width of lines that will be drawn into the canvas, provided from settings. \sa Settings */ - property double linewidth: Helper.getSettingInt('default_graph.linewidth') + property double linewidth: Helper.getSetting('default_graph.linewidth') /*! \qmlproperty double Settings::textsize Font size of the text that will be drawn into the canvas, provided from settings. \sa Settings */ - property double textsize: Helper.getSettingInt('default_graph.textsize') + property double textsize: Helper.getSetting('default_graph.textsize') /*! \qmlproperty bool Settings::logscalex true if the canvas should be in logarithmic mode, false otherwise. Provided from settings. \sa Settings */ - property bool logscalex: Helper.getSettingBool('default_graph.logscalex') + property bool logscalex: Helper.getSetting('default_graph.logscalex') /*! \qmlproperty bool Settings::showxgrad true if the x graduation should be shown, false otherwise. Provided from settings. \sa Settings */ - property bool showxgrad: Helper.getSettingBool('default_graph.showxgrad') + property bool showxgrad: Helper.getSetting('default_graph.showxgrad') /*! \qmlproperty bool Settings::showygrad true if the y graduation should be shown, false otherwise. Provided from settings. \sa Settings */ - property bool showygrad: Helper.getSettingBool('default_graph.showygrad') + property bool showygrad: Helper.getSetting('default_graph.showygrad') Column { spacing: 10 diff --git a/runtime-pyside6/LogarithmPlotter/util/helper.py b/runtime-pyside6/LogarithmPlotter/util/helper.py index 6db4570..344e425 100644 --- a/runtime-pyside6/LogarithmPlotter/util/helper.py +++ b/runtime-pyside6/LogarithmPlotter/util/helper.py @@ -15,10 +15,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . """ - from PySide6.QtWidgets import QMessageBox, QApplication from PySide6.QtCore import QRunnable, QThreadPool, QThread, QObject, Signal, Slot, QCoreApplication -from PySide6.QtQml import QQmlApplicationEngine +from PySide6.QtQml import QJSValue from PySide6.QtGui import QImage from PySide6 import __version__ as PySide6_version @@ -135,29 +134,13 @@ class Helper(QObject): def getVersion(self): return __VERSION__ - @Slot(str, result=str) - def getSetting(self, namespace): - return str(config.getSetting(namespace)) + @Slot(str, result=QJSValue) + def getSetting(self, namespace: str) -> QJSValue: + return QJSValue(config.getSetting(namespace)) - @Slot(str, result=float) - def getSettingInt(self, namespace): - return float(config.getSetting(namespace)) - - @Slot(str, result=bool) - def getSettingBool(self, namespace): - return bool(config.getSetting(namespace)) - - @Slot(str, str) - def setSetting(self, namespace, value): - return config.setSetting(namespace, str(value)) - - @Slot(str, bool) - def setSettingBool(self, namespace, value): - return config.setSetting(namespace, bool(value)) - - @Slot(str, float) - def setSettingInt(self, namespace, value): - return config.setSetting(namespace, float(value)) + @Slot(str, QJSValue) + def setSetting(self, namespace: str, value: QJSValue): + return config.setSetting(namespace, value.toPrimitive().toVariant()) @Slot(result=str) def getDebugInfos(self): diff --git a/runtime-pyside6/tests/test_helper.py b/runtime-pyside6/tests/test_helper.py index 412eac3..73dfb23 100644 --- a/runtime-pyside6/tests/test_helper.py +++ b/runtime-pyside6/tests/test_helper.py @@ -158,16 +158,16 @@ class TestHelper: obj = Helper(pwd, tmpfile) assert obj.getVersion() == version assert type(obj.getDebugInfos()) == str - assert type(obj.getSetting("check_for_updates")) == str - assert type(obj.getSettingInt("check_for_updates")) == float - assert type(obj.getSettingBool("check_for_updates")) == bool + assert type(obj.getSetting("last_install_greet").toVariant()) == str + assert type(obj.getSetting("check_for_updates").toVariant()) == bool + assert type(obj.getSetting("default_graph.xzoom").toVariant()) in [float, int] def test_set_config(self, temporary): tmpfile, directory = temporary obj = Helper(pwd, tmpfile) obj.setSetting("last_install_greet", obj.getSetting("last_install_greet")) - obj.setSettingBool("check_for_updates", obj.getSettingBool("check_for_updates")) - obj.setSettingInt("default_graph.xzoom", obj.getSettingInt("default_graph.xzoom")) + obj.setSetting("check_for_updates", obj.getSetting("check_for_updates")) + obj.setSetting("default_graph.xzoom", obj.getSetting("default_graph.xzoom")) def test_fetch_changelog(self, temporary, qtbot): tmpfile, directory = temporary From f734e40ad9e986357c2e591a7ce50e35c97799f9 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 15 Oct 2024 01:22:25 +0200 Subject: [PATCH 046/104] Starting PyPromise --- .../LogarithmPlotter/Popup/Changelog.qml | 20 ++-- .../LogarithmPlotter/util/helper.py | 57 ++++----- runtime-pyside6/LogarithmPlotter/util/js.py | 8 +- .../LogarithmPlotter/util/latex.py | 6 +- .../LogarithmPlotter/util/promise.py | 110 ++++++++++++++++++ 5 files changed, 157 insertions(+), 44 deletions(-) create mode 100644 runtime-pyside6/LogarithmPlotter/util/promise.py diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Changelog.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Changelog.qml index 844e22a..93d76db 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Changelog.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Changelog.qml @@ -45,17 +45,17 @@ Popup { property bool changelogNeedsFetching: true onAboutToShow: if(changelogNeedsFetching) { - Helper.fetchChangelog() - } - - Connections { - target: Helper - function onChangelogFetched(chl) { - changelogNeedsFetching = false; - changelog.text = chl + Helper.fetchChangelog().then((fetchedText) => { + changelogNeedsFetching = false + changelog.text = fetchedText changelogView.contentItem.implicitHeight = changelog.height - // console.log(changelog.height, changelogView.contentItem.implicitHeight) - } + }, (error) => { + const e = qsTranslate("changelog", "Could not fetch update: {}.").replace('{}', error) + console.error(e) + changelogNeedsFetching = false + changelog.text = e + changelogView.contentItem.implicitHeight = changelog.height + }) } ScrollView { diff --git a/runtime-pyside6/LogarithmPlotter/util/helper.py b/runtime-pyside6/LogarithmPlotter/util/helper.py index 344e425..7f7afb9 100644 --- a/runtime-pyside6/LogarithmPlotter/util/helper.py +++ b/runtime-pyside6/LogarithmPlotter/util/helper.py @@ -29,13 +29,16 @@ from urllib.error import HTTPError, URLError from LogarithmPlotter import __VERSION__ from LogarithmPlotter.util import config +from LogarithmPlotter.util.promise import PyPromise SHOW_GUI_MESSAGES = "--test-build" not in argv CHANGELOG_VERSION = __VERSION__ +CHANGELOG_CACHE_PATH = path.join(path.dirname(path.realpath(__file__)), "CHANGELOG.md") class InvalidFileException(Exception): pass + def show_message(msg: str) -> None: """ Shows a GUI message if GUI messages are enabled @@ -46,31 +49,30 @@ def show_message(msg: str) -> None: raise InvalidFileException(msg) +def fetch_changelog(): + msg_text = "Unknown changelog error." + try: + # Fetching version + r = urlopen("https://api.ad5001.eu/changelog/logarithmplotter/?version=" + CHANGELOG_VERSION) + lines = r.readlines() + r.close() + msg_text = "".join(map(lambda x: x.decode('utf-8'), lines)).strip() + except HTTPError as e: + msg_text = QCoreApplication.translate("changelog", "Could not fetch changelog: Server error {}.").format( + str(e.code)) + except URLError as e: + msg_text = QCoreApplication.translate("changelog", "Could not fetch update: {}.").format(str(e.reason)) + return msg_text -class ChangelogFetcher(QRunnable): - def __init__(self, helper): - QRunnable.__init__(self) - self.helper = helper - def run(self): - msg_text = "Unknown changelog error." - try: - # Fetching version - r = urlopen("https://api.ad5001.eu/changelog/logarithmplotter/?version=" + CHANGELOG_VERSION) - lines = r.readlines() - r.close() - msg_text = "".join(map(lambda x: x.decode('utf-8'), lines)).strip() - except HTTPError as e: - msg_text = QCoreApplication.translate("changelog", "Could not fetch changelog: Server error {}.").format( - str(e.code)) - except URLError as e: - msg_text = QCoreApplication.translate("changelog", "Could not fetch update: {}.").format(str(e.reason)) - self.helper.changelogFetched.emit(msg_text) +def read_changelog(): + f = open(CHANGELOG_CACHE_PATH, 'r', -1) + data = f.read().strip() + f.close() + return data class Helper(QObject): - changelogFetched = Signal(str) - def __init__(self, cwd: str, tmpfile: str): QObject.__init__(self) self.cwd = cwd @@ -150,15 +152,14 @@ class Helper(QObject): msg = QCoreApplication.translate('main', "Built with PySide6 (Qt) v{} and python v{}") return msg.format(PySide6_version, sys_version.split("\n")[0]) - @Slot() + @Slot(result=PyPromise) def fetchChangelog(self): - changelog_cache_path = path.join(path.dirname(path.realpath(__file__)), "CHANGELOG.md") - if path.exists(changelog_cache_path): + """ + Fetches the changelog and returns a Promise. + """ + if path.exists(CHANGELOG_CACHE_PATH): # We have a cached version of the changelog, for env that don't have access to the internet. - f = open(changelog_cache_path); - self.changelogFetched.emit("".join(f.readlines()).strip()) - f.close() + return PyPromise(read_changelog) else: # Fetch it from the internet. - runnable = ChangelogFetcher(self) - QThreadPool.globalInstance().start(runnable) + return PyPromise(fetch_changelog) diff --git a/runtime-pyside6/LogarithmPlotter/util/js.py b/runtime-pyside6/LogarithmPlotter/util/js.py index dbe60bc..05f30d5 100644 --- a/runtime-pyside6/LogarithmPlotter/util/js.py +++ b/runtime-pyside6/LogarithmPlotter/util/js.py @@ -16,13 +16,13 @@ * along with this program. If not, see . """ from re import Pattern +from typing import Callable from PySide6.QtCore import QMetaObject, QObject, QDateTime from PySide6.QtQml import QJSValue class InvalidAttributeValueException(Exception): pass class NotAPrimitiveException(Exception): pass -class Function: pass class URL: pass class PyJSValue: @@ -78,7 +78,7 @@ class PyJSValue: matcher = [ (lambda: self.qjs_value.isArray(), list), (lambda: self.qjs_value.isBool(), bool), - (lambda: self.qjs_value.isCallable(), Function), + (lambda: self.qjs_value.isCallable(), Callable), (lambda: self.qjs_value.isDate(), QDateTime), (lambda: self.qjs_value.isError(), Exception), (lambda: self.qjs_value.isNull(), None), @@ -103,4 +103,6 @@ class PyJSValue: """ if self.type() not in [bool, float, str, None]: raise NotAPrimitiveException() - return self.qjs_value.toPrimitive().toVariant() \ No newline at end of file + return self.qjs_value.toPrimitive().toVariant() + + diff --git a/runtime-pyside6/LogarithmPlotter/util/latex.py b/runtime-pyside6/LogarithmPlotter/util/latex.py index df32d46..aac5c5b 100644 --- a/runtime-pyside6/LogarithmPlotter/util/latex.py +++ b/runtime-pyside6/LogarithmPlotter/util/latex.py @@ -16,18 +16,17 @@ * along with this program. If not, see . """ -from PySide6.QtCore import QObject, Slot, Property, QCoreApplication +from PySide6.QtCore import QObject, Slot, Property, QCoreApplication, Signal from PySide6.QtGui import QImage, QColor from PySide6.QtWidgets import QMessageBox -from os import path, remove, environ, makedirs +from os import path, remove, makedirs from string import Template from subprocess import Popen, TimeoutExpired, PIPE from hashlib import sha512 from shutil import which from sys import argv - """ Searches for a valid Latex and DVIPNG (http://savannah.nongnu.org/projects/dvipng/) installation and collects the binary path in the DVIPNG_PATH variable. @@ -76,6 +75,7 @@ class Latex(QObject): dvipng to be installed on the system. """ + def __init__(self, cache_path): QObject.__init__(self) self.tempdir = path.join(cache_path, "latex") diff --git a/runtime-pyside6/LogarithmPlotter/util/promise.py b/runtime-pyside6/LogarithmPlotter/util/promise.py new file mode 100644 index 0000000..1ccfe8e --- /dev/null +++ b/runtime-pyside6/LogarithmPlotter/util/promise.py @@ -0,0 +1,110 @@ +""" + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +""" +from typing import Callable + +from PySide6.QtCore import QRunnable, Signal, QObject, Slot, QThreadPool +from PySide6.QtQml import QJSValue + +from LogarithmPlotter.util.js import PyJSValue + + +class InvalidReturnValue(Exception): pass + + +class PyPromiseRunner(QRunnable): + """ + QRunnable for running Promises in different threads. + """ + def __init__(self, runner, promise): + QRunnable.__init__(self) + self.runner = runner + self.promise = promise + print("Initialized", self.runner) + + def run(self): + try: + data = self.runner() + if isinstance(data, QObject): + data = data + elif type(data) in [int, str, float, bool, bytes]: + data = QJSValue(data) + elif data is None: + data = QJSValue.SpecialValue.UndefinedValue + elif isinstance(data, QJSValue): + data = data + elif isinstance(data, PyJSValue): + data = data.qjs_value + else: + raise InvalidReturnValue("Must return either a primitive, a valid QObject, JS Value, or None.") + self.promise.finished.emit(data) + except Exception as e: + self.promise.errored.emit(repr(e)) + + +class PyPromise(QObject): + """ + Asynchronous Promise-like object meant to interface between Python and Javascript easily. + Runs to_run in another thread, and calls fulfilled (populated by then) with its return value. + """ + finished = Signal((QJSValue,), (QObject,)) + errored = Signal(Exception) + + def __init__(self, to_run: Callable): + QObject.__init__(self) + self._fulfills = [] + self._rejects = [] + self.finished.connect(self._fulfill) + self.errored.connect(self._reject) + self._runner = PyPromiseRunner(to_run, self) + QThreadPool.globalInstance().start(self._runner) + + + @Slot(QJSValue, result=QObject) + @Slot(QJSValue, QJSValue, result=QObject) + def then(self, on_fulfill: QJSValue | Callable, on_reject: QJSValue | Callable = None): + """ + Adds listeners for both fulfilment and catching errors of the Promise. + """ + if isinstance(on_fulfill, QJSValue): + self._fulfills.append(PyJSValue(on_fulfill)) + elif isinstance(on_fulfill, Callable): + self._fulfills.append(on_fulfill) + if isinstance(on_reject, QJSValue): + self._rejects.append(PyJSValue(on_reject)) + elif isinstance(on_reject, Callable): + self._rejects.append(on_reject) + + @Slot(QJSValue) + @Slot(QObject) + def _fulfill(self, data): + no_return = [None, QJSValue.SpecialValue.UndefinedValue] + for on_fulfill in self._fulfills: + try: + result = on_fulfill(data) + data = result if result not in no_return else data # Forward data. + except Exception as e: + self._reject(repr(e)) + break + + @Slot(QJSValue) + @Slot(str) + def _reject(self, error): + no_return = [None, QJSValue.SpecialValue.UndefinedValue] + for on_reject in self._rejects: + result = on_reject(error) + error = result if result not in no_return else error # Forward data. From cf73b35a9ab1494485006ec4dafcb9653a29e106 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 15 Oct 2024 03:01:27 +0200 Subject: [PATCH 047/104] Adding experimental async LaTeX renderer (speeds up rendering ridiculously, but causes instability) --- common/src/module/interface.mjs | 10 +++++++- common/src/module/latex.mjs | 7 +++++- common/src/preferences/general.mjs | 9 ++++++- .../LogarithmPlotter/util/config.py | 1 + .../LogarithmPlotter/util/latex.py | 24 +++++++++++++++---- .../LogarithmPlotter/util/promise.py | 11 +++++---- 6 files changed, 50 insertions(+), 12 deletions(-) diff --git a/common/src/module/interface.mjs b/common/src/module/interface.mjs index b6d462f..a96621c 100644 --- a/common/src/module/interface.mjs +++ b/common/src/module/interface.mjs @@ -84,13 +84,21 @@ export class DialogInterface extends Interface { } export class LatexInterface extends Interface { + supportsAsyncRender = BOOLEAN /** * @param {string} markup - LaTeX markup to render * @param {number} fontSize - Font size (in pt) to render * @param {string} color - Color of the text to render * @returns {string} - Comma separated data of the image (source, width, height) */ - render = FUNCTION + renderSync = FUNCTION + /** + * @param {string} markup - LaTeX markup to render + * @param {number} fontSize - Font size (in pt) to render + * @param {string} color - Color of the text to render + * @returns {Promise} - Comma separated data of the image (source, width, height) + */ + renderAsync = FUNCTION /** * @param {string} markup - LaTeX markup to render * @param {number} fontSize - Font size (in pt) to render diff --git a/common/src/module/latex.mjs b/common/src/module/latex.mjs index a6aa216..830f096 100644 --- a/common/src/module/latex.mjs +++ b/common/src/module/latex.mjs @@ -112,7 +112,12 @@ class LatexAPI extends Module { */ async requestAsyncRender(markup, fontSize, color) { if(!this.initialized) throw new Error("Attempting requestAsyncRender before initialize!") - let args = this.#latex.render(markup, fontSize, color).split(",") + let render + if(this.#latex.supportsAsyncRender) + render = await this.#latex.renderAsync(markup, fontSize, color) + else + render = this.#latex.renderSync(markup, fontSize, color) + const args = render.split(",") return new LatexRenderResult(...args) } diff --git a/common/src/preferences/general.mjs b/common/src/preferences/general.mjs index 81c5e3d..4a1098f 100644 --- a/common/src/preferences/general.mjs +++ b/common/src/preferences/general.mjs @@ -46,8 +46,15 @@ class EnableLatex extends BoolSetting { } } +const ENABLE_LATEX_ASYNC = new BoolSetting( + qsTranslate("general", "Enable asynchronous LaTeX renderer (experimental)"), + "enable_latex_async", + "new" +) + export default [ CHECK_FOR_UPDATES, RESET_REDO_STACK, - new EnableLatex() + new EnableLatex(), + ENABLE_LATEX_ASYNC ] diff --git a/runtime-pyside6/LogarithmPlotter/util/config.py b/runtime-pyside6/LogarithmPlotter/util/config.py index a5ee23c..ae10adb 100644 --- a/runtime-pyside6/LogarithmPlotter/util/config.py +++ b/runtime-pyside6/LogarithmPlotter/util/config.py @@ -26,6 +26,7 @@ DEFAULT_SETTINGS = { "reset_redo_stack": True, "last_install_greet": "0", "enable_latex": False, + "enable_latex_async": False, "expression_editor": { "autoclose": True, "colorize": True, diff --git a/runtime-pyside6/LogarithmPlotter/util/latex.py b/runtime-pyside6/LogarithmPlotter/util/latex.py index aac5c5b..0d720c3 100644 --- a/runtime-pyside6/LogarithmPlotter/util/latex.py +++ b/runtime-pyside6/LogarithmPlotter/util/latex.py @@ -15,6 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . """ +from time import sleep from PySide6.QtCore import QObject, Slot, Property, QCoreApplication, Signal from PySide6.QtGui import QImage, QColor @@ -27,6 +28,9 @@ from hashlib import sha512 from shutil import which from sys import argv +from LogarithmPlotter.util import config +from LogarithmPlotter.util.promise import PyPromise + """ Searches for a valid Latex and DVIPNG (http://savannah.nongnu.org/projects/dvipng/) installation and collects the binary path in the DVIPNG_PATH variable. @@ -75,7 +79,6 @@ class Latex(QObject): dvipng to be installed on the system. """ - def __init__(self, cache_path): QObject.__init__(self) self.tempdir = path.join(cache_path, "latex") @@ -85,6 +88,10 @@ class Latex(QObject): def latexSupported(self) -> bool: return LATEX_PATH is not None and DVIPNG_PATH is not None + @Property(bool) + def supportsAsyncRender(self) -> bool: + return config.getSetting("enable_latex_async") + @Slot(result=bool) def checkLatexInstallation(self) -> bool: """ @@ -105,13 +112,20 @@ class Latex(QObject): valid_install = False else: try: - self.render("", 14, QColor(0, 0, 0, 255)) + self.renderSync("", 14, QColor(0, 0, 0, 255)) except MissingPackageException: valid_install = False # Should have sent an error message if failed to render return valid_install + @Slot(str, float, QColor, result=PyPromise) + def renderAsync(self, latex_markup: str, font_size: float, color: QColor) -> PyPromise: + """ + Prepares and renders a latex string into a png file asynchronously. + """ + return PyPromise(self.renderSync, [latex_markup, font_size, color]) + @Slot(str, float, QColor, result=str) - def render(self, latex_markup: str, font_size: float, color: QColor) -> str: + def renderSync(self, latex_markup: str, font_size: float, color: QColor) -> str: """ Prepares and renders a latex string into a png file. """ @@ -124,12 +138,14 @@ class Latex(QObject): if not path.exists(latex_path + ".dvi"): self.create_latex_doc(latex_path, latex_markup) self.convert_latex_to_dvi(latex_path) - self.cleanup(latex_path) + # self.cleanup(latex_path) # Creating four pictures of different sizes to better handle dpi. self.convert_dvi_to_png(latex_path, export_path, font_size, color) # self.convert_dvi_to_png(latex_path, export_path+"@2", font_size*2, color) # self.convert_dvi_to_png(latex_path, export_path+"@3", font_size*3, color) # self.convert_dvi_to_png(latex_path, export_path+"@4", font_size*4, color) + else: + sleep(0) img = QImage(export_path) # Small hack, not very optimized since we load the image twice, but you can't pass a QImage to QML and expect it to be loaded return f'{export_path}.png,{img.width()},{img.height()}' diff --git a/runtime-pyside6/LogarithmPlotter/util/promise.py b/runtime-pyside6/LogarithmPlotter/util/promise.py index 1ccfe8e..6868432 100644 --- a/runtime-pyside6/LogarithmPlotter/util/promise.py +++ b/runtime-pyside6/LogarithmPlotter/util/promise.py @@ -30,15 +30,15 @@ class PyPromiseRunner(QRunnable): """ QRunnable for running Promises in different threads. """ - def __init__(self, runner, promise): + def __init__(self, runner, promise, args): QRunnable.__init__(self) self.runner = runner self.promise = promise - print("Initialized", self.runner) + self.args = args def run(self): try: - data = self.runner() + data = self.runner(*self.args) if isinstance(data, QObject): data = data elif type(data) in [int, str, float, bool, bytes]: @@ -64,13 +64,13 @@ class PyPromise(QObject): finished = Signal((QJSValue,), (QObject,)) errored = Signal(Exception) - def __init__(self, to_run: Callable): + def __init__(self, to_run: Callable, args): QObject.__init__(self) self._fulfills = [] self._rejects = [] self.finished.connect(self._fulfill) self.errored.connect(self._reject) - self._runner = PyPromiseRunner(to_run, self) + self._runner = PyPromiseRunner(to_run, self, args) QThreadPool.globalInstance().start(self._runner) @@ -88,6 +88,7 @@ class PyPromise(QObject): self._rejects.append(PyJSValue(on_reject)) elif isinstance(on_reject, Callable): self._rejects.append(on_reject) + return self @Slot(QJSValue) @Slot(QObject) From 531342825095e0703d251c38e382e293289b263b Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 15 Oct 2024 03:52:06 +0200 Subject: [PATCH 048/104] Improving stability of asynchronous LaTeX renderer. --- common/src/module/canvas.mjs | 16 +++++++++++----- common/src/preferences/general.mjs | 2 +- runtime-pyside6/LogarithmPlotter/util/promise.py | 7 ++++++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/common/src/module/canvas.mjs b/common/src/module/canvas.mjs index c46c9a1..62649cf 100644 --- a/common/src/module/canvas.mjs +++ b/common/src/module/canvas.mjs @@ -30,16 +30,18 @@ class CanvasAPI extends Module { #canvas = null /** @type {CanvasRenderingContext2D} */ #ctx = null + /** Lock to prevent asynchronous stuff from printing stuff that is outdated. */ + #redrawCount = 0 /** @type {{show(string, string, string)}} */ #drawingErrorDialog = null - - + + constructor() { super("Canvas", { canvas: CanvasInterface, drawingErrorDialog: DialogInterface }) - + /** * * @type {Object.} @@ -207,6 +209,7 @@ class CanvasAPI extends Module { */ redraw() { if(!this.initialized) throw new Error("Attempting redraw before initialize!") + this.#redrawCount = (this.#redrawCount + 1) % 10000 this.#ctx = this.#canvas.getContext("2d") this._computeAxes() this._reset() @@ -519,15 +522,18 @@ class CanvasAPI extends Module { * @param {function(LatexRenderResult|{width: number, height: number, source: string})} callback */ renderLatexImage(ltxText, color, callback) { + const currentRedrawCount = this.#redrawCount const onRendered = (imgData) => { if(!this.#canvas.isImageLoaded(imgData.source) && !this.#canvas.isImageLoading(imgData.source)) { // Wait until the image is loaded to callback. this.#canvas.loadImageAsync(imgData.source).then(() => { - callback(imgData) + if(this.#redrawCount === currentRedrawCount) + callback(imgData) }) } else { // Callback directly - callback(imgData) + if(this.#redrawCount === currentRedrawCount) + callback(imgData) } } const prerendered = Latex.findPrerendered(ltxText, this.textsize, color) diff --git a/common/src/preferences/general.mjs b/common/src/preferences/general.mjs index 4a1098f..a6957c6 100644 --- a/common/src/preferences/general.mjs +++ b/common/src/preferences/general.mjs @@ -47,7 +47,7 @@ class EnableLatex extends BoolSetting { } const ENABLE_LATEX_ASYNC = new BoolSetting( - qsTranslate("general", "Enable asynchronous LaTeX renderer (experimental)"), + qsTranslate("general", "Enable asynchronous LaTeX renderer"), "enable_latex_async", "new" ) diff --git a/runtime-pyside6/LogarithmPlotter/util/promise.py b/runtime-pyside6/LogarithmPlotter/util/promise.py index 6868432..f129d41 100644 --- a/runtime-pyside6/LogarithmPlotter/util/promise.py +++ b/runtime-pyside6/LogarithmPlotter/util/promise.py @@ -53,7 +53,12 @@ class PyPromiseRunner(QRunnable): raise InvalidReturnValue("Must return either a primitive, a valid QObject, JS Value, or None.") self.promise.finished.emit(data) except Exception as e: - self.promise.errored.emit(repr(e)) + try: + self.promise.errored.emit(repr(e)) + except RuntimeError as e2: + # Happens when the PyPromise has already been garbage collected. + # In other words, nothing to report to nowhere. + pass class PyPromise(QObject): From 37ac400f230591edb0e14efaaff50de127b7e19a Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 15 Oct 2024 03:52:47 +0200 Subject: [PATCH 049/104] Enabling latex async generation by default, default LaTeX setting now depends on state of installation. --- runtime-pyside6/LogarithmPlotter/util/config.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/runtime-pyside6/LogarithmPlotter/util/config.py b/runtime-pyside6/LogarithmPlotter/util/config.py index ae10adb..e01deae 100644 --- a/runtime-pyside6/LogarithmPlotter/util/config.py +++ b/runtime-pyside6/LogarithmPlotter/util/config.py @@ -19,14 +19,16 @@ from os import path, environ, makedirs from platform import system from json import load, dumps +from shutil import which + from PySide6.QtCore import QLocale, QTranslator DEFAULT_SETTINGS = { "check_for_updates": True, "reset_redo_stack": True, "last_install_greet": "0", - "enable_latex": False, - "enable_latex_async": False, + "enable_latex": which("latex") is not None and which("dvipng") is not None, + "enable_latex_async": True, "expression_editor": { "autoclose": True, "colorize": True, From ccddb068a670ceb607c9e034c4dfb0accdebf2e9 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 15 Oct 2024 18:06:24 +0200 Subject: [PATCH 050/104] Fixing tests for Promises (new ones need to be written) --- runtime-pyside6/.coverage | Bin 0 -> 53248 bytes .../LogarithmPlotter/util/promise.py | 22 +++-- runtime-pyside6/tests/test_helper.py | 83 ++++++++---------- runtime-pyside6/tests/test_latex.py | 10 +-- 4 files changed, 57 insertions(+), 58 deletions(-) create mode 100644 runtime-pyside6/.coverage diff --git a/runtime-pyside6/.coverage b/runtime-pyside6/.coverage new file mode 100644 index 0000000000000000000000000000000000000000..8eab2ed6efa5c8f1c8ebd2f83154347499e04eff GIT binary patch literal 53248 zcmeI4Uu+yl9mn^dZ*T99CykY!ToW=tsbkfDVxWm=B~q70q7X<+LtjwY?%j>;EqA-; z-95)fRM9m>k&s#m5aI#aClC+tzynD92`LpX1PM@t5J*rWifHpd2^B4hlm_#g{o}if z?W!+6tMPYrH?uoCGr!;OGryVHxxL+oA3E+vg3tRw(~0;8l|728D)(}(D2hejGJUhn zq#YwWpjhqM-)h%VroXUMW{)VP+|vsCT=@i>Dt)VbNAY5*X??l)oatCKI)M!YKmY_l zV0RPfJXA6(qoeARPee|&A)>&ki69BfAN};Pxs%8E$+`QEALB_HKUmCgD*wD# zos2W2(ju`EB?(lCa2Gt8gC9(bPw+s@i$Hia5hhw3bn6p^i8H4QW@ThVJu70HoS;UZ zVxKjX&^6_Od8(-92X(1^HE_Jzq6jCsvuY>vuyh+J4ds=v&l=J)yYqy{jO@(8fy>_!o z$RBSvTe5MeL?Sryw<@_+*~m|gecNrbNn3X9?Q6~qxopv-RNHfx+G4%&CwaHzWNe1# zPjYDldBFRNxypw}RE4}!tb|Jqy56##cI3y$HZ{IIOF`+WTk>Y*zybB_QtT)ak6m@6 zaDB(>bDH(!EnG*Q-`a0vFX?v@*^3$t?$5_vMwaGDf#bIO|k#E#p zCX?dhL%GU5`?gYCs$kE`Fn8v&TCDQf(U^Xd27UR}`&5=GU6nr}R;QMo28|{y#|@~< z(ioh~09l$~qR7$77wc$wdzHC#lnA{fl;* zO~s4kg}?sp;)xlO@kmROnCu}(Q5uLXim(p)+*uD_KV$kwuFWhht4d3h<SLAkPXI@z4^MxfKvrq&vcfL2 zH{O{BLTeBJ0T2KI5C8!X009sH0T2KI5CDOUKuO=PX1@Yx1%1p)e*}>C|BJ;jg?)wX zAO7C(-Q{1EKT~?8v|L;(K26EkKmY_l00ck)1V8`;Kw!5JXcY~mBW9YS?m9D0{jNiY zW@o~%E+0~!nQOJendAO~6S&c0^TCE6MIzXk5VSq{Q1Mi2HFWFZ@Wu@7$ZgEDTU4i@ zhnHK00ZH`eH()%aoT`4ipNTNG{ zcC>BRb0ga(nN5{s+S@C$N1VL>Uo5^$VP7pN?A^oPAHJu2p>(-)s`yO#5lY4e0w4ea zAOHd&00JNY0=tI5lFwhyaItzo4)?NSS2IV^I>;IuawPCjYHwIm;$mD4{x@{6DUY;5d3dks2whoLDy{?G5mXFv8A`^2|bZ`CPn zS|=l}`)fyE|N2wc_l{pZ{_k>5qx4}-wN%5hZq<|zJ*UUd|Fa({>>7KWegSxyU1EP? z7um1bFWEUt#s&f)00JNY0w4eaAOHd&00JNY0wAzc1mv#-YOxqcg+d%zRvhK?ab%it zl*`4@&`=y1MjYvS9BGH^_To3>O5C8!X009sH0T2KI5C8!X7zhD* z{~zoBfuM#E5C8!X009sH0T2KI5C8!X009u#F#^f+{}<%{|NqNgWB+8Yu$S12^bEl7 z*>Bl}9a9T}K>!3m00ck)1V8`;KmY_l00ck)1U4g}7wK*OdO-%34DvECWssA>kPHkN M=rYh`Am9K0e?Y`G00000 literal 0 HcmV?d00001 diff --git a/runtime-pyside6/LogarithmPlotter/util/promise.py b/runtime-pyside6/LogarithmPlotter/util/promise.py index f129d41..41b916d 100644 --- a/runtime-pyside6/LogarithmPlotter/util/promise.py +++ b/runtime-pyside6/LogarithmPlotter/util/promise.py @@ -17,7 +17,7 @@ """ from typing import Callable -from PySide6.QtCore import QRunnable, Signal, QObject, Slot, QThreadPool +from PySide6.QtCore import QRunnable, Signal, Property, QObject, Slot, QThreadPool from PySide6.QtQml import QJSValue from LogarithmPlotter.util.js import PyJSValue @@ -51,10 +51,10 @@ class PyPromiseRunner(QRunnable): data = data.qjs_value else: raise InvalidReturnValue("Must return either a primitive, a valid QObject, JS Value, or None.") - self.promise.finished.emit(data) + self.promise.fulfilled.emit(data) except Exception as e: try: - self.promise.errored.emit(repr(e)) + self.promise.rejected.emit(repr(e)) except RuntimeError as e2: # Happens when the PyPromise has already been garbage collected. # In other words, nothing to report to nowhere. @@ -66,18 +66,22 @@ class PyPromise(QObject): Asynchronous Promise-like object meant to interface between Python and Javascript easily. Runs to_run in another thread, and calls fulfilled (populated by then) with its return value. """ - finished = Signal((QJSValue,), (QObject,)) - errored = Signal(Exception) + fulfilled = Signal((QJSValue,), (QObject,)) + rejected = Signal(Exception) - def __init__(self, to_run: Callable, args): + def __init__(self, to_run: Callable, args=[]): QObject.__init__(self) self._fulfills = [] self._rejects = [] - self.finished.connect(self._fulfill) - self.errored.connect(self._reject) + self._state = "pending" + self.fulfilled.connect(self._fulfill) + self.rejected.connect(self._reject) self._runner = PyPromiseRunner(to_run, self, args) QThreadPool.globalInstance().start(self._runner) + @Property(str) + def state(self): + return self._state @Slot(QJSValue, result=QObject) @Slot(QJSValue, QJSValue, result=QObject) @@ -98,6 +102,7 @@ class PyPromise(QObject): @Slot(QJSValue) @Slot(QObject) def _fulfill(self, data): + self._state = "fulfilled" no_return = [None, QJSValue.SpecialValue.UndefinedValue] for on_fulfill in self._fulfills: try: @@ -110,6 +115,7 @@ class PyPromise(QObject): @Slot(QJSValue) @Slot(str) def _reject(self, error): + self._state = "rejected" no_return = [None, QJSValue.SpecialValue.UndefinedValue] for on_reject in self._rejects: result = on_reject(error) diff --git a/runtime-pyside6/tests/test_helper.py b/runtime-pyside6/tests/test_helper.py index 73dfb23..5cfb239 100644 --- a/runtime-pyside6/tests/test_helper.py +++ b/runtime-pyside6/tests/test_helper.py @@ -17,7 +17,7 @@ """ import pytest -from os import getcwd, remove +from os import getcwd, remove, path from os.path import join from tempfile import TemporaryDirectory from json import loads @@ -25,11 +25,12 @@ from shutil import copy2 from PySide6.QtCore import QObject, Signal, QThreadPool from PySide6.QtGui import QImage +from PySide6.QtQml import QJSValue from PySide6.QtWidgets import QApplication from LogarithmPlotter import __VERSION__ as version from LogarithmPlotter.util import config, helper -from LogarithmPlotter.util.helper import ChangelogFetcher, Helper, InvalidFileException +from LogarithmPlotter.util.helper import Helper, InvalidFileException pwd = getcwd() helper.SHOW_GUI_MESSAGES = False @@ -43,41 +44,45 @@ def temporary(): directory.cleanup() -class MockHelperSignals(QObject): - changelogFetched = Signal(str) +def create_changelog_callback_asserter(promise, expect_404=False): + def cb(changelog, expect_404=expect_404): + # print("Got changelog", changelog) + assert isinstance(changelog, QJSValue) + assert changelog.isString() + changlogValue = changelog.toVariant() + assert ('404' in changlogValue) == expect_404 + def error(e): + raise eval(e) + promise.then(cb, error) - def __init__(self, expect_404): - QObject.__init__(self) - self.expect_404 = expect_404 - self.changelogFetched.connect(self.changelog_fetched) - self.changelog = None - - def changelog_fetched(self, changelog): - self.changelog = changelog - - -class TestChangelog: - - def test_exists(self, qtbot): - helper.CHANGELOG_VERSION = '0.5.0' - mock_helper = MockHelperSignals(False) - fetcher = ChangelogFetcher(mock_helper) - fetcher.run() # Does not raise an exception - qtbot.waitSignal(mock_helper.changelogFetched, timeout=10000) - assert type(mock_helper.changelog) == str - assert '404' not in mock_helper.changelog - - def tests_no_exist(self, qtbot): - mock_helper = MockHelperSignals(True) - helper.CHANGELOG_VERSION = '1.0.0' - fetcher = ChangelogFetcher(mock_helper) - fetcher.run() - qtbot.waitSignal(mock_helper.changelogFetched, timeout=10000) - assert type(mock_helper.changelog) == str - assert '404' in mock_helper.changelog +CHANGELOG_BASE_PATH = path.realpath(path.join(path.dirname(path.realpath(__file__)), "..", "CHANGELOG.md")) class TestHelper: + def test_changelog(self, temporary, qtbot): + helper.CHANGELOG_VERSION = '0.5.0' + tmpfile, directory = temporary + obj = Helper(pwd, tmpfile) + promise = obj.fetchChangelog() + create_changelog_callback_asserter(promise, expect_404=False) + qtbot.waitSignal(promise.fulfilled, timeout=10000) + # No exist + helper.CHANGELOG_VERSION = '2.0.0' + tmpfile, directory = temporary + obj = Helper(pwd, tmpfile) + promise = obj.fetchChangelog() + create_changelog_callback_asserter(promise, expect_404=True) + qtbot.waitSignal(promise.fulfilled, timeout=10000) + # Local + tmpfile, directory = temporary + obj = Helper(pwd, tmpfile) + assert path.exists(CHANGELOG_BASE_PATH) + copy2(CHANGELOG_BASE_PATH, helper.CHANGELOG_CACHE_PATH) + assert path.exists(helper.CHANGELOG_CACHE_PATH) + promise = obj.fetchChangelog() + create_changelog_callback_asserter(promise, expect_404=False) + qtbot.waitSignal(promise.fulfilled, timeout=10000) # Local + def test_read(self, temporary): # Test file reading and information loading. tmpfile, directory = temporary @@ -168,15 +173,3 @@ class TestHelper: obj.setSetting("last_install_greet", obj.getSetting("last_install_greet")) obj.setSetting("check_for_updates", obj.getSetting("check_for_updates")) obj.setSetting("default_graph.xzoom", obj.getSetting("default_graph.xzoom")) - - def test_fetch_changelog(self, temporary, qtbot): - tmpfile, directory = temporary - obj = Helper(pwd, tmpfile) - copy2("../../CHANGELOG.md", "../../LogarithmPlotter/util/CHANGELOG.md") - obj.fetchChangelog() - assert QThreadPool.globalInstance().activeThreadCount() == 0 - qtbot.waitSignal(obj.changelogFetched, timeout=10000) - remove("../../LogarithmPlotter/util/CHANGELOG.md") - obj.fetchChangelog() - assert QThreadPool.globalInstance().activeThreadCount() > 0 - qtbot.waitSignal(obj.changelogFetched, timeout=10000) \ No newline at end of file diff --git a/runtime-pyside6/tests/test_latex.py b/runtime-pyside6/tests/test_latex.py index d74f9f1..6fd5c97 100644 --- a/runtime-pyside6/tests/test_latex.py +++ b/runtime-pyside6/tests/test_latex.py @@ -54,8 +54,8 @@ class TestLatex: # Reset [latex.DVIPNG_PATH, latex.LATEX_PATH] = bkp - def test_render(self, latex_obj: latex.Latex) -> None: - result = latex_obj.render(r"\frac{d\sqrt{\mathrm{f}(x \times 2.3)}}{dx}", 14, QColor(0, 0, 0, 255)) + def test_render_sync(self, latex_obj: latex.Latex) -> None: + result = latex_obj.renderSync(r"\frac{d\sqrt{\mathrm{f}(x \times 2.3)}}{dx}", 14, QColor(0, 0, 0, 255)) # Ensure result format assert type(result) == str [path, width, height] = result.split(",") @@ -64,17 +64,17 @@ class TestLatex: assert match(r"\d+", height) # Ensure it returns errors on invalid latex. with pytest.raises(latex.RenderError): - latex_obj.render(r"\nonexistant", 14, QColor(0, 0, 0, 255)) + latex_obj.renderSync(r"\nonexistant", 14, QColor(0, 0, 0, 255)) # Replace latex bin with one that returns errors bkp = latex.LATEX_PATH latex.LATEX_PATH = which("false") with pytest.raises(latex.RenderError): - latex_obj.render(r"\mathrm{f}(x)", 14, QColor(0, 0, 0, 255)) + latex_obj.renderSync(r"\mathrm{f}(x)", 14, QColor(0, 0, 0, 255)) latex.LATEX_PATH = bkp def test_prerendered(self, latex_obj: latex.Latex) -> None: args = [r"\frac{d\sqrt{\mathrm{f}(x \times 2.3)}}{dx}", 14, QColor(0, 0, 0, 255)] - latex_obj.render(*args) + latex_obj.renderSync(*args) prerendered = latex_obj.findPrerendered(*args) assert type(prerendered) == str [path, width, height] = prerendered.split(",") From aeaaba759f90a86100c69cabf08531f385d50e85 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 15 Oct 2024 19:21:40 +0200 Subject: [PATCH 051/104] Starting latex render locking. --- common/src/module/canvas.mjs | 4 + runtime-pyside6/.coverage | Bin 53248 -> 0 bytes .../LogarithmPlotter/util/latex.py | 69 ++++++++++++++++-- .../LogarithmPlotter/util/promise.py | 43 ++++++++--- 4 files changed, 99 insertions(+), 17 deletions(-) delete mode 100644 runtime-pyside6/.coverage diff --git a/common/src/module/canvas.mjs b/common/src/module/canvas.mjs index 62649cf..6abbf2d 100644 --- a/common/src/module/canvas.mjs +++ b/common/src/module/canvas.mjs @@ -529,11 +529,15 @@ class CanvasAPI extends Module { this.#canvas.loadImageAsync(imgData.source).then(() => { if(this.#redrawCount === currentRedrawCount) callback(imgData) + else + console.log("2Discard render of", imgData.source, this.#redrawCount, currentRedrawCount) }) } else { // Callback directly if(this.#redrawCount === currentRedrawCount) callback(imgData) + else + console.log("2Discard render of", imgData.source, this.#redrawCount, currentRedrawCount) } } const prerendered = Latex.findPrerendered(ltxText, this.textsize, color) diff --git a/runtime-pyside6/.coverage b/runtime-pyside6/.coverage deleted file mode 100644 index 8eab2ed6efa5c8f1c8ebd2f83154347499e04eff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53248 zcmeI4Uu+yl9mn^dZ*T99CykY!ToW=tsbkfDVxWm=B~q70q7X<+LtjwY?%j>;EqA-; z-95)fRM9m>k&s#m5aI#aClC+tzynD92`LpX1PM@t5J*rWifHpd2^B4hlm_#g{o}if z?W!+6tMPYrH?uoCGr!;OGryVHxxL+oA3E+vg3tRw(~0;8l|728D)(}(D2hejGJUhn zq#YwWpjhqM-)h%VroXUMW{)VP+|vsCT=@i>Dt)VbNAY5*X??l)oatCKI)M!YKmY_l zV0RPfJXA6(qoeARPee|&A)>&ki69BfAN};Pxs%8E$+`QEALB_HKUmCgD*wD# zos2W2(ju`EB?(lCa2Gt8gC9(bPw+s@i$Hia5hhw3bn6p^i8H4QW@ThVJu70HoS;UZ zVxKjX&^6_Od8(-92X(1^HE_Jzq6jCsvuY>vuyh+J4ds=v&l=J)yYqy{jO@(8fy>_!o z$RBSvTe5MeL?Sryw<@_+*~m|gecNrbNn3X9?Q6~qxopv-RNHfx+G4%&CwaHzWNe1# zPjYDldBFRNxypw}RE4}!tb|Jqy56##cI3y$HZ{IIOF`+WTk>Y*zybB_QtT)ak6m@6 zaDB(>bDH(!EnG*Q-`a0vFX?v@*^3$t?$5_vMwaGDf#bIO|k#E#p zCX?dhL%GU5`?gYCs$kE`Fn8v&TCDQf(U^Xd27UR}`&5=GU6nr}R;QMo28|{y#|@~< z(ioh~09l$~qR7$77wc$wdzHC#lnA{fl;* zO~s4kg}?sp;)xlO@kmROnCu}(Q5uLXim(p)+*uD_KV$kwuFWhht4d3h<SLAkPXI@z4^MxfKvrq&vcfL2 zH{O{BLTeBJ0T2KI5C8!X009sH0T2KI5CDOUKuO=PX1@Yx1%1p)e*}>C|BJ;jg?)wX zAO7C(-Q{1EKT~?8v|L;(K26EkKmY_l00ck)1V8`;Kw!5JXcY~mBW9YS?m9D0{jNiY zW@o~%E+0~!nQOJendAO~6S&c0^TCE6MIzXk5VSq{Q1Mi2HFWFZ@Wu@7$ZgEDTU4i@ zhnHK00ZH`eH()%aoT`4ipNTNG{ zcC>BRb0ga(nN5{s+S@C$N1VL>Uo5^$VP7pN?A^oPAHJu2p>(-)s`yO#5lY4e0w4ea zAOHd&00JNY0=tI5lFwhyaItzo4)?NSS2IV^I>;IuawPCjYHwIm;$mD4{x@{6DUY;5d3dks2whoLDy{?G5mXFv8A`^2|bZ`CPn zS|=l}`)fyE|N2wc_l{pZ{_k>5qx4}-wN%5hZq<|zJ*UUd|Fa({>>7KWegSxyU1EP? z7um1bFWEUt#s&f)00JNY0w4eaAOHd&00JNY0wAzc1mv#-YOxqcg+d%zRvhK?ab%it zl*`4@&`=y1MjYvS9BGH^_To3>O5C8!X009sH0T2KI5C8!X7zhD* z{~zoBfuM#E5C8!X009sH0T2KI5C8!X009u#F#^f+{}<%{|NqNgWB+8Yu$S12^bEl7 z*>Bl}9a9T}K>!3m00ck)1V8`;KmY_l00ck)1U4g}7wK*OdO-%34DvECWssA>kPHkN M=rYh`Am9K0e?Y`G00000 diff --git a/runtime-pyside6/LogarithmPlotter/util/latex.py b/runtime-pyside6/LogarithmPlotter/util/latex.py index 0d720c3..2db62eb 100644 --- a/runtime-pyside6/LogarithmPlotter/util/latex.py +++ b/runtime-pyside6/LogarithmPlotter/util/latex.py @@ -82,6 +82,7 @@ class Latex(QObject): def __init__(self, cache_path): QObject.__init__(self) self.tempdir = path.join(cache_path, "latex") + self.render_pipeline_locks = {} makedirs(self.tempdir, exist_ok=True) @Property(bool) @@ -116,20 +117,71 @@ class Latex(QObject): except MissingPackageException: valid_install = False # Should have sent an error message if failed to render return valid_install + + def lock(self, markup_hash, render_hash, promise): + """ + Locks the render pipeline for a given markup hash and render hash. + """ + # print("Locking", markup_hash, render_hash) + if markup_hash not in self.render_pipeline_locks: + self.render_pipeline_locks[markup_hash] = promise + self.render_pipeline_locks[render_hash] = promise + + + def release_lock(self, markup_hash, render_hash): + """ + Release locks on the markup and render hashes. + """ + # print("Releasing", markup_hash, render_hash) + if markup_hash in self.render_pipeline_locks: + del self.render_pipeline_locks[markup_hash] + del self.render_pipeline_locks[render_hash] @Slot(str, float, QColor, result=PyPromise) def renderAsync(self, latex_markup: str, font_size: float, color: QColor) -> PyPromise: """ Prepares and renders a latex string into a png file asynchronously. """ - return PyPromise(self.renderSync, [latex_markup, font_size, color]) + markup_hash, render_hash, export_path = self.create_export_path(latex_markup, font_size, color) + promise = None + if render_hash in self.render_pipeline_locks: + # A PyPromise for this specific render is already running. + # print("Already running render of", latex_markup) + promise = self.render_pipeline_locks[render_hash] + elif markup_hash in self.render_pipeline_locks: + # A PyPromise with the same markup, but not the same color or font size is already running. + print("Chaining render of", latex_markup) + existing_promise = self.render_pipeline_locks[markup_hash] + promise = self._create_async_promise(latex_markup, font_size, color) + existing_promise.then(lambda x, latex_markup=latex_markup: print("> Starting chained render of", latex_markup)) + promise.then(lambda x, latex_markup=latex_markup: print("> Fulfilled chained render of", latex_markup, "\n with", x.toVariant())) + existing_promise.then(promise.start) + else: + # No such PyPromise is running. + promise = self._create_async_promise(latex_markup, font_size, color) + promise.start() + return promise + + def _create_async_promise(self, latex_markup: str, font_size: float, color: QColor) -> PyPromise: + """ + Createsa PyPromise to render a latex string into a PNG file. + Internal method. Use renderAsync that makes use of locks. + """ + markup_hash, render_hash, export_path = self.create_export_path(latex_markup, font_size, color) + promise = PyPromise(self.renderSync, [latex_markup, font_size, color], start_automatically=False) + self.lock(markup_hash, render_hash, promise) + # Make the lock release at the end. + def unlock(data, markup_hash=markup_hash, render_hash=render_hash): + self.release_lock(markup_hash, render_hash) + promise.then(unlock, unlock) + return promise @Slot(str, float, QColor, result=str) def renderSync(self, latex_markup: str, font_size: float, color: QColor) -> str: """ Prepares and renders a latex string into a png file. """ - markup_hash, export_path = self.create_export_path(latex_markup, font_size, color) + markup_hash, render_hash, export_path = self.create_export_path(latex_markup, font_size, color) if self.latexSupported and not path.exists(export_path + ".png"): print("Rendering", latex_markup, export_path) # Generating file @@ -138,14 +190,12 @@ class Latex(QObject): if not path.exists(latex_path + ".dvi"): self.create_latex_doc(latex_path, latex_markup) self.convert_latex_to_dvi(latex_path) - # self.cleanup(latex_path) + self.cleanup(latex_path) # Creating four pictures of different sizes to better handle dpi. self.convert_dvi_to_png(latex_path, export_path, font_size, color) # self.convert_dvi_to_png(latex_path, export_path+"@2", font_size*2, color) # self.convert_dvi_to_png(latex_path, export_path+"@3", font_size*3, color) # self.convert_dvi_to_png(latex_path, export_path+"@4", font_size*4, color) - else: - sleep(0) img = QImage(export_path) # Small hack, not very optimized since we load the image twice, but you can't pass a QImage to QML and expect it to be loaded return f'{export_path}.png,{img.width()},{img.height()}' @@ -155,7 +205,7 @@ class Latex(QObject): """ Finds a prerendered image and returns its data if possible, and an empty string if not. """ - markup_hash, export_path = self.create_export_path(latex_markup, font_size, color) + markup_hash, render_hash, export_path = self.create_export_path(latex_markup, font_size, color) data = "" if path.exists(export_path + ".png"): img = QImage(export_path) @@ -165,10 +215,13 @@ class Latex(QObject): def create_export_path(self, latex_markup: str, font_size: float, color: QColor): """ Standardizes export path for renders. + Markup hash is unique for the markup + Render hash is unique for the markup, the font size and the color. """ markup_hash = "render" + str(sha512(latex_markup.encode()).hexdigest()) - export_path = path.join(self.tempdir, f'{markup_hash}_{int(font_size)}_{color.rgb()}') - return markup_hash, export_path + render_hash = f'{markup_hash}_{int(font_size)}_{color.rgb()}' + export_path = path.join(self.tempdir, render_hash) + return markup_hash, render_hash, export_path def create_latex_doc(self, export_path: str, latex_markup: str): """ diff --git a/runtime-pyside6/LogarithmPlotter/util/promise.py b/runtime-pyside6/LogarithmPlotter/util/promise.py index 41b916d..e475b36 100644 --- a/runtime-pyside6/LogarithmPlotter/util/promise.py +++ b/runtime-pyside6/LogarithmPlotter/util/promise.py @@ -23,6 +23,18 @@ from PySide6.QtQml import QJSValue from LogarithmPlotter.util.js import PyJSValue +def check_callable(function: Callable|QJSValue) -> Callable|None: + """ + Checks if the given function can be called (either a python callable + or a QJSValue function), and returns the object that can be called directly. + Returns None if not a function. + """ + if isinstance(function, QJSValue) and function.isCallable(): + return PyJSValue(function) + elif isinstance(function, Callable): + return function + return None + class InvalidReturnValue(Exception): pass @@ -69,16 +81,30 @@ class PyPromise(QObject): fulfilled = Signal((QJSValue,), (QObject,)) rejected = Signal(Exception) - def __init__(self, to_run: Callable, args=[]): + def __init__(self, to_run: Callable|QJSValue, args=[], start_automatically=True): QObject.__init__(self) self._fulfills = [] self._rejects = [] self._state = "pending" + self._started = False self.fulfilled.connect(self._fulfill) self.rejected.connect(self._reject) + to_run = check_callable(to_run) + if to_run is None: + raise ValueError("New PyPromise created with invalid function") self._runner = PyPromiseRunner(to_run, self, args) - QThreadPool.globalInstance().start(self._runner) - + if start_automatically: + self._start() + + @Slot() + def start(self, *args, **kwargs): + """ + Starts the thread that will run the promise. + """ + if not self._started: # Avoid getting started twice. + QThreadPool.globalInstance().start(self._runner) + self._started = True + @Property(str) def state(self): return self._state @@ -89,13 +115,11 @@ class PyPromise(QObject): """ Adds listeners for both fulfilment and catching errors of the Promise. """ - if isinstance(on_fulfill, QJSValue): - self._fulfills.append(PyJSValue(on_fulfill)) - elif isinstance(on_fulfill, Callable): + on_fulfill = check_callable(on_fulfill) + on_reject = check_callable(on_reject) + if on_fulfill is not None: self._fulfills.append(on_fulfill) - if isinstance(on_reject, QJSValue): - self._rejects.append(PyJSValue(on_reject)) - elif isinstance(on_reject, Callable): + if on_reject is not None: self._rejects.append(on_reject) return self @@ -107,6 +131,7 @@ class PyPromise(QObject): for on_fulfill in self._fulfills: try: result = on_fulfill(data) + result = result.qjs_value if isinstance(result, PyJSValue) else result data = result if result not in no_return else data # Forward data. except Exception as e: self._reject(repr(e)) From a85a4721e3988756e3da1524219381214f8d599b Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 15 Oct 2024 20:39:03 +0200 Subject: [PATCH 052/104] Fixing double redraw when opening a file. --- common/src/module/canvas.mjs | 2 +- common/src/module/io.mjs | 1 - runtime-pyside6/LogarithmPlotter/util/debug.py | 3 +++ runtime-pyside6/LogarithmPlotter/util/latex.py | 4 +--- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/src/module/canvas.mjs b/common/src/module/canvas.mjs index 6abbf2d..913442f 100644 --- a/common/src/module/canvas.mjs +++ b/common/src/module/canvas.mjs @@ -530,7 +530,7 @@ class CanvasAPI extends Module { if(this.#redrawCount === currentRedrawCount) callback(imgData) else - console.log("2Discard render of", imgData.source, this.#redrawCount, currentRedrawCount) + console.log("1Discard render of", imgData.source, this.#redrawCount, currentRedrawCount) }) } else { // Callback directly diff --git a/common/src/module/io.mjs b/common/src/module/io.mjs index 472b061..92096e9 100644 --- a/common/src/module/io.mjs +++ b/common/src/module/io.mjs @@ -201,7 +201,6 @@ class IOAPI extends Module { // TODO: Error handling return } - Canvas.redraw() this.#alert.show(qsTranslate("io", "Loaded file '%1'.").arg(basename)) this.#saved = true this.emit(new LoadedEvent()) diff --git a/runtime-pyside6/LogarithmPlotter/util/debug.py b/runtime-pyside6/LogarithmPlotter/util/debug.py index 8b57687..f899fd5 100644 --- a/runtime-pyside6/LogarithmPlotter/util/debug.py +++ b/runtime-pyside6/LogarithmPlotter/util/debug.py @@ -19,10 +19,12 @@ from PySide6.QtCore import QtMsgType, qInstallMessageHandler, QMessageLogContext from math import ceil, log10 from os import path +from re import compile CURRENT_PATH = path.dirname(path.realpath(__file__)) SOURCEMAP_PATH = path.realpath(f"{CURRENT_PATH}/../qml/eu/ad5001/LogarithmPlotter/js/index.mjs.map") SOURCEMAP_INDEX = None +INDEX_REG = compile(r"build\/runtime-pyside6\/LogarithmPlotter\/qml\/eu\/ad5001\/LogarithmPlotter\/js\/index.mjs:(\d+)") class LOG_COLORS: @@ -77,6 +79,7 @@ def create_log_terminal_message(mode: QtMsgType, context: QMessageLogContext, me # Check MJS if line is not None and source_file is not None and source_file.endswith("index.mjs"): source_file, line = map_javascript_source(source_file, line) + # Parse message prefix = f"{LOG_COLORS.INVERT}{mode[1]}[{mode[0].upper()}]{LOG_COLORS.RESET_INVERT}" message = message + LOG_COLORS.RESET context = f"{context.function} at {source_file}:{line}" diff --git a/runtime-pyside6/LogarithmPlotter/util/latex.py b/runtime-pyside6/LogarithmPlotter/util/latex.py index 2db62eb..f36f07f 100644 --- a/runtime-pyside6/LogarithmPlotter/util/latex.py +++ b/runtime-pyside6/LogarithmPlotter/util/latex.py @@ -150,11 +150,9 @@ class Latex(QObject): promise = self.render_pipeline_locks[render_hash] elif markup_hash in self.render_pipeline_locks: # A PyPromise with the same markup, but not the same color or font size is already running. - print("Chaining render of", latex_markup) + # print("Chaining render of", latex_markup) existing_promise = self.render_pipeline_locks[markup_hash] promise = self._create_async_promise(latex_markup, font_size, color) - existing_promise.then(lambda x, latex_markup=latex_markup: print("> Starting chained render of", latex_markup)) - promise.then(lambda x, latex_markup=latex_markup: print("> Fulfilled chained render of", latex_markup, "\n with", x.toVariant())) existing_promise.then(promise.start) else: # No such PyPromise is running. From 34caf20593859dcd4d2cd111487d51927d2eda0e Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Wed, 16 Oct 2024 05:38:49 +0200 Subject: [PATCH 053/104] Fixing LaTeX tests, adding new sexy natural language method spy, started testing Promises. --- common/src/module/canvas.mjs | 4 +- common/test/mock/latex.mjs | 18 +- runtime-pyside6/LogarithmPlotter/util/js.py | 6 +- .../LogarithmPlotter/util/promise.py | 41 ++- runtime-pyside6/tests/spy.py | 254 ++++++++++++++++++ runtime-pyside6/tests/test_config.py | 18 ++ runtime-pyside6/tests/test_helper.py | 16 +- runtime-pyside6/tests/test_latex.py | 57 +++- runtime-pyside6/tests/test_native.py | 1 - runtime-pyside6/tests/test_promise.py | 115 ++++++++ runtime-pyside6/tests/test_update.py | 15 +- scripts/run-tests.sh | 1 + 12 files changed, 511 insertions(+), 35 deletions(-) create mode 100644 runtime-pyside6/tests/spy.py create mode 100644 runtime-pyside6/tests/test_promise.py diff --git a/common/src/module/canvas.mjs b/common/src/module/canvas.mjs index 913442f..ba6d5ca 100644 --- a/common/src/module/canvas.mjs +++ b/common/src/module/canvas.mjs @@ -530,14 +530,14 @@ class CanvasAPI extends Module { if(this.#redrawCount === currentRedrawCount) callback(imgData) else - console.log("1Discard render of", imgData.source, this.#redrawCount, currentRedrawCount) + console.log("1. Discard render of", imgData.source, this.#redrawCount, currentRedrawCount) }) } else { // Callback directly if(this.#redrawCount === currentRedrawCount) callback(imgData) else - console.log("2Discard render of", imgData.source, this.#redrawCount, currentRedrawCount) + console.log("2. Discard render of", imgData.source, this.#redrawCount, currentRedrawCount) } } const prerendered = Latex.findPrerendered(ltxText, this.textsize, color) diff --git a/common/test/mock/latex.mjs b/common/test/mock/latex.mjs index ab56999..c0a029c 100644 --- a/common/test/mock/latex.mjs +++ b/common/test/mock/latex.mjs @@ -23,6 +23,10 @@ const PIXEL = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVR4AWNgAAAAA export class MockLatex { constructor() { } + + get supportsAsyncRender() { + return true + } /** * Creates a simple string hash. @@ -55,13 +59,23 @@ export class MockLatex { return `${TMP}/${name}.png` } + /** + * @param {string} markup - LaTeX markup to render + * @param {number} fontSize - Font size (in pt) to render + * @param {string} color - Color of the text to render + * @returns {Promise} - Comma separated data of the image (source, width, height) + */ + async renderAsync(markup, fontSize, color) { + return this.renderSync(markup, fontSize, color) + } + /** * @param {string} markup - LaTeX markup to render * @param {number} fontSize - Font size (in pt) to render * @param {string} color - Color of the text to render * @returns {string} - Comma separated data of the image (source, width, height) */ - render(markup, fontSize, color) { + renderSync(markup, fontSize, color) { const file = this.__getFileName(markup, fontSize, color) writeFileSync(file, PIXEL, "base64") return `${file},1,1` @@ -87,4 +101,4 @@ export class MockLatex { checkLatexInstallation() { return true // We're not *actually* doing any latex. } -} \ No newline at end of file +} diff --git a/runtime-pyside6/LogarithmPlotter/util/js.py b/runtime-pyside6/LogarithmPlotter/util/js.py index 05f30d5..944c2b0 100644 --- a/runtime-pyside6/LogarithmPlotter/util/js.py +++ b/runtime-pyside6/LogarithmPlotter/util/js.py @@ -75,6 +75,7 @@ class PyJSValue: return value def type(self) -> any: + ret = None matcher = [ (lambda: self.qjs_value.isArray(), list), (lambda: self.qjs_value.isBool(), bool), @@ -93,8 +94,9 @@ class PyJSValue: ] for (test, value) in matcher: if test(): - return value - return None + ret = value + break + return ret def primitive(self): """ diff --git a/runtime-pyside6/LogarithmPlotter/util/promise.py b/runtime-pyside6/LogarithmPlotter/util/promise.py index e475b36..3c2d223 100644 --- a/runtime-pyside6/LogarithmPlotter/util/promise.py +++ b/runtime-pyside6/LogarithmPlotter/util/promise.py @@ -31,7 +31,7 @@ def check_callable(function: Callable|QJSValue) -> Callable|None: """ if isinstance(function, QJSValue) and function.isCallable(): return PyJSValue(function) - elif isinstance(function, Callable): + elif callable(function): return function return None @@ -51,9 +51,7 @@ class PyPromiseRunner(QRunnable): def run(self): try: data = self.runner(*self.args) - if isinstance(data, QObject): - data = data - elif type(data) in [int, str, float, bool, bytes]: + if type(data) in [int, str, float, bool]: data = QJSValue(data) elif data is None: data = QJSValue.SpecialValue.UndefinedValue @@ -62,7 +60,7 @@ class PyPromiseRunner(QRunnable): elif isinstance(data, PyJSValue): data = data.qjs_value else: - raise InvalidReturnValue("Must return either a primitive, a valid QObject, JS Value, or None.") + raise InvalidReturnValue("Must return either a primitive, a JS Value, or None.") self.promise.fulfilled.emit(data) except Exception as e: try: @@ -79,7 +77,7 @@ class PyPromise(QObject): Runs to_run in another thread, and calls fulfilled (populated by then) with its return value. """ fulfilled = Signal((QJSValue,), (QObject,)) - rejected = Signal(Exception) + rejected = Signal(str) def __init__(self, to_run: Callable|QJSValue, args=[], start_automatically=True): QObject.__init__(self) @@ -94,7 +92,7 @@ class PyPromise(QObject): raise ValueError("New PyPromise created with invalid function") self._runner = PyPromiseRunner(to_run, self, args) if start_automatically: - self._start() + self.start() @Slot() def start(self, *args, **kwargs): @@ -122,6 +120,35 @@ class PyPromise(QObject): if on_reject is not None: self._rejects.append(on_reject) return self + + def calls_upon_fulfillment(self, function: Callable | QJSValue) -> bool: + """ + Returns True if the given function will be callback upon the promise fulfillment. + False otherwise. + """ + return self._calls_in(function, self._fulfills) + + def calls_upon_rejection(self, function: Callable | QJSValue) -> bool: + """ + Returns True if the given function will be callback upon the promise rejection. + False otherwise. + """ + return self._calls_in(function, self._rejects) + + def _calls_in(self, function: Callable | QJSValue, within: list) -> bool: + """ + Returns True if the given function resides in the given within list, False otherwise. + Internal method of calls_upon_fulfill + """ + function = check_callable(function) + ret = False + if isinstance(function, PyJSValue): + found = next((f for f in within if f.qjs_value == function.qjs_value), None) + ret = found is not None + elif callable(function): + found = next((f for f in within if f == function), None) + ret = found is not None + return ret @Slot(QJSValue) @Slot(QObject) diff --git a/runtime-pyside6/tests/spy.py b/runtime-pyside6/tests/spy.py new file mode 100644 index 0000000..01f9aa0 --- /dev/null +++ b/runtime-pyside6/tests/spy.py @@ -0,0 +1,254 @@ +""" + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +""" +from typing import Callable, Self + +from PySide6.QtQml import QJSValue + +PRINT_PREFIX = (" " * 24) + +class SpyAssertionFailed(Exception): + def __init__(self, message, calls): + self.message = message + "\n" + if len(calls) > 0: + self.message += self.render_calls(calls) + else: + self.message += f"{PRINT_PREFIX}0 registered calls." + + def repr(self, data): + if isinstance(data, QJSValue): + variant = data.toVariant() + return f"QJSValue<{type(variant).__name__}>({repr(variant)})" + else: + return repr(data) + + def render_calls(self, calls): + lines = [f"{PRINT_PREFIX}{len(calls)} registered call(s):"] + for call in calls: + repr_args = [self.repr(arg) for arg in call[0]] + repr_kwargs =[f"{key}={self.repr(arg)}" for key, arg in call[1].items()] + lines.append(f" - {', '.join([*repr_args, *repr_kwargs])}") + return ("\n" + PRINT_PREFIX).join(lines) + + def __str__(self): + return self.message + +class Methods: + AT_LEAST_ONCE = "AT_LEAST_ONCE" + EXACTLY = "EXACTLY" + AT_LEAST = "AT_LEAST" + AT_MOST = "AT_MOST" + MORE_THAN = "AT_LEAST" + LESS_THAN = "AT_MOST" + +class CalledInterface: + """ + Internal class generated by Spy.was_called. + """ + + def __init__(self, calls: list[tuple[list, dict]]): + self.__calls = calls + self.__method = Methods.AT_LEAST_ONCE + self.__times = None + + def __apply_method(self, calls): + required = self.__times + calls_count = len(calls) + match self.__method: + case Methods.AT_LEAST_ONCE: + compare = len(calls) >= 1 + error = "Method was not called" + case Methods.EXACTLY: + compare = len(calls) == required + error = f"Method was not called {required} times ({required} != {calls_count})" + case Methods.AT_LEAST: + compare = len(calls) >= required + error = f"Method was not called at least {required} times ({required} > {calls_count})" + case Methods.AT_MOST: + compare = len(calls) <= required + error = f"Method was not called at most {required} times ({required} < {calls_count})" + case Methods.MORE_THAN: + compare = len(calls) > required + error = f"Method was not called more than {required} times ({required} >= {calls_count})" + case Methods.LESS_THAN: + compare = len(calls) < required + error = f"Method was not called less than {required} times ({required} <= {calls_count})" + case _: + raise RuntimeError(f"Unknown method {self.__method}.") + return compare, error + + def __bool__(self): + """ + Converts to boolean on assertion. + """ + compare, error = self.__apply_method(self.__calls) + if not compare: + raise SpyAssertionFailed(error+".") + return compare + + + """ + Chaining methods + """ + def __call__(self, *args, **kwargs) -> Self: + if len(args) != 1: + raise RuntimeError("Cannot call called interface with more than one argument.") + self.__times = int(args[0]) + if self.__method == Methods.AT_LEAST_ONCE: + self.__method = Methods.EXACTLY + return self + + @property + def never(self) -> Self: + return self(0) + + @property + def once(self) -> Self: + return self(1) + + @property + def twice(self) -> Self: + return self(2) + + @property + def thrice(self) -> Self: + return self(3) + + @property + def at_least(self) -> Self: + self.__method = Methods.AT_LEAST + return self + + @property + def at_most(self) -> Self: + self.__method = Methods.AT_MOST + return self + + @property + def more_than(self) -> Self: + self.__method = Methods.MORE_THAN + return self + + @property + def less_than(self) -> Self: + self.__method = Methods.LESS_THAN + return self + + @property + def times(self) -> Self: + return self + + """ + Class properties. + """ + def __match_calls_for_condition(self, condition: Callable[[list, dict], bool]) -> tuple[bool, str]: + calls = [] + for call in self.__calls: + if condition(call[0], call[1]): + calls.append(call) + compare, error = self.__apply_method(calls) + return compare, error + + + def with_arguments(self, *args, **kwargs): + """ + Checks if the Spy has been called the given number of times + with at least the given arguments. + """ + def some_args_matched(a, kw): + args_matched = all(( + arg in a + for arg in args + )) + kwargs_matched = all(( + key in kw and kw[key] == arg + for key, arg in kwargs.items() + )) + return args_matched and kwargs_matched + compare, error = self.__match_calls_for_condition(some_args_matched) + if not compare: + repr_args = ', '.join([repr(arg) for arg in args]) + repr_kwargs = ', '.join([f"{key}={repr(arg)}" for key, arg in kwargs.items()]) + raise SpyAssertionFailed(f"{error} with arguments ({repr_args}) and keyword arguments ({repr_kwargs}).", self.__calls) + return compare + + + def with_arguments_matching(self, test_condition: Callable[[list, dict], bool]): + """ + Checks if the Spy has been called the given number of times + with arguments matching the given conditions. + """ + compare, error = self.__match_calls_for_condition(test_condition) + if not compare: + raise SpyAssertionFailed(f"{error} with arguments matching given conditions.", self.__calls) + return compare + + + def with_exact_arguments(self, *args, **kwargs): + """ + Checks if the Spy has been called the given number of times + with all the given arguments. + """ + compare, error = self.__match_calls_for_condition(lambda a, kw: a == args and kw == kwargs) + if not compare: + repr_args = ', '.join([repr(arg) for arg in args]) + repr_kwargs = ', '.join([f"{key}={repr(arg)}" for key, arg in kwargs.items()]) + raise SpyAssertionFailed(f"{error} with exact arguments ({repr_args}) and keyword arguments ({repr_kwargs}).", self.__calls) + return compare + + def with_no_argument(self): + """ + Checks if the Spy has been called the given number of times + with all the given arguments. + """ + compare, error = self.__match_calls_for_condition(lambda a, kw: len(a) == 0 and len(kw) == 0) + if not compare: + raise SpyAssertionFailed(f"{error} with no arguments.", self.__calls) + return compare + + + +class Spy: + """ + Class to spy into method calls with natural language expressions. + """ + + def __init__(self, function: Callable = None): + self.function = function + self.calls = [] + + def __call__(self, *args, **kwargs): + self.calls.append((args, kwargs)) + if self.function is not None: + self.function(*args, **kwargs) + + @property + def was_called(self) -> CalledInterface: + """ + Returns a boolean-able interface to check conditions for a given number of + time the spy was called. + """ + return CalledInterface(self.calls) + + @property + def was_not_called(self) -> CalledInterface: + """ + Returns a boolean-able interface to check that conditions were never fulfilled + in the times the spy was called. + """ + ret = CalledInterface(self.calls) + return ret(0) diff --git a/runtime-pyside6/tests/test_config.py b/runtime-pyside6/tests/test_config.py index c919c6f..cef3673 100644 --- a/runtime-pyside6/tests/test_config.py +++ b/runtime-pyside6/tests/test_config.py @@ -1,3 +1,21 @@ +""" + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +""" + import pytest from LogarithmPlotter.util import config from tempfile import TemporaryDirectory diff --git a/runtime-pyside6/tests/test_helper.py b/runtime-pyside6/tests/test_helper.py index 5cfb239..6bc1f0d 100644 --- a/runtime-pyside6/tests/test_helper.py +++ b/runtime-pyside6/tests/test_helper.py @@ -30,7 +30,7 @@ from PySide6.QtWidgets import QApplication from LogarithmPlotter import __VERSION__ as version from LogarithmPlotter.util import config, helper -from LogarithmPlotter.util.helper import Helper, InvalidFileException +from LogarithmPlotter.util.helper import Helper, fetch_changelog, read_changelog, InvalidFileException pwd = getcwd() helper.SHOW_GUI_MESSAGES = False @@ -60,19 +60,23 @@ CHANGELOG_BASE_PATH = path.realpath(path.join(path.dirname(path.realpath(__file_ class TestHelper: def test_changelog(self, temporary, qtbot): + # Exists helper.CHANGELOG_VERSION = '0.5.0' tmpfile, directory = temporary obj = Helper(pwd, tmpfile) promise = obj.fetchChangelog() create_changelog_callback_asserter(promise, expect_404=False) - qtbot.waitSignal(promise.fulfilled, timeout=10000) - # No exist + with qtbot.waitSignal(promise.fulfilled, timeout=10000): + pass + assert type(fetch_changelog()) == str + # Does not exist helper.CHANGELOG_VERSION = '2.0.0' tmpfile, directory = temporary obj = Helper(pwd, tmpfile) promise = obj.fetchChangelog() create_changelog_callback_asserter(promise, expect_404=True) - qtbot.waitSignal(promise.fulfilled, timeout=10000) + with qtbot.waitSignal(promise.fulfilled, timeout=10000): + pass # Local tmpfile, directory = temporary obj = Helper(pwd, tmpfile) @@ -81,7 +85,9 @@ class TestHelper: assert path.exists(helper.CHANGELOG_CACHE_PATH) promise = obj.fetchChangelog() create_changelog_callback_asserter(promise, expect_404=False) - qtbot.waitSignal(promise.fulfilled, timeout=10000) # Local + with qtbot.waitSignal(promise.fulfilled, timeout=100): # Local + pass + assert type(read_changelog()) == str def test_read(self, temporary): # Test file reading and information loading. diff --git a/runtime-pyside6/tests/test_latex.py b/runtime-pyside6/tests/test_latex.py index 6fd5c97..124186b 100644 --- a/runtime-pyside6/tests/test_latex.py +++ b/runtime-pyside6/tests/test_latex.py @@ -22,6 +22,7 @@ from shutil import which from os.path import exists from re import match from PySide6.QtGui import QColor +from PySide6.QtQml import QJSValue from LogarithmPlotter.util import latex @@ -38,10 +39,24 @@ def latex_obj(): directory.cleanup() +BLACK = QColor(0, 0, 0, 255) +BLUE = QColor(128, 128, 255, 255) + +def check_render_results(result): + if isinstance(result, QJSValue): + result = result.toVariant() + assert type(result) == str + [path, width, height] = result.split(",") + assert exists(path) + assert match(r"\d+", width) + assert match(r"\d+", height) + return True + class TestLatex: def test_check_install(self, latex_obj: latex.Latex) -> None: assert latex_obj.latexSupported == True assert latex_obj.checkLatexInstallation() == True + assert type(latex_obj.supportsAsyncRender) is bool bkp = [latex.DVIPNG_PATH, latex.LATEX_PATH] # Check what happens when one is missing. latex.DVIPNG_PATH = None @@ -55,25 +70,25 @@ class TestLatex: [latex.DVIPNG_PATH, latex.LATEX_PATH] = bkp def test_render_sync(self, latex_obj: latex.Latex) -> None: - result = latex_obj.renderSync(r"\frac{d\sqrt{\mathrm{f}(x \times 2.3)}}{dx}", 14, QColor(0, 0, 0, 255)) + result = latex_obj.renderSync("\\frac{d \\sqrt{\\mathrm{f}(x \\times 2.3)}}{dx}", 14, BLACK) # Ensure result format - assert type(result) == str - [path, width, height] = result.split(",") - assert exists(path) - assert match(r"\d+", width) - assert match(r"\d+", height) + check_render_results(result) # Ensure it returns errors on invalid latex. with pytest.raises(latex.RenderError): - latex_obj.renderSync(r"\nonexistant", 14, QColor(0, 0, 0, 255)) + latex_obj.renderSync("\\nonexistant", 14, BLACK) # Replace latex bin with one that returns errors bkp = latex.LATEX_PATH latex.LATEX_PATH = which("false") with pytest.raises(latex.RenderError): - latex_obj.renderSync(r"\mathrm{f}(x)", 14, QColor(0, 0, 0, 255)) + latex_obj.renderSync("\\mathrm{f}(x)", 14, BLACK) + # Replace latex bin with one goes indefinitely + latex.LATEX_PATH = which("import") + with pytest.raises(latex.RenderError): + latex_obj.renderSync("\\mathrm{f}(x)", 14, BLACK) latex.LATEX_PATH = bkp def test_prerendered(self, latex_obj: latex.Latex) -> None: - args = [r"\frac{d\sqrt{\mathrm{f}(x \times 2.3)}}{dx}", 14, QColor(0, 0, 0, 255)] + args = ["\\frac{d \\sqrt{\\mathrm{f}(x \\times 2.3)}}{dx}", 14, BLACK] latex_obj.renderSync(*args) prerendered = latex_obj.findPrerendered(*args) assert type(prerendered) == str @@ -84,3 +99,27 @@ class TestLatex: prerendered2 = latex_obj.findPrerendered(args[0], args[1]+2, args[2]) assert prerendered2 == "" + def test_render_async(self, latex_obj: latex.Latex, qtbot) -> None: + formula = "\\int\\limits^{3x}_{-\\infty}9\\mathrm{f}(x)^3+t dx" + og_promise = latex_obj.renderAsync(formula, 14, BLACK) + # Ensure we get the same locked one if we try to render it again. + assert og_promise == latex_obj.renderAsync(formula, 14, BLACK) + # Ensure queued renders. + promises = [ + latex_obj.renderAsync(formula, 14, BLUE), + latex_obj.renderAsync(formula, 10, BLACK), + latex_obj.renderAsync(formula, 10, BLUE), + ] + for prom in promises: + assert og_promise.calls_upon_fulfillment(prom.start) + # Ensure other renders get done in parallel. + other_promise = latex_obj.renderAsync(formula+" dt", 10, BLACK) + assert not og_promise.calls_upon_fulfillment(other_promise.start) + # Ensure all of them render. + proms = [og_promise, *promises, other_promise] + with qtbot.waitSignals( + [p.fulfilled for p in proms], + raising=True, timeout=10000, + check_params_cbs=[check_render_results]*len(proms) + ): + pass diff --git a/runtime-pyside6/tests/test_native.py b/runtime-pyside6/tests/test_native.py index 6fc2d65..3ca4834 100644 --- a/runtime-pyside6/tests/test_native.py +++ b/runtime-pyside6/tests/test_native.py @@ -17,7 +17,6 @@ """ import pytest -from os.path import exists from PySide6.QtCore import QEvent, QObject, QUrl from PySide6.QtGui import QActionEvent, QFileOpenEvent diff --git a/runtime-pyside6/tests/test_promise.py b/runtime-pyside6/tests/test_promise.py new file mode 100644 index 0000000..06c0b8a --- /dev/null +++ b/runtime-pyside6/tests/test_promise.py @@ -0,0 +1,115 @@ +""" + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +""" +from time import sleep + +import pytest +from PySide6.QtCore import QObject +from PySide6.QtQml import QJSValue + +from spy import Spy +from LogarithmPlotter.util.js import PyJSValue +from LogarithmPlotter.util.promise import PyPromise + + +def check_promise_result(value): + def got_result(args, kwargs, val=value): + valid = len(args) == 1 and len(kwargs) == 0 + if valid: + got_value = args[0].toVariant() if isinstance(args[0], QJSValue) else args[0] + valid = got_value == val + return valid + return got_result + +def create_async_func(value): + def async_function(val=value): + sleep(1) + return val + + return async_function + + +def qjs_eq(origin): + def compare(result): + res = result.toVariant() == origin + print("Unknown res!", res, repr(result.toVariant()), repr(origin)) + return res + return compare + + +def async_throw(): + sleep(1) + raise Exception("aaaa") + + +class TestPyPromise: + + def test_fulfill_values(self, qtbot): + qjsv = QJSValue(3) + values = [ + [True, qjs_eq(True)], + [3, qjs_eq(3)], + [2.2, qjs_eq(2.2)], + ["String", qjs_eq("String")], + [qjsv, qjs_eq(3)], + [None, qjs_eq(None)], + [PyJSValue(QJSValue("aaa")), qjs_eq("aaa")] + ] + for [value, test] in values: + promise = PyPromise(create_async_func(value)) + with qtbot.assertNotEmitted(promise.rejected, wait=1000): + print("Testing", value) + with qtbot.waitSignal(promise.fulfilled, check_params_cb=test, timeout=2000): + assert promise.state == "pending" + assert promise.state == "fulfilled" + + def test_reject(self, qtbot): + promise = PyPromise(async_throw) + with qtbot.assertNotEmitted(promise.fulfilled, wait=1000): + with qtbot.waitSignal(promise.rejected, timeout=10000, + check_params_cb=lambda t: t == "Exception('aaaa')"): + assert promise.state == "pending" + assert promise.state == "rejected" + + def test_fulfill(self, qtbot): + spy_fulfilled = Spy() + spy_rejected = Spy() + promise = PyPromise(create_async_func(3)) + then_res = promise.then(spy_fulfilled, spy_rejected) + # Check if the return value is the same promise (so we can chain then) + assert then_res == promise + # Check on our spy. + with qtbot.waitSignal(promise.fulfilled, timeout=10000): + pass + assert spy_fulfilled.was_called.once + assert spy_fulfilled.was_not_called.with_arguments(3) + assert spy_fulfilled.was_called.with_arguments_matching(check_promise_result(3)) + assert spy_rejected.was_not_called + + def test_rejected(self, qtbot): + spy_fulfilled = Spy() + spy_rejected = Spy() + promise = PyPromise(async_throw) + then_res = promise.then(spy_fulfilled, spy_rejected) + # Check if the return value is the same promise (so we can chain then) + assert then_res == promise + # Check on our spies. + with qtbot.waitSignal(promise.rejected, timeout=10000): + pass + assert spy_rejected.was_called.once + assert spy_rejected.was_called.with_arguments("Exception('aaaa')") + assert spy_fulfilled.was_not_called diff --git a/runtime-pyside6/tests/test_update.py b/runtime-pyside6/tests/test_update.py index 5e1a705..ff71e61 100644 --- a/runtime-pyside6/tests/test_update.py +++ b/runtime-pyside6/tests/test_update.py @@ -49,19 +49,20 @@ def test_update(qtbot): update_info_newer = UpdateInformation() update_info_newer.got_update_info.connect(check_newer) runnable = UpdateCheckerRunnable('1.0.0', update_info_newer) - runnable.run() - qtbot.waitSignal(update_info_newer.got_update_info, timeout=10000) + with qtbot.waitSignal(update_info_newer.got_update_info, timeout=10000): + runnable.run() runnable = UpdateCheckerRunnable('0.1.0', update_info_older) - runnable.run() - qtbot.waitSignal(update_info_older.got_update_info, timeout=10000) + with qtbot.waitSignal(update_info_older.got_update_info, timeout=10000): + runnable.run() runnable = UpdateCheckerRunnable('0.5.0+dev0+git20240101', update_info_older) - runnable.run() - qtbot.waitSignal(update_info_older.got_update_info, timeout=10000) + with qtbot.waitSignal(update_info_older.got_update_info, timeout=10000): + runnable.run() def test_update_checker(qtbot): update_info = check_for_updates('0.6.0', MockWindow()) assert QThreadPool.globalInstance().activeThreadCount() >= 1 - qtbot.waitSignal(update_info.got_update_info, timeout=10000) + with qtbot.waitSignal(update_info.got_update_info, timeout=10000): + pass argv.append("--no-check-for-updates") update_info = check_for_updates('0.6.0', MockWindow()) assert QThreadPool.globalInstance().activeThreadCount() < 2 # No new update checks where added diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh index 1410244..ac1fdc5 100644 --- a/scripts/run-tests.sh +++ b/scripts/run-tests.sh @@ -23,6 +23,7 @@ fi # Run python tests +rm -rf build/runtime-pyside6/tests cp -r runtime-pyside6/tests build/runtime-pyside6 cp -r ci CHANGELOG.md build/runtime-pyside6 cd build/runtime-pyside6 || exit 1 From 8fab9d8e529772a1dfcde801996d03002d3e829f Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Wed, 16 Oct 2024 22:18:53 +0200 Subject: [PATCH 054/104] Starting natural language plugin. --- runtime-pyside6/tests/__init__.py | 0 runtime-pyside6/tests/plugins/__init__.py | 0 .../tests/plugins/natural/__init__.py | 21 ++ .../plugins/natural/interfaces/__init__.py | 0 .../plugins/natural/interfaces/assertion.py | 30 +++ .../tests/plugins/natural/interfaces/base.py | 101 ++++++++ .../tests/plugins/natural/interfaces/basic.py | 61 +++++ .../tests/plugins/natural/interfaces/int.py | 229 ++++++++++++++++++ .../tests/plugins/natural/interfaces/utils.py | 27 +++ .../tests/{ => plugins/natural}/spy.py | 128 +++++----- runtime-pyside6/tests/plugins/natural/that.py | 57 +++++ runtime-pyside6/tests/test_promise.py | 20 +- 12 files changed, 593 insertions(+), 81 deletions(-) create mode 100644 runtime-pyside6/tests/__init__.py create mode 100644 runtime-pyside6/tests/plugins/__init__.py create mode 100644 runtime-pyside6/tests/plugins/natural/__init__.py create mode 100644 runtime-pyside6/tests/plugins/natural/interfaces/__init__.py create mode 100644 runtime-pyside6/tests/plugins/natural/interfaces/assertion.py create mode 100644 runtime-pyside6/tests/plugins/natural/interfaces/base.py create mode 100644 runtime-pyside6/tests/plugins/natural/interfaces/basic.py create mode 100644 runtime-pyside6/tests/plugins/natural/interfaces/int.py create mode 100644 runtime-pyside6/tests/plugins/natural/interfaces/utils.py rename runtime-pyside6/tests/{ => plugins/natural}/spy.py (69%) create mode 100644 runtime-pyside6/tests/plugins/natural/that.py diff --git a/runtime-pyside6/tests/__init__.py b/runtime-pyside6/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/runtime-pyside6/tests/plugins/__init__.py b/runtime-pyside6/tests/plugins/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/runtime-pyside6/tests/plugins/natural/__init__.py b/runtime-pyside6/tests/plugins/natural/__init__.py new file mode 100644 index 0000000..7a67869 --- /dev/null +++ b/runtime-pyside6/tests/plugins/natural/__init__.py @@ -0,0 +1,21 @@ +""" + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +""" + +from .spy import Spy +from .that import that + diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/__init__.py b/runtime-pyside6/tests/plugins/natural/interfaces/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/assertion.py b/runtime-pyside6/tests/plugins/natural/interfaces/assertion.py new file mode 100644 index 0000000..f2504a2 --- /dev/null +++ b/runtime-pyside6/tests/plugins/natural/interfaces/assertion.py @@ -0,0 +1,30 @@ +""" + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +""" + +class Assertion(Exception): + def __init__(self, assertion: bool, message: str): + self.assertion = assertion + self.message = message + + def __str__(self): + return self.message + + def __bool__(self): + if not self.assertion: + raise self + return self.assertion \ No newline at end of file diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/base.py b/runtime-pyside6/tests/plugins/natural/interfaces/base.py new file mode 100644 index 0000000..88b9e06 --- /dev/null +++ b/runtime-pyside6/tests/plugins/natural/interfaces/base.py @@ -0,0 +1,101 @@ +""" + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +""" +from typing import Self + +from tests.plugins.natural.interfaces.assertion import Assertion +from tests.plugins.natural.interfaces.utils import repr_ + + +class AssertionInterface: + """ + Most basic assertion interface. + You probably want to use BaseAssertionInterface + """ + def __init__(self, value): + self._value = value + + @property + def was(self) -> Self: + return self + + @property + def be(self) -> Self: + return self + + @property + def been(self) -> Self: + return self + + @property + def have(self) -> Self: + return self + + @property + def has(self) -> Self: + return self + + @property + def a(self) -> Self: + return self + + @property + def an(self) -> Self: + return self + + def is_a(self, type_) -> Assertion: + """ + Checks if the current value is equal to the provided value + """ + value_type_name = type(self._value).__name__ + return Assertion(isinstance(type_, type_), f"The value ({value_type_name} {repr_(self._value)}) is not a {type_.__name__}.") + + + +class EqualAssertionInterface(AssertionInterface): + """ + Interface created for when its value should be checked for equality + """ + def __init__(self, value): + super().__init__(value) + + def __call__(self, value) -> Assertion: + return Assertion(value == self._value, f"The value ({repr_(self._value)}) is not equal to {repr(value)}.") + + def to(self, value) -> Self: + return self(value) + + def of(self, value) -> Self: + return self(value) + + + +class BaseAssertionInterface(AssertionInterface): + + @property + def equals(self) -> EqualAssertionInterface: + """ + Checks if the current value is equal to the provided value + """ + return EqualAssertionInterface(self._value) + + @property + def is_equal(self) -> EqualAssertionInterface: + """ + Checks if the current value is equal to the provided value + """ + return self.equals \ No newline at end of file diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/basic.py b/runtime-pyside6/tests/plugins/natural/interfaces/basic.py new file mode 100644 index 0000000..1d5a878 --- /dev/null +++ b/runtime-pyside6/tests/plugins/natural/interfaces/basic.py @@ -0,0 +1,61 @@ +""" + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +""" +from tests.plugins.natural.interfaces.assertion import Assertion +from tests.plugins.natural.interfaces.base import BaseAssertionInterface +from tests.plugins.natural.interfaces.int import IntInterface +from tests.plugins.natural.interfaces.utils import repr_ + + +class FixedIteratorInterface(BaseAssertionInterface): + @property + def length(self) -> IntInterface: + return IntInterface(len(self._value)) + + def elements(self, *elements) -> Assertion: + tests = [elem for elem in elements if elem in self._value] + return Assertion( + len(tests) == 0, + f"This value ({repr_(self._value)}) does not have elements ({repr_(tests)})" + ) + + def element(self, element) -> Assertion: + return Assertion( + element in self._value, + f"This value ({repr_(self._value)}) does not have element ({repr_(element)})" + ) + + def contains(self, *elements) -> Assertion: + return self.elements(*elements) + +class BoolInterface(BaseAssertionInterface): + @property + def is_true(self): + return Assertion( + self._value == True, + f"The value ({repr_(self._value)}) is not True." + ) + + @property + def is_false(self): + return Assertion( + self._value == False, + f"The value ({repr_(self._value)}) is not False." + ) + +class StringInterface(LengthInterface): + pass \ No newline at end of file diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/int.py b/runtime-pyside6/tests/plugins/natural/interfaces/int.py new file mode 100644 index 0000000..aaf0511 --- /dev/null +++ b/runtime-pyside6/tests/plugins/natural/interfaces/int.py @@ -0,0 +1,229 @@ +""" + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +""" +from typing import Self + +from tests.plugins.natural.interfaces.assertion import Assertion +from tests.plugins.natural.interfaces.base import BaseAssertionInterface, EqualAssertionInterface, AssertionInterface +from tests.plugins.natural.interfaces.utils import repr_ + + +class IntComparisonAssertionInterface(AssertionInterface): + def __init__(self, value): + super().__init__(value) + self._compare_to = None + + def _compare(self) -> Assertion: + raise RuntimeError(f"No comparison method defined in {type(self).__name__}.") + + def __bool__(self) -> bool: + return bool(self._compare()) + + def __call__(self, compare_to: int) -> Self: + if self._compare_to is None: + self._compare_to = int(compare_to) + else: + self._compare_to *= int(compare_to) + return self + + @property + def time(self) -> Self: + return self + + @property + def times(self) -> Self: + return self + + @property + def never(self) -> Self: + return self(0) + + @property + def once(self) -> Self: + return self(1) + + @property + def twice(self) -> Self: + return self(2) + + @property + def thrice(self) -> Self: + return self(3) + + @property + def zero(self) -> Self: + return self(0) + + @property + def one(self) -> Self: + return self(1) + + @property + def two(self) -> Self: + return self(2) + + @property + def three(self) -> Self: + return self(3) + + @property + def four(self) -> Self: + return self(4) + + @property + def five(self) -> Self: + return self(5) + + @property + def six(self) -> Self: + return self(6) + + @property + def seven(self) -> Self: + return self(7) + + @property + def eight(self) -> Self: + return self(8) + + @property + def nine(self) -> Self: + return self(9) + + @property + def ten(self) -> Self: + return self(10) + + @property + def twenty(self) -> Self: + return self(20) + + @property + def thirty(self) -> Self: + return self(30) + + @property + def forty(self) -> Self: + return self(40) + + @property + def fifty(self) -> Self: + return self(50) + + @property + def sixty(self) -> Self: + return self(60) + + @property + def seventy(self) -> Self: + return self(70) + + @property + def eighty(self) -> Self: + return self(70) + + @property + def ninety(self) -> Self: + return self(70) + + @property + def hundred(self) -> Self: + return self(100) + + @property + def thousand(self) -> Self: + return self(1_000) + + @property + def million(self) -> Self: + return self(1_000_000) + + @property + def billion(self) -> Self: + return self(1_000_000_000) + + +class LessThanComparisonInterface(IntComparisonAssertionInterface): + def _compare(self) -> Assertion: + return Assertion( + self._value < self._compare_to, + f"The value ({repr_(self._value)}) is not less than to {repr_(self._compare_to)}." + ) + +class MoreThanComparisonInterface(IntComparisonAssertionInterface): + def _compare(self) -> Assertion: + return Assertion( + self._value > self._compare_to, + f"The value ({repr_(self._value)}) is not more than to {repr_(self._compare_to)}." + ) + +class AtLeastComparisonInterface(IntComparisonAssertionInterface): + def _compare(self) -> Assertion: + return Assertion( + self._value >= self._compare_to, + f"The value ({repr_(self._value)}) is not at least to {repr_(self._compare_to)}." + ) + +class AtMostComparisonInterface(IntComparisonAssertionInterface): + def _compare(self) -> Assertion: + return Assertion( + self._value <= self._compare_to, + f"The value ({repr_(self._value)}) is not at least to {repr_(self._compare_to)}." + ) + +class EqualComparisonInterface(IntComparisonAssertionInterface): + def _compare(self) -> Assertion: + return Assertion( + self._value == self._compare_to, + f"The value ({repr_(self._value)}) is not equal to {repr_(self._compare_to)}." + ) + + def to(self) -> Self: + return self + + def of(self) -> Self: + return self + + +class IntInterface(AssertionInterface): + def less_than(self) -> LessThanComparisonInterface: + return LessThanComparisonInterface(self._value) + + @property + def more_than(self) -> MoreThanComparisonInterface: + return MoreThanComparisonInterface(self._value) + + @property + def at_least(self) -> AtLeastComparisonInterface: + return AtLeastComparisonInterface(self._value) + + @property + def at_most(self) -> AtMostComparisonInterface: + return AtMostComparisonInterface(self._value) + + @property + def equals(self) -> EqualComparisonInterface: + return EqualComparisonInterface(self._value) + + @property + def is_equal(self) -> EqualComparisonInterface: + return EqualComparisonInterface(self._value) + + @property + def exactly(self) -> EqualComparisonInterface: + return EqualComparisonInterface(self._value) + diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/utils.py b/runtime-pyside6/tests/plugins/natural/interfaces/utils.py new file mode 100644 index 0000000..50e3777 --- /dev/null +++ b/runtime-pyside6/tests/plugins/natural/interfaces/utils.py @@ -0,0 +1,27 @@ +""" + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +""" + +from PySide6.QtQml import QJSValue + + +def repr_(data): + if isinstance(data, QJSValue): + variant = data.toVariant() + return f"QJSValue<{type(variant).__name__}>({repr(variant)})" + else: + return repr(data) \ No newline at end of file diff --git a/runtime-pyside6/tests/spy.py b/runtime-pyside6/tests/plugins/natural/spy.py similarity index 69% rename from runtime-pyside6/tests/spy.py rename to runtime-pyside6/tests/plugins/natural/spy.py index 01f9aa0..1d77629 100644 --- a/runtime-pyside6/tests/spy.py +++ b/runtime-pyside6/tests/plugins/natural/spy.py @@ -17,35 +17,29 @@ """ from typing import Callable, Self -from PySide6.QtQml import QJSValue +from tests.plugins.natural.interfaces.base import Assertion, repr_, AssertionInterface +from tests.plugins.natural.interfaces.int import IntComparisonAssertionInterface PRINT_PREFIX = (" " * 24) -class SpyAssertionFailed(Exception): - def __init__(self, message, calls): - self.message = message + "\n" + +class SpyAssertion(Assertion): + def __init__(self, assertion: bool, message: str, calls: list): + super().__init__(assertion, message + "\n") if len(calls) > 0: self.message += self.render_calls(calls) else: self.message += f"{PRINT_PREFIX}0 registered calls." - def repr(self, data): - if isinstance(data, QJSValue): - variant = data.toVariant() - return f"QJSValue<{type(variant).__name__}>({repr(variant)})" - else: - return repr(data) def render_calls(self, calls): lines = [f"{PRINT_PREFIX}{len(calls)} registered call(s):"] for call in calls: - repr_args = [self.repr(arg) for arg in call[0]] - repr_kwargs =[f"{key}={self.repr(arg)}" for key, arg in call[1].items()] + repr_args = [repr_(arg) for arg in call[0]] + repr_kwargs = [f"{key}={repr_(arg)}" for key, arg in call[1].items()] lines.append(f" - {', '.join([*repr_args, *repr_kwargs])}") return ("\n" + PRINT_PREFIX).join(lines) - def __str__(self): - return self.message class Methods: AT_LEAST_ONCE = "AT_LEAST_ONCE" @@ -55,18 +49,19 @@ class Methods: MORE_THAN = "AT_LEAST" LESS_THAN = "AT_MOST" -class CalledInterface: + +class CalledInterface(IntComparisonAssertionInterface): """ Internal class generated by Spy.was_called. """ def __init__(self, calls: list[tuple[list, dict]]): + super().__init__(len(calls)) self.__calls = calls self.__method = Methods.AT_LEAST_ONCE - self.__times = None def __apply_method(self, calls): - required = self.__times + required = self._compare_to calls_count = len(calls) match self.__method: case Methods.AT_LEAST_ONCE: @@ -91,61 +86,59 @@ class CalledInterface: raise RuntimeError(f"Unknown method {self.__method}.") return compare, error - def __bool__(self): + def __bool__(self) -> bool: """ Converts to boolean on assertion. """ compare, error = self.__apply_method(self.__calls) - if not compare: - raise SpyAssertionFailed(error+".") - return compare - + return bool(SpyAssertion(compare, error + ".", self.__calls)) """ Chaining methods """ + def __call__(self, *args, **kwargs) -> Self: if len(args) != 1: raise RuntimeError("Cannot call called interface with more than one argument.") - self.__times = int(args[0]) + self._compare_to = int(args[0]) if self.__method == Methods.AT_LEAST_ONCE: self.__method = Methods.EXACTLY return self - @property - def never(self) -> Self: - return self(0) - - @property - def once(self) -> Self: - return self(1) - - @property - def twice(self) -> Self: - return self(2) - - @property - def thrice(self) -> Self: - return self(3) - @property def at_least(self) -> Self: - self.__method = Methods.AT_LEAST + if self.__method == Methods.AT_LEAST_ONCE: + self.__method = Methods.AT_LEAST + else: + raise RuntimeError(f"Cannot redefine method from {self.__method} to {Methods.AT_MOST}") return self @property def at_most(self) -> Self: - self.__method = Methods.AT_MOST + if self.__method == Methods.AT_LEAST_ONCE: + self.__method = Methods.AT_MOST + else: + raise RuntimeError(f"Cannot redefine method from {self.__method} to {Methods.AT_MOST}") return self @property def more_than(self) -> Self: - self.__method = Methods.MORE_THAN + if self.__method == Methods.AT_LEAST_ONCE: + self.__method = Methods.MORE_THAN + else: + raise RuntimeError(f"Cannot redefine method from {self.__method} to {Methods.MORE_THAN}") return self @property def less_than(self) -> Self: - self.__method = Methods.LESS_THAN + if self.__method == Methods.AT_LEAST_ONCE: + self.__method = Methods.LESS_THAN + else: + raise RuntimeError(f"Cannot redefine method from {self.__method} to {Methods.LESS_THAN}") + return self + + @property + def time(self) -> Self: return self @property @@ -155,6 +148,7 @@ class CalledInterface: """ Class properties. """ + def __match_calls_for_condition(self, condition: Callable[[list, dict], bool]) -> tuple[bool, str]: calls = [] for call in self.__calls: @@ -163,12 +157,12 @@ class CalledInterface: compare, error = self.__apply_method(calls) return compare, error - - def with_arguments(self, *args, **kwargs): + def with_arguments(self, *args, **kwargs) -> SpyAssertion: """ Checks if the Spy has been called the given number of times with at least the given arguments. """ + def some_args_matched(a, kw): args_matched = all(( arg in a @@ -179,55 +173,49 @@ class CalledInterface: for key, arg in kwargs.items() )) return args_matched and kwargs_matched + compare, error = self.__match_calls_for_condition(some_args_matched) - if not compare: - repr_args = ', '.join([repr(arg) for arg in args]) - repr_kwargs = ', '.join([f"{key}={repr(arg)}" for key, arg in kwargs.items()]) - raise SpyAssertionFailed(f"{error} with arguments ({repr_args}) and keyword arguments ({repr_kwargs}).", self.__calls) - return compare + repr_args = ', '.join([repr(arg) for arg in args]) + repr_kwargs = ', '.join([f"{key}={repr(arg)}" for key, arg in kwargs.items()]) + msg = f"{error} with arguments ({repr_args}) and keyword arguments ({repr_kwargs})." + return SpyAssertion(compare, msg, self.__calls) - - def with_arguments_matching(self, test_condition: Callable[[list, dict], bool]): + def with_arguments_matching(self, test_condition: Callable[[list, dict], bool]) -> SpyAssertion: """ Checks if the Spy has been called the given number of times with arguments matching the given conditions. """ compare, error = self.__match_calls_for_condition(test_condition) - if not compare: - raise SpyAssertionFailed(f"{error} with arguments matching given conditions.", self.__calls) - return compare + msg = f"{error} with arguments matching given conditions." + return SpyAssertion(compare, msg, self.__calls) - - def with_exact_arguments(self, *args, **kwargs): + def with_exact_arguments(self, *args, **kwargs) -> SpyAssertion: """ Checks if the Spy has been called the given number of times with all the given arguments. """ compare, error = self.__match_calls_for_condition(lambda a, kw: a == args and kw == kwargs) - if not compare: - repr_args = ', '.join([repr(arg) for arg in args]) - repr_kwargs = ', '.join([f"{key}={repr(arg)}" for key, arg in kwargs.items()]) - raise SpyAssertionFailed(f"{error} with exact arguments ({repr_args}) and keyword arguments ({repr_kwargs}).", self.__calls) - return compare + repr_args = ', '.join([repr(arg) for arg in args]) + repr_kwargs = ', '.join([f"{key}={repr(arg)}" for key, arg in kwargs.items()]) + msg = f"{error} with exact arguments ({repr_args}) and keyword arguments ({repr_kwargs})." + return SpyAssertion(compare, msg, self.__calls) - def with_no_argument(self): + def with_no_argument(self) -> SpyAssertion: """ Checks if the Spy has been called the given number of times with all the given arguments. """ compare, error = self.__match_calls_for_condition(lambda a, kw: len(a) == 0 and len(kw) == 0) - if not compare: - raise SpyAssertionFailed(f"{error} with no arguments.", self.__calls) - return compare + return SpyAssertion(compare, f"{error} with no arguments.", self.__calls) - -class Spy: +class Spy(AssertionInterface): """ Class to spy into method calls with natural language expressions. """ def __init__(self, function: Callable = None): + super().__init__(function) self.function = function self.calls = [] @@ -237,7 +225,7 @@ class Spy: self.function(*args, **kwargs) @property - def was_called(self) -> CalledInterface: + def called(self) -> CalledInterface: """ Returns a boolean-able interface to check conditions for a given number of time the spy was called. @@ -245,7 +233,7 @@ class Spy: return CalledInterface(self.calls) @property - def was_not_called(self) -> CalledInterface: + def not_called(self) -> CalledInterface: """ Returns a boolean-able interface to check that conditions were never fulfilled in the times the spy was called. diff --git a/runtime-pyside6/tests/plugins/natural/that.py b/runtime-pyside6/tests/plugins/natural/that.py new file mode 100644 index 0000000..38ee54e --- /dev/null +++ b/runtime-pyside6/tests/plugins/natural/that.py @@ -0,0 +1,57 @@ +""" + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +""" +from typing import overload, Generic, TypeVar + +from .spy import Spy +from .interfaces.base import AssertionInterface, BaseAssertionInterface +from .interfaces.basic import StringInterface, BoolInterface +from .interfaces.int import IntInterface + +Interface = TypeVar("Interface", bound=AssertionInterface) + +MATCHES = [ + (str, StringInterface), + (int, IntInterface), + (bool, BoolInterface), +] + + +@overload +def that(value: str) -> StringInterface: ... + + +@overload +def that(value: int) -> IntInterface: ... + + +@overload +def that(value: bool) -> BoolInterface: ... + + +@overload +def that[Interface](value: Interface) -> Interface: ... + + +def that(value: any) -> AssertionInterface: + if not isinstance(value, AssertionInterface): + interface = next((i for t, i in MATCHES if isinstance(value, t)), None) + if interface is not None: + value = interface(value) + else: + value = BaseAssertionInterface(value) + return value diff --git a/runtime-pyside6/tests/test_promise.py b/runtime-pyside6/tests/test_promise.py index 06c0b8a..a97f864 100644 --- a/runtime-pyside6/tests/test_promise.py +++ b/runtime-pyside6/tests/test_promise.py @@ -17,11 +17,9 @@ """ from time import sleep -import pytest -from PySide6.QtCore import QObject from PySide6.QtQml import QJSValue -from spy import Spy +from tests.plugins.natural import that, Spy from LogarithmPlotter.util.js import PyJSValue from LogarithmPlotter.util.promise import PyPromise @@ -95,10 +93,10 @@ class TestPyPromise: # Check on our spy. with qtbot.waitSignal(promise.fulfilled, timeout=10000): pass - assert spy_fulfilled.was_called.once - assert spy_fulfilled.was_not_called.with_arguments(3) - assert spy_fulfilled.was_called.with_arguments_matching(check_promise_result(3)) - assert spy_rejected.was_not_called + assert that(spy_fulfilled).was.called.once + assert that(spy_fulfilled).was.not_called.with_arguments(3) + assert that(spy_fulfilled).was.called.with_arguments_matching(check_promise_result(3)) + assert spy_rejected.was.not_called def test_rejected(self, qtbot): spy_fulfilled = Spy() @@ -106,10 +104,10 @@ class TestPyPromise: promise = PyPromise(async_throw) then_res = promise.then(spy_fulfilled, spy_rejected) # Check if the return value is the same promise (so we can chain then) - assert then_res == promise + assert that(then_res).is_equal.to(promise) # Check on our spies. with qtbot.waitSignal(promise.rejected, timeout=10000): pass - assert spy_rejected.was_called.once - assert spy_rejected.was_called.with_arguments("Exception('aaaa')") - assert spy_fulfilled.was_not_called + assert that(spy_rejected).was.called.once + assert that(spy_rejected).was.called.with_arguments("Exception('aaaa')") + assert that(spy_fulfilled).was.not_called From ef465b34e7f9cf9d78d4dd9aa25a14af5b7050a5 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 17 Oct 2024 02:08:24 +0200 Subject: [PATCH 055/104] Finishing natural language plugin. --- .../tests/plugins/natural/__init__.py | 1 + .../plugins/natural/interfaces/assertion.py | 15 +- .../tests/plugins/natural/interfaces/base.py | 122 +++++++--- .../tests/plugins/natural/interfaces/basic.py | 54 +++-- .../tests/plugins/natural/interfaces/int.py | 208 ++++++++++++----- .../tests/plugins/natural/interfaces/spy.py | 218 ++++++++++++++++++ runtime-pyside6/tests/plugins/natural/spy.py | 213 +---------------- runtime-pyside6/tests/plugins/natural/that.py | 23 +- .../tests/plugins/tests/__init__.py | 0 .../tests/plugins/tests/test_natural.py | 217 +++++++++++++++++ 10 files changed, 751 insertions(+), 320 deletions(-) create mode 100644 runtime-pyside6/tests/plugins/natural/interfaces/spy.py create mode 100644 runtime-pyside6/tests/plugins/tests/__init__.py create mode 100644 runtime-pyside6/tests/plugins/tests/test_natural.py diff --git a/runtime-pyside6/tests/plugins/natural/__init__.py b/runtime-pyside6/tests/plugins/natural/__init__.py index 7a67869..4cfe179 100644 --- a/runtime-pyside6/tests/plugins/natural/__init__.py +++ b/runtime-pyside6/tests/plugins/natural/__init__.py @@ -18,4 +18,5 @@ from .spy import Spy from .that import that +from .interfaces.base import Assertion diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/assertion.py b/runtime-pyside6/tests/plugins/natural/interfaces/assertion.py index f2504a2..e1e43c4 100644 --- a/runtime-pyside6/tests/plugins/natural/interfaces/assertion.py +++ b/runtime-pyside6/tests/plugins/natural/interfaces/assertion.py @@ -17,14 +17,23 @@ """ class Assertion(Exception): - def __init__(self, assertion: bool, message: str): + def __init__(self, assertion: bool, message: str, invert: bool): self.assertion = assertion self.message = message + self.invert = invert + + def _invert_message(self): + for verb in ('is', 'was', 'has', 'have'): + for negative in ("n't", ' not', ' never', ' no'): + self.message = self.message.replace(f"{verb}{negative}", verb.upper()) def __str__(self): return self.message def __bool__(self): - if not self.assertion: + if not self.invert and not self.assertion: raise self - return self.assertion \ No newline at end of file + if self.invert and self.assertion: + self._invert_message() + raise self + return True # Raises otherwise. \ No newline at end of file diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/base.py b/runtime-pyside6/tests/plugins/natural/interfaces/base.py index 88b9e06..0786285 100644 --- a/runtime-pyside6/tests/plugins/natural/interfaces/base.py +++ b/runtime-pyside6/tests/plugins/natural/interfaces/base.py @@ -15,10 +15,10 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . """ -from typing import Self +from typing import Self, Callable, Any -from tests.plugins.natural.interfaces.assertion import Assertion -from tests.plugins.natural.interfaces.utils import repr_ +from .assertion import Assertion +from .utils import repr_ class AssertionInterface: @@ -26,15 +26,91 @@ class AssertionInterface: Most basic assertion interface. You probably want to use BaseAssertionInterface """ - def __init__(self, value): + + def __init__(self, value, parent: Self = None): self._value = value + self._parent = parent + if parent is None: + self.__not = False @property - def was(self) -> Self: + def _not(self) -> bool: + """ + Internal state of whether the expression was negated. + Use "not_" to set it. + :return: + """ + return self.__not if self._parent is None else self._parent._not + + @_not.setter + def _not(self, value: bool): + if self._not is True: + raise RuntimeError("Cannot call is_not or was_not twice in the same statement.") + if self._parent is None: + self.__not = True + else: + self._parent._not = True + + def instance_of(self, type_: type) -> Assertion: + """ + Checks if the current value is equal to the provided value + """ + value_type_name = type(self._value).__name__ + if not isinstance(type_, type): + raise RuntimeError("Provided 'type' provided is not a class.") + return Assertion( + isinstance(self._value, type_), + f"The value ({value_type_name} {repr_(self._value)}) is not a {type_.__name__}.", + self._not + ) + + def __call__(self, condition: Callable[[Any], bool]) -> Assertion: + """ + Apply condition to value that returns whether or not the value is valid. + """ + return Assertion( + condition(self._value), + f"The value ({repr_(self._value)}) did not match given conditions.", + self._not + ) + + """ + NOT Properties. + """ + + @property + def NOT(self) -> Self: + self._not = True return self @property - def be(self) -> Self: + def not_(self) -> Self: + self._not = True + return self + + @property + def never(self) -> Self: + self._not = True + return self + + """ + Chain self properties to sound natural + """ + + @property + def that(self) -> Self: + return self + + @property + def is_(self) -> Self: + return self + + @property + def does(self) -> Self: + return self + + @property + def was(self) -> Self: return self @property @@ -57,31 +133,25 @@ class AssertionInterface: def an(self) -> Self: return self - def is_a(self, type_) -> Assertion: - """ - Checks if the current value is equal to the provided value - """ - value_type_name = type(self._value).__name__ - return Assertion(isinstance(type_, type_), f"The value ({value_type_name} {repr_(self._value)}) is not a {type_.__name__}.") - - class EqualAssertionInterface(AssertionInterface): """ Interface created for when its value should be checked for equality """ - def __init__(self, value): - super().__init__(value) + + def __init__(self, value, parent: AssertionInterface = None): + super().__init__(value, parent) def __call__(self, value) -> Assertion: - return Assertion(value == self._value, f"The value ({repr_(self._value)}) is not equal to {repr(value)}.") - - def to(self, value) -> Self: - return self(value) - - def of(self, value) -> Self: - return self(value) + return Assertion( + value == self._value, + f"The value {repr_(self._value)} is different from {repr(value)}.", + self._not + ) + @property + def to(self) -> Self: + return self class BaseAssertionInterface(AssertionInterface): @@ -91,11 +161,11 @@ class BaseAssertionInterface(AssertionInterface): """ Checks if the current value is equal to the provided value """ - return EqualAssertionInterface(self._value) + return EqualAssertionInterface(self._value, self) @property - def is_equal(self) -> EqualAssertionInterface: + def equal(self) -> EqualAssertionInterface: """ Checks if the current value is equal to the provided value """ - return self.equals \ No newline at end of file + return self.equals diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/basic.py b/runtime-pyside6/tests/plugins/natural/interfaces/basic.py index 1d5a878..25d45cb 100644 --- a/runtime-pyside6/tests/plugins/natural/interfaces/basic.py +++ b/runtime-pyside6/tests/plugins/natural/interfaces/basic.py @@ -15,47 +15,69 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . """ -from tests.plugins.natural.interfaces.assertion import Assertion -from tests.plugins.natural.interfaces.base import BaseAssertionInterface -from tests.plugins.natural.interfaces.int import IntInterface -from tests.plugins.natural.interfaces.utils import repr_ +from .assertion import Assertion +from .base import BaseAssertionInterface +from .int import NumberInterface +from .utils import repr_ class FixedIteratorInterface(BaseAssertionInterface): @property - def length(self) -> IntInterface: - return IntInterface(len(self._value)) + def length(self) -> NumberInterface: + return NumberInterface(len(self._value), self) def elements(self, *elements) -> Assertion: - tests = [elem for elem in elements if elem in self._value] + tests = [repr_(elem) for elem in elements if elem not in self._value] return Assertion( len(tests) == 0, - f"This value ({repr_(self._value)}) does not have elements ({repr_(tests)})" + f"This value ({repr_(self._value)}) does not have elements {', '.join(tests)}.", + self._not ) def element(self, element) -> Assertion: return Assertion( element in self._value, - f"This value ({repr_(self._value)}) does not have element ({repr_(element)})" + f"This value ({repr_(self._value)}) does not have element {repr_(element)}.", + self._not ) def contains(self, *elements) -> Assertion: - return self.elements(*elements) + """ + Check if the element(s) are contained in the iterator. + """ + if len(elements) == 1: + return self.element(elements[0]) + else: + return self.elements(*elements) + + def contain(self, *elements): + """ + Check if the element(s) are contained in the iterator. + """ + return self.contains(*elements) + class BoolInterface(BaseAssertionInterface): @property - def is_true(self): + def true(self): return Assertion( self._value == True, - f"The value ({repr_(self._value)}) is not True." + f"The value ({repr_(self._value)}) is not True.", + self._not ) @property - def is_false(self): + def false(self): return Assertion( self._value == False, - f"The value ({repr_(self._value)}) is not False." + f"The value ({repr_(self._value)}) is not False.", + self._not ) -class StringInterface(LengthInterface): - pass \ No newline at end of file + +class StringInterface(FixedIteratorInterface): + pass + + +class ListInterface(FixedIteratorInterface): + pass diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/int.py b/runtime-pyside6/tests/plugins/natural/interfaces/int.py index aaf0511..7ac8871 100644 --- a/runtime-pyside6/tests/plugins/natural/interfaces/int.py +++ b/runtime-pyside6/tests/plugins/natural/interfaces/int.py @@ -15,17 +15,47 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . """ +from idlelib.configdialog import is_int +from math import log10, floor, ceil from typing import Self -from tests.plugins.natural.interfaces.assertion import Assertion -from tests.plugins.natural.interfaces.base import BaseAssertionInterface, EqualAssertionInterface, AssertionInterface -from tests.plugins.natural.interfaces.utils import repr_ +from .assertion import Assertion +from .base import AssertionInterface +from .utils import repr_ -class IntComparisonAssertionInterface(AssertionInterface): - def __init__(self, value): - super().__init__(value) - self._compare_to = None +class NumberComparisonAssertionInterface(AssertionInterface): + def __init__(self, value, parent: AssertionInterface = None): + super().__init__(value, parent) + self._compare_stack = [] + + def _generate_compare_to(self) -> int: + """ + The number generated by the comparison stack. + E.g. can parse one.hundred.million.and.thirty.three.thousand.and.twelve.hundred.and.seven + as ['one', 'hundred', 'million', 'thirty', 'three', 'thousand', 'twelve', 'hundred', 'seven'] + which results 100,034,207 + """ + minus = len(self._compare_stack) > 0 and self._compare_stack[0] == -1 + if len(self._compare_stack) < (2 if minus else 1): + raise RuntimeError("No number to compare the value to provided.") + if minus: + self._compare_stack.pop(0) + # Compute the number + add_stack = [self._compare_stack.pop(0)] + for element in self._compare_stack: + last_power = floor(log10(abs(add_stack[-1]))) + current_power = floor(log10(abs(element))) + if last_power < current_power: # E.g. one hundred + add_stack[-1] *= element + elif last_power == 1 and current_power == 0: # E.g thirty four + add_stack[-1] += element + elif last_power > current_power: # E.g a hundred and five + add_stack.append(element) + else: + raise RuntimeError(f"Cannot chain two numbers with the same power ({add_stack[-1]} => {element}.") + total = sum(add_stack) + return -total if minus else total def _compare(self) -> Assertion: raise RuntimeError(f"No comparison method defined in {type(self).__name__}.") @@ -34,23 +64,26 @@ class IntComparisonAssertionInterface(AssertionInterface): return bool(self._compare()) def __call__(self, compare_to: int) -> Self: - if self._compare_to is None: - self._compare_to = int(compare_to) - else: - self._compare_to *= int(compare_to) + if type(compare_to) not in (float, int): + raise RuntimeError(f"Cannot compare number ({self._value}) to non number ({repr_(compare_to)}).") + self._compare_stack.append(compare_to) + return self + + """ + Chain self properties + """ + + @property + def and_(self) -> Self: return self @property - def time(self) -> Self: + def AND(self) -> Self: return self - @property - def times(self) -> Self: - return self - - @property - def never(self) -> Self: - return self(0) + """ + Number shorthands + """ @property def once(self) -> Self: @@ -64,6 +97,10 @@ class IntComparisonAssertionInterface(AssertionInterface): def thrice(self) -> Self: return self(3) + @property + def minus(self) -> Self: + return self(-1) + @property def zero(self) -> Self: return self(0) @@ -108,6 +145,42 @@ class IntComparisonAssertionInterface(AssertionInterface): def ten(self) -> Self: return self(10) + @property + def eleven(self) -> Self: + return self(11) + + @property + def twelve(self) -> Self: + return self(12) + + @property + def thirteen(self) -> Self: + return self(13) + + @property + def fourteen(self) -> Self: + return self(14) + + @property + def fifteen(self) -> Self: + return self(15) + + @property + def sixteen(self) -> Self: + return self(16) + + @property + def seventeen(self) -> Self: + return self(17) + + @property + def eighteen(self) -> Self: + return self(18) + + @property + def nineteen(self) -> Self: + return self(19) + @property def twenty(self) -> Self: return self(20) @@ -134,11 +207,11 @@ class IntComparisonAssertionInterface(AssertionInterface): @property def eighty(self) -> Self: - return self(70) + return self(80) @property def ninety(self) -> Self: - return self(70) + return self(90) @property def hundred(self) -> Self: @@ -157,73 +230,92 @@ class IntComparisonAssertionInterface(AssertionInterface): return self(1_000_000_000) -class LessThanComparisonInterface(IntComparisonAssertionInterface): +class LessThanComparisonInterface(NumberComparisonAssertionInterface): def _compare(self) -> Assertion: + compare = self._generate_compare_to() return Assertion( - self._value < self._compare_to, - f"The value ({repr_(self._value)}) is not less than to {repr_(self._compare_to)}." + self._value < compare, + f"The value ({repr_(self._value)}) is not less than to {repr_(compare)}.", + self._not ) -class MoreThanComparisonInterface(IntComparisonAssertionInterface): + +class MoreThanComparisonInterface(NumberComparisonAssertionInterface): def _compare(self) -> Assertion: + compare = self._generate_compare_to() return Assertion( - self._value > self._compare_to, - f"The value ({repr_(self._value)}) is not more than to {repr_(self._compare_to)}." + self._value > compare, + f"The value ({repr_(self._value)}) is not more than to {repr_(compare)}.", + self._not ) -class AtLeastComparisonInterface(IntComparisonAssertionInterface): + +class AtLeastComparisonInterface(NumberComparisonAssertionInterface): def _compare(self) -> Assertion: + compare = self._generate_compare_to() return Assertion( - self._value >= self._compare_to, - f"The value ({repr_(self._value)}) is not at least to {repr_(self._compare_to)}." + self._value >= compare, + f"The value ({repr_(self._value)}) is not at least to {repr_(compare)}.", + self._not ) -class AtMostComparisonInterface(IntComparisonAssertionInterface): + +class AtMostComparisonInterface(NumberComparisonAssertionInterface): def _compare(self) -> Assertion: + compare = self._generate_compare_to() return Assertion( - self._value <= self._compare_to, - f"The value ({repr_(self._value)}) is not at least to {repr_(self._compare_to)}." + self._value <= compare, + f"The value ({repr_(self._value)}) is not at least to {repr_(compare)}.", + self._not ) -class EqualComparisonInterface(IntComparisonAssertionInterface): + +class EqualComparisonInterface(NumberComparisonAssertionInterface): def _compare(self) -> Assertion: + compare = self._generate_compare_to() return Assertion( - self._value == self._compare_to, - f"The value ({repr_(self._value)}) is not equal to {repr_(self._compare_to)}." + self._value == compare, + f"The value ({repr_(self._value)}) is not equal to {repr_(compare)}.", + self._not ) + @property def to(self) -> Self: return self - def of(self) -> Self: - return self - -class IntInterface(AssertionInterface): - def less_than(self) -> LessThanComparisonInterface: - return LessThanComparisonInterface(self._value) - - @property - def more_than(self) -> MoreThanComparisonInterface: - return MoreThanComparisonInterface(self._value) - - @property - def at_least(self) -> AtLeastComparisonInterface: - return AtLeastComparisonInterface(self._value) - - @property - def at_most(self) -> AtMostComparisonInterface: - return AtMostComparisonInterface(self._value) +class NumberInterface(AssertionInterface): + def __call__(self, value): + return EqualComparisonInterface(self._value, self)(value) @property def equals(self) -> EqualComparisonInterface: - return EqualComparisonInterface(self._value) + return EqualComparisonInterface(self._value, self) @property - def is_equal(self) -> EqualComparisonInterface: - return EqualComparisonInterface(self._value) + def equal(self) -> EqualComparisonInterface: + return EqualComparisonInterface(self._value, self) @property def exactly(self) -> EqualComparisonInterface: - return EqualComparisonInterface(self._value) + return EqualComparisonInterface(self._value, self) + @property + def of(self) -> EqualComparisonInterface: + return EqualComparisonInterface(self._value, self) + + @property + def less_than(self) -> LessThanComparisonInterface: + return LessThanComparisonInterface(self._value, self) + + @property + def more_than(self) -> MoreThanComparisonInterface: + return MoreThanComparisonInterface(self._value, self) + + @property + def at_least(self) -> AtLeastComparisonInterface: + return AtLeastComparisonInterface(self._value, self) + + @property + def at_most(self) -> AtMostComparisonInterface: + return AtMostComparisonInterface(self._value, self) diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/spy.py b/runtime-pyside6/tests/plugins/natural/interfaces/spy.py new file mode 100644 index 0000000..59b09d3 --- /dev/null +++ b/runtime-pyside6/tests/plugins/natural/interfaces/spy.py @@ -0,0 +1,218 @@ +""" + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +""" + +from typing import Callable, Self + +from .base import Assertion, repr_, AssertionInterface +from .int import NumberComparisonAssertionInterface + +PRINT_PREFIX = (" " * 24) + + +class SpyAssertion(Assertion): + def __init__(self, assertion: bool, message: str, calls: list, invert: bool): + super().__init__(assertion, message + "\n", invert) + if len(calls) > 0: + self.message += self.render_calls(calls) + else: + self.message += f"{PRINT_PREFIX}0 registered calls." + + def render_calls(self, calls): + lines = [f"{PRINT_PREFIX}{len(calls)} registered call(s):"] + for call in calls: + repr_args = [repr_(arg) for arg in call[0]] + repr_kwargs = [f"{key}={repr_(arg)}" for key, arg in call[1].items()] + lines.append(f" - {', '.join([*repr_args, *repr_kwargs])}") + return ("\n" + PRINT_PREFIX).join(lines) + + +class Methods: + AT_LEAST_ONCE = "AT_LEAST_ONCE" + EXACTLY = "EXACTLY" + AT_LEAST = "AT_LEAST" + AT_MOST = "AT_MOST" + MORE_THAN = "MORE_THAN" + LESS_THAN = "LESS_THAN" + + +class CalledInterface(NumberComparisonAssertionInterface): + """ + Internal class generated by Spy.called. + """ + + def __init__(self, calls: list[tuple[list, dict]], parent: AssertionInterface): + super().__init__(len(calls), parent) + self.__calls = calls + self.__method = Methods.AT_LEAST_ONCE + + def __apply_method(self, calls): + required = None if self._compare_stack == [] else self._generate_compare_to() + calls_count = len(calls) + match self.__method: + case Methods.AT_LEAST_ONCE: + compare = len(calls) >= 1 + error = f"Method was not called" + case Methods.EXACTLY: + compare = len(calls) == required + error = f"Method was not called {required} times ({required} != {calls_count})" + case Methods.AT_LEAST: + compare = len(calls) >= required + error = f"Method was not called at least {required} times ({required} >= {calls_count})" + case Methods.AT_MOST: + compare = len(calls) <= required + error = f"Method was not called at most {required} times ({required} <= {calls_count})" + case Methods.MORE_THAN: + compare = len(calls) > required + error = f"Method was not called more than {required} times ({required} > {calls_count})" + case Methods.LESS_THAN: + compare = len(calls) < required + error = f"Method was not called less than {required} times ({required} < {calls_count})" + case _: + raise RuntimeError(f"Unknown method {self.__method}.") + return compare, error + + def __bool__(self) -> bool: + """ + Converts to boolean on assertion. + """ + compare, error = self.__apply_method(self.__calls) + return bool(SpyAssertion(compare, error + ".", self.__calls, self._not)) + + """ + Chaining methods + """ + + def __call__(self, compare_to: int) -> Self: + super().__call__(compare_to) + if self.__method == Methods.AT_LEAST_ONCE: + self.__method = Methods.EXACTLY + return self + + @property + def at_least(self) -> Self: + if self.__method == Methods.AT_LEAST_ONCE: + self.__method = Methods.AT_LEAST + else: + raise RuntimeError(f"Cannot redefine method from {self.__method} to {Methods.AT_MOST}") + return self + + @property + def at_most(self) -> Self: + if self.__method == Methods.AT_LEAST_ONCE: + self.__method = Methods.AT_MOST + else: + raise RuntimeError(f"Cannot redefine method from {self.__method} to {Methods.AT_MOST}") + return self + + @property + def more_than(self) -> Self: + if self.__method == Methods.AT_LEAST_ONCE: + self.__method = Methods.MORE_THAN + else: + raise RuntimeError(f"Cannot redefine method from {self.__method} to {Methods.MORE_THAN}") + return self + + @property + def less_than(self) -> Self: + if self.__method == Methods.AT_LEAST_ONCE: + self.__method = Methods.LESS_THAN + else: + raise RuntimeError(f"Cannot redefine method from {self.__method} to {Methods.LESS_THAN}") + return self + + @property + def time(self) -> Self: + return self + + @property + def times(self) -> Self: + return self + + """ + Class properties. + """ + + def __match_calls_for_condition(self, condition: Callable[[list, dict], bool]) -> tuple[bool, str]: + calls = [] + for call in self.__calls: + if condition(call[0], call[1]): + calls.append(call) + compare, error = self.__apply_method(calls) + return compare, error + + def with_arguments(self, *args, **kwargs) -> SpyAssertion: + """ + Checks if the Spy has been called the given number of times + with at least the given arguments. + """ + + def some_args_matched(a, kw): + args_matched = all(( + arg in a + for arg in args + )) + kwargs_matched = all(( + key in kw and kw[key] == arg + for key, arg in kwargs.items() + )) + return args_matched and kwargs_matched + + compare, error = self.__match_calls_for_condition(some_args_matched) + repr_args = ', '.join([repr(arg) for arg in args]) + repr_kwargs = ', '.join([f"{key}={repr(arg)}" for key, arg in kwargs.items()]) + msg = f"{error} with arguments ({repr_args}) and keyword arguments ({repr_kwargs})." + return SpyAssertion(compare, msg, self.__calls, self._not) + + def with_arguments_matching(self, test_condition: Callable[[list, dict], bool]) -> SpyAssertion: + """ + Checks if the Spy has been called the given number of times + with arguments matching the given conditions. + """ + compare, error = self.__match_calls_for_condition(test_condition) + msg = f"{error} with arguments matching given conditions." + return SpyAssertion(compare, msg, self.__calls, self._not) + + def with_exact_arguments(self, *args, **kwargs) -> SpyAssertion: + """ + Checks if the Spy has been called the given number of times + with all the given arguments. + """ + compare, error = self.__match_calls_for_condition(lambda a, kw: a == args and kw == kwargs) + repr_args = ', '.join([repr(arg) for arg in args]) + repr_kwargs = ', '.join([f"{key}={repr(arg)}" for key, arg in kwargs.items()]) + msg = f"{error} with exact arguments ({repr_args}) and keyword arguments ({repr_kwargs})." + return SpyAssertion(compare, msg, self.__calls, self._not) + + def with_no_argument(self) -> SpyAssertion: + """ + Checks if the Spy has been called the given number of times + with all the given arguments. + """ + compare, error = self.__match_calls_for_condition(lambda a, kw: len(a) == 0 and len(kw) == 0) + return SpyAssertion(compare, f"{error} with no arguments.", self.__calls, self._not) + + +class SpyAssertionInterface(AssertionInterface): + + @property + def called(self) -> CalledInterface: + """ + Returns a boolean-able interface to check conditions for a given number of + time the spy was called. + """ + return CalledInterface(self._value.calls, self) diff --git a/runtime-pyside6/tests/plugins/natural/spy.py b/runtime-pyside6/tests/plugins/natural/spy.py index 1d77629..fbd8e17 100644 --- a/runtime-pyside6/tests/plugins/natural/spy.py +++ b/runtime-pyside6/tests/plugins/natural/spy.py @@ -15,207 +15,15 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . """ -from typing import Callable, Self - -from tests.plugins.natural.interfaces.base import Assertion, repr_, AssertionInterface -from tests.plugins.natural.interfaces.int import IntComparisonAssertionInterface - -PRINT_PREFIX = (" " * 24) +from typing import Callable -class SpyAssertion(Assertion): - def __init__(self, assertion: bool, message: str, calls: list): - super().__init__(assertion, message + "\n") - if len(calls) > 0: - self.message += self.render_calls(calls) - else: - self.message += f"{PRINT_PREFIX}0 registered calls." - - - def render_calls(self, calls): - lines = [f"{PRINT_PREFIX}{len(calls)} registered call(s):"] - for call in calls: - repr_args = [repr_(arg) for arg in call[0]] - repr_kwargs = [f"{key}={repr_(arg)}" for key, arg in call[1].items()] - lines.append(f" - {', '.join([*repr_args, *repr_kwargs])}") - return ("\n" + PRINT_PREFIX).join(lines) - - -class Methods: - AT_LEAST_ONCE = "AT_LEAST_ONCE" - EXACTLY = "EXACTLY" - AT_LEAST = "AT_LEAST" - AT_MOST = "AT_MOST" - MORE_THAN = "AT_LEAST" - LESS_THAN = "AT_MOST" - - -class CalledInterface(IntComparisonAssertionInterface): - """ - Internal class generated by Spy.was_called. - """ - - def __init__(self, calls: list[tuple[list, dict]]): - super().__init__(len(calls)) - self.__calls = calls - self.__method = Methods.AT_LEAST_ONCE - - def __apply_method(self, calls): - required = self._compare_to - calls_count = len(calls) - match self.__method: - case Methods.AT_LEAST_ONCE: - compare = len(calls) >= 1 - error = "Method was not called" - case Methods.EXACTLY: - compare = len(calls) == required - error = f"Method was not called {required} times ({required} != {calls_count})" - case Methods.AT_LEAST: - compare = len(calls) >= required - error = f"Method was not called at least {required} times ({required} > {calls_count})" - case Methods.AT_MOST: - compare = len(calls) <= required - error = f"Method was not called at most {required} times ({required} < {calls_count})" - case Methods.MORE_THAN: - compare = len(calls) > required - error = f"Method was not called more than {required} times ({required} >= {calls_count})" - case Methods.LESS_THAN: - compare = len(calls) < required - error = f"Method was not called less than {required} times ({required} <= {calls_count})" - case _: - raise RuntimeError(f"Unknown method {self.__method}.") - return compare, error - - def __bool__(self) -> bool: - """ - Converts to boolean on assertion. - """ - compare, error = self.__apply_method(self.__calls) - return bool(SpyAssertion(compare, error + ".", self.__calls)) - - """ - Chaining methods - """ - - def __call__(self, *args, **kwargs) -> Self: - if len(args) != 1: - raise RuntimeError("Cannot call called interface with more than one argument.") - self._compare_to = int(args[0]) - if self.__method == Methods.AT_LEAST_ONCE: - self.__method = Methods.EXACTLY - return self - - @property - def at_least(self) -> Self: - if self.__method == Methods.AT_LEAST_ONCE: - self.__method = Methods.AT_LEAST - else: - raise RuntimeError(f"Cannot redefine method from {self.__method} to {Methods.AT_MOST}") - return self - - @property - def at_most(self) -> Self: - if self.__method == Methods.AT_LEAST_ONCE: - self.__method = Methods.AT_MOST - else: - raise RuntimeError(f"Cannot redefine method from {self.__method} to {Methods.AT_MOST}") - return self - - @property - def more_than(self) -> Self: - if self.__method == Methods.AT_LEAST_ONCE: - self.__method = Methods.MORE_THAN - else: - raise RuntimeError(f"Cannot redefine method from {self.__method} to {Methods.MORE_THAN}") - return self - - @property - def less_than(self) -> Self: - if self.__method == Methods.AT_LEAST_ONCE: - self.__method = Methods.LESS_THAN - else: - raise RuntimeError(f"Cannot redefine method from {self.__method} to {Methods.LESS_THAN}") - return self - - @property - def time(self) -> Self: - return self - - @property - def times(self) -> Self: - return self - - """ - Class properties. - """ - - def __match_calls_for_condition(self, condition: Callable[[list, dict], bool]) -> tuple[bool, str]: - calls = [] - for call in self.__calls: - if condition(call[0], call[1]): - calls.append(call) - compare, error = self.__apply_method(calls) - return compare, error - - def with_arguments(self, *args, **kwargs) -> SpyAssertion: - """ - Checks if the Spy has been called the given number of times - with at least the given arguments. - """ - - def some_args_matched(a, kw): - args_matched = all(( - arg in a - for arg in args - )) - kwargs_matched = all(( - key in kw and kw[key] == arg - for key, arg in kwargs.items() - )) - return args_matched and kwargs_matched - - compare, error = self.__match_calls_for_condition(some_args_matched) - repr_args = ', '.join([repr(arg) for arg in args]) - repr_kwargs = ', '.join([f"{key}={repr(arg)}" for key, arg in kwargs.items()]) - msg = f"{error} with arguments ({repr_args}) and keyword arguments ({repr_kwargs})." - return SpyAssertion(compare, msg, self.__calls) - - def with_arguments_matching(self, test_condition: Callable[[list, dict], bool]) -> SpyAssertion: - """ - Checks if the Spy has been called the given number of times - with arguments matching the given conditions. - """ - compare, error = self.__match_calls_for_condition(test_condition) - msg = f"{error} with arguments matching given conditions." - return SpyAssertion(compare, msg, self.__calls) - - def with_exact_arguments(self, *args, **kwargs) -> SpyAssertion: - """ - Checks if the Spy has been called the given number of times - with all the given arguments. - """ - compare, error = self.__match_calls_for_condition(lambda a, kw: a == args and kw == kwargs) - repr_args = ', '.join([repr(arg) for arg in args]) - repr_kwargs = ', '.join([f"{key}={repr(arg)}" for key, arg in kwargs.items()]) - msg = f"{error} with exact arguments ({repr_args}) and keyword arguments ({repr_kwargs})." - return SpyAssertion(compare, msg, self.__calls) - - def with_no_argument(self) -> SpyAssertion: - """ - Checks if the Spy has been called the given number of times - with all the given arguments. - """ - compare, error = self.__match_calls_for_condition(lambda a, kw: len(a) == 0 and len(kw) == 0) - return SpyAssertion(compare, f"{error} with no arguments.", self.__calls) - - -class Spy(AssertionInterface): +class Spy: """ Class to spy into method calls with natural language expressions. """ def __init__(self, function: Callable = None): - super().__init__(function) self.function = function self.calls = [] @@ -223,20 +31,3 @@ class Spy(AssertionInterface): self.calls.append((args, kwargs)) if self.function is not None: self.function(*args, **kwargs) - - @property - def called(self) -> CalledInterface: - """ - Returns a boolean-able interface to check conditions for a given number of - time the spy was called. - """ - return CalledInterface(self.calls) - - @property - def not_called(self) -> CalledInterface: - """ - Returns a boolean-able interface to check that conditions were never fulfilled - in the times the spy was called. - """ - ret = CalledInterface(self.calls) - return ret(0) diff --git a/runtime-pyside6/tests/plugins/natural/that.py b/runtime-pyside6/tests/plugins/natural/that.py index 38ee54e..05a3e31 100644 --- a/runtime-pyside6/tests/plugins/natural/that.py +++ b/runtime-pyside6/tests/plugins/natural/that.py @@ -17,17 +17,21 @@ """ from typing import overload, Generic, TypeVar -from .spy import Spy +from . import Spy from .interfaces.base import AssertionInterface, BaseAssertionInterface -from .interfaces.basic import StringInterface, BoolInterface -from .interfaces.int import IntInterface +from .interfaces.basic import StringInterface, BoolInterface, ListInterface +from .interfaces.int import NumberInterface +from .interfaces.spy import SpyAssertionInterface Interface = TypeVar("Interface", bound=AssertionInterface) MATCHES = [ (str, StringInterface), - (int, IntInterface), (bool, BoolInterface), + (int, NumberInterface), + (float, NumberInterface), + (list, ListInterface), + (Spy, SpyAssertionInterface) ] @@ -36,11 +40,18 @@ def that(value: str) -> StringInterface: ... @overload -def that(value: int) -> IntInterface: ... +def that(value: bool) -> BoolInterface: ... @overload -def that(value: bool) -> BoolInterface: ... +def that(value: int) -> NumberInterface: ... + + +@overload +def that(value: float) -> NumberInterface: ... + +@overload +def that(value: Spy) -> SpyAssertionInterface: ... @overload diff --git a/runtime-pyside6/tests/plugins/tests/__init__.py b/runtime-pyside6/tests/plugins/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/runtime-pyside6/tests/plugins/tests/test_natural.py b/runtime-pyside6/tests/plugins/tests/test_natural.py new file mode 100644 index 0000000..d7fe26c --- /dev/null +++ b/runtime-pyside6/tests/plugins/tests/test_natural.py @@ -0,0 +1,217 @@ +""" + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +""" +import pytest + +from ..natural import that, Assertion, Spy + + +def test_string(): + assert that("QWERTY").is_.an.instance_of(str) + assert that("QWERTY").is_.not_.an.instance_of(int) + assert that("QWERTY").is_.equal.to("QWERTY") + assert that("QWERTY").is_.NOT.equal.to("QWERTYUIOP") + assert that("QWERTY").is_.NOT.equal.to(3) + assert that("QWERTY").has.a.length.of(6) + assert that("QWERTY").does.NOT.have.a.length.of(7) + assert that("QWERTY").has.a.length.that.is_.NOT(5) + assert that("QWERTY").contains("WER") + assert that("QWERTY").contains("WER", "TY") + assert that("QWERTY").does.not_.contain("AZERTY") + with pytest.raises(Assertion): + assert that("QWERTY").is_.an.instance_of(int) + with pytest.raises(Assertion): + assert that("QWERTY").is_.equal.to(False) + with pytest.raises(Assertion): + assert that("QWERTY").has.a.length.of(1) + with pytest.raises(Assertion): + assert that("QWERTY").contains("AZERTY") + with pytest.raises(Assertion): + assert that("QWERTY").does.NOT.contain("QWE") + +def test_bool(): + assert that(True).is_.an.instance_of(bool) + assert that(True).is_.an.instance_of(int) + assert that(True).is_.NOT.an.instance_of(str) + assert that(True).equals(True) + assert that(True).is_.true + assert that(True).is_.NOT.false + assert that(False).is_.equal.to(False) + assert that(False).is_.false + assert that(False).is_.NOT.true + with pytest.raises(Assertion): + assert that(True).is_.false + with pytest.raises(Assertion): + assert that(True).is_.NOT.true + +def test_int(): + assert that(2).is_.an.instance_of(int) + assert that(2).is_.NOT.an.instance_of(bool) + assert that(2).is_.NOT.an.instance_of(str) + assert that(2).is_.more_than(1) + assert that(2).is_.NOT.less_than(1) + assert that(2).is_.less_than(3) + assert that(2).is_.NOT.more_than(3) + assert that(2).is_.at_least(1) + assert that(2).is_.NOT.at_most(1) + assert that(2).is_.at_most(3) + assert that(2).is_.NOT.at_least(3) + assert that(2).is_.at_most(2) + assert that(2).is_.at_least(2) + # Equality + assert that(2).is_(2) + assert that(2).was(2) + assert that(2).is_.exactly(2) + assert that(2).is_.equal.to(2) + assert that(2).equals(2) + assert that(2).is_.NOT(3) + assert that(2).does.NOT.equal(3) + +def test_int_shorthands(): + # Direct numbers + assert that(0).equals.zero + assert that(1).equals.one + assert that(2).equals.two + assert that(3).equals.three + assert that(4).equals.four + assert that(5).equals.five + assert that(6).equals.six + assert that(7).equals.seven + assert that(8).equals.eight + assert that(9).equals.nine + assert that(10).equals.ten + assert that(11).equals.eleven + assert that(12).equals.twelve + assert that(13).equals.thirteen + assert that(14).equals.fourteen + assert that(15).equals.fifteen + assert that(16).equals.sixteen + assert that(17).equals.seventeen + assert that(18).equals.eighteen + assert that(19).equals.nineteen + assert that(20).equals.twenty + assert that(30).equals.thirty + assert that(40).equals.forty + assert that(50).equals.fifty + assert that(60).equals.sixty + assert that(70).equals.seventy + assert that(80).equals.eighty + assert that(90).equals.ninety + assert that(100).equals.a.hundred + assert that(1000).equals.a.thousand + assert that(1_000_000).equals.a.million + +def test_add_natural_complex(): + # Test composed + assert that(34).equals.thirty.four + assert that(-34).equals.minus.thirty.four + assert that(100_033_207).equals.one.hundred.million.AND.thirty.three.thousand.AND.two.hundred.AND.seven + assert that(-1_200_033_207).equals.minus.one.billion.AND.two.hundred.million.AND.thirty.three.thousand.AND.two.hundred.AND.seven + assert that(7890).equals.seven.thousand.eight.hundred.and_.ninety + assert that(7890).equals.seventy.eight.hundred.and_.ninety + assert that(7890).equals(78)(100)(90) + with pytest.raises(RuntimeError): + assert that(1_000_000).equals.a.thousand.thousand + with pytest.raises(RuntimeError): + assert that(600).equals.one.twenty.thirty + with pytest.raises(RuntimeError): + assert that(2).equals + with pytest.raises(RuntimeError): + assert that(2).equals.one.minus.two + +def test_spy(): + spy = Spy() + assert that(spy).is_.an.instance_of(Spy) + assert that(spy).is_(callable) + # Check calls + assert that(spy).was.never.called + assert that(spy).was.called.zero.times + spy(30, arg="string") + assert that(spy).was.called + assert that(spy).was.called.once + assert that(spy).was.called.one.time + assert that(spy).was.NOT.called.more_than.once + assert that(spy).was.called.with_arguments(30) + assert that(spy).was.called.with_arguments_matching(lambda args, kwargs: len(args) == 1 and len(kwargs) == 1) + assert that(spy).was.NOT.called.with_arguments(50) + assert that(spy).was.NOT.called.with_exact_arguments(30) + assert that(spy).was.NOT.called.with_no_argument() + assert that(spy).was.called.with_exact_arguments(30, arg="string") + with pytest.raises(Assertion): + assert that(spy).was.called.with_arguments(50) + with pytest.raises(Assertion): + assert that(spy).was.called.with_exact_arguments(30) + with pytest.raises(Assertion): + assert that(spy).was.called.with_no_argument() + +def test_spy_seral_calls(): + spy = Spy(lambda *args, **kw: None) + obj = object() + spy() + spy(30, arg="string") + spy(obj, 30, example=obj, none=None) + assert that(spy).was.called + assert that(spy).was.called.more_than.once + assert that(spy).was.called.more_than.twice + assert that(spy).was.NOT.called.more_than.thrice + assert that(spy).was.called.at_most.thrice + assert that(spy).was.called.at_least.thrice + assert that(spy).was.called.three.times + assert that(spy).was.called.less_than(4).times + # Check arguments + assert that(spy).was.called.once.with_no_argument() + assert that(spy).was.called.at_most.once.with_no_argument() + assert that(spy).was.called.twice.with_arguments(30) + assert that(spy).was.NOT.called.less_than.twice.with_arguments(30) + assert that(spy).was.called.once.with_arguments(obj) + assert that(spy).was.called.once.with_arguments(arg="string") + assert that(spy).was.called.once.with_arguments(30, obj) + assert that(spy).was.called.once.with_arguments(none=None) + assert that(spy).was.NOT.called.with_arguments(None) + assert that(spy).was.NOT.called.with_arguments(obj, 30, arg="string") + with pytest.raises(Assertion): + assert that(spy).was.called.with_arguments(obj, 30, arg="string") + # Checking with exact arguments + assert that(spy).was.called.once.with_exact_arguments(30, arg="string") + assert that(spy).was.called.once.with_exact_arguments(obj, 30, example=obj, none=None) + assert that(spy).was.NOT.called.with_exact_arguments(obj, 30, arg="string") + with pytest.raises(Assertion): + assert that(spy).was.called.with_exact_arguments(obj, 30, arg="string") + # Check arguments matching + assert that(spy).has.NOT.been.called.with_arguments_matching(lambda a, kw: len(a) + len(kw) == 3) + assert that(spy).was.called.once.with_arguments_matching(lambda a, kw: len(a) + len(kw) == 2) + assert that(spy).was.called.once.with_arguments_matching(lambda a, kw: len(a) + len(kw) == 4) + with pytest.raises(Assertion): + assert that(spy).was.called.with_arguments_matching(lambda a, kw: len(a) + len(kw) == 3) + + +def test_wrongful_expressions(): + spy = Spy() + with pytest.raises(RuntimeError): + assert that(3).is_.less_than("str") + with pytest.raises(RuntimeError): + assert that(3).does.NOT.NOT.equal(3) + with pytest.raises(RuntimeError): + assert that(3).is_.an.instance_of("non type") + with pytest.raises(RuntimeError): + assert that(spy).was.called.more_than.at_least.once + with pytest.raises(RuntimeError): + assert that(spy).was.called.more_than.at_most.once + with pytest.raises(RuntimeError): + assert that(spy).was.called.more_than.less_than.once + with pytest.raises(RuntimeError): + assert that(spy).was.called.more_than.more_than.once \ No newline at end of file From a182c703f43a9542bb55662b0dd68bc12872b48a Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 17 Oct 2024 03:38:36 +0200 Subject: [PATCH 056/104] Finishing testing promises. --- .../LogarithmPlotter/util/promise.py | 24 ++--- .../tests/plugins/natural/interfaces/spy.py | 2 +- runtime-pyside6/tests/plugins/natural/spy.py | 2 +- .../tests/plugins/tests/test_natural.py | 6 +- runtime-pyside6/tests/test_main.py | 3 +- runtime-pyside6/tests/test_promise.py | 98 +++++++++++++++---- runtime-pyside6/tests/test_pyjs.py | 1 - scripts/run-tests.sh | 14 +++ 8 files changed, 114 insertions(+), 36 deletions(-) diff --git a/runtime-pyside6/LogarithmPlotter/util/promise.py b/runtime-pyside6/LogarithmPlotter/util/promise.py index 3c2d223..f43e85b 100644 --- a/runtime-pyside6/LogarithmPlotter/util/promise.py +++ b/runtime-pyside6/LogarithmPlotter/util/promise.py @@ -73,10 +73,10 @@ class PyPromiseRunner(QRunnable): class PyPromise(QObject): """ - Asynchronous Promise-like object meant to interface between Python and Javascript easily. + Threaded A+/Promise implementation meant to interface between Python and Javascript easily. Runs to_run in another thread, and calls fulfilled (populated by then) with its return value. """ - fulfilled = Signal((QJSValue,), (QObject,)) + fulfilled = Signal(QJSValue) rejected = Signal(str) def __init__(self, to_run: Callable|QJSValue, args=[], start_automatically=True): @@ -115,10 +115,8 @@ class PyPromise(QObject): """ on_fulfill = check_callable(on_fulfill) on_reject = check_callable(on_reject) - if on_fulfill is not None: - self._fulfills.append(on_fulfill) - if on_reject is not None: - self._rejects.append(on_reject) + self._fulfills.append(on_fulfill) + self._rejects.append(on_reject) return self def calls_upon_fulfillment(self, function: Callable | QJSValue) -> bool: @@ -155,20 +153,22 @@ class PyPromise(QObject): def _fulfill(self, data): self._state = "fulfilled" no_return = [None, QJSValue.SpecialValue.UndefinedValue] - for on_fulfill in self._fulfills: + print("Fulfill") + for i in range(len(self._fulfills)): try: - result = on_fulfill(data) + result = self._fulfills[i](data) result = result.qjs_value if isinstance(result, PyJSValue) else result data = result if result not in no_return else data # Forward data. except Exception as e: - self._reject(repr(e)) + self._reject(repr(e), start_at=i) break @Slot(QJSValue) @Slot(str) - def _reject(self, error): + def _reject(self, error, start_at=0): self._state = "rejected" no_return = [None, QJSValue.SpecialValue.UndefinedValue] - for on_reject in self._rejects: - result = on_reject(error) + for i in range(start_at, len(self._rejects)): + result = self._rejects[i](error) + result = result.qjs_value if isinstance(result, PyJSValue) else result error = result if result not in no_return else error # Forward data. diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/spy.py b/runtime-pyside6/tests/plugins/natural/interfaces/spy.py index 59b09d3..524fd71 100644 --- a/runtime-pyside6/tests/plugins/natural/interfaces/spy.py +++ b/runtime-pyside6/tests/plugins/natural/interfaces/spy.py @@ -21,7 +21,7 @@ from typing import Callable, Self from .base import Assertion, repr_, AssertionInterface from .int import NumberComparisonAssertionInterface -PRINT_PREFIX = (" " * 24) +PRINT_PREFIX = (" " * 3) class SpyAssertion(Assertion): diff --git a/runtime-pyside6/tests/plugins/natural/spy.py b/runtime-pyside6/tests/plugins/natural/spy.py index fbd8e17..2f9211a 100644 --- a/runtime-pyside6/tests/plugins/natural/spy.py +++ b/runtime-pyside6/tests/plugins/natural/spy.py @@ -30,4 +30,4 @@ class Spy: def __call__(self, *args, **kwargs): self.calls.append((args, kwargs)) if self.function is not None: - self.function(*args, **kwargs) + return self.function(*args, **kwargs) diff --git a/runtime-pyside6/tests/plugins/tests/test_natural.py b/runtime-pyside6/tests/plugins/tests/test_natural.py index d7fe26c..f381639 100644 --- a/runtime-pyside6/tests/plugins/tests/test_natural.py +++ b/runtime-pyside6/tests/plugins/tests/test_natural.py @@ -134,13 +134,13 @@ def test_add_natural_complex(): assert that(2).equals.one.minus.two def test_spy(): - spy = Spy() + spy = Spy(lambda *args, **kw: 10) assert that(spy).is_.an.instance_of(Spy) assert that(spy).is_(callable) # Check calls assert that(spy).was.never.called assert that(spy).was.called.zero.times - spy(30, arg="string") + assert spy(30, arg="string") == 10 assert that(spy).was.called assert that(spy).was.called.once assert that(spy).was.called.one.time @@ -159,7 +159,7 @@ def test_spy(): assert that(spy).was.called.with_no_argument() def test_spy_seral_calls(): - spy = Spy(lambda *args, **kw: None) + spy = Spy() obj = object() spy() spy(30, arg="string") diff --git a/runtime-pyside6/tests/test_main.py b/runtime-pyside6/tests/test_main.py index 047e21f..6b161ad 100644 --- a/runtime-pyside6/tests/test_main.py +++ b/runtime-pyside6/tests/test_main.py @@ -22,12 +22,13 @@ from os.path import exists, join from PySide6.QtGui import QIcon from tempfile import TemporaryDirectory +from .globals import app + from LogarithmPlotter.logarithmplotter import get_linux_theme, LINUX_THEMES, get_platform_qt_style, \ register_icon_directories, install_translation, create_engine from LogarithmPlotter.util import config from LogarithmPlotter.util.helper import Helper from LogarithmPlotter.util.latex import Latex -from globals import app THEMES = [ "Basic", diff --git a/runtime-pyside6/tests/test_promise.py b/runtime-pyside6/tests/test_promise.py index a97f864..30f0a1e 100644 --- a/runtime-pyside6/tests/test_promise.py +++ b/runtime-pyside6/tests/test_promise.py @@ -17,9 +17,10 @@ """ from time import sleep +import pytest from PySide6.QtQml import QJSValue -from tests.plugins.natural import that, Spy +from .plugins.natural import that, Spy from LogarithmPlotter.util.js import PyJSValue from LogarithmPlotter.util.promise import PyPromise @@ -56,6 +57,10 @@ def async_throw(): class TestPyPromise: + def test_invalid_function(self): + with pytest.raises(ValueError): + promise = PyPromise("not a function") + def test_fulfill_values(self, qtbot): qjsv = QJSValue(3) values = [ @@ -70,7 +75,6 @@ class TestPyPromise: for [value, test] in values: promise = PyPromise(create_async_func(value)) with qtbot.assertNotEmitted(promise.rejected, wait=1000): - print("Testing", value) with qtbot.waitSignal(promise.fulfilled, check_params_cb=test, timeout=2000): assert promise.state == "pending" assert promise.state == "fulfilled" @@ -84,30 +88,90 @@ class TestPyPromise: assert promise.state == "rejected" def test_fulfill(self, qtbot): - spy_fulfilled = Spy() - spy_rejected = Spy() + fulfilled = Spy() + rejected = Spy() promise = PyPromise(create_async_func(3)) - then_res = promise.then(spy_fulfilled, spy_rejected) + then_res = promise.then(fulfilled, rejected) # Check if the return value is the same promise (so we can chain then) - assert then_res == promise + assert that(then_res).does.equal(promise) # Check on our spy. with qtbot.waitSignal(promise.fulfilled, timeout=10000): pass - assert that(spy_fulfilled).was.called.once - assert that(spy_fulfilled).was.not_called.with_arguments(3) - assert that(spy_fulfilled).was.called.with_arguments_matching(check_promise_result(3)) - assert spy_rejected.was.not_called + assert that(fulfilled).was.called.once + assert that(fulfilled).was.NOT.called.with_arguments(3) + assert that(fulfilled).was.called.with_arguments_matching(check_promise_result(3)) + assert that(rejected).was.never.called def test_rejected(self, qtbot): - spy_fulfilled = Spy() - spy_rejected = Spy() + fulfilled = Spy() + rejected = Spy() promise = PyPromise(async_throw) - then_res = promise.then(spy_fulfilled, spy_rejected) + then_res = promise.then(fulfilled, rejected) # Check if the return value is the same promise (so we can chain then) - assert that(then_res).is_equal.to(promise) + assert that(then_res).does.equal(promise) # Check on our spies. with qtbot.waitSignal(promise.rejected, timeout=10000): pass - assert that(spy_rejected).was.called.once - assert that(spy_rejected).was.called.with_arguments("Exception('aaaa')") - assert that(spy_fulfilled).was.not_called + assert that(rejected).was.called.once + assert that(rejected).was.called.with_arguments("Exception('aaaa')") + assert that(fulfilled).has.never.been.called + + def test_chain_fulfill(self, qtbot): + convert = Spy(lambda v: v.toVariant()) + plus = Spy(lambda v: v + 1) + rejected = Spy() + promise = PyPromise(create_async_func(5)) + then_res = promise.then(convert, rejected).then(plus, rejected).then(plus, rejected).then(plus, rejected) + # Check if the return value is the same promise (so we can chain then) + assert that(then_res).does.equal(promise) + with qtbot.waitSignal(promise.fulfilled, timeout=10000): + pass + assert that(convert).was.called.once.with_arguments_matching(check_promise_result(5)) + assert that(rejected).was.never.called + assert that(plus).was.called.three.times + assert that(plus).was.called.once.with_exact_arguments(5) + assert that(plus).was.called.once.with_exact_arguments(6) + assert that(plus).was.called.once.with_exact_arguments(7) + + def test_chain_reject(self, qtbot): + fulfilled = Spy() + convert = Spy(lambda v: len(v)) + minus = Spy(lambda v: v - 1) + promise = PyPromise(async_throw) + then_res = promise.then(fulfilled, convert).then(fulfilled, minus).then(fulfilled, minus).then(fulfilled, minus) + # Check if the return value is the same promise (so we can chain then) + assert that(then_res).does.equal(promise) + with qtbot.waitSignal(promise.rejected, timeout=10000): + pass + assert that(fulfilled).was.never.called + assert that(convert).was.called.once.with_arguments_matching(check_promise_result("Exception('aaaa')")) + assert that(minus).was.called.three.times + assert that(minus).was.called.once.with_exact_arguments(17) + assert that(minus).was.called.once.with_exact_arguments(16) + assert that(minus).was.called.once.with_exact_arguments(15) + + def test_check_calls_upon(self): + promise = PyPromise(async_throw) + fulfilled = Spy() + rejected = Spy() + promise.then(fulfilled, rejected) + assert promise.calls_upon_fulfillment(fulfilled) + assert promise.calls_upon_rejection(rejected) + assert not promise.calls_upon_fulfillment(rejected) + assert not promise.calls_upon_rejection(fulfilled) + + def test_reject_in_fulfill(self, qtbot): + def fulfilled_throw(x): + raise Exception('noooo') + promise = PyPromise(create_async_func("3")) + fulfilled_throw = Spy(fulfilled_throw) + fulfilled = Spy() + rejected = Spy() + then_res = promise.then(fulfilled, rejected).then(fulfilled_throw, rejected).then(fulfilled, rejected).then(fulfilled, rejected) + # Check if the return value is the same promise (so we can chain then) + assert that(then_res).does.equal(promise) + with qtbot.waitSignal(promise.fulfilled, timeout=10000): + pass + assert that(fulfilled_throw).has.been.called.once + assert that(rejected).has.been.called.three.times + assert that(rejected).has.been.called.three.times.with_arguments("Exception('noooo')") \ No newline at end of file diff --git a/runtime-pyside6/tests/test_pyjs.py b/runtime-pyside6/tests/test_pyjs.py index 5742cfc..95c3cf6 100644 --- a/runtime-pyside6/tests/test_pyjs.py +++ b/runtime-pyside6/tests/test_pyjs.py @@ -21,7 +21,6 @@ from re import Pattern from PySide6.QtQml import QJSEngine, QJSValue from LogarithmPlotter.util.js import PyJSValue, InvalidAttributeValueException, NotAPrimitiveException -from globals import app @pytest.fixture() def data(): diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh index ac1fdc5..8c09c54 100644 --- a/scripts/run-tests.sh +++ b/scripts/run-tests.sh @@ -1,8 +1,20 @@ #!/bin/bash cd "$(dirname "$(readlink -f "$0" || realpath "$0")")/.." || exit 1 +box() { + len=${#1} + echo "┌─$(printf '─%.0s' $(seq 1 "$len"))─┐" + echo "│ $1 │" + echo "└─$(printf '─%.0s' $(seq 1 "$len"))─┘" +} + rebuild=true +cd runtime-pyside6/tests/plugins || exit 1 +box "Testing pytest natural plugins..." +PYTHONPATH="$PYTHONPATH:." pytest --cov=natural --cov-report term-missing . +cd ../../../ + while [ $# -gt 0 ]; do case "$1" in --no-rebuild) @@ -27,10 +39,12 @@ rm -rf build/runtime-pyside6/tests cp -r runtime-pyside6/tests build/runtime-pyside6 cp -r ci CHANGELOG.md build/runtime-pyside6 cd build/runtime-pyside6 || exit 1 +box "Testing runtime-pyside6..." PYTHONPATH="$PYTHONPATH:." pytest --cov=LogarithmPlotter --cov-report term-missing . cd ../../ # Run js tests cd common || exit 1 +box "Testing common..." npm test From 2899ac6cde0c8cdca2efd60edd7b325314c0fe80 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 17 Oct 2024 03:41:41 +0200 Subject: [PATCH 057/104] Fixing unit testing importing unexpected and unused libraries. --- .gitignore | 6 ++++-- runtime-pyside6/tests/plugins/natural/interfaces/int.py | 3 +-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 3961125..e2308a5 100644 --- a/.gitignore +++ b/.gitignore @@ -37,8 +37,10 @@ docs/html *.lpf *.lgg +# Tests +common/coverage/ +**/.coverage + # npm common/node_modules -common/coverage/ -common/.coverage runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/index.mjs* diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/int.py b/runtime-pyside6/tests/plugins/natural/interfaces/int.py index 7ac8871..75bd8b8 100644 --- a/runtime-pyside6/tests/plugins/natural/interfaces/int.py +++ b/runtime-pyside6/tests/plugins/natural/interfaces/int.py @@ -15,8 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . """ -from idlelib.configdialog import is_int -from math import log10, floor, ceil +from math import log10, floor from typing import Self from .assertion import Assertion From 3c0d99d9c037b1d153f776024098951f29eb71df Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 17 Oct 2024 03:44:35 +0200 Subject: [PATCH 058/104] Exiting when not all tests are fulfilled. --- scripts/run-tests.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh index 8c09c54..3f73e37 100644 --- a/scripts/run-tests.sh +++ b/scripts/run-tests.sh @@ -12,7 +12,7 @@ rebuild=true cd runtime-pyside6/tests/plugins || exit 1 box "Testing pytest natural plugins..." -PYTHONPATH="$PYTHONPATH:." pytest --cov=natural --cov-report term-missing . +PYTHONPATH="$PYTHONPATH:." pytest --cov=natural --cov-report term-missing . || exit 1 cd ../../../ while [ $# -gt 0 ]; do @@ -40,11 +40,11 @@ cp -r runtime-pyside6/tests build/runtime-pyside6 cp -r ci CHANGELOG.md build/runtime-pyside6 cd build/runtime-pyside6 || exit 1 box "Testing runtime-pyside6..." -PYTHONPATH="$PYTHONPATH:." pytest --cov=LogarithmPlotter --cov-report term-missing . +PYTHONPATH="$PYTHONPATH:." pytest --cov=LogarithmPlotter --cov-report term-missing . || exit 1 cd ../../ # Run js tests cd common || exit 1 box "Testing common..." -npm test +npm test || exit 1 From 811262b1fbbabf8933c7b6ac222d7815d7b7b7fc Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 17 Oct 2024 05:09:33 +0200 Subject: [PATCH 059/104] Changing lupdate and lrelease to use pyside6 versions, updating images so I no longer have to install node to build. --- assets/i18n/release.sh | 2 +- assets/i18n/update.sh | 2 +- ci/drone.yml | 13 +++---------- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/assets/i18n/release.sh b/assets/i18n/release.sh index 93475b5..58477c3 100755 --- a/assets/i18n/release.sh +++ b/assets/i18n/release.sh @@ -1,2 +1,2 @@ #!/bin/bash -lrelease *.ts +pyside6-lrelease *.ts diff --git a/assets/i18n/update.sh b/assets/i18n/update.sh index ff96ef8..98f4201 100755 --- a/assets/i18n/update.sh +++ b/assets/i18n/update.sh @@ -40,7 +40,7 @@ done echo "----------------------------" echo "| Updating translations... |" echo "----------------------------" -lupdate -extensions js,qs,qml,py -recursive ../../common/src -recursive ../../runtime-pyside6/LogarithmPlotter -ts lp_*.ts +pyside6-lupdate -extensions js,qs,qml,py -recursive ../../common/src -recursive ../../runtime-pyside6/LogarithmPlotter -ts lp_*.ts # Updating locations in files for lp in *.ts; do echo "Replacing locations in $lp..." diff --git a/ci/drone.yml b/ci/drone.yml index da7d1c7..d49a6d4 100644 --- a/ci/drone.yml +++ b/ci/drone.yml @@ -12,28 +12,21 @@ steps: - git submodule update --init --recursive - name: Build - image: node:18-bookworm + image: ad5001/ubuntu-pyside-xvfb:linux-6-latest-latex-node commands: - cd common && npm install && cd .. - - apt update - - apt install -y qtchooser qttools5-dev-tools - # Start building - bash scripts/build.sh - when: - event: [ push, tag ] - name: Unit Tests - image: ad5001/ubuntu-pyside-xvfb:linux-6-latest-latex + image: ad5001/ubuntu-pyside-xvfb:linux-6-latest-latex-node commands: - - apt update - - apt install -y npm - cd common && npm install -D && cd .. - xvfb-run bash scripts/run-tests.sh --no-rebuild when: event: [ push, tag ] - name: File Tests - image: ad5001/ubuntu-pyside-xvfb:linux-6-latest-latex + image: ad5001/ubuntu-pyside-xvfb:linux-6-latest-latex-node commands: - xvfb-run python3 run.py --test-build --no-check-for-updates - xvfb-run python3 run.py --test-build --no-check-for-updates ./ci/test1.lpf From 14c092b9fa87b1f09e3f56226bb7439487267a0c Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 17 Oct 2024 05:28:03 +0200 Subject: [PATCH 060/104] Fixing tests --- README.md | 2 +- runtime-pyside6/tests/test_latex.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5d4ba57..249792a 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ First, you'll need to install all the required dependencies: - [npm](https://npmjs.com) (or [yarn](https://yarnpkg.com/)), go to the `common` directory, and run `npm install` (or `yarn install`). You can simply run LogarithmPlotter using `python3 run.py`. It automatically compiles the language files (requires -`lrelease` to be installed and in path), and the JavaScript modules. +`pyside6-lrelease` to be installed and in path), and the JavaScript modules. If you do not wish do recompile the files again on every run, you can use the build script (`scripts/build.sh`) and run `python3 build/runtime-pyside6/LogarithmPlotter/logarithmplotter.py`. diff --git a/runtime-pyside6/tests/test_latex.py b/runtime-pyside6/tests/test_latex.py index 124186b..ee87fa5 100644 --- a/runtime-pyside6/tests/test_latex.py +++ b/runtime-pyside6/tests/test_latex.py @@ -82,9 +82,9 @@ class TestLatex: with pytest.raises(latex.RenderError): latex_obj.renderSync("\\mathrm{f}(x)", 14, BLACK) # Replace latex bin with one goes indefinitely - latex.LATEX_PATH = which("import") - with pytest.raises(latex.RenderError): - latex_obj.renderSync("\\mathrm{f}(x)", 14, BLACK) + # latex.LATEX_PATH = which("import") # TODO: Find one such executable + # with pytest.raises(latex.RenderError): + # latex_obj.renderSync("\\mathrm{f}(x)", 14, BLACK) latex.LATEX_PATH = bkp def test_prerendered(self, latex_obj: latex.Latex) -> None: From 6251835aa0c1d96ec0e4752260c90a34b297cd3a Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 18 Oct 2024 14:08:31 +0000 Subject: [PATCH 061/104] Translated using Weblate (German) Currently translated at 100.0% (265 of 265 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/ --- assets/i18n/lp_de.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/i18n/lp_de.ts b/assets/i18n/lp_de.ts index 59a9725..7d66a7a 100644 --- a/assets/i18n/lp_de.ts +++ b/assets/i18n/lp_de.ts @@ -145,7 +145,7 @@ &Changelog - &Changelog + &Versionshinweise @@ -388,7 +388,7 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" Changelog - Changelog + Versionshinweise From e35f6cebecdcdbf9db28ffb1491fefd04268ca6a Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sun, 20 Oct 2024 00:11:35 +0200 Subject: [PATCH 062/104] Starting Latex tests. --- common/package-lock.json | 11 ++- common/package.json | 1 + common/src/module/latex.mjs | 7 +- common/test/hooks.mjs | 2 + common/test/mock/helper.mjs | 3 +- common/test/mock/latex.mjs | 5 +- common/test/module/latex.mjs | 144 +++++++++++++++++++++++++++++++++++ 7 files changed, 164 insertions(+), 9 deletions(-) create mode 100644 common/test/module/latex.mjs diff --git a/common/package-lock.json b/common/package-lock.json index ee15bf5..5df6794 100644 --- a/common/package-lock.json +++ b/common/package-lock.json @@ -13,6 +13,7 @@ "@rollup/plugin-babel": "^6.0.4", "@rollup/plugin-commonjs": "^28.0.0", "@rollup/plugin-node-resolve": "^15.3.0", + "@types/chai-as-promised": "^8.0.1", "c8": "^10.1.2", "rollup": "^4.22.4", "rollup-plugin-cleanup": "^3.2.1" @@ -2198,9 +2199,17 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.0.0.tgz", "integrity": "sha512-+DwhEHAaFPPdJ2ral3kNHFQXnTfscEEFsUxzD+d7nlcLrFK23JtNjH71RGasTcHb88b4vVi4mTyfpf8u2L8bdA==", - "dev": true, "license": "MIT" }, + "node_modules/@types/chai-as-promised": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-8.0.1.tgz", + "integrity": "sha512-dAlDhLjJlABwAVYObo9TPWYTRg9NaQM5CXeaeJYcYAkvzUf0JRLIiog88ao2Wqy/20WUnhbbUZcgvngEbJ3YXQ==", + "license": "MIT", + "dependencies": { + "@types/chai": "*" + } + }, "node_modules/@types/chai-spies": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/chai-spies/-/chai-spies-1.0.6.tgz", diff --git a/common/package.json b/common/package.json index e85d3ff..a368ef5 100644 --- a/common/package.json +++ b/common/package.json @@ -25,6 +25,7 @@ "devDependencies": { "@types/chai": "^5.0.0", "@types/chai-spies": "^1.0.6", + "@types/chai-as-promised": "^8.0.1", "@types/mocha": "^10.0.8", "chai": "^5.1.1", "chai-as-promised": "^8.0.0", diff --git a/common/src/module/latex.mjs b/common/src/module/latex.mjs index 830f096..dca9422 100644 --- a/common/src/module/latex.mjs +++ b/common/src/module/latex.mjs @@ -62,7 +62,7 @@ class LatexRenderResult { class LatexAPI extends Module { /** @type {LatexInterface} */ #latex = null - + constructor() { super("Latex", { latex: LatexInterface, @@ -142,9 +142,10 @@ class LatexAPI extends Module { */ parif(elem, contents) { elem = elem.toString() - if(elem[0] !== "(" && elem.at(-1) !== ")" && contents.some(x => elem.indexOf(x) > 0)) + const contains = contents.some(x => elem.indexOf(x) > 0) + if(elem[0] !== "(" && elem.at(-1) !== ")" && contains) return this.par(elem) - if(elem[0] === "(" && elem.at(-1) === ")") + if(elem[0] === "(" && elem.at(-1) === ")" && !contains) return elem.removeEnclosure() return elem } diff --git a/common/test/hooks.mjs b/common/test/hooks.mjs index abe468f..66e9da9 100644 --- a/common/test/hooks.mjs +++ b/common/test/hooks.mjs @@ -22,8 +22,10 @@ import { MockLatex } from "./mock/latex.mjs" import { use } from "chai" import spies from "chai-spies" +import promised from "chai-as-promised" function setup() { + use(promised) const { spy } = use(spies) globalThis.Helper = new MockHelper() diff --git a/common/test/mock/helper.mjs b/common/test/mock/helper.mjs index c2b024f..4cab472 100644 --- a/common/test/mock/helper.mjs +++ b/common/test/mock/helper.mjs @@ -22,7 +22,8 @@ const DEFAULT_SETTINGS = { "check_for_updates": true, "reset_redo_stack": true, "last_install_greet": "0", - "enable_latex": false, + "enable_latex": true, + "enable_latex_async": true, "expression_editor": { "autoclose": true, "colorize": true, diff --git a/common/test/mock/latex.mjs b/common/test/mock/latex.mjs index c0a029c..2d6fb5f 100644 --- a/common/test/mock/latex.mjs +++ b/common/test/mock/latex.mjs @@ -22,10 +22,7 @@ const PIXEL = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVR4AWNgAAAAA export class MockLatex { constructor() { - } - - get supportsAsyncRender() { - return true + this.supportsAsyncRender = true } /** diff --git a/common/test/module/latex.mjs b/common/test/module/latex.mjs new file mode 100644 index 0000000..13ffd03 --- /dev/null +++ b/common/test/module/latex.mjs @@ -0,0 +1,144 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// Load prior tests +import "./base.mjs" +import "./expreval.mjs" + +import { describe, it } from "mocha" +import { expect } from "chai" +import { existsSync } from "../mock/fs.mjs" + +const { spy } = chaiPlugins + +import LatexAPI from "../../src/module/latex.mjs" + +describe("Module/Latex", function() { + it("is defined as a global", function() { + expect(globalThis.Modules.Latex).to.equal(LatexAPI) + }) + + describe("#initialize", function() { + it("isn't enabled before initialization", function() { + expect(LatexAPI.enabled).to.be.false + }) + + it("is enabled after initialization", function() { + LatexAPI.initialize({ latex: Latex, helper: Helper }) + expect(LatexAPI.enabled).to.equal(Helper.getSetting("enable_latex")) + expect(LatexAPI.initialized).to.be.true + }) + }) + + describe("#requestAsyncRender", function() { + it("should return a render result with a valid source, a width, and a height", async function() { + const data = await LatexAPI.requestAsyncRender("\\frac{x}{3}", 13, "#AA0033") + expect(data).to.be.an("object") + expect(data.source).to.be.a("string") + expect(data.source).to.satisfy(existsSync) + expect(data.height).to.be.a("number") + expect(data.width).to.be.a("number") + }) + + it("should call functions from the LaTeX module", async function() { + const renderSyncSpy = spy.on(Latex, "renderSync") + const renderAsyncSpy = spy.on(Latex, "renderAsync") + Latex.supportsAsyncRender = true + await LatexAPI.requestAsyncRender("\\frac{x}{3}", 13, "#AA0033") + expect(renderAsyncSpy).to.have.been.called.once + expect(renderSyncSpy).to.have.been.called.once // Called async + Latex.supportsAsyncRender = false + await LatexAPI.requestAsyncRender("\\frac{x}{3}", 13, "#AA0033") + expect(renderAsyncSpy).to.have.been.called.once // From the time before + expect(renderSyncSpy).to.have.been.called.twice + Latex.supportsAsyncRender = true + }) + + it("should not reply with the same source for different markup, font size, or color.", async function() { + const datas = [ + await LatexAPI.requestAsyncRender("\\frac{x}{3}", 13, "#AA0033"), + await LatexAPI.requestAsyncRender("\\frac{x}{4}", 13, "#AA0033"), + await LatexAPI.requestAsyncRender("\\frac{x}{3}", 14, "#AA0033"), + await LatexAPI.requestAsyncRender("\\frac{x}{3}", 13, "#0033AA") + ] + const sources = datas.map(x => x.source) + expect(new Set(sources)).to.have.a.lengthOf(4) + }) + }) + + describe("#findPrerendered", function() { + it("should return the same data as async render for the same markup, font size, and color", async function() { + const data = await LatexAPI.requestAsyncRender("\\frac{x}{3}", 13, "#AA0033") + const found = LatexAPI.findPrerendered("\\frac{x}{3}", 13, "#AA0033") + expect(found).to.not.be.null + expect(found.source).to.equal(data.source) + expect(found.width).to.equal(data.width) + }) + + it("should return null if the markup hasn't been prerendered with the same markup, font size, and color", async function() { + await LatexAPI.requestAsyncRender("\\frac{x}{3}", 13, "#AA0033") + expect(LatexAPI.findPrerendered("\\frac{y}{3}", 13, "#AA0033")).to.be.null + expect(LatexAPI.findPrerendered("\\frac{x}{3}", 12, "#AA0033")).to.be.null + expect(LatexAPI.findPrerendered("\\frac{x}{3}", 13, "#3300AA")).to.be.null + }) + }) + + describe("#par", function() { + it("should add parentheses to strings", function() { + expect(LatexAPI.par("string")).to.equal("(string)") + expect(LatexAPI.par("aaaa")).to.equal("(aaaa)") + expect(LatexAPI.par("")).to.equal("()") + expect(LatexAPI.par("(example)")).to.equal("((example))") + }) + }) + + describe("#parif", function() { + it("should add parentheses to strings that contain one of the ones in the list", function() { + expect(LatexAPI.parif("string", ["+"])).to.equal("string") + expect(LatexAPI.parif("string+assert", ["+"])).to.equal("(string+assert)") + expect(LatexAPI.parif("string+assert", ["+", "-"])).to.equal("(string+assert)") + expect(LatexAPI.parif("string-assert", ["+", "-"])).to.equal("(string-assert)") + }) + + it("shouldn't add new parentheses to strings that contains one of the ones in the list if they already have one", function() { + expect(LatexAPI.parif("(string+assert", ["+"])).to.equal("((string+assert)") + expect(LatexAPI.parif("string+assert)", ["+"])).to.equal("(string+assert))") + expect(LatexAPI.parif("(string+assert)", ["+"])).to.equal("(string+assert)") + expect(LatexAPI.parif("(string+assert)", ["+", "-"])).to.equal("(string+assert)") + expect(LatexAPI.parif("(string-assert)", ["+", "-"])).to.equal("(string-assert)") + }) + + it("shouldn't add parentheses to strings that does not contains one of the ones in the list", function() { + expect(LatexAPI.parif("string", ["+"])).to.equal("string") + expect(LatexAPI.parif("string+assert", ["-"])).to.equal("string+assert)") + expect(LatexAPI.parif("(string*assert", ["+", "-"])).to.equal("(string*assert") + expect(LatexAPI.parif("string/assert)", ["+", "-"])).to.equal("string/assert)") + }) + + it("should remove parentheses from strings that does not contains one of the ones in the list", function() { + expect(LatexAPI.parif("(string)", ["+"])).to.equal("string") + expect(LatexAPI.parif("(string+assert)", ["-"])).to.equal("string+assert") + expect(LatexAPI.parif("((string*assert)", ["+", "-"])).to.equal("(string*assert") + expect(LatexAPI.parif("(string/assert))", ["+", "-"])).to.equal("string/assert)") + }) + }) + + describe("#variable", function() { + + }) +}) \ No newline at end of file From b989a685e9bbca5a8343c95d4dfcd3ff623ccb6b Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 22 Oct 2024 01:05:06 +0200 Subject: [PATCH 063/104] Fixing issue with LaTeX sqrt. --- common/src/module/latex.mjs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/common/src/module/latex.mjs b/common/src/module/latex.mjs index dca9422..c9904de 100644 --- a/common/src/module/latex.mjs +++ b/common/src/module/latex.mjs @@ -143,9 +143,9 @@ class LatexAPI extends Module { parif(elem, contents) { elem = elem.toString() const contains = contents.some(x => elem.indexOf(x) > 0) - if(elem[0] !== "(" && elem.at(-1) !== ")" && contains) + if((elem[0] !== "(" || elem.at(-1) !== ")") && contains) return this.par(elem) - if(elem[0] === "(" && elem.at(-1) === ")" && !contains) + if((elem[0] === "(" || elem.at(-1) === ")") && !contains) return elem.removeEnclosure() return elem } @@ -170,13 +170,14 @@ class LatexAPI extends Module { else return `\\int\\limits_{${args[0]}}^{${args[1]}}${args[2]}(t) dt` case "sqrt": - return `\\sqrt\\left(${args.join(", ")}\\right)` + const arg = this.parif(args.join(", "), []) + return `\\sqrt{${arg}}` case "abs": return `\\left|${args.join(", ")}\\right|` case "floor": - return `\\left\\lfloor${args.join(", ")}\\right\\rfloor` + return `\\left\\lfloor{${args.join(", ")}}\\right\\rfloor` case "ceil": - return `\\left\\lceil${args.join(", ")}\\right\\rceil` + return `\\left\\lceil{${args.join(", ")}}\\right\\rceil` default: return `\\mathrm{${f}}\\left(${args.join(", ")}\\right)` } @@ -294,7 +295,7 @@ class LatexAPI extends Module { nstack.push(this.parif(n1, ["+", "-", "*", "/", "^"]) + "!") break default: - nstack.push(f + this.parif(n1, ["+", "-", "*", "/", "^"])) + nstack.push(this.functionToLatex(f, [this.parif(n1, ["+", "-", "*", "/", "^"])])) break } break @@ -332,6 +333,7 @@ class LatexAPI extends Module { if(nstack.length > 1) { nstack = [nstack.join(";")] } + console.log(nstack[0]) return String(nstack[0]) } } From 14e8cef6af89decfe44866d84598366cf344bc29 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 22 Oct 2024 02:50:00 +0200 Subject: [PATCH 064/104] Fixing issues with LaTeX and rendering variable pi. --- common/src/lib/expr-eval/polyfill.mjs | 5 ----- common/src/module/latex.mjs | 23 ++++++++++------------- common/test/basics/polyfill.mjs | 0 3 files changed, 10 insertions(+), 18 deletions(-) create mode 100644 common/test/basics/polyfill.mjs diff --git a/common/src/lib/expr-eval/polyfill.mjs b/common/src/lib/expr-eval/polyfill.mjs index c618aaf..a15c741 100644 --- a/common/src/lib/expr-eval/polyfill.mjs +++ b/common/src/lib/expr-eval/polyfill.mjs @@ -266,11 +266,6 @@ export function roundTo(value, exp) { return +(value[0] + "e" + (value[1] ? (+value[1] + exp) : exp)) } -export function setVar(name, value, variables) { - if(variables) variables[name] = value - return value -} - export function arrayIndex(array, index) { return array[index | 0] } diff --git a/common/src/module/latex.mjs b/common/src/module/latex.mjs index c9904de..216e3be 100644 --- a/common/src/module/latex.mjs +++ b/common/src/module/latex.mjs @@ -21,7 +21,7 @@ import * as Instruction from "../lib/expr-eval/instruction.mjs" import { escapeValue } from "../lib/expr-eval/expression.mjs" import { HelperInterface, LatexInterface } from "./interface.mjs" -const unicodechars = [ +const unicodechars = ["pi", "∞", "α", "β", "γ", "δ", "ε", "ζ", "η", "π", "θ", "κ", "λ", "μ", "ξ", "ρ", "ς", "σ", "τ", "φ", "χ", "ψ", "ω", @@ -30,9 +30,9 @@ const unicodechars = [ "ₕ", "ₖ", "ₗ", "ₘ", "ₙ", "ₚ", "ₛ", "ₜ", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹", "⁰", "₁", "₂", "₃", - "₄", "₅", "₆", "₇", "₈", "₉", "₀", - "pi", "∞"] -const equivalchars = [ + "₄", "₅", "₆", "₇", "₈", "₉", "₀" +] +const equivalchars = ["\\pi", "\\infty", "\\alpha", "\\beta", "\\gamma", "\\delta", "\\epsilon", "\\zeta", "\\eta", "\\pi", "\\theta", "\\kappa", "\\lambda", "\\mu", "\\xi", "\\rho", "\\sigma", "\\sigma", "\\tau", "\\phi", "\\chi", "\\psi", "\\omega", @@ -42,7 +42,7 @@ const equivalchars = [ "{}_{t}", "{}^{1}", "{}^{2}", "{}^{3}", "{}^{4}", "{}^{5}", "{}^{6}", "{}^{7}", "{}^{8}", "{}^{9}", "{}^{0}", "{}_{1}", "{}_{2}", "{}_{3}", "{}_{4}", "{}_{5}", "{}_{6}", "{}_{7}", "{}_{8}", "{}_{9}", "{}_{0}", - "\\pi", "\\infty"] +] /** * Class containing the result of a LaTeX render. @@ -143,9 +143,9 @@ class LatexAPI extends Module { parif(elem, contents) { elem = elem.toString() const contains = contents.some(x => elem.indexOf(x) > 0) - if((elem[0] !== "(" || elem.at(-1) !== ")") && contains) + if(contains && (elem[0] !== "(" || elem.at(-1) !== ")")) return this.par(elem) - if((elem[0] === "(" || elem.at(-1) === ")") && !contains) + if(!contains && elem[0] === "(" && elem.at(-1) === ")") return elem.removeEnclosure() return elem } @@ -191,16 +191,17 @@ class LatexAPI extends Module { * @returns {string} */ variable(vari, wrapIn$ = false) { - if(wrapIn$) + if(wrapIn$) { for(let i = 0; i < unicodechars.length; i++) { if(vari.includes(unicodechars[i])) vari = vari.replaceAll(unicodechars[i], "$" + equivalchars[i] + "$") } - else + } else { for(let i = 0; i < unicodechars.length; i++) { if(vari.includes(unicodechars[i])) vari = vari.replaceAll(unicodechars[i], equivalchars[i]) } + } return vari } @@ -330,10 +331,6 @@ class LatexAPI extends Module { throw new EvalError("invalid Expression") } } - if(nstack.length > 1) { - nstack = [nstack.join(";")] - } - console.log(nstack[0]) return String(nstack[0]) } } diff --git a/common/test/basics/polyfill.mjs b/common/test/basics/polyfill.mjs new file mode 100644 index 0000000..e69de29 From d53f50193a1988a002e35ce0bdac91f001ce6ac4 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 22 Oct 2024 02:50:24 +0200 Subject: [PATCH 065/104] Finishing latex and polyfill tests. --- common/test/basics/polyfill.mjs | 231 ++++++++++++++++++++++++++++++++ common/test/module/latex.mjs | 91 ++++++++++++- 2 files changed, 320 insertions(+), 2 deletions(-) diff --git a/common/test/basics/polyfill.mjs b/common/test/basics/polyfill.mjs index e69de29..ce018f2 100644 --- a/common/test/basics/polyfill.mjs +++ b/common/test/basics/polyfill.mjs @@ -0,0 +1,231 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// Load prior tests + +import { describe, it } from "mocha" +import { expect } from "chai" + +import * as Polyfill from "../../src/lib/expr-eval/polyfill.mjs" +import { + andOperator, + cbrt, + equal, + expm1, + hypot, + lessThan, + log1p, + log2, + notEqual +} from "../../src/lib/expr-eval/polyfill.mjs" + +describe("Math/Polyfill", () => { + describe("#AADDDD", function() { + it("should add two numbers", function() { + expect(Polyfill.add(2, 3)).to.equal(5) + expect(Polyfill.add("2", "3")).to.equal(5) + }) + }) + + describe("#sub", function() { + it("should subtract two numbers", function() { + expect(Polyfill.sub(2, 1)).to.equal(1) + expect(Polyfill.sub("2", "1")).to.equal(1) + }) + }) + + describe("#mul", function() { + it("should multiply two numbers", function() { + expect(Polyfill.mul(2, 3)).to.equal(6) + expect(Polyfill.mul("2", "3")).to.equal(6) + }) + }) + + describe("#div", function() { + it("should divide two numbers", function() { + expect(Polyfill.div(10, 2)).to.equal(5) + expect(Polyfill.div("10", "2")).to.equal(5) + }) + }) + + describe("#mod", function() { + it("should return the modulo of two numbers", function() { + expect(Polyfill.mod(10, 3)).to.equal(1) + expect(Polyfill.mod("10", "3")).to.equal(1) + }) + }) + + describe("#concat", function() { + it("should return the concatenation of two strings", function() { + expect(Polyfill.concat(10, 3)).to.equal("103") + expect(Polyfill.concat("abc", "def")).to.equal("abcdef") + }) + }) + + describe("#equal", function() { + it("should return whether its two arguments are equal", function() { + expect(Polyfill.equal(10, 3)).to.be.false + expect(Polyfill.equal(10, 10)).to.be.true + expect(Polyfill.equal("abc", "def")).to.be.false + expect(Polyfill.equal("abc", "abc")).to.be.true + }) + }) + + describe("#notEqual", function() { + it("should return whether its two arguments are not equal", function() { + expect(Polyfill.notEqual(10, 3)).to.be.true + expect(Polyfill.notEqual(10, 10)).to.be.false + expect(Polyfill.notEqual("abc", "def")).to.be.true + expect(Polyfill.notEqual("abc", "abc")).to.be.false + }) + }) + + describe("#greaterThan", function() { + it("should return whether its first argument is strictly greater than its second", function() { + expect(Polyfill.greaterThan(10, 3)).to.be.true + expect(Polyfill.greaterThan(10, 10)).to.be.false + expect(Polyfill.greaterThan(10, 30)).to.be.false + }) + }) + + describe("#lessThan", function() { + it("should return whether its first argument is strictly less than its second", function() { + expect(Polyfill.lessThan(10, 3)).to.be.false + expect(Polyfill.lessThan(10, 10)).to.be.false + expect(Polyfill.lessThan(10, 30)).to.be.true + }) + }) + + describe("#greaterThanEqual", function() { + it("should return whether its first argument is greater or equal to its second", function() { + expect(Polyfill.greaterThanEqual(10, 3)).to.be.true + expect(Polyfill.greaterThanEqual(10, 10)).to.be.true + expect(Polyfill.greaterThanEqual(10, 30)).to.be.false + }) + }) + + describe("#lessThanEqual", function() { + it("should return whether its first argument is strictly less than its second", function() { + expect(Polyfill.lessThanEqual(10, 3)).to.be.false + expect(Polyfill.lessThanEqual(10, 10)).to.be.true + expect(Polyfill.lessThanEqual(10, 30)).to.be.true + }) + }) + + describe("#andOperator", function() { + it("should return whether its arguments are both true", function() { + expect(Polyfill.andOperator(true, true)).to.be.true + expect(Polyfill.andOperator(true, false)).to.be.false + expect(Polyfill.andOperator(false, true)).to.be.false + expect(Polyfill.andOperator(false, false)).to.be.false + expect(Polyfill.andOperator(10, 3)).to.be.true + expect(Polyfill.andOperator(10, 0)).to.be.false + expect(Polyfill.andOperator(0, 0)).to.be.false + }) + }) + + describe("#orOperator", function() { + it("should return whether one of its arguments is true", function() { + expect(Polyfill.orOperator(true, true)).to.be.true + expect(Polyfill.orOperator(true, false)).to.be.true + expect(Polyfill.orOperator(false, true)).to.be.true + expect(Polyfill.orOperator(false, false)).to.be.false + expect(Polyfill.orOperator(10, 3)).to.be.true + expect(Polyfill.orOperator(10, 0)).to.be.true + expect(Polyfill.orOperator(0, 0)).to.be.false + }) + }) + + describe("#inOperator", function() { + it("should check if second argument contains first", function() { + expect(Polyfill.inOperator("a", ["a", "b", "c"])).to.be.true + expect(Polyfill.inOperator(3, [0, 1, 2])).to.be.false + expect(Polyfill.inOperator(3, [0, 1, 3, 2])).to.be.true + expect(Polyfill.inOperator("a", "abcdef")).to.be.true + expect(Polyfill.inOperator("a", "bcdefg")).to.be.false + }) + }) + + describe("#sinh, #cosh, #tanh, #asinh, #acosh, #atanh", function() { + const EPSILON = 1e-12 + for(let x = -.9; x < 1; x += 0.1) { + expect(Polyfill.sinh(x)).to.be.approximately(Math.sinh(x), EPSILON) + expect(Polyfill.cosh(x)).to.be.approximately(Math.cosh(x), EPSILON) + expect(Polyfill.tanh(x)).to.be.approximately(Math.tanh(x), EPSILON) + expect(Polyfill.asinh(x)).to.be.approximately(Math.asinh(x), EPSILON) + expect(Polyfill.atanh(x)).to.be.approximately(Math.atanh(x), EPSILON) + } + for(let x = 1.1; x < 10; x += 0.1) { + expect(Polyfill.sinh(x)).to.be.approximately(Math.sinh(x), EPSILON) + expect(Polyfill.cosh(x)).to.be.approximately(Math.cosh(x), EPSILON) + expect(Polyfill.tanh(x)).to.be.approximately(Math.tanh(x), EPSILON) + expect(Polyfill.asinh(x)).to.be.approximately(Math.asinh(x), EPSILON) + expect(Polyfill.acosh(x)).to.be.approximately(Math.acosh(x), EPSILON) + expect(Polyfill.log10(x)).to.be.approximately(Math.log10(x), EPSILON) + } + }) + + describe("#trunc", function() { + it("should return the decimal part of floats", function() { + for(let x = -10; x < 10; x += 0.1) + expect(Polyfill.trunc(x)).to.equal(Math.trunc(x)) + }) + }) + + describe("#gamma", function() { + it("should return the product of factorial(x - 1)", function() { + expect(Polyfill.gamma(0)).to.equal(Infinity) + expect(Polyfill.gamma(1)).to.equal(1) + expect(Polyfill.gamma(2)).to.equal(1) + expect(Polyfill.gamma(3)).to.equal(2) + expect(Polyfill.gamma(4)).to.equal(6) + expect(Polyfill.gamma(5)).to.equal(24) + expect(Polyfill.gamma(172)).to.equal(Infinity) + expect(Polyfill.gamma(172.3)).to.equal(Infinity) + expect(Polyfill.gamma(.2)).to.approximately(4.590_843_712, 1e-8) + expect(Polyfill.gamma(5.5)).to.be.approximately(52.34277778, 1e-8) + expect(Polyfill.gamma(90.2)).to.equal(4.0565358202825355e+136) + }) + }) + + describe("#hypot", function() { + it("should return the hypothenus length of a triangle whose length are provided in arguments", function() { + for(let x = 0; x < 10; x += 0.3) { + expect(Polyfill.hypot(x)).to.be.approximately(Math.hypot(x), Number.EPSILON) + for(let y = 0; y < 10; y += 0.3) { + expect(Polyfill.hypot(x, y)).to.be.approximately(Math.hypot(x, y), Number.EPSILON) + } + } + }) + }) + + describe("#sign, #cbrt, #exmp1", function() { + for(let x = -10; x < 10; x += 0.3) { + expect(Polyfill.sign(x)).to.approximately(Math.sign(x), 1e-12) + expect(Polyfill.cbrt(x)).to.approximately(Math.cbrt(x), 1e-12) + expect(Polyfill.expm1(x)).to.approximately(Math.expm1(x), 1e-12) + } + }) + + describe("#log1p, #log2", function() { + for(let x = 1; x < 10; x += 0.3) { + expect(Polyfill.log1p(x)).to.be.approximately(Math.log1p(x), 1e-12) + expect(Polyfill.log2(x)).to.be.approximately(Math.log2(x), 1e-12) + } + }) +}) \ No newline at end of file diff --git a/common/test/module/latex.mjs b/common/test/module/latex.mjs index 13ffd03..02aaca5 100644 --- a/common/test/module/latex.mjs +++ b/common/test/module/latex.mjs @@ -17,6 +17,7 @@ */ // Load prior tests +import "../basics/utils.mjs" import "./base.mjs" import "./expreval.mjs" @@ -26,6 +27,7 @@ import { existsSync } from "../mock/fs.mjs" const { spy } = chaiPlugins +import ExprEval from "../../src/module/expreval.mjs" import LatexAPI from "../../src/module/latex.mjs" describe("Module/Latex", function() { @@ -125,7 +127,7 @@ describe("Module/Latex", function() { it("shouldn't add parentheses to strings that does not contains one of the ones in the list", function() { expect(LatexAPI.parif("string", ["+"])).to.equal("string") - expect(LatexAPI.parif("string+assert", ["-"])).to.equal("string+assert)") + expect(LatexAPI.parif("string+assert", ["-"])).to.equal("string+assert") expect(LatexAPI.parif("(string*assert", ["+", "-"])).to.equal("(string*assert") expect(LatexAPI.parif("string/assert)", ["+", "-"])).to.equal("string/assert)") }) @@ -139,6 +141,91 @@ describe("Module/Latex", function() { }) describe("#variable", function() { - + const from = [ + "α", "β", "γ", "δ", "ε", "ζ", "η", + "π", "θ", "κ", "λ", "μ", "ξ", "ρ", + "ς", "σ", "τ", "φ", "χ", "ψ", "ω", + "Γ", "Δ", "Θ", "Λ", "Ξ", "Π", "Σ", + "Φ", "Ψ", "Ω", "ₐ", "ₑ", "ₒ", "ₓ", + "ₕ", "ₖ", "ₗ", "ₘ", "ₙ", "ₚ", "ₛ", + "ₜ", "¹", "²", "³", "⁴", "⁵", "⁶", + "⁷", "⁸", "⁹", "⁰", "₁", "₂", "₃", + "₄", "₅", "₆", "₇", "₈", "₉", "₀", + "pi", "∞"] + const to = [ + "\\alpha", "\\beta", "\\gamma", "\\delta", "\\epsilon", "\\zeta", "\\eta", + "\\pi", "\\theta", "\\kappa", "\\lambda", "\\mu", "\\xi", "\\rho", + "\\sigma", "\\sigma", "\\tau", "\\phi", "\\chi", "\\psi", "\\omega", + "\\Gamma", "\\Delta", "\\Theta", "\\Lambda", "\\Xi", "\\Pi", "\\Sigma", + "\\Phy", "\\Psi", "\\Omega", "{}_{a}", "{}_{e}", "{}_{o}", "{}_{x}", + "{}_{h}", "{}_{k}", "{}_{l}", "{}_{m}", "{}_{n}", "{}_{p}", "{}_{s}", + "{}_{t}", "{}^{1}", "{}^{2}", "{}^{3}", "{}^{4}", "{}^{5}", "{}^{6}", + "{}^{7}", "{}^{8}", "{}^{9}", "{}^{0}", "{}_{1}", "{}_{2}", "{}_{3}", + "{}_{4}", "{}_{5}", "{}_{6}", "{}_{7}", "{}_{8}", "{}_{9}", "{}_{0}", + "\\pi", "\\infty"] + + it("should convert unicode characters to their latex equivalent", function() { + for(let i = 0; i < from.length; i++) + expect(LatexAPI.variable(from[i])).to.include(to[i]) + }) + + it("should wrap within dollar signs when the option is included", function() { + for(let i = 0; i < from.length; i++) { + expect(LatexAPI.variable(from[i], false)).to.equal(to[i]) + expect(LatexAPI.variable(from[i], true)).to.equal(`$${to[i]}$`) + } + }) + + it("should be able to convert multiple of them", function() { + expect(LatexAPI.variable("α₂", false)).to.equal("\\alpha{}_{2}") + expect(LatexAPI.variable("∞piΠ", false)).to.equal("\\infty\\pi\\Pi") + }) + }) + + describe("#functionToLatex", function() { + it("should transform derivatives into latex fractions", function() { + const d1 = LatexAPI.functionToLatex("derivative", ["'3t'", "'t'", "x+2"]) + const d2 = LatexAPI.functionToLatex("derivative", ["f", "x+2"]) + expect(d1).to.equal("\\frac{d3x}{dx}") + expect(d2).to.equal("\\frac{df}{dx}(x+2)") + }) + + it("should transform integrals into latex limits", function() { + const i1 = LatexAPI.functionToLatex("integral", ["0", "x", "'3y'", "'y'"]) + const i2 = LatexAPI.functionToLatex("integral", ["1", "2", "f"]) + expect(i1).to.equal("\\int\\limits_{0}^{x}3y dy") + expect(i2).to.equal("\\int\\limits_{1}^{2}f(t) dt") + }) + + it("should transform sqrt functions to sqrt latex", function() { + const sqrt1 = LatexAPI.functionToLatex("sqrt", ["(x+2)"]) + const sqrt2 = LatexAPI.functionToLatex("sqrt", ["\\frac{x}{2}"]) + expect(sqrt1).to.equal("\\sqrt{x+2}") + expect(sqrt2).to.equal("\\sqrt{\\frac{x}{2}}") + }) + + it("should transform abs, floor and ceil", function() { + const abs = LatexAPI.functionToLatex("abs", ["x+3"]) + const floor = LatexAPI.functionToLatex("floor", ["x+3"]) + const ceil = LatexAPI.functionToLatex("ceil", ["x+3"]) + expect(abs).to.equal("\\left|x+3\\right|") + expect(floor).to.equal("\\left\\lfloor{x+3}\\right\\rfloor") + expect(ceil).to.equal("\\left\\lceil{x+3}\\right\\rceil") + }) + + it("should transform regular functions into latex", function() { + const f1 = LatexAPI.functionToLatex("f", ["x+3", true]) + const f2 = LatexAPI.functionToLatex("h_1", ["10"]) + expect(f1).to.equal("\\mathrm{f}\\left(x+3, true\\right)") + expect(f2).to.equal("\\mathrm{h_1}\\left(10\\right)") + }) + }) + + describe("#expression", function() { + it("should transform parsed expressions", function() { + const expr = ExprEval.parse("(+1! == 2/2 ? sin [-2.2][0] : f(t)^(1+1-1) + sqrt(A.t)) * 3 % 1") + const expected = "((((+1!))==(\\frac{2}{2}) ? (\\mathrm{sin}\\left(([(-2.2)][0])\\right)) : (\\mathrm{f}\\left(t\\right)^{1+1-1}+\\sqrt{A.t})) \\times 3) \\mathrm{mod} 1" + expect(LatexAPI.expression(expr.tokens)).to.equal(expected) + }) }) }) \ No newline at end of file From 67799e99083dae45e480a319c0bc82093142a2e8 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 22 Oct 2024 02:50:56 +0200 Subject: [PATCH 066/104] Removing debug from python. --- runtime-pyside6/LogarithmPlotter/util/latex.py | 2 +- runtime-pyside6/LogarithmPlotter/util/promise.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/runtime-pyside6/LogarithmPlotter/util/latex.py b/runtime-pyside6/LogarithmPlotter/util/latex.py index f36f07f..71064fa 100644 --- a/runtime-pyside6/LogarithmPlotter/util/latex.py +++ b/runtime-pyside6/LogarithmPlotter/util/latex.py @@ -181,7 +181,7 @@ class Latex(QObject): """ markup_hash, render_hash, export_path = self.create_export_path(latex_markup, font_size, color) if self.latexSupported and not path.exists(export_path + ".png"): - print("Rendering", latex_markup, export_path) + print("Rendering", latex_markup) # Generating file latex_path = path.join(self.tempdir, str(markup_hash)) # If the formula is just recolored or the font is just changed, no need to recreate the DVI. diff --git a/runtime-pyside6/LogarithmPlotter/util/promise.py b/runtime-pyside6/LogarithmPlotter/util/promise.py index f43e85b..f65efa8 100644 --- a/runtime-pyside6/LogarithmPlotter/util/promise.py +++ b/runtime-pyside6/LogarithmPlotter/util/promise.py @@ -153,7 +153,6 @@ class PyPromise(QObject): def _fulfill(self, data): self._state = "fulfilled" no_return = [None, QJSValue.SpecialValue.UndefinedValue] - print("Fulfill") for i in range(len(self._fulfills)): try: result = self._fulfills[i](data) From 2594fd68442113819f62dcef988adcd1555d8c54 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sat, 26 Oct 2024 01:06:24 +0200 Subject: [PATCH 067/104] Adding new expression tests. --- README.md | 6 +- common/src/math/expression.mjs | 53 +++++++--- common/src/module/io.mjs | 1 - common/src/objs/common.mjs | 2 +- common/test/basics/polyfill.mjs | 41 ++++---- common/test/math/expression.mjs | 181 ++++++++++++++++++++++++++++++++ common/test/mock/qt.mjs | 13 ++- common/test/module/latex.mjs | 36 +++---- common/test/module/objects.mjs | 3 +- 9 files changed, 274 insertions(+), 62 deletions(-) create mode 100644 common/test/math/expression.mjs diff --git a/README.md b/README.md index 249792a..976df53 100644 --- a/README.md +++ b/README.md @@ -95,8 +95,8 @@ Finally, to actually run the tests: You should have received a copy of the GNU General Public License along with this program. If not, see . -Language files translations located at LogarithmPlotter/i18n are licensed under GNU GPL3.0+ and are copyrighted by their -original authors. See LICENSE.md for more details: +See LICENSE.md for more details. Language files translations located at assets/i18n are licensed under GNU GPL3.0+ and +are copyrighted by their original authors: - 🇭🇺 Hungarian translation by [Óvári](https://github.com/ovari) - 🇳🇴 Norwegian translation by [Allan Nordhøy](https://github.com/comradekingu) @@ -109,5 +109,5 @@ of [ndef.parser](https://web.archive.org/web/20111023001618/http://www.undefined <r@undefined.ch>, ported to javascript by Matthew Crumley <email@matthewcrumley.com> (http://silentmatt.com/), and then to QMLJS by Ad5001. -All files in (LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/lib/expr-eval/) except integration.mjs are licensed +All files in (common/src/lib/expr-eval/) except integration.mjs are licensed under the [MIT License](https://raw.githubusercontent.com/silentmatt/expr-eval/master/LICENSE.txt). diff --git a/common/src/math/expression.mjs b/common/src/math/expression.mjs index 2862183..5701ac6 100644 --- a/common/src/math/expression.mjs +++ b/common/src/math/expression.mjs @@ -21,24 +21,34 @@ import * as Utils from "../utils.mjs" import Latex from "../module/latex.mjs" import ExprParser from "../module/expreval.mjs" import Objects from "../module/objects.mjs" +import { ExprEvalExpression } from "../lib/expr-eval/expression.mjs" + +const NUMBER_MATCHER = /^\d*\.\d+(e[+-]\d+)?$/ /** * Represents any kind of x-based or non variable based expression. */ export class Expression { + /** + * + * @param {string|ExprEvalExpression} expr + */ constructor(expr) { if(typeof expr === "string") { this.expr = Utils.exponentsToExpression(expr) this.calc = ExprParser.parse(this.expr).simplify() - } else { + } else if(expr instanceof ExprEvalExpression) { // Passed an expression here directly. this.calc = expr.simplify() this.expr = expr.toString() + } else { + const type = expr != null ? "a " + expr.constructor.name : expr + throw new Error(`Cannot create an expression with ${type}.`) } - this.cached = this.isConstant() + this.canBeCached = this.isConstant() this.cachedValue = null - if(this.cached && this.allRequirementsFulfilled()) - this.cachedValue = this.calc.evaluate(Objects.currentObjectsByName) + if(this.canBeCached && this.allRequirementsFulfilled()) + this.recache() this.latexMarkup = Latex.expression(this.calc.tokens) } @@ -77,21 +87,20 @@ export class Expression { /** * Returns a list of names whose corresponding objects this expression is dependant on and are missing. - * @return {boolean} + * @return {string[]} */ undefinedVariables() { return this.requiredObjects().filter(objName => !(objName in Objects.currentObjectsByName)) } recache() { - if(this.cached) - this.cachedValue = this.calc.evaluate(Objects.currentObjectsByName) + this.cachedValue = this.calc.evaluate(Objects.currentObjectsByName) } execute(x = 1) { - if(this.cached) { + if(this.canBeCached) { if(this.cachedValue == null) - this.cachedValue = this.calc.evaluate(Objects.currentObjectsByName) + this.recache() return this.cachedValue } ExprParser.currentVars = Object.assign({ "x": x }, Objects.currentObjectsByName) @@ -99,9 +108,10 @@ export class Expression { } simplify(x) { - let expr = this.calc.substitute("x", x).simplify() - if(expr.evaluate() === 0) expr = "0" - return new Expression(expr) + let expr = new Expression(this.calc.substitute("x", x).simplify()) + if(expr.allRequirementsFulfilled() && expr.execute() === 0) + expr = new Expression("0") + return expr } toEditableString() { @@ -110,17 +120,28 @@ export class Expression { toString(forceSign = false) { let str = Utils.makeExpressionReadable(this.calc.toString()) - if(str !== undefined && str.match(/^\d*\.\d+$/)) { - if(str.split(".")[1].split("0").length > 7) { + if(str !== undefined && str.match(NUMBER_MATCHER)) { + const decimals = str.split(".")[1].split("e")[0] + const zeros = decimals.split("0").length + const nines = decimals.split("9").length + if(zeros > 7 || nines > 7) { // Likely rounding error - str = parseFloat(str.substring(0, str.length - 1)).toString() + str = parseFloat(str).toDecimalPrecision(8).toString() } } - if(str[0] !== "-" && forceSign) str = "+" + str + if(str[0] === "(" && str.at(-1) === ")") + str = str.substring(1, str.length - 1) + if(str[0] !== "-" && forceSign) + str = "+" + str return str } } +/** + * Parses and executes the given expression + * @param {string} expr + * @return {number} + */ export function executeExpression(expr) { return (new Expression(expr.toString())).execute() } diff --git a/common/src/module/io.mjs b/common/src/module/io.mjs index 92096e9..1ac6e58 100644 --- a/common/src/module/io.mjs +++ b/common/src/module/io.mjs @@ -19,7 +19,6 @@ import { Module } from "./common.mjs" import Objects from "./objects.mjs" import History from "./history.mjs" -import Canvas from "./canvas.mjs" import Settings from "./settings.mjs" import { DialogInterface, RootInterface } from "./interface.mjs" import { BaseEvent } from "../events.mjs" diff --git a/common/src/objs/common.mjs b/common/src/objs/common.mjs index 891fdd5..1534a9a 100644 --- a/common/src/objs/common.mjs +++ b/common/src/objs/common.mjs @@ -224,7 +224,7 @@ export class DrawableObject { currentObjectsByName[objName].requiredBy.push(this) } } - if(this[property].cached && this[property].requiredObjects().length > 0) + if(this[property].canBeCached && this[property].requiredObjects().length > 0) // Recalculate this[property].recache() diff --git a/common/test/basics/polyfill.mjs b/common/test/basics/polyfill.mjs index ce018f2..4c44514 100644 --- a/common/test/basics/polyfill.mjs +++ b/common/test/basics/polyfill.mjs @@ -35,50 +35,50 @@ import { } from "../../src/lib/expr-eval/polyfill.mjs" describe("Math/Polyfill", () => { - describe("#AADDDD", function() { - it("should add two numbers", function() { + describe("#add", function() { + it("adds two numbers", function() { expect(Polyfill.add(2, 3)).to.equal(5) expect(Polyfill.add("2", "3")).to.equal(5) }) }) describe("#sub", function() { - it("should subtract two numbers", function() { + it("subtracts two numbers", function() { expect(Polyfill.sub(2, 1)).to.equal(1) expect(Polyfill.sub("2", "1")).to.equal(1) }) }) describe("#mul", function() { - it("should multiply two numbers", function() { + it("multiplies two numbers", function() { expect(Polyfill.mul(2, 3)).to.equal(6) expect(Polyfill.mul("2", "3")).to.equal(6) }) }) describe("#div", function() { - it("should divide two numbers", function() { + it("divides two numbers", function() { expect(Polyfill.div(10, 2)).to.equal(5) expect(Polyfill.div("10", "2")).to.equal(5) }) }) describe("#mod", function() { - it("should return the modulo of two numbers", function() { + it("returns the modulo of two numbers", function() { expect(Polyfill.mod(10, 3)).to.equal(1) expect(Polyfill.mod("10", "3")).to.equal(1) }) }) describe("#concat", function() { - it("should return the concatenation of two strings", function() { + it("returns the concatenation of two strings", function() { expect(Polyfill.concat(10, 3)).to.equal("103") expect(Polyfill.concat("abc", "def")).to.equal("abcdef") }) }) describe("#equal", function() { - it("should return whether its two arguments are equal", function() { + it("returns whether its two arguments are equal", function() { expect(Polyfill.equal(10, 3)).to.be.false expect(Polyfill.equal(10, 10)).to.be.true expect(Polyfill.equal("abc", "def")).to.be.false @@ -87,7 +87,7 @@ describe("Math/Polyfill", () => { }) describe("#notEqual", function() { - it("should return whether its two arguments are not equal", function() { + it("returns whether its two arguments are not equal", function() { expect(Polyfill.notEqual(10, 3)).to.be.true expect(Polyfill.notEqual(10, 10)).to.be.false expect(Polyfill.notEqual("abc", "def")).to.be.true @@ -96,7 +96,7 @@ describe("Math/Polyfill", () => { }) describe("#greaterThan", function() { - it("should return whether its first argument is strictly greater than its second", function() { + it("returns whether its first argument is strictly greater than its second", function() { expect(Polyfill.greaterThan(10, 3)).to.be.true expect(Polyfill.greaterThan(10, 10)).to.be.false expect(Polyfill.greaterThan(10, 30)).to.be.false @@ -104,7 +104,7 @@ describe("Math/Polyfill", () => { }) describe("#lessThan", function() { - it("should return whether its first argument is strictly less than its second", function() { + it("returns whether its first argument is strictly less than its second", function() { expect(Polyfill.lessThan(10, 3)).to.be.false expect(Polyfill.lessThan(10, 10)).to.be.false expect(Polyfill.lessThan(10, 30)).to.be.true @@ -112,7 +112,7 @@ describe("Math/Polyfill", () => { }) describe("#greaterThanEqual", function() { - it("should return whether its first argument is greater or equal to its second", function() { + it("returns whether its first argument is greater or equal to its second", function() { expect(Polyfill.greaterThanEqual(10, 3)).to.be.true expect(Polyfill.greaterThanEqual(10, 10)).to.be.true expect(Polyfill.greaterThanEqual(10, 30)).to.be.false @@ -120,7 +120,7 @@ describe("Math/Polyfill", () => { }) describe("#lessThanEqual", function() { - it("should return whether its first argument is strictly less than its second", function() { + it("returns whether its first argument is strictly less than its second", function() { expect(Polyfill.lessThanEqual(10, 3)).to.be.false expect(Polyfill.lessThanEqual(10, 10)).to.be.true expect(Polyfill.lessThanEqual(10, 30)).to.be.true @@ -128,7 +128,7 @@ describe("Math/Polyfill", () => { }) describe("#andOperator", function() { - it("should return whether its arguments are both true", function() { + it("returns whether its arguments are both true", function() { expect(Polyfill.andOperator(true, true)).to.be.true expect(Polyfill.andOperator(true, false)).to.be.false expect(Polyfill.andOperator(false, true)).to.be.false @@ -140,7 +140,7 @@ describe("Math/Polyfill", () => { }) describe("#orOperator", function() { - it("should return whether one of its arguments is true", function() { + it("returns whether one of its arguments is true", function() { expect(Polyfill.orOperator(true, true)).to.be.true expect(Polyfill.orOperator(true, false)).to.be.true expect(Polyfill.orOperator(false, true)).to.be.true @@ -152,7 +152,7 @@ describe("Math/Polyfill", () => { }) describe("#inOperator", function() { - it("should check if second argument contains first", function() { + it("checks if second argument contains first", function() { expect(Polyfill.inOperator("a", ["a", "b", "c"])).to.be.true expect(Polyfill.inOperator(3, [0, 1, 2])).to.be.false expect(Polyfill.inOperator(3, [0, 1, 3, 2])).to.be.true @@ -181,14 +181,14 @@ describe("Math/Polyfill", () => { }) describe("#trunc", function() { - it("should return the decimal part of floats", function() { + it("returns the decimal part of floats", function() { for(let x = -10; x < 10; x += 0.1) expect(Polyfill.trunc(x)).to.equal(Math.trunc(x)) }) }) describe("#gamma", function() { - it("should return the product of factorial(x - 1)", function() { + it("returns the product of factorial(x - 1)", function() { expect(Polyfill.gamma(0)).to.equal(Infinity) expect(Polyfill.gamma(1)).to.equal(1) expect(Polyfill.gamma(2)).to.equal(1) @@ -204,7 +204,7 @@ describe("Math/Polyfill", () => { }) describe("#hypot", function() { - it("should return the hypothenus length of a triangle whose length are provided in arguments", function() { + it("returns the hypothenus length of a triangle whose length are provided in arguments", function() { for(let x = 0; x < 10; x += 0.3) { expect(Polyfill.hypot(x)).to.be.approximately(Math.hypot(x), Number.EPSILON) for(let y = 0; y < 10; y += 0.3) { @@ -224,7 +224,8 @@ describe("Math/Polyfill", () => { describe("#log1p, #log2", function() { for(let x = 1; x < 10; x += 0.3) { - expect(Polyfill.log1p(x)).to.be.approximately(Math.log1p(x), 1e-12) + expect(Polyfill.log1p(x)).to + .be.approximately(Math.log1p(x), 1e-12) expect(Polyfill.log2(x)).to.be.approximately(Math.log2(x), 1e-12) } }) diff --git a/common/test/math/expression.mjs b/common/test/math/expression.mjs new file mode 100644 index 0000000..a0ee113 --- /dev/null +++ b/common/test/math/expression.mjs @@ -0,0 +1,181 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// Load prior tests +import "../basics/utils.mjs" +import "../module/latex.mjs" +import "../module/expreval.mjs" +import "../module/objects.mjs" + +import { describe, it } from "mocha" +import { expect } from "chai" + +import { executeExpression, Expression } from "../../src/math/expression.mjs" +import ExprEval from "../../src/module/expreval.mjs" + + +describe("Math/Expression", function() { + describe("#constructor", function() { + it("accepts strings", function() { + expect(() => new Expression("2+3")).to.not.throw + expect(() => new Expression("x+2")).to.not.throw + }) + + it("accepts already parsed expressions", function() { + expect(() => new Expression(ExprEval.parse("2+3"))).to.not.throw + expect(() => new Expression(ExprEval.parse("x+2"))).to.not.throw + }) + + it("doesn't accept anything else", function() { + expect(() => new Expression()).to.throw("Cannot create an expression with undefined.") + expect(() => new Expression(12)).to.throw("Cannot create an expression with a Number.") + expect(() => new Expression({})).to.throw("Cannot create an expression with a Object.") + expect(() => new Expression(true)).to.throw("Cannot create an expression with a Boolean.") + }) + }) + + describe("#variables", function() { + it("returns a list of variables for non-constant expressions", function() { + expect(new Expression("x+1").variables()).to.deep.equal(["x"]) + expect(new Expression("x+n").variables()).to.deep.equal(["x", "n"]) + expect(new Expression("u[n] + A.x").variables()).to.deep.equal(["u", "n", "A"]) + }) + + it("returns an empty array if the expression is constant", function() { + expect(new Expression("2+1").variables()).to.deep.equal([]) + expect(new Expression("sin π").variables()).to.deep.equal([]) + expect(new Expression("e^3").variables()).to.deep.equal([]) + }) + }) + + describe("#isConstant", function() { + it("returns true if neither x nor n are included into the expression", function() { + expect(new Expression("2+1").isConstant()).to.be.true + expect(new Expression("e^3").isConstant()).to.be.true + expect(new Expression("2+f(3)").isConstant()).to.be.true + expect(new Expression("sin A.x").isConstant()).to.be.true + }) + + it("returns false if either x or n are included into the expression", function() { + expect(new Expression("2+x").isConstant()).to.be.false + expect(new Expression("e^n").isConstant()).to.be.false + expect(new Expression("2+f(x)").isConstant()).to.be.false + expect(new Expression("n + sin x").isConstant()).to.be.false + }) + }) + + describe("#requiredObjects", function() { + it("returns the list of objects that need to be registered for this expression", function() { + expect(new Expression("x^n").requiredObjects()).to.deep.equal([]) + expect(new Expression("2+f(3)").requiredObjects()).to.deep.equal(["f"]) + expect(new Expression("A.x+x").requiredObjects()).to.deep.equal(["A"]) + expect(new Expression("2+f(sin A.x)+n").requiredObjects()).to.deep.equal(["f", "A"]) + }) + }) + + describe.skip("#allRequirementsFulfilled", function() { + // TODO: Make tests for objects + }) + + describe.skip("#undefinedVariables", function() { + // TODO: Make tests for objects + }) + + describe("#toEditableString", function() { + it("should return a readable expression", function() { + expect(new Expression("2+1").toEditableString()).to.equal("3") + expect(new Expression("2+x").toEditableString()).to.equal("(2 + x)") + expect(new Expression("x*2+x/3").toEditableString()).to.equal("((x * 2) + (x / 3))") + }) + + it("should be able to be reparsed and equal the same expression", function() { + const exprs = ["5", "x/2", "4/2", "sin x"] + for(const expr of exprs) { + const exprObj = new Expression(expr) + expect(new Expression(exprObj.toEditableString()).calc).to.deep.equal(exprObj.calc) + } + }) + }) + + describe("#execute", function() { + it("returns the result of the computation of the expression", function() { + expect(new Expression("2+3").execute()).to.equal(5) + expect(new Expression("2+3").execute(10)).to.equal(5) + expect(new Expression("2+x").execute(10)).to.equal(12) + expect(new Expression("sin x").execute(Math.PI)).to.be.approximately(0, Number.EPSILON) + }) + + it("returns the cached value if the expression can be cached", function() { + const exprs = ["2+3", "x/2", "4/2", "sin x"] + for(const expr of exprs) { + const exprObj = new Expression(expr) + if(exprObj.canBeCached) + expect(exprObj.execute()).to.equal(exprObj.cachedValue) + else + expect(exprObj.execute()).to.not.equal(exprObj.cachedValue) + } + }) + + it("throws an error if some variables are undefined.", function() { + expect(() => new Expression("x+n").execute()).to.throw("Undefined variable n.") + expect(() => new Expression("sin A.t").execute()).to.throw("Undefined variable A.") + expect(() => new Expression("f(3)").execute()).to.throw("Undefined variable f.") + }) + }) + + describe("#simplify", function() { + it("returns an expression with just the result when no constant or object are used", function() { + expect(new Expression("2+2").simplify(Math.PI/2)).to.deep.equal(new Expression("4")) + expect(new Expression("x+3").simplify(5)).to.deep.equal(new Expression("8")) + expect(new Expression("sin x").simplify(Math.PI/2)).to.deep.equal(new Expression("1")) + expect(new Expression("0*e^x").simplify(Math.PI/2)).to.deep.equal(new Expression("0")) + }) + + it("returns a simplified version of the expression if constants are used", function() { + const original = new Expression("e^x").simplify(2) + const to = new Expression("e^2") + expect(original.toEditableString()).to.deep.equal(to.toEditableString()) + }) + }) + + describe("#toString", function() { + it("returns a human readable string of the expression", function() { + expect(new Expression("-2-3").toString()).to.equal("-5") + expect(new Expression("0.2+0.1").toString()).to.equal("0.3") + expect(new Expression("sin x").toString()).to.equal("sin x") + expect(new Expression("sin π").toString()).to.equal("sin π") + }) + + it("should add a sign if the option is passed", function() { + expect(new Expression("-2-3").toString(true)).to.equal("-5") + expect(new Expression("2+3").toString(true)).to.equal("+5") + }) + }) + + describe("#executeExpression", function() { + it("directly computes the result of the expression with no variable", function() { + expect(executeExpression("2+3")).to.equal(5) + expect(executeExpression("sin (π/2)")).to.equal(1) + expect(executeExpression("e^3")).to.be.approximately(Math.pow(Math.E, 3), Number.EPSILON) + }) + + it("throws an error if variables are employed", function() { + expect(() => executeExpression("x+n")).to.throw("Undefined variable n.") + }) + }) +}) \ No newline at end of file diff --git a/common/test/mock/qt.mjs b/common/test/mock/qt.mjs index 50ec349..58ceae0 100644 --- a/common/test/mock/qt.mjs +++ b/common/test/mock/qt.mjs @@ -40,6 +40,17 @@ function QT_TRANSLATE_NOOP(category, string) { return string } +/** + * Polyfilling Qt arg function. + * @param {string} argument + */ +String.prototype.arg = function(argument) { + for(let i = 0; i < 10; i++) + if(this.includes("%"+i)) + return this.replaceAll("%" + i, argument) + throw new Error("Too many arguments used.") +} + function setup() { globalThis.Qt = { rect @@ -47,8 +58,6 @@ function setup() { globalThis.QT_TRANSLATE_NOOP = QT_TRANSLATE_NOOP globalThis.qsTranslate = QT_TRANSLATE_NOOP - - String.prototype.arg = function() { return this; } // No need to reimplement it for now. } setup() diff --git a/common/test/module/latex.mjs b/common/test/module/latex.mjs index 02aaca5..e038e63 100644 --- a/common/test/module/latex.mjs +++ b/common/test/module/latex.mjs @@ -48,7 +48,7 @@ describe("Module/Latex", function() { }) describe("#requestAsyncRender", function() { - it("should return a render result with a valid source, a width, and a height", async function() { + it("returns a render result with a valid source, a width, and a height", async function() { const data = await LatexAPI.requestAsyncRender("\\frac{x}{3}", 13, "#AA0033") expect(data).to.be.an("object") expect(data.source).to.be.a("string") @@ -57,7 +57,7 @@ describe("Module/Latex", function() { expect(data.width).to.be.a("number") }) - it("should call functions from the LaTeX module", async function() { + it("calls functions from the LaTeX module", async function() { const renderSyncSpy = spy.on(Latex, "renderSync") const renderAsyncSpy = spy.on(Latex, "renderAsync") Latex.supportsAsyncRender = true @@ -84,7 +84,7 @@ describe("Module/Latex", function() { }) describe("#findPrerendered", function() { - it("should return the same data as async render for the same markup, font size, and color", async function() { + it("returns the same data as async render for the same markup, font size, and color", async function() { const data = await LatexAPI.requestAsyncRender("\\frac{x}{3}", 13, "#AA0033") const found = LatexAPI.findPrerendered("\\frac{x}{3}", 13, "#AA0033") expect(found).to.not.be.null @@ -92,7 +92,7 @@ describe("Module/Latex", function() { expect(found.width).to.equal(data.width) }) - it("should return null if the markup hasn't been prerendered with the same markup, font size, and color", async function() { + it("returns null if the markup hasn't been prerendered with the same markup, font size, and color", async function() { await LatexAPI.requestAsyncRender("\\frac{x}{3}", 13, "#AA0033") expect(LatexAPI.findPrerendered("\\frac{y}{3}", 13, "#AA0033")).to.be.null expect(LatexAPI.findPrerendered("\\frac{x}{3}", 12, "#AA0033")).to.be.null @@ -101,7 +101,7 @@ describe("Module/Latex", function() { }) describe("#par", function() { - it("should add parentheses to strings", function() { + it("adds parentheses to strings", function() { expect(LatexAPI.par("string")).to.equal("(string)") expect(LatexAPI.par("aaaa")).to.equal("(aaaa)") expect(LatexAPI.par("")).to.equal("()") @@ -110,14 +110,14 @@ describe("Module/Latex", function() { }) describe("#parif", function() { - it("should add parentheses to strings that contain one of the ones in the list", function() { + it("adds parentheses to strings that contain one of the ones in the list", function() { expect(LatexAPI.parif("string", ["+"])).to.equal("string") expect(LatexAPI.parif("string+assert", ["+"])).to.equal("(string+assert)") expect(LatexAPI.parif("string+assert", ["+", "-"])).to.equal("(string+assert)") expect(LatexAPI.parif("string-assert", ["+", "-"])).to.equal("(string-assert)") }) - it("shouldn't add new parentheses to strings that contains one of the ones in the list if they already have one", function() { + it("doesn't add new parentheses to strings that contains one of the ones in the list if they already have one", function() { expect(LatexAPI.parif("(string+assert", ["+"])).to.equal("((string+assert)") expect(LatexAPI.parif("string+assert)", ["+"])).to.equal("(string+assert))") expect(LatexAPI.parif("(string+assert)", ["+"])).to.equal("(string+assert)") @@ -125,14 +125,14 @@ describe("Module/Latex", function() { expect(LatexAPI.parif("(string-assert)", ["+", "-"])).to.equal("(string-assert)") }) - it("shouldn't add parentheses to strings that does not contains one of the ones in the list", function() { + it("doesn't add parentheses to strings that does not contains one of the ones in the list", function() { expect(LatexAPI.parif("string", ["+"])).to.equal("string") expect(LatexAPI.parif("string+assert", ["-"])).to.equal("string+assert") expect(LatexAPI.parif("(string*assert", ["+", "-"])).to.equal("(string*assert") expect(LatexAPI.parif("string/assert)", ["+", "-"])).to.equal("string/assert)") }) - it("should remove parentheses from strings that does not contains one of the ones in the list", function() { + it("removes parentheses from strings that does not contains one of the ones in the list", function() { expect(LatexAPI.parif("(string)", ["+"])).to.equal("string") expect(LatexAPI.parif("(string+assert)", ["-"])).to.equal("string+assert") expect(LatexAPI.parif("((string*assert)", ["+", "-"])).to.equal("(string*assert") @@ -164,47 +164,47 @@ describe("Module/Latex", function() { "{}_{4}", "{}_{5}", "{}_{6}", "{}_{7}", "{}_{8}", "{}_{9}", "{}_{0}", "\\pi", "\\infty"] - it("should convert unicode characters to their latex equivalent", function() { + it("converts unicode characters to their latex equivalent", function() { for(let i = 0; i < from.length; i++) expect(LatexAPI.variable(from[i])).to.include(to[i]) }) - it("should wrap within dollar signs when the option is included", function() { + it("wraps within dollar signs when the option is included", function() { for(let i = 0; i < from.length; i++) { expect(LatexAPI.variable(from[i], false)).to.equal(to[i]) expect(LatexAPI.variable(from[i], true)).to.equal(`$${to[i]}$`) } }) - it("should be able to convert multiple of them", function() { + it("can convert multiple of them", function() { expect(LatexAPI.variable("α₂", false)).to.equal("\\alpha{}_{2}") expect(LatexAPI.variable("∞piΠ", false)).to.equal("\\infty\\pi\\Pi") }) }) describe("#functionToLatex", function() { - it("should transform derivatives into latex fractions", function() { + it("transforms derivatives into latex fractions", function() { const d1 = LatexAPI.functionToLatex("derivative", ["'3t'", "'t'", "x+2"]) const d2 = LatexAPI.functionToLatex("derivative", ["f", "x+2"]) expect(d1).to.equal("\\frac{d3x}{dx}") expect(d2).to.equal("\\frac{df}{dx}(x+2)") }) - it("should transform integrals into latex limits", function() { + it("transforms integrals into latex limits", function() { const i1 = LatexAPI.functionToLatex("integral", ["0", "x", "'3y'", "'y'"]) const i2 = LatexAPI.functionToLatex("integral", ["1", "2", "f"]) expect(i1).to.equal("\\int\\limits_{0}^{x}3y dy") expect(i2).to.equal("\\int\\limits_{1}^{2}f(t) dt") }) - it("should transform sqrt functions to sqrt latex", function() { + it("transforms sqrt functions to sqrt latex", function() { const sqrt1 = LatexAPI.functionToLatex("sqrt", ["(x+2)"]) const sqrt2 = LatexAPI.functionToLatex("sqrt", ["\\frac{x}{2}"]) expect(sqrt1).to.equal("\\sqrt{x+2}") expect(sqrt2).to.equal("\\sqrt{\\frac{x}{2}}") }) - it("should transform abs, floor and ceil", function() { + it("transforms abs, floor and ceil", function() { const abs = LatexAPI.functionToLatex("abs", ["x+3"]) const floor = LatexAPI.functionToLatex("floor", ["x+3"]) const ceil = LatexAPI.functionToLatex("ceil", ["x+3"]) @@ -213,7 +213,7 @@ describe("Module/Latex", function() { expect(ceil).to.equal("\\left\\lceil{x+3}\\right\\rceil") }) - it("should transform regular functions into latex", function() { + it("transforms regular functions into latex", function() { const f1 = LatexAPI.functionToLatex("f", ["x+3", true]) const f2 = LatexAPI.functionToLatex("h_1", ["10"]) expect(f1).to.equal("\\mathrm{f}\\left(x+3, true\\right)") @@ -222,7 +222,7 @@ describe("Module/Latex", function() { }) describe("#expression", function() { - it("should transform parsed expressions", function() { + it("transforms parsed expressions", function() { const expr = ExprEval.parse("(+1! == 2/2 ? sin [-2.2][0] : f(t)^(1+1-1) + sqrt(A.t)) * 3 % 1") const expected = "((((+1!))==(\\frac{2}{2}) ? (\\mathrm{sin}\\left(([(-2.2)][0])\\right)) : (\\mathrm{f}\\left(t\\right)^{1+1-1}+\\sqrt{A.t})) \\times 3) \\mathrm{mod} 1" expect(LatexAPI.expression(expr.tokens)).to.equal(expected) diff --git a/common/test/module/objects.mjs b/common/test/module/objects.mjs index 4665232..d598097 100644 --- a/common/test/module/objects.mjs +++ b/common/test/module/objects.mjs @@ -26,5 +26,6 @@ import { expect } from "chai" // import Objects from "../../src/module/objects.mjs" // // describe("Module/Objects", function() { -// +// describe("#getNewName", function() { +// }) // }) \ No newline at end of file From c39498c60fdb5a5ecebc48819397c0387749d088 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sat, 26 Oct 2024 05:55:34 +0200 Subject: [PATCH 068/104] Finally got rid of the camelCase2Readable Utils function. --- .../definitionDomain.svg} | 0 .../destinationDomain.svg} | 0 assets/icons/properties/displayMode.svg | 1 + assets/icons/properties/displayStyle.svg | 1 + .../Expression.svg => properties/expression.svg} | 0 .../custom/Gain.svg => properties/gain.svg} | 0 assets/icons/properties/labelPosition.svg | 1 + assets/icons/properties/labelX.svg | 1 + assets/icons/properties/om_0.svg | 1 + .../custom/Pass.svg => properties/pass.svg} | 0 assets/icons/properties/phase.svg | 1 + assets/icons/properties/pointStyle.svg | 1 + .../custom/Rounding.svg => properties/rounding.svg} | 0 assets/icons/properties/targetElement.svg | 1 + assets/icons/properties/targetValuePosition.svg | 1 + assets/icons/properties/text.svg | 1 + assets/icons/properties/unit.svg | 1 + assets/icons/properties/x.svg | 1 + assets/icons/properties/y.svg | 1 + assets/icons/settings/custom/Display Mode.svg | 1 - assets/icons/settings/custom/Display Style.svg | 1 - assets/icons/settings/custom/Label Position.svg | 1 - assets/icons/settings/custom/Label X.svg | 1 - assets/icons/settings/custom/Phase.svg | 1 - assets/icons/settings/custom/Point Style.svg | 1 - assets/icons/settings/custom/Target Element.svg | 1 - .../icons/settings/custom/Target Value Position.svg | 1 - assets/icons/settings/custom/Text.svg | 1 - assets/icons/settings/custom/Unit.svg | 1 - assets/icons/settings/custom/X.svg | 1 - assets/icons/settings/custom/Y.svg | 1 - assets/icons/settings/custom/ω_0.svg | 1 - common/src/utils.mjs | 12 ------------ runtime-pyside6/LogarithmPlotter/logarithmplotter.py | 2 +- .../ObjectLists/Editor/CustomPropertyList.qml | 12 ++++++------ 35 files changed, 20 insertions(+), 32 deletions(-) rename assets/icons/{settings/custom/Definition Domain.svg => properties/definitionDomain.svg} (100%) rename assets/icons/{settings/custom/Destination Domain.svg => properties/destinationDomain.svg} (100%) create mode 120000 assets/icons/properties/displayMode.svg create mode 120000 assets/icons/properties/displayStyle.svg rename assets/icons/{settings/custom/Expression.svg => properties/expression.svg} (100%) rename assets/icons/{settings/custom/Gain.svg => properties/gain.svg} (100%) create mode 120000 assets/icons/properties/labelPosition.svg create mode 120000 assets/icons/properties/labelX.svg create mode 120000 assets/icons/properties/om_0.svg rename assets/icons/{settings/custom/Pass.svg => properties/pass.svg} (100%) create mode 120000 assets/icons/properties/phase.svg create mode 120000 assets/icons/properties/pointStyle.svg rename assets/icons/{settings/custom/Rounding.svg => properties/rounding.svg} (100%) create mode 120000 assets/icons/properties/targetElement.svg create mode 120000 assets/icons/properties/targetValuePosition.svg create mode 120000 assets/icons/properties/text.svg create mode 120000 assets/icons/properties/unit.svg create mode 120000 assets/icons/properties/x.svg create mode 120000 assets/icons/properties/y.svg delete mode 120000 assets/icons/settings/custom/Display Mode.svg delete mode 120000 assets/icons/settings/custom/Display Style.svg delete mode 120000 assets/icons/settings/custom/Label Position.svg delete mode 120000 assets/icons/settings/custom/Label X.svg delete mode 120000 assets/icons/settings/custom/Phase.svg delete mode 120000 assets/icons/settings/custom/Point Style.svg delete mode 120000 assets/icons/settings/custom/Target Element.svg delete mode 120000 assets/icons/settings/custom/Target Value Position.svg delete mode 120000 assets/icons/settings/custom/Text.svg delete mode 120000 assets/icons/settings/custom/Unit.svg delete mode 120000 assets/icons/settings/custom/X.svg delete mode 120000 assets/icons/settings/custom/Y.svg delete mode 120000 assets/icons/settings/custom/ω_0.svg diff --git a/assets/icons/settings/custom/Definition Domain.svg b/assets/icons/properties/definitionDomain.svg similarity index 100% rename from assets/icons/settings/custom/Definition Domain.svg rename to assets/icons/properties/definitionDomain.svg diff --git a/assets/icons/settings/custom/Destination Domain.svg b/assets/icons/properties/destinationDomain.svg similarity index 100% rename from assets/icons/settings/custom/Destination Domain.svg rename to assets/icons/properties/destinationDomain.svg diff --git a/assets/icons/properties/displayMode.svg b/assets/icons/properties/displayMode.svg new file mode 120000 index 0000000..41b711b --- /dev/null +++ b/assets/icons/properties/displayMode.svg @@ -0,0 +1 @@ +../common/appearance.svg \ No newline at end of file diff --git a/assets/icons/properties/displayStyle.svg b/assets/icons/properties/displayStyle.svg new file mode 120000 index 0000000..41b711b --- /dev/null +++ b/assets/icons/properties/displayStyle.svg @@ -0,0 +1 @@ +../common/appearance.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/Expression.svg b/assets/icons/properties/expression.svg similarity index 100% rename from assets/icons/settings/custom/Expression.svg rename to assets/icons/properties/expression.svg diff --git a/assets/icons/settings/custom/Gain.svg b/assets/icons/properties/gain.svg similarity index 100% rename from assets/icons/settings/custom/Gain.svg rename to assets/icons/properties/gain.svg diff --git a/assets/icons/properties/labelPosition.svg b/assets/icons/properties/labelPosition.svg new file mode 120000 index 0000000..3e4c849 --- /dev/null +++ b/assets/icons/properties/labelPosition.svg @@ -0,0 +1 @@ +../common/arrow.svg \ No newline at end of file diff --git a/assets/icons/properties/labelX.svg b/assets/icons/properties/labelX.svg new file mode 120000 index 0000000..4eecad3 --- /dev/null +++ b/assets/icons/properties/labelX.svg @@ -0,0 +1 @@ +../common/position.svg \ No newline at end of file diff --git a/assets/icons/properties/om_0.svg b/assets/icons/properties/om_0.svg new file mode 120000 index 0000000..e4130be --- /dev/null +++ b/assets/icons/properties/om_0.svg @@ -0,0 +1 @@ +../common/angle.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/Pass.svg b/assets/icons/properties/pass.svg similarity index 100% rename from assets/icons/settings/custom/Pass.svg rename to assets/icons/properties/pass.svg diff --git a/assets/icons/properties/phase.svg b/assets/icons/properties/phase.svg new file mode 120000 index 0000000..e4130be --- /dev/null +++ b/assets/icons/properties/phase.svg @@ -0,0 +1 @@ +../common/angle.svg \ No newline at end of file diff --git a/assets/icons/properties/pointStyle.svg b/assets/icons/properties/pointStyle.svg new file mode 120000 index 0000000..41b711b --- /dev/null +++ b/assets/icons/properties/pointStyle.svg @@ -0,0 +1 @@ +../common/appearance.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/Rounding.svg b/assets/icons/properties/rounding.svg similarity index 100% rename from assets/icons/settings/custom/Rounding.svg rename to assets/icons/properties/rounding.svg diff --git a/assets/icons/properties/targetElement.svg b/assets/icons/properties/targetElement.svg new file mode 120000 index 0000000..659962b --- /dev/null +++ b/assets/icons/properties/targetElement.svg @@ -0,0 +1 @@ +../common/target.svg \ No newline at end of file diff --git a/assets/icons/properties/targetValuePosition.svg b/assets/icons/properties/targetValuePosition.svg new file mode 120000 index 0000000..4eecad3 --- /dev/null +++ b/assets/icons/properties/targetValuePosition.svg @@ -0,0 +1 @@ +../common/position.svg \ No newline at end of file diff --git a/assets/icons/properties/text.svg b/assets/icons/properties/text.svg new file mode 120000 index 0000000..280f9ad --- /dev/null +++ b/assets/icons/properties/text.svg @@ -0,0 +1 @@ +../common/label.svg \ No newline at end of file diff --git a/assets/icons/properties/unit.svg b/assets/icons/properties/unit.svg new file mode 120000 index 0000000..e4130be --- /dev/null +++ b/assets/icons/properties/unit.svg @@ -0,0 +1 @@ +../common/angle.svg \ No newline at end of file diff --git a/assets/icons/properties/x.svg b/assets/icons/properties/x.svg new file mode 120000 index 0000000..4eecad3 --- /dev/null +++ b/assets/icons/properties/x.svg @@ -0,0 +1 @@ +../common/position.svg \ No newline at end of file diff --git a/assets/icons/properties/y.svg b/assets/icons/properties/y.svg new file mode 120000 index 0000000..4eecad3 --- /dev/null +++ b/assets/icons/properties/y.svg @@ -0,0 +1 @@ +../common/position.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/Display Mode.svg b/assets/icons/settings/custom/Display Mode.svg deleted file mode 120000 index 7a5ba45..0000000 --- a/assets/icons/settings/custom/Display Mode.svg +++ /dev/null @@ -1 +0,0 @@ -../../common/appearance.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/Display Style.svg b/assets/icons/settings/custom/Display Style.svg deleted file mode 120000 index 7a5ba45..0000000 --- a/assets/icons/settings/custom/Display Style.svg +++ /dev/null @@ -1 +0,0 @@ -../../common/appearance.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/Label Position.svg b/assets/icons/settings/custom/Label Position.svg deleted file mode 120000 index 43aa15f..0000000 --- a/assets/icons/settings/custom/Label Position.svg +++ /dev/null @@ -1 +0,0 @@ -../../common/arrow.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/Label X.svg b/assets/icons/settings/custom/Label X.svg deleted file mode 120000 index 6b40925..0000000 --- a/assets/icons/settings/custom/Label X.svg +++ /dev/null @@ -1 +0,0 @@ -../../common/position.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/Phase.svg b/assets/icons/settings/custom/Phase.svg deleted file mode 120000 index 21699e9..0000000 --- a/assets/icons/settings/custom/Phase.svg +++ /dev/null @@ -1 +0,0 @@ -../../common/angle.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/Point Style.svg b/assets/icons/settings/custom/Point Style.svg deleted file mode 120000 index 7a5ba45..0000000 --- a/assets/icons/settings/custom/Point Style.svg +++ /dev/null @@ -1 +0,0 @@ -../../common/appearance.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/Target Element.svg b/assets/icons/settings/custom/Target Element.svg deleted file mode 120000 index 50124dc..0000000 --- a/assets/icons/settings/custom/Target Element.svg +++ /dev/null @@ -1 +0,0 @@ -../../common/target.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/Target Value Position.svg b/assets/icons/settings/custom/Target Value Position.svg deleted file mode 120000 index 6b40925..0000000 --- a/assets/icons/settings/custom/Target Value Position.svg +++ /dev/null @@ -1 +0,0 @@ -../../common/position.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/Text.svg b/assets/icons/settings/custom/Text.svg deleted file mode 120000 index 69be9e1..0000000 --- a/assets/icons/settings/custom/Text.svg +++ /dev/null @@ -1 +0,0 @@ -../../common/label.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/Unit.svg b/assets/icons/settings/custom/Unit.svg deleted file mode 120000 index 21699e9..0000000 --- a/assets/icons/settings/custom/Unit.svg +++ /dev/null @@ -1 +0,0 @@ -../../common/angle.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/X.svg b/assets/icons/settings/custom/X.svg deleted file mode 120000 index 6b40925..0000000 --- a/assets/icons/settings/custom/X.svg +++ /dev/null @@ -1 +0,0 @@ -../../common/position.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/Y.svg b/assets/icons/settings/custom/Y.svg deleted file mode 120000 index 6b40925..0000000 --- a/assets/icons/settings/custom/Y.svg +++ /dev/null @@ -1 +0,0 @@ -../../common/position.svg \ No newline at end of file diff --git a/assets/icons/settings/custom/ω_0.svg b/assets/icons/settings/custom/ω_0.svg deleted file mode 120000 index 21699e9..0000000 --- a/assets/icons/settings/custom/ω_0.svg +++ /dev/null @@ -1 +0,0 @@ -../../common/angle.svg \ No newline at end of file diff --git a/common/src/utils.mjs b/common/src/utils.mjs index 0e451f4..5c51f62 100644 --- a/common/src/utils.mjs +++ b/common/src/utils.mjs @@ -401,18 +401,6 @@ export function parseName(str, removeUnallowed = true) { return str } -/** - * Transforms camel case strings to a space separated one. - * - * @deprecated - * @param {string} label - Camel case to parse - * @returns {string} Parsed label. - */ -export function camelCase2readable(label) { - let parsed = parseName(label, false) - return parsed.charAt(0).toLatinUppercase() + parsed.slice(1).replace(/([A-Z])/g, " $1") -} - /** * Creates a randomized color string. * @returns {string} diff --git a/runtime-pyside6/LogarithmPlotter/logarithmplotter.py b/runtime-pyside6/LogarithmPlotter/logarithmplotter.py index 115083a..c4c16b9 100644 --- a/runtime-pyside6/LogarithmPlotter/logarithmplotter.py +++ b/runtime-pyside6/LogarithmPlotter/logarithmplotter.py @@ -104,7 +104,7 @@ def get_platform_qt_style(os) -> str: def register_icon_directories() -> None: icon_fallbacks = QIcon.fallbackSearchPaths() base_icon_path = path.join(logarithmplotter_path, "qml", "eu", "ad5001", "LogarithmPlotter", "icons") - paths = [["common"], ["objects"], ["history"], ["settings"], ["settings", "custom"]] + paths = [["common"], ["objects"], ["history"], ["settings"], ["properties"]] for p in paths: icon_fallbacks.append(path.realpath(path.join(base_icon_path, *p))) QIcon.setFallbackSearchPaths(icon_fallbacks) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml index 1ca75e4..49cea8e 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml @@ -74,7 +74,7 @@ Repeater { Setting.ExpressionEditor { height: 30 label: propertyLabel - icon: `settings/custom/${propertyIcon}.svg` + icon: `properties/${propertyIcon}.svg` defValue: JS.Utils.simplifyExpression(obj[propertyName].toEditableString()) self: obj.name variables: propertyType.variables @@ -99,7 +99,7 @@ Repeater { Setting.TextSetting { height: 30 label: propertyLabel - icon: `settings/custom/${propertyIcon}.svg` + icon: `properties/${propertyIcon}.svg` min: propertyType == "int" ? 0 : -Infinity isInt: propertyType == "int" isDouble: propertyType == "number" @@ -159,7 +159,7 @@ Repeater { CheckBox { height: 20 text: propertyLabel - //icon: `settings/custom/${propertyIcon}.svg` + //icon: `properties/${propertyIcon}.svg` checked: { //if(obj[propertyName] == null) { @@ -185,7 +185,7 @@ Repeater { Setting.ComboBoxSetting { height: 30 label: propertyLabel - icon: `settings/custom/${propertyIcon}.svg` + icon: `properties/${propertyIcon}.svg` // True to select an object of type, false for enums. property bool selectObjMode: paramTypeIn(propertyType, ['ObjectType']) property bool isRealObject: !selectObjMode || (propertyType.objType != "ExecutableObject" && propertyType.objType != "DrawableObject") @@ -246,7 +246,7 @@ Repeater { Setting.ListSetting { label: propertyLabel - //icon: `settings/custom/${propertyIcon}.svg` + //icon: `properties/${propertyIcon}.svg` dictionaryMode: paramTypeIn(propertyType, ['Dict']) keyType: dictionaryMode ? propertyType.keyType : 'string' valueType: propertyType.valueType @@ -283,7 +283,7 @@ Repeater { property string propertyName: modelData[0] property var propertyType: modelData[1] property string propertyLabel: qsTranslate('prop',propertyName) - property string propertyIcon: JS.Utils.camelCase2readable(propertyName) + property string propertyIcon: propertyName sourceComponent: { if(propertyName.startsWith('comment')) From 90f4691c54e936e33e9690716d04e7c13ae1ee6f Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sat, 26 Oct 2024 22:44:18 +0200 Subject: [PATCH 069/104] Updating icons to comply with KDE HIG. --- assets/logarithmplotter.svg | 187 ++++++++++++++++++++++++++++-------- 1 file changed, 147 insertions(+), 40 deletions(-) diff --git a/assets/logarithmplotter.svg b/assets/logarithmplotter.svg index 77a2817..1f3a5e0 100644 --- a/assets/logarithmplotter.svg +++ b/assets/logarithmplotter.svg @@ -1,64 +1,171 @@ + + LogarithmPlotter Icon v1.0image/svg+xmlLogarithmPlotter Icon v1.02021Ad5001(c) Ad5001 2021 - All rights reserved + LogarithmPlotter Icon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + d="m 18,3.5 c 0,7 -4,12 -13,12" /> + + + + + LogarithmPlotter Icon + 2024-10-06 + + + Adsooi <mail@ad5001.eu> + + + + + (c) Adsooi 2021-2024 + + + + + + + + + + + + + + + + From 5d0542ffcc4f8ea102b60a68f46ee06633357f0f Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sat, 26 Oct 2024 22:46:22 +0200 Subject: [PATCH 070/104] Ensuring app icons are white. --- .../eu/ad5001/LogarithmPlotter/AppMenuBar.qml | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml index f4e2f35..87dd625 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml @@ -41,6 +41,7 @@ MenuBar { shortcut: StandardKey.Open onTriggered: settings.load() icon.name: 'document-open' + icon.color: sysPalette.windowText } Action { @@ -48,13 +49,14 @@ MenuBar { shortcut: StandardKey.Save onTriggered: settings.save() icon.name: 'document-save' + icon.color: sysPalette.windowText } Action { text: qsTr("Save &As...") shortcut: StandardKey.SaveAs onTriggered: settings.saveAs() - icon.name: 'document-save-as' - + icon.color: sysPalette.windowText + icon.name: 'document-save-as' } MenuSeparator { } Action { @@ -68,6 +70,7 @@ MenuBar { } icon.name: 'application-exit' + icon.color: sysPalette.windowText } } @@ -92,6 +95,7 @@ MenuBar { shortcut: StandardKey.Copy onTriggered: root.copyDiagramToClipboard() icon.name: 'edit-copy' + icon.color: sysPalette.windowText } MenuSeparator { } Action { @@ -99,6 +103,7 @@ MenuBar { shortcut: StandardKey.Copy onTriggered: preferences.open() icon.name: 'settings' + icon.color: sysPalette.windowText } } @@ -129,38 +134,45 @@ MenuBar { Action { text: qsTr("&Source code") icon.name: 'software-sources' + icon.color: sysPalette.windowText onTriggered: Qt.openUrlExternally("https://git.ad5001.eu/Ad5001/LogarithmPlotter") } Action { text: qsTr("&Report a bug") icon.name: 'tools-report-bug' + icon.color: sysPalette.windowText onTriggered: Qt.openUrlExternally("https://git.ad5001.eu/Ad5001/LogarithmPlotter/issues") } Action { text: qsTr("&User manual") icon.name: 'documentation' + icon.color: sysPalette.windowText onTriggered: Qt.openUrlExternally("https://git.ad5001.eu/Ad5001/LogarithmPlotter/wiki/_Sidebar") } Action { text: qsTr("&Changelog") icon.name: 'state-information' + icon.color: sysPalette.windowText onTriggered: changelog.open() } Action { text: qsTr("&Help translating!") - icon.name: 'translator' + icon.name: 'translate' + icon.color: sysPalette.windowText onTriggered: Qt.openUrlExternally("https://hosted.weblate.org/engage/logarithmplotter/") } MenuSeparator { } Action { text: qsTr("&Thanks") - icon.name: 'about' + icon.name: 'help-about' + icon.color: sysPalette.windowText onTriggered: thanksTo.open() } Action { text: qsTr("&About") shortcut: StandardKey.HelpContents - icon.name: 'about' + icon.name: 'help-about' + icon.color: sysPalette.windowText onTriggered: about.open() } } From 8da10497d232c38bcf0805308028c19449530f50 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sat, 26 Oct 2024 22:46:41 +0200 Subject: [PATCH 071/104] Adding different revisions for different debian packages depending on their dependencies --- scripts/package-deb.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/package-deb.sh b/scripts/package-deb.sh index eea10ba..e01c370 100755 --- a/scripts/package-deb.sh +++ b/scripts/package-deb.sh @@ -30,7 +30,7 @@ cp ../../README.md . python3 setup.py --remove-git-version --command-packages=stdeb.command sdist_dsc \ --package logarithmplotter --copyright-file assets/native/linux/debian/copyright \ --suite noble --depends3 "$(cat assets/native/linux/debian/depends.wheels)" --section science \ - bdist_deb + --debian-version +wheels-1 bdist_deb mv deb_dist deb_dist.noble @@ -38,6 +38,6 @@ mv deb_dist deb_dist.noble python3 setup.py --remove-git-version --command-packages=stdeb.command sdist_dsc \ --package logarithmplotter --copyright-file assets/native/linux/debian/copyright \ --suite oracular --depends3 "$(cat assets/native/linux/debian/depends.packaged)" --section science \ - bdist_deb + --debian-version +packaged-1 bdist_deb mv deb_dist deb_dist.oracular From f52ee65c56ad243877a7ea41a33fbba45d4a18ad Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sat, 26 Oct 2024 23:37:20 +0200 Subject: [PATCH 072/104] Improving stability of Function drawing. --- common/src/objs/function.mjs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/common/src/objs/function.mjs b/common/src/objs/function.mjs index 1e345cb..b056cc3 100644 --- a/common/src/objs/function.mjs +++ b/common/src/objs/function.mjs @@ -122,7 +122,9 @@ export default class Function extends ExecutableObject { */ static drawFunction(canvas, expr, definitionDomain, destinationDomain, drawPoints = true, drawDash = true) { let pxprecision = 10 - let previousX = canvas.px2x(0) + const startDrawFrom = canvas.x2px(1)%pxprecision-pxprecision + let previousX = canvas.px2x(startDrawFrom) + // console.log("Starting draw from", previousX, startDrawFrom, canvas.x2px(1)) let previousY = null if(definitionDomain instanceof SpecialDomain && definitionDomain.moveSupported) { // Point based functions. @@ -160,7 +162,7 @@ export default class Function extends ExecutableObject { // Calculate the previousY at the start of the canvas if(definitionDomain.includes(previousX)) previousY = expr.execute(previousX) - for(let px = pxprecision; px < canvas.width; px += pxprecision) { + for(let px = pxprecision; px-pxprecision < canvas.width; px += pxprecision) { let currentX = canvas.px2x(px) if(!definitionDomain.includes(previousX) && definitionDomain.includes(currentX)) { // Should draw up to currentX, but NOT at previousX. @@ -169,7 +171,7 @@ export default class Function extends ExecutableObject { do { tmpPx++ previousX = canvas.px2x(tmpPx) - } while(!definitionDomain.includes(previousX)) + } while(!definitionDomain.includes(previousX) && currentX > previousX) // Recaclulate previousY previousY = expr.execute(previousX) } else if(!definitionDomain.includes(currentX)) { @@ -179,7 +181,7 @@ export default class Function extends ExecutableObject { do { tmpPx-- currentX = canvas.px2x(tmpPx) - } while(!definitionDomain.includes(currentX) && currentX !== previousX) + } while(!definitionDomain.includes(currentX) && currentX > previousX) } // This max variation is needed for functions with asymptotical vertical lines (e.g. 1/x, tan x...) let maxvariation = (canvas.px2y(0) - canvas.px2y(canvas.height)) From e6de739d0cce9ed202f4b6e82445591aa8184149 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sun, 27 Oct 2024 00:45:04 +0200 Subject: [PATCH 073/104] Rewirring paths to improve import names and such. --- common/rollup.config.mjs | 2 +- .../eu/ad5001/LogarithmPlotter/AppMenuBar.qml | 2 +- .../eu/ad5001/LogarithmPlotter/Common/qmldir | 3 +++ .../{HistoryBrowser.qml => Browser.qml} | 6 +++--- .../{HistoryItem.qml => SingleItem.qml} | 2 +- .../eu/ad5001/LogarithmPlotter/History/qmldir | 4 ++-- .../LogarithmPlotter/LogarithmPlotter.qml | 21 ++++++++++++------- .../ObjectLists/Editor/CustomPropertyList.qml | 2 +- .../ObjectLists/Editor/Dialog.qml | 3 +-- .../ObjectLists/ObjectCreationGrid.qml | 2 +- .../ObjectLists/ObjectRow.qml | 2 +- .../LogarithmPlotter/Overlay/Loading.qml | 19 +++++++++++++++++ .../PickLocation.qml} | 19 +++++++---------- .../ViewPositionChange.qml} | 2 +- .../eu/ad5001/LogarithmPlotter/Overlay/qmldir | 4 ++++ .../LogarithmPlotter/Popup/Preferences.qml | 2 +- .../Setting/ExpressionEditor.qml | 2 +- .../eu/ad5001/LogarithmPlotter/Settings.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/qmldir | 2 -- .../LogarithmPlotter/util/latex.py | 1 - .../LogarithmPlotter/util/promise.py | 2 ++ scripts/build.sh | 20 +++++++++++------- 22 files changed, 79 insertions(+), 45 deletions(-) create mode 100644 runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Common/qmldir rename runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/{HistoryBrowser.qml => Browser.qml} (98%) rename runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/{HistoryItem.qml => SingleItem.qml} (99%) create mode 100644 runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/Loading.qml rename runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/{PickLocationOverlay.qml => Overlay/PickLocation.qml} (97%) rename runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/{ViewPositionChangeOverlay.qml => Overlay/ViewPositionChange.qml} (99%) create mode 100644 runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/qmldir diff --git a/common/rollup.config.mjs b/common/rollup.config.mjs index 6a18a41..6156873 100644 --- a/common/rollup.config.mjs +++ b/common/rollup.config.mjs @@ -22,7 +22,7 @@ import { babel } from "@rollup/plugin-babel" import cleanup from "rollup-plugin-cleanup" const src = "./src/index.mjs" -const dest = "../build/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/index.mjs" +const dest = "../build/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Common/index.mjs" export default { input: src, diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml index 87dd625..79fa6b0 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml @@ -20,7 +20,7 @@ import QtQuick import Qt.labs.platform as Native //import QtQuick.Controls 2.15 import eu.ad5001.MixedMenu 1.1 -import "js/index.mjs" as JS +import eu.ad5001.LogarithmPlotter.Common /*! diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Common/qmldir b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Common/qmldir new file mode 100644 index 0000000..af9eb16 --- /dev/null +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Common/qmldir @@ -0,0 +1,3 @@ +module eu.ad5001.LogarithmPlotter.Common + +JS 1.0 index.mjs diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/Browser.qml similarity index 98% rename from runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml rename to runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/Browser.qml index eb84340..645916c 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryBrowser.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/Browser.qml @@ -24,7 +24,7 @@ import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting /*! - \qmltype HistoryBrowser + \qmltype Browser \inqmlmodule eu.ad5001.LogarithmPlotter.History \brief Tab of the drawer that allows to navigate through the undo and redo history. @@ -95,7 +95,7 @@ Item { Repeater { model: historyBrowser.redoCount - HistoryItem { + SingleItem { id: redoButton width: historyBrowser.actionWidth //height: actionHeight @@ -147,7 +147,7 @@ Item { model: historyBrowser.undoCount - HistoryItem { + SingleItem { id: undoButton width: historyBrowser.actionWidth //height: actionHeight diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryItem.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/SingleItem.qml similarity index 99% rename from runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryItem.qml rename to runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/SingleItem.qml index 6ad6556..bffdb9b 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/HistoryItem.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/SingleItem.qml @@ -22,7 +22,7 @@ import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting /*! - \qmltype HistoryItem + \qmltype SingleItem \inqmlmodule eu.ad5001.LogarithmPlotter.History \brief Item representing an history action. diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/qmldir b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/qmldir index 7f8a628..66c4408 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/qmldir +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/qmldir @@ -1,4 +1,4 @@ module eu.ad5001.LogarithmPlotter.History -HistoryBrowser 1.0 HistoryBrowser.qml -HistoryItem 1.0 HistoryItem.qml +Browser 1.0 Browser.qml +SingleItem 1.0 SingleItem.qml diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml index d541a0c..b8799de 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml @@ -23,10 +23,11 @@ import QtQuick.Layouts 1.12 import QtQuick // Auto loading all modules. -import "js/index.mjs" as JS +import eu.ad5001.LogarithmPlotter.Common -import eu.ad5001.LogarithmPlotter.History 1.0 +import eu.ad5001.LogarithmPlotter.History 1.0 as History import eu.ad5001.LogarithmPlotter.ObjectLists 1.0 +import eu.ad5001.LogarithmPlotter.Overlay 1.0 as Overlay import eu.ad5001.LogarithmPlotter.Popup 1.0 as Popup /*! @@ -120,16 +121,16 @@ ApplicationWindow { ObjectLists { id: objectLists - onChanged: drawCanvas.requestPaint() + onChanged: Modules.Canvas.requestPaint() } Settings { id: settings canvas: drawCanvas - onChanged: drawCanvas.requestPaint() + onChanged: Modules.Canvas.requestPaint() } - HistoryBrowser { + History.Browser { id: historyBrowser } } @@ -154,18 +155,24 @@ ApplicationWindow { } } - ViewPositionChangeOverlay { + Overlay.ViewPositionChange { id: viewPositionChanger anchors.fill: parent canvas: parent settingsInstance: settings } - PickLocationOverlay { + Overlay.PickLocation { id: positionPicker anchors.fill: parent canvas: parent } + + // Overlay.Loading { + // id: loadingOverlay + // anchors.fill: parent + // canvas: parent + // } } Timer { diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml index 49cea8e..e688202 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml @@ -20,7 +20,7 @@ import QtQuick import QtQuick.Controls import Qt.labs.platform as Native import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting -import "../../js/index.mjs" as JS +import eu.ad5001.LogarithmPlotter.Common /*! \qmltype CustomPropertyList diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml index 715602a..ced0cdd 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml @@ -18,11 +18,10 @@ import QtQuick import QtQuick.Controls -import QtQuick.Dialogs as D import Qt.labs.platform as Native import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting import eu.ad5001.LogarithmPlotter.Popup 1.0 as Popup -import "../../js/index.mjs" as JS +import eu.ad5001.LogarithmPlotter.Common /*! \qmltype Dialog diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectCreationGrid.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectCreationGrid.qml index e8d4912..e3894cd 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectCreationGrid.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectCreationGrid.qml @@ -19,7 +19,7 @@ import QtQuick import QtQuick.Controls import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting -import "../js/index.mjs" as JS +import eu.ad5001.LogarithmPlotter.Common /*! diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml index 9624d23..5812252 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml @@ -21,7 +21,7 @@ import QtQuick.Dialogs import QtQuick.Controls import QtQuick.Window import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting -import "../js/index.mjs" as JS +import eu.ad5001.LogarithmPlotter.Common /*! diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/Loading.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/Loading.qml new file mode 100644 index 0000000..a69f2cd --- /dev/null +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/Loading.qml @@ -0,0 +1,19 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import QtQuick diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/PickLocation.qml similarity index 97% rename from runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml rename to runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/PickLocation.qml index b364e73..f005756 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/PickLocation.qml @@ -18,12 +18,12 @@ import QtQuick import QtQuick.Controls -import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting -import "js/index.mjs" as JS +import eu.ad5001.LogarithmPlotter.Setting as Setting +import eu.ad5001.LogarithmPlotter.Common /*! - \qmltype PickLocationOverlay - \inqmlmodule eu.ad5001.LogarithmPlotter + \qmltype PickLocation + \inqmlmodule eu.ad5001.LogarithmPlotter.Overlay \brief Overlay used to pick a new location for an object. Provides an overlay over the canvas that can be shown when the user clicks the "Set position" button @@ -32,11 +32,13 @@ import "js/index.mjs" as JS \sa LogarithmPlotter, LogGraphCanvas */ -Item { +Rectangle { id: pickerRoot visible: false clip: true - + color: sysPalette.window + opacity: 0.35 + /*! \qmlsignal PickLocationOverlay::picked(var obj) @@ -96,11 +98,6 @@ Item { */ readonly property bool userPickY: pickY && pickYCheckbox.checked - Rectangle { - color: sysPalette.window - opacity: 0.35 - anchors.fill: parent - } MouseArea { id: picker diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ViewPositionChangeOverlay.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/ViewPositionChange.qml similarity index 99% rename from runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ViewPositionChangeOverlay.qml rename to runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/ViewPositionChange.qml index 7a7072b..1931536 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ViewPositionChangeOverlay.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/ViewPositionChange.qml @@ -19,7 +19,7 @@ import QtQuick /*! - \qmltype ViewPositionChangeOverlay + \qmltype ViewPositionChange.Overlay \inqmlmodule eu.ad5001.LogarithmPlotter \brief Overlay used allow the user to drag the canvas' position and change the zoom level. diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/qmldir b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/qmldir new file mode 100644 index 0000000..8daae21 --- /dev/null +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/qmldir @@ -0,0 +1,4 @@ +module eu.ad5001.LogarithmPlotter.Overlay + +PickLocation 1.0 PickLocation.qml +ViewPositionChange 1.0 ViewPositionChange.qml diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Preferences.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Preferences.qml index a76410f..70d77a9 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Preferences.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Preferences.qml @@ -20,7 +20,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting -import "../js/index.mjs" as JS +import eu.ad5001.LogarithmPlotter.Common /*! \qmltype Preferences diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml index bb99f52..8251a3f 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml @@ -20,7 +20,7 @@ import QtQuick.Controls import QtQuick import Qt.labs.platform as Native import eu.ad5001.LogarithmPlotter.Popup 1.0 as P -import "../js/index.mjs" as JS +import eu.ad5001.LogarithmPlotter.Common /*! diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml index 992e9b1..3f17ea3 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml @@ -20,7 +20,7 @@ import QtQuick import QtQuick.Controls import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting import eu.ad5001.LogarithmPlotter.Popup 1.0 as Popup -import "js/index.mjs" as JS +import eu.ad5001.LogarithmPlotter.Common /*! \qmltype Settings diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/qmldir b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/qmldir index 3aeaa15..c80cae5 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/qmldir +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/qmldir @@ -2,6 +2,4 @@ module eu.ad5001.LogarithmPlotter AppMenuBar 1.0 AppMenuBar.qml LogGraphCanvas 1.0 LogGraphCanvas.qml -PickLocationOverlay 1.0 PickLocationOverlay.qml Settings 1.0 Settings.qml -ViewPositionChangeOverlay 1.0 ViewPositionChangeOverlay.qml \ No newline at end of file diff --git a/runtime-pyside6/LogarithmPlotter/util/latex.py b/runtime-pyside6/LogarithmPlotter/util/latex.py index 71064fa..78c9d44 100644 --- a/runtime-pyside6/LogarithmPlotter/util/latex.py +++ b/runtime-pyside6/LogarithmPlotter/util/latex.py @@ -181,7 +181,6 @@ class Latex(QObject): """ markup_hash, render_hash, export_path = self.create_export_path(latex_markup, font_size, color) if self.latexSupported and not path.exists(export_path + ".png"): - print("Rendering", latex_markup) # Generating file latex_path = path.join(self.tempdir, str(markup_hash)) # If the formula is just recolored or the font is just changed, no need to recreate the DVI. diff --git a/runtime-pyside6/LogarithmPlotter/util/promise.py b/runtime-pyside6/LogarithmPlotter/util/promise.py index f65efa8..c917660 100644 --- a/runtime-pyside6/LogarithmPlotter/util/promise.py +++ b/runtime-pyside6/LogarithmPlotter/util/promise.py @@ -100,6 +100,7 @@ class PyPromise(QObject): Starts the thread that will run the promise. """ if not self._started: # Avoid getting started twice. + print("Starting", self._runner.args) QThreadPool.globalInstance().start(self._runner) self._started = True @@ -153,6 +154,7 @@ class PyPromise(QObject): def _fulfill(self, data): self._state = "fulfilled" no_return = [None, QJSValue.SpecialValue.UndefinedValue] + print("Finished", self._runner.args) for i in range(len(self._fulfills)): try: result = self._fulfills[i](data) diff --git a/scripts/build.sh b/scripts/build.sh index be25274..b63d7f6 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -22,6 +22,10 @@ DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$DIR/.." || exit 1 +BUILD_DIR="build/runtime-pyside6" +BUILD_QML_DIR="$BUILD_DIR/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter" + + box() { len=${#1} echo "┌─$(printf '─%.0s' $(seq 1 "$len"))─┐" @@ -30,20 +34,22 @@ box() { } rm -rf build -mkdir -p build/runtime-pyside6 +mkdir -p "$BUILD_DIR" # Copy python box "Copying pyside6 python runtime..." -cp -r runtime-pyside6/{setup.py,LogarithmPlotter} build/runtime-pyside6 +cp -r runtime-pyside6/{setup.py,LogarithmPlotter} "$BUILD_DIR" box "Building ecmascript modules..." -mkdir -p build/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js -cd common && (npm run build || exit) && cd .. +mkdir -p "$BUILD_QML_DIR/js" +cd common && \ + (npm run build || exit) && \ + cd .. box "Building translations..." cd assets/i18n/ && (bash release.sh || exit) && cd ../../ -mkdir -p build/runtime-pyside6/LogarithmPlotter/i18n && cp assets/i18n/*.qm build/runtime-pyside6/LogarithmPlotter/i18n/ +mkdir -p "$BUILD_DIR/LogarithmPlotter/i18n" && cp assets/i18n/*.qm "$BUILD_DIR/LogarithmPlotter/i18n/" box "Building icons..." -cp -r assets/icons build/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ -cp assets/logarithmplotter.svg build/runtime-pyside6/LogarithmPlotter/ +cp -r assets/icons "$BUILD_QML_DIR" +cp assets/logarithmplotter.svg "$BUILD_DIR/LogarithmPlotter/" From 27c9fe0473f61cec7758108dff0a4d8d7f5b6468 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sun, 27 Oct 2024 00:46:42 +0200 Subject: [PATCH 074/104] Fixing newly made issue with PickLocation. --- .../eu/ad5001/LogarithmPlotter/Overlay/PickLocation.qml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/PickLocation.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/PickLocation.qml index f005756..60eb90e 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/PickLocation.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/PickLocation.qml @@ -32,12 +32,10 @@ import eu.ad5001.LogarithmPlotter.Common \sa LogarithmPlotter, LogGraphCanvas */ -Rectangle { +Item { id: pickerRoot visible: false clip: true - color: sysPalette.window - opacity: 0.35 /*! \qmlsignal PickLocationOverlay::picked(var obj) @@ -98,6 +96,11 @@ Rectangle { */ readonly property bool userPickY: pickY && pickYCheckbox.checked + Rectangle { + anchors.fill: parent + color: sysPalette.window + opacity: 0.35 + } MouseArea { id: picker From 727dda26235ecb57829d97667e2305610b5185bf Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sun, 27 Oct 2024 02:40:42 +0200 Subject: [PATCH 075/104] Adding loading screen for rendering LaTeX formula when threaded setting is enabled. --- common/src/history/common.mjs | 8 +- common/src/module/canvas.mjs | 3 + common/src/module/latex.mjs | 33 +++++- common/src/preferences/general.mjs | 4 +- common/test/mock/helper.mjs | 4 +- .../LogarithmPlotter/LogarithmPlotter.qml | 18 ++- .../ObjectLists/ObjectLists.qml | 2 +- .../LogarithmPlotter/Overlay/Loading.qml | 111 ++++++++++++++++++ .../Overlay/ViewPositionChange.qml | 10 -- .../eu/ad5001/LogarithmPlotter/Overlay/qmldir | 1 + .../LogarithmPlotter/util/config.py | 2 +- .../LogarithmPlotter/util/debug.py | 4 +- .../LogarithmPlotter/util/latex.py | 2 +- 13 files changed, 168 insertions(+), 34 deletions(-) diff --git a/common/src/history/common.mjs b/common/src/history/common.mjs index 33f9118..e8e5795 100644 --- a/common/src/history/common.mjs +++ b/common/src/history/common.mjs @@ -95,11 +95,15 @@ export class Action { if(!Latex.enabled) throw new Error("Cannot render an item as LaTeX when LaTeX is disabled.") const imgDepth = History.imageDepth - const { source, width, height } = await Latex.requestAsyncRender( + const renderArguments = [ latexString, imgDepth * (History.fontSize + 2), History.themeTextColor - ) + ] + let render = Latex.findPrerendered(...renderArguments) + if(render === null) + render = await Latex.requestAsyncRender(...renderArguments) + const { source, width, height } = render return `` } diff --git a/common/src/module/canvas.mjs b/common/src/module/canvas.mjs index ba6d5ca..5736cfc 100644 --- a/common/src/module/canvas.mjs +++ b/common/src/module/canvas.mjs @@ -25,7 +25,10 @@ import Objects from "./objects.mjs" import History from "./history.mjs" import Settings from "./settings.mjs" + class CanvasAPI extends Module { + + /** @type {CanvasInterface} */ #canvas = null /** @type {CanvasRenderingContext2D} */ diff --git a/common/src/module/latex.mjs b/common/src/module/latex.mjs index 216e3be..65ce689 100644 --- a/common/src/module/latex.mjs +++ b/common/src/module/latex.mjs @@ -17,6 +17,7 @@ */ import { Module } from "./common.mjs" +import { BaseEvent } from "../events.mjs" import * as Instruction from "../lib/expr-eval/instruction.mjs" import { escapeValue } from "../lib/expr-eval/expression.mjs" import { HelperInterface, LatexInterface } from "./interface.mjs" @@ -44,6 +45,28 @@ const equivalchars = ["\\pi", "\\infty", "{}_{4}", "{}_{5}", "{}_{6}", "{}_{7}", "{}_{8}", "{}_{9}", "{}_{0}", ] + + + +class AsyncRenderStartedEvent extends BaseEvent { + constructor(markup, fontSize, color) { + super("async-render-started") + this.markup = markup + this.fontSize = fontSize + this.color = color + } +} + + +class AsyncRenderFinishedEvent extends BaseEvent { + constructor(markup, fontSize, color) { + super("async-render-finished") + this.markup = markup + this.fontSize = fontSize + this.color = color + } +} + /** * Class containing the result of a LaTeX render. * @@ -60,6 +83,8 @@ class LatexRenderResult { } class LatexAPI extends Module { + static emits = ["async-render-started", "async-render-finished"] + /** @type {LatexInterface} */ #latex = null @@ -113,10 +138,14 @@ class LatexAPI extends Module { async requestAsyncRender(markup, fontSize, color) { if(!this.initialized) throw new Error("Attempting requestAsyncRender before initialize!") let render - if(this.#latex.supportsAsyncRender) + if(this.#latex.supportsAsyncRender) { + console.trace() + this.emit(new AsyncRenderStartedEvent(markup, fontSize, color)) render = await this.#latex.renderAsync(markup, fontSize, color) - else + this.emit(new AsyncRenderFinishedEvent(markup, fontSize, color)) + } else { render = this.#latex.renderSync(markup, fontSize, color) + } const args = render.split(",") return new LatexRenderResult(...args) } diff --git a/common/src/preferences/general.mjs b/common/src/preferences/general.mjs index a6957c6..a00a813 100644 --- a/common/src/preferences/general.mjs +++ b/common/src/preferences/general.mjs @@ -47,8 +47,8 @@ class EnableLatex extends BoolSetting { } const ENABLE_LATEX_ASYNC = new BoolSetting( - qsTranslate("general", "Enable asynchronous LaTeX renderer"), - "enable_latex_async", + qsTranslate("general", "Enable threaded LaTeX renderer (experimental)"), + "enable_latex_threaded", "new" ) diff --git a/common/test/mock/helper.mjs b/common/test/mock/helper.mjs index 4cab472..b912b44 100644 --- a/common/test/mock/helper.mjs +++ b/common/test/mock/helper.mjs @@ -23,7 +23,7 @@ const DEFAULT_SETTINGS = { "reset_redo_stack": true, "last_install_greet": "0", "enable_latex": true, - "enable_latex_async": true, + "enable_latex_threaded": true, "expression_editor": { "autoclose": true, "colorize": true, @@ -113,4 +113,4 @@ export class MockHelper { throw new Error(`File not found.`) } -} \ No newline at end of file +} diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml index b8799de..064a0be 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml @@ -17,10 +17,10 @@ */ import QtQml -import QtQuick.Controls -import eu.ad5001.MixedMenu 1.1 -import QtQuick.Layouts 1.12 import QtQuick +import QtQuick.Controls +import QtQuick.Layouts 1.12 +import eu.ad5001.MixedMenu 1.1 // Auto loading all modules. import eu.ad5001.LogarithmPlotter.Common @@ -158,21 +158,17 @@ ApplicationWindow { Overlay.ViewPositionChange { id: viewPositionChanger anchors.fill: parent - canvas: parent - settingsInstance: settings } Overlay.PickLocation { id: positionPicker anchors.fill: parent - canvas: parent } + } - // Overlay.Loading { - // id: loadingOverlay - // anchors.fill: parent - // canvas: parent - // } + Overlay.Loading { + id: loadingOverlay + anchors.fill: parent } Timer { diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml index f755a6f..c2a5a23 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml @@ -56,7 +56,7 @@ ScrollView { property var editingRows: [] model: Modules.Objects.currentObjects[objType] width: objectsListView.width - implicitHeight: contentItem.childrenRect.height + height: contentItem.childrenRect.height + 10 visible: model != undefined && model.length > 0 interactive: false diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/Loading.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/Loading.qml index a69f2cd..6aec616 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/Loading.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/Loading.qml @@ -17,3 +17,114 @@ */ import QtQuick +import QtQuick.Controls + + +/*! + \qmltype Loading + \inqmlmodule eu.ad5001.LogarithmPlotter.Overlay + \brief Overlay notifiying the user when a file is loading. + + Provides an overlay over the canvas that is shown when the user loads a new file, both to lock the ViewPositionChange + overlay and inform the user of what is loading and how much remains. + + \sa Common, ViewPositionChange +*/ +Item { + id: loadingRoot + opacity: 0 + visible: opacity !== 0 + clip: true + + property int currentlyLoading: 0 + property int maxCurrentLoadingSteps: 0 + + Behavior on opacity { PropertyAnimation {} } + + Rectangle { + anchors.fill: parent + color: sysPalette.window + opacity: 0.85 + } + + Column { + spacing: 5 + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + right: parent.right + } + + Text { + id: loadingTitle + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 20 + color: sysPalette.windowText + } + + ProgressBar { + id: progress + anchors.horizontalCenter: parent.horizontalCenter + width: 300 + from: 0 + value: loadingRoot.maxCurrentLoadingSteps - loadingRoot.currentlyLoading + to: loadingRoot.maxCurrentLoadingSteps + } + + Text { + id: lastFinishedStep + anchors.horizontalCenter: parent.horizontalCenter + color: sysPalette.windowText + } + } + + MouseArea { + id: picker + anchors.fill: parent + hoverEnabled: parent.visible + cursorShape: Qt.ArrowCursor + acceptedButtons: Qt.LeftButton | Qt.RightButton + } + + + + /*! + \qmlmethod void Loading::addedLoadingStep() + Registers one new loading step that will eventually call \c finishedLoadingStep. + */ + function addedLoadingStep() { + if(loadingRoot.maxCurrentLoadingSteps === 1) { + // Only when several ones need to be loaded. + const fileName = Modules.Settings.saveFilename.split('/').pop().split('\\').pop() + loadingTitle.text = qsTr("Loading...") + loadingRoot.opacity = 1 + } + loadingRoot.currentlyLoading++ + loadingRoot.maxCurrentLoadingSteps++ + } + + /*! + \qmlmethod void Loading::finishedLoadingStep() + Marks a loading step as finished and displays the message to the user. + */ + function finishedLoadingStep(message) { + loadingRoot.currentlyLoading-- + const current = loadingRoot.maxCurrentLoadingSteps - loadingRoot.currentlyLoading + lastFinishedStep.text = `${message} (${current}/${loadingRoot.maxCurrentLoadingSteps})` + if(loadingRoot.currentlyLoading === 0) { + loadingRoot.maxCurrentLoadingSteps = 0 + loadingRoot.opacity = 0 + } + } + + + Component.onCompleted: function() { + Modules.Latex.on("async-render-started", (e) => { + addedLoadingStep() + }) + Modules.Latex.on("async-render-finished", (e) => { + const markup = e.markup.length > 20 ? e.markup.substring(0, 15)+"..." : e.markup + finishedLoadingStep(qsTr("Finished rendering of %1").arg(markup)) + }) + } +} diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/ViewPositionChange.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/ViewPositionChange.qml index 1931536..41ce60a 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/ViewPositionChange.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/ViewPositionChange.qml @@ -57,16 +57,6 @@ Item { */ signal endPositionChange(int deltaX, int deltaY) - /*! - \qmlproperty var ViewPositionChangeOverlay::canvas - LogGraphCanvas instance. - */ - property var canvas - /*! - \qmlproperty var ViewPositionChangeOverlay::settingsInstance - Settings instance. - */ - property var settingsInstance /*! \qmlproperty int ViewPositionChangeOverlay::prevX The x coordinate (on the mousearea) at the last change of the canvas position. diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/qmldir b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/qmldir index 8daae21..0288c9e 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/qmldir +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/qmldir @@ -1,4 +1,5 @@ module eu.ad5001.LogarithmPlotter.Overlay +Loading 1.0 Loading.qml PickLocation 1.0 PickLocation.qml ViewPositionChange 1.0 ViewPositionChange.qml diff --git a/runtime-pyside6/LogarithmPlotter/util/config.py b/runtime-pyside6/LogarithmPlotter/util/config.py index e01deae..020569a 100644 --- a/runtime-pyside6/LogarithmPlotter/util/config.py +++ b/runtime-pyside6/LogarithmPlotter/util/config.py @@ -28,7 +28,7 @@ DEFAULT_SETTINGS = { "reset_redo_stack": True, "last_install_greet": "0", "enable_latex": which("latex") is not None and which("dvipng") is not None, - "enable_latex_async": True, + "enable_latex_threaded": True, "expression_editor": { "autoclose": True, "colorize": True, diff --git a/runtime-pyside6/LogarithmPlotter/util/debug.py b/runtime-pyside6/LogarithmPlotter/util/debug.py index f899fd5..ef02d62 100644 --- a/runtime-pyside6/LogarithmPlotter/util/debug.py +++ b/runtime-pyside6/LogarithmPlotter/util/debug.py @@ -22,9 +22,9 @@ from os import path from re import compile CURRENT_PATH = path.dirname(path.realpath(__file__)) -SOURCEMAP_PATH = path.realpath(f"{CURRENT_PATH}/../qml/eu/ad5001/LogarithmPlotter/js/index.mjs.map") +SOURCEMAP_PATH = path.realpath(f"{CURRENT_PATH}/../qml/eu/ad5001/LogarithmPlotter/Common/index.mjs.map") SOURCEMAP_INDEX = None -INDEX_REG = compile(r"build\/runtime-pyside6\/LogarithmPlotter\/qml\/eu\/ad5001\/LogarithmPlotter\/js\/index.mjs:(\d+)") +INDEX_REG = compile(r"build\/runtime-pyside6\/LogarithmPlotter\/qml\/eu\/ad5001\/LogarithmPlotter\/Common\/index.mjs:(\d+)") class LOG_COLORS: diff --git a/runtime-pyside6/LogarithmPlotter/util/latex.py b/runtime-pyside6/LogarithmPlotter/util/latex.py index 78c9d44..570e083 100644 --- a/runtime-pyside6/LogarithmPlotter/util/latex.py +++ b/runtime-pyside6/LogarithmPlotter/util/latex.py @@ -91,7 +91,7 @@ class Latex(QObject): @Property(bool) def supportsAsyncRender(self) -> bool: - return config.getSetting("enable_latex_async") + return config.getSetting("enable_latex_threaded") @Slot(result=bool) def checkLatexInstallation(self) -> bool: From 49e94317d4f3de3868c5329840238ef817e22170 Mon Sep 17 00:00:00 2001 From: ovari Date: Sun, 27 Oct 2024 07:13:26 +0000 Subject: [PATCH 076/104] Translated using Weblate (Hungarian) Currently translated at 100.0% (265 of 265 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/ --- assets/i18n/lp_hu.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/i18n/lp_hu.ts b/assets/i18n/lp_hu.ts index a43da4d..ac521eb 100644 --- a/assets/i18n/lp_hu.ts +++ b/assets/i18n/lp_hu.ts @@ -1321,7 +1321,7 @@ Kiértékelt kifejezés: %3 Could not load file: - + Nem sikerült betölteni a fájlt: Could not save file: From 687b14429a17b627935acf6b51d41f3ae0431811 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Mon, 28 Oct 2024 18:45:34 +0100 Subject: [PATCH 077/104] Improving reliability of threaded rendering, separating JS Utils into separate files. --- common/src/history/position.mjs | 2 +- common/src/index.mjs | 5 +- common/src/math/expression.mjs | 4 +- common/src/math/sequence.mjs | 2 +- common/src/module/canvas.mjs | 2 +- common/src/module/latex.mjs | 8 +- common/src/module/objects.mjs | 2 +- common/src/objs/common.mjs | 2 +- common/src/objs/function.mjs | 2 +- .../src/{utils.mjs => utils/expression.mjs} | 178 +----------------- common/src/utils/index.mjs | 22 +++ common/src/utils/other.mjs | 41 ++++ common/src/utils/prototype.mjs | 51 +++++ common/src/utils/subsup.mjs | 140 ++++++++++++++ common/test/basics/utils.mjs | 2 +- common/test/math/expression.mjs | 2 +- .../LogarithmPlotter/logarithmplotter.py | 9 +- .../LogarithmPlotter/util/promise.py | 8 +- 18 files changed, 285 insertions(+), 197 deletions(-) rename common/src/{utils.mjs => utils/expression.mjs} (72%) create mode 100644 common/src/utils/index.mjs create mode 100644 common/src/utils/other.mjs create mode 100644 common/src/utils/prototype.mjs create mode 100644 common/src/utils/subsup.mjs diff --git a/common/src/history/position.mjs b/common/src/history/position.mjs index 4c1af60..3bf2fe8 100644 --- a/common/src/history/position.mjs +++ b/common/src/history/position.mjs @@ -19,7 +19,7 @@ import Objects from "../module/objects.mjs" import Latex from "../module/latex.mjs" import * as MathLib from "../math/index.mjs" -import { escapeHTML } from "../utils.mjs" +import { escapeHTML } from "../utils/index.mjs" import { Action } from "./common.mjs" /** diff --git a/common/src/index.mjs b/common/src/index.mjs index c19e2fe..9b5684c 100644 --- a/common/src/index.mjs +++ b/common/src/index.mjs @@ -18,10 +18,11 @@ import js from "./lib/polyfills/js.mjs" -import * as Modules from "./module/index.mjs" +export * as Utils from "./utils/index.mjs" + import * as ObjsAutoload from "./objs/autoload.mjs" +export * as Modules from "./module/index.mjs" export * as MathLib from "./math/index.mjs" export * as HistoryLib from "./history/index.mjs" export * as Parsing from "./parsing/index.mjs" -export * as Utils from "./utils.mjs" diff --git a/common/src/math/expression.mjs b/common/src/math/expression.mjs index 5701ac6..7c7170b 100644 --- a/common/src/math/expression.mjs +++ b/common/src/math/expression.mjs @@ -17,11 +17,11 @@ */ -import * as Utils from "../utils.mjs" +import * as Utils from "../utils/index.mjs" +import { ExprEvalExpression } from "../lib/expr-eval/expression.mjs" import Latex from "../module/latex.mjs" import ExprParser from "../module/expreval.mjs" import Objects from "../module/objects.mjs" -import { ExprEvalExpression } from "../lib/expr-eval/expression.mjs" const NUMBER_MATCHER = /^\d*\.\d+(e[+-]\d+)?$/ diff --git a/common/src/math/sequence.mjs b/common/src/math/sequence.mjs index 5394237..b295708 100644 --- a/common/src/math/sequence.mjs +++ b/common/src/math/sequence.mjs @@ -17,7 +17,7 @@ */ import * as Expr from "./expression.mjs" -import * as Utils from "../utils.mjs" +import * as Utils from "../utils/index.mjs" import Latex from "../module/latex.mjs" import Objects from "../module/objects.mjs" import ExprParser from "../module/expreval.mjs" diff --git a/common/src/module/canvas.mjs b/common/src/module/canvas.mjs index 5736cfc..dcc3f33 100644 --- a/common/src/module/canvas.mjs +++ b/common/src/module/canvas.mjs @@ -18,7 +18,7 @@ import { Module } from "./common.mjs" import { CanvasInterface, DialogInterface } from "./interface.mjs" -import { textsup } from "../utils.mjs" +import { textsup } from "../utils/index.mjs" import { Expression } from "../math/index.mjs" import Latex from "./latex.mjs" import Objects from "./objects.mjs" diff --git a/common/src/module/latex.mjs b/common/src/module/latex.mjs index 65ce689..3b48ebc 100644 --- a/common/src/module/latex.mjs +++ b/common/src/module/latex.mjs @@ -97,6 +97,7 @@ class LatexAPI extends Module { * true if latex has been enabled by the user, false otherwise. */ this.enabled = false + this.promises = new Set() } /** @@ -139,9 +140,12 @@ class LatexAPI extends Module { if(!this.initialized) throw new Error("Attempting requestAsyncRender before initialize!") let render if(this.#latex.supportsAsyncRender) { - console.trace() this.emit(new AsyncRenderStartedEvent(markup, fontSize, color)) - render = await this.#latex.renderAsync(markup, fontSize, color) + // Storing promise so that it does not get dereferenced. + const promise = this.#latex.renderAsync(markup, fontSize, color) + this.promises.add(promise) + render = await promise + this.promises.delete(promise) this.emit(new AsyncRenderFinishedEvent(markup, fontSize, color)) } else { render = this.#latex.renderSync(markup, fontSize, color) diff --git a/common/src/module/objects.mjs b/common/src/module/objects.mjs index 23801be..979dba4 100644 --- a/common/src/module/objects.mjs +++ b/common/src/module/objects.mjs @@ -17,7 +17,7 @@ */ import { Module } from "./common.mjs" -import { textsub } from "../utils.mjs" +import { textsub } from "../utils/index.mjs" class ObjectsAPI extends Module { diff --git a/common/src/objs/common.mjs b/common/src/objs/common.mjs index 1534a9a..380ac5d 100644 --- a/common/src/objs/common.mjs +++ b/common/src/objs/common.mjs @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -import { getRandomColor } from "../utils.mjs" import Objects from "../module/objects.mjs" import Latex from "../module/latex.mjs" +import { getRandomColor } from "../utils/index.mjs" import { ensureTypeSafety, serializesByPropertyType } from "../parameters.mjs" // This file contains the default data to be imported from all other objects diff --git a/common/src/objs/function.mjs b/common/src/objs/function.mjs index b056cc3..70d0b69 100644 --- a/common/src/objs/function.mjs +++ b/common/src/objs/function.mjs @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { textsub } from "../utils.mjs" +import { textsub } from "../utils/index.mjs" import Objects from "../module/objects.mjs" import { ExecutableObject } from "./common.mjs" import { parseDomain, Expression, SpecialDomain } from "../math/index.mjs" diff --git a/common/src/utils.mjs b/common/src/utils/expression.mjs similarity index 72% rename from common/src/utils.mjs rename to common/src/utils/expression.mjs index 5c51f62..ef20b27 100644 --- a/common/src/utils.mjs +++ b/common/src/utils/expression.mjs @@ -16,151 +16,7 @@ * along with this program. If not, see . */ -// Add string methods -/** - * Replaces latin characters with their uppercase versions. - * @return {string} - */ -String.prototype.toLatinUppercase = function() { - return this.replace(/[a-z]/g, function(match) { - return match.toUpperCase() - }) -} - -/** - * Removes the first and last character of a string - * Used to remove enclosing characters like quotes, parentheses, brackets... - * @note Does NOT check for their existence ahead of time. - * @return {string} - */ -String.prototype.removeEnclosure = function() { - return this.substring(1, this.length - 1) -} - -/** - * Rounds to a certain number of decimal places. - * From https://stackoverflow.com/a/48764436 - * - * @param {number} decimalPlaces - * @return {number} - */ -Number.prototype.toDecimalPrecision = function(decimalPlaces = 0) { - const p = Math.pow(10, decimalPlaces) - const n = (this * p) * (1 + Number.EPSILON) - return Math.round(n) / p -} - -const CHARACTER_TO_POWER = new Map([ - ["-", "⁻"], - ["+", "⁺"], - ["=", "⁼"], - [" ", " "], - ["(", "⁽"], - [")", "⁾"], - ["0", "⁰"], - ["1", "¹"], - ["2", "²"], - ["3", "³"], - ["4", "⁴"], - ["5", "⁵"], - ["6", "⁶"], - ["7", "⁷"], - ["8", "⁸"], - ["9", "⁹"], - ["a", "ᵃ"], - ["b", "ᵇ"], - ["c", "ᶜ"], - ["d", "ᵈ"], - ["e", "ᵉ"], - ["f", "ᶠ"], - ["g", "ᵍ"], - ["h", "ʰ"], - ["i", "ⁱ"], - ["j", "ʲ"], - ["k", "ᵏ"], - ["l", "ˡ"], - ["m", "ᵐ"], - ["n", "ⁿ"], - ["o", "ᵒ"], - ["p", "ᵖ"], - ["r", "ʳ"], - ["s", "ˢ"], - ["t", "ᵗ"], - ["u", "ᵘ"], - ["v", "ᵛ"], - ["w", "ʷ"], - ["x", "ˣ"], - ["y", "ʸ"], - ["z", "ᶻ"] -]) - -const CHARACTER_TO_INDICE = new Map([ - ["-", "₋"], - ["+", "₊"], - ["=", "₌"], - ["(", "₍"], - [")", "₎"], - [" ", " "], - ["0", "₀"], - ["1", "₁"], - ["2", "₂"], - ["3", "₃"], - ["4", "₄"], - ["5", "₅"], - ["6", "₆"], - ["7", "₇"], - ["8", "₈"], - ["9", "₉"], - ["a", "ₐ"], - ["e", "ₑ"], - ["h", "ₕ"], - ["i", "ᵢ"], - ["j", "ⱼ"], - ["k", "ₖ"], - ["l", "ₗ"], - ["m", "ₘ"], - ["n", "ₙ"], - ["o", "ₒ"], - ["p", "ₚ"], - ["r", "ᵣ"], - ["s", "ₛ"], - ["t", "ₜ"], - ["u", "ᵤ"], - ["v", "ᵥ"], - ["x", "ₓ"] -]) - -const EXPONENTS = [ - "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹" -] - -const EXPONENTS_REG = new RegExp("([" + EXPONENTS.join("") + "]+)", "g") - -/** - * Put a text in sup position - * @param {string} text - * @return {string} - */ -export function textsup(text) { - let ret = "" - text = text.toString() - for(let letter of text) - ret += CHARACTER_TO_POWER.has(letter) ? CHARACTER_TO_POWER.get(letter) : letter - return ret -} - -/** - * Put a text in sub position - * @param {string} text - * @return {string} - */ -export function textsub(text) { - let ret = "" - text = text.toString() - for(let letter of text) - ret += CHARACTER_TO_INDICE.has(letter) ? CHARACTER_TO_INDICE.get(letter) : letter - return ret -} +import { textsub, textsup } from "./subsup.mjs" /** * Simplifies (mathematically) a mathematical expression. @@ -400,35 +256,3 @@ export function parseName(str, removeUnallowed = true) { return str } - -/** - * Creates a randomized color string. - * @returns {string} - */ -export function getRandomColor() { - let clrs = "0123456789ABCDEF" - let color = "#" - for(let i = 0; i < 6; i++) { - color += clrs[Math.floor(Math.random() * (16 - 5 * (i % 2 === 0)))] - } - return color -} - -/** - * Escapes text to html entities. - * @param {string} str - * @returns {string} - */ -export function escapeHTML(str) { - return str.replace(/&/g, "&").replace(//g, ">") -} - - -/** - * Parses exponents and replaces them with expression values - * @param {string} expression - The expression to replace in. - * @return {string} The parsed expression - */ -export function exponentsToExpression(expression) { - return expression.replace(EXPONENTS_REG, (m, exp) => "^" + exp.split("").map((x) => EXPONENTS.indexOf(x)).join("")) -} diff --git a/common/src/utils/index.mjs b/common/src/utils/index.mjs new file mode 100644 index 0000000..02adfd6 --- /dev/null +++ b/common/src/utils/index.mjs @@ -0,0 +1,22 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export * from "./prototype.mjs" +export * from "./subsup.mjs" +export * from "./expression.mjs" +export * from "./other.mjs" diff --git a/common/src/utils/other.mjs b/common/src/utils/other.mjs new file mode 100644 index 0000000..bcafd6b --- /dev/null +++ b/common/src/utils/other.mjs @@ -0,0 +1,41 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + + +/** + * Creates a randomized color string. + * @returns {string} + */ +export function getRandomColor() { + let clrs = "0123456789ABCDEF" + let color = "#" + for(let i = 0; i < 6; i++) { + color += clrs[Math.floor(Math.random() * (16 - 5 * (i % 2 === 0)))] + } + return color +} + +/** + * Escapes text to html entities. + * @param {string} str + * @returns {string} + */ +export function escapeHTML(str) { + return str.replace(/&/g, "&").replace(//g, ">") +} diff --git a/common/src/utils/prototype.mjs b/common/src/utils/prototype.mjs new file mode 100644 index 0000000..cb2cc15 --- /dev/null +++ b/common/src/utils/prototype.mjs @@ -0,0 +1,51 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// Add string methods +/** + * Replaces latin characters with their uppercase versions. + * @return {string} + */ +String.prototype.toLatinUppercase = function() { + return this.replace(/[a-z]/g, function(match) { + return match.toUpperCase() + }) +} + +/** + * Removes the first and last character of a string + * Used to remove enclosing characters like quotes, parentheses, brackets... + * @note Does NOT check for their existence ahead of time. + * @return {string} + */ +String.prototype.removeEnclosure = function() { + return this.substring(1, this.length - 1) +} + +/** + * Rounds to a certain number of decimal places. + * From https://stackoverflow.com/a/48764436 + * + * @param {number} decimalPlaces + * @return {number} + */ +Number.prototype.toDecimalPrecision = function(decimalPlaces = 0) { + const p = Math.pow(10, decimalPlaces) + const n = (this * p) * (1 + Number.EPSILON) + return Math.round(n) / p +} diff --git a/common/src/utils/subsup.mjs b/common/src/utils/subsup.mjs new file mode 100644 index 0000000..ff6ed50 --- /dev/null +++ b/common/src/utils/subsup.mjs @@ -0,0 +1,140 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +const CHARACTER_TO_POWER = new Map([ + ["-", "⁻"], + ["+", "⁺"], + ["=", "⁼"], + [" ", " "], + ["(", "⁽"], + [")", "⁾"], + ["0", "⁰"], + ["1", "¹"], + ["2", "²"], + ["3", "³"], + ["4", "⁴"], + ["5", "⁵"], + ["6", "⁶"], + ["7", "⁷"], + ["8", "⁸"], + ["9", "⁹"], + ["a", "ᵃ"], + ["b", "ᵇ"], + ["c", "ᶜ"], + ["d", "ᵈ"], + ["e", "ᵉ"], + ["f", "ᶠ"], + ["g", "ᵍ"], + ["h", "ʰ"], + ["i", "ⁱ"], + ["j", "ʲ"], + ["k", "ᵏ"], + ["l", "ˡ"], + ["m", "ᵐ"], + ["n", "ⁿ"], + ["o", "ᵒ"], + ["p", "ᵖ"], + ["r", "ʳ"], + ["s", "ˢ"], + ["t", "ᵗ"], + ["u", "ᵘ"], + ["v", "ᵛ"], + ["w", "ʷ"], + ["x", "ˣ"], + ["y", "ʸ"], + ["z", "ᶻ"] +]) + +const CHARACTER_TO_INDICE = new Map([ + ["-", "₋"], + ["+", "₊"], + ["=", "₌"], + ["(", "₍"], + [")", "₎"], + [" ", " "], + ["0", "₀"], + ["1", "₁"], + ["2", "₂"], + ["3", "₃"], + ["4", "₄"], + ["5", "₅"], + ["6", "₆"], + ["7", "₇"], + ["8", "₈"], + ["9", "₉"], + ["a", "ₐ"], + ["e", "ₑ"], + ["h", "ₕ"], + ["i", "ᵢ"], + ["j", "ⱼ"], + ["k", "ₖ"], + ["l", "ₗ"], + ["m", "ₘ"], + ["n", "ₙ"], + ["o", "ₒ"], + ["p", "ₚ"], + ["r", "ᵣ"], + ["s", "ₛ"], + ["t", "ₜ"], + ["u", "ᵤ"], + ["v", "ᵥ"], + ["x", "ₓ"] +]) + +const EXPONENTS = [ + "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹" +] + +const EXPONENTS_REG = new RegExp("([" + EXPONENTS.join("") + "]+)", "g") + +/** + * Put a text in sup position + * @param {string} text + * @return {string} + */ +export function textsup(text) { + let ret = "" + text = text.toString() + for(let letter of text) + ret += CHARACTER_TO_POWER.has(letter) ? CHARACTER_TO_POWER.get(letter) : letter + return ret +} + +/** + * Put a text in sub position + * @param {string} text + * @return {string} + */ +export function textsub(text) { + let ret = "" + text = text.toString() + for(let letter of text) + ret += CHARACTER_TO_INDICE.has(letter) ? CHARACTER_TO_INDICE.get(letter) : letter + return ret +} + + +/** + * Parses exponents and replaces them with expression values + * @param {string} expression - The expression to replace in. + * @return {string} The parsed expression + */ +export function exponentsToExpression(expression) { + return expression.replace(EXPONENTS_REG, (m, exp) => "^" + exp.split("").map((x) => EXPONENTS.indexOf(x)).join("")) +} + diff --git a/common/test/basics/utils.mjs b/common/test/basics/utils.mjs index aab2cf5..42adead 100644 --- a/common/test/basics/utils.mjs +++ b/common/test/basics/utils.mjs @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { textsup, textsub, parseName, getRandomColor, escapeHTML, exponentsToExpression } from "../../src/utils.mjs" +import { textsup, textsub, parseName, getRandomColor, escapeHTML, exponentsToExpression } from "../../src/utils/index.mjs" import { describe, it } from "mocha" diff --git a/common/test/math/expression.mjs b/common/test/math/expression.mjs index a0ee113..0c15f9c 100644 --- a/common/test/math/expression.mjs +++ b/common/test/math/expression.mjs @@ -178,4 +178,4 @@ describe("Math/Expression", function() { expect(() => executeExpression("x+n")).to.throw("Undefined variable n.") }) }) -}) \ No newline at end of file +}) diff --git a/runtime-pyside6/LogarithmPlotter/logarithmplotter.py b/runtime-pyside6/LogarithmPlotter/logarithmplotter.py index c4c16b9..8940e56 100644 --- a/runtime-pyside6/LogarithmPlotter/logarithmplotter.py +++ b/runtime-pyside6/LogarithmPlotter/logarithmplotter.py @@ -21,9 +21,10 @@ from platform import system as os_name, release as OS_RELEASE from sys import path as sys_path from sys import argv, exit from tempfile import TemporaryDirectory +from math import ceil from time import time -from PySide6.QtCore import QTranslator, QLocale +from PySide6.QtCore import QTranslator, QLocale, QThreadPool, QThread from PySide6.QtGui import QIcon from PySide6.QtQml import QQmlApplicationEngine from PySide6.QtQuickControls2 import QQuickStyle @@ -162,7 +163,11 @@ def run(): dep_time = time() print("Loaded dependencies in " + str((dep_time - start_time) * 1000) + "ms.") - + + # Maxing thread count to half the computer's thread count to avoid maxing CPU + # with too many threads (and also leaving some for rendering). + QThreadPool.globalInstance().setMaxThreadCount(int(ceil(QThread.idealThreadCount() / 2))) + register_icon_directories() app = create_qapp() translator = install_translation(app) diff --git a/runtime-pyside6/LogarithmPlotter/util/promise.py b/runtime-pyside6/LogarithmPlotter/util/promise.py index c917660..f4f21c2 100644 --- a/runtime-pyside6/LogarithmPlotter/util/promise.py +++ b/runtime-pyside6/LogarithmPlotter/util/promise.py @@ -22,6 +22,8 @@ from PySide6.QtQml import QJSValue from LogarithmPlotter.util.js import PyJSValue +NO_RETURN = [None, QJSValue.SpecialValue.UndefinedValue] + def check_callable(function: Callable|QJSValue) -> Callable|None: """ @@ -153,13 +155,12 @@ class PyPromise(QObject): @Slot(QObject) def _fulfill(self, data): self._state = "fulfilled" - no_return = [None, QJSValue.SpecialValue.UndefinedValue] print("Finished", self._runner.args) for i in range(len(self._fulfills)): try: result = self._fulfills[i](data) result = result.qjs_value if isinstance(result, PyJSValue) else result - data = result if result not in no_return else data # Forward data. + data = result if result not in NO_RETURN else data # Forward data. except Exception as e: self._reject(repr(e), start_at=i) break @@ -168,8 +169,7 @@ class PyPromise(QObject): @Slot(str) def _reject(self, error, start_at=0): self._state = "rejected" - no_return = [None, QJSValue.SpecialValue.UndefinedValue] for i in range(start_at, len(self._rejects)): result = self._rejects[i](error) result = result.qjs_value if isinstance(result, PyJSValue) else result - error = result if result not in no_return else error # Forward data. + error = result if result not in NO_RETURN else error # Forward data. From 43e41a5da4f4f7b7f9c8bfe66da5898c1f1ca3af Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Mon, 28 Oct 2024 18:51:13 +0100 Subject: [PATCH 078/104] Adding new test files Including: - magnitude.lpf & phase.lpf: regular use case magnitude and phase - all.lpf: tests all objects - stress.lpf: over 200 objects to be rendered --- ci/all.lpf | 1 + ci/drone.yml | 4 ++++ ci/magnitude.lpf | 1 + ci/phase.lpf | 1 + ci/stress.lpf | 1 + 5 files changed, 8 insertions(+) create mode 100644 ci/all.lpf create mode 100644 ci/magnitude.lpf create mode 100644 ci/phase.lpf create mode 100644 ci/stress.lpf diff --git a/ci/all.lpf b/ci/all.lpf new file mode 100644 index 0000000..9eeb0b9 --- /dev/null +++ b/ci/all.lpf @@ -0,0 +1 @@ +LPFv1{"xzoom":100,"yzoom":10,"xmin":0.2696454905834007,"ymax":33.115625,"xaxisstep":"4","yaxisstep":"π","xaxislabel":"","yaxislabel":"","logscalex":true,"linewidth":1,"showxgrad":true,"showygrad":true,"textsize":18,"history":[[["CreateNewObject",["A","Point",["A",true,"#941A97","name + value","1","0","above","●"]]],["EditedPosition",["A","Point","1","175.36","0","9.9"]],["CreateNewObject",["f","Function",["f",true,"#6E590E","name + value","x","ℝ⁺*","ℝ","application","above",1,true,true]]],["EditedProperty",["f","Function","expression","x","((x / 2) - 1)",true]],["CreateNewObject",["t","Text",["t",true,"#118455","null","1","0","center","New text",false]]],["EditedPosition",["t","Text","1","36.48","0","(-13.7)"]],["EditedProperty",["t","Text","text","New text","AEZA",false]],["CreateNewObject",["ω","Point",["ω",true,"#5A3A52","name","1","0","above","●"]]],["CreateNewObject",["G₀","Gain Bode",["G₀",true,"#5A3A52","name + value","ω","high","20","below",1,false]]],["EditedPosition",["ω","Point","1","17.76","0","(-8.9)"]],["EditedProperty",["G₀","Gain Bode","gain","20","10",true]],["EditedProperty",["G₀","Gain Bode","labelPosition","below","below-left",false]],["EditedProperty",["G₀","Gain Bode","pass","high","low",false]],["EditedProperty",["G₀","Gain Bode","labelX",1,62.61,false]],["CreateNewObject",["X","X Cursor",["X",true,"#5909A9","name + value","1",null,"left",true,3,"— — — — — — —","Next to target"]]],["EditedProperty",["X","X Cursor","x","1","5.04",true]],["CreateNewObject",["u","Sequence",["u",true,"#78929E","name + value",true,true,{"1":"n"},{"0":0},"above",1]]],["EditedProperty",["u","Sequence","defaultExpression",{"1":"n"},{"1":"n+1"},false]],["EditedProperty",["u","Sequence","defaultExpression",{"1":"n+1"},{"1":"n+1"},false]],["EditedProperty",["u","Sequence","baseValues",{"0":0},{"0":"-1"},false]],["EditedProperty",["u","Sequence","baseValues",{"0":"-1"},{"0":"-1"},false]],["CreateNewObject",["F_X","Repartition",["F_X",true,"#231931","name + value",{"0":"0"},"above",1]]],["EditedProperty",["F_X","Repartition","labelX",1,12.64,false]],["EditedProperty",["f","Function","labelPosition","above","right",false]],["EditedProperty",["f","Function","labelX",1,30,false]],["EditedProperty",["u","Sequence","labelX",1,3,false]],["EditedProperty",["F_X","Repartition","labelX",12.64,40,false]],["EditedProperty",["ω","Point","labelPosition","above","below",false]],["CreateNewObject",["ω₀","Point",["ω₀","#7C2981","name","name + value","1","0","above","●"]]],["CreateNewObject",["φ₀","Phase Bode",["φ₀",true,"#7C2981","name + value","ω₀","90","°","below",1]]],["EditedPosition",["ω₀","Point","1","3","0","(-8)"]],["EditedPosition",["ω₀","Point","3","2","(-8)","8"]],["EditedProperty",["ω₀","Point","labelPosition","above","above-right",false]],["EditedProperty",["u","Sequence","labelPosition","above","above-left",false]],["EditedProperty",["u","Sequence","labelX",3,20,false]],["EditedProperty",["G","Somme gains Bode","labelX",1,2,false]]],[]],"width":1000,"height":500,"objects":{"Point":[["A",true,"#941A97","name + value","175.36","9.9","above","●"],["ω",true,"#5A3A52","name","17.76","(-8.9)","below","●"],["ω₀",false,"name","name","2","8","above-right","●"]],"Function":[["f",true,"#6E590E","name + value","((x / 2) - 1)","ℝ⁺*","ℝ","application","right",30,true,true]],"Text":[["t",true,"#118455","null","36.48","(-13.7)","center","AEZA",false]],"Gain Bode":[["G₀",true,"#5A3A52","name + value","ω","low","10","below-left",62.61,false]],"Somme gains Bode":[["G",true,"#A83C72","name + value","above",2]],"X Cursor":[["X",true,"#5909A9","name + value","5.04",null,"left",true,null,"— — — — — — —","Next to target"]],"Sequence":[["u",true,"#78929E","name + value",true,true,{"1":"n+1"},{"0":"-1"},"above-left",20]],"Repartition":[["F_X",true,"#231931","name + value",{"0":"0"},"above",40]],"Phase Bode":[["φ₀",true,"#7C2981","name + value","ω₀","90","°","below",1]],"Somme phases Bode":[["φ",true,"#A08B14","name + value","above",1]]},"type":"logplotv1"} \ No newline at end of file diff --git a/ci/drone.yml b/ci/drone.yml index d49a6d4..54ef658 100644 --- a/ci/drone.yml +++ b/ci/drone.yml @@ -31,6 +31,10 @@ steps: - xvfb-run python3 run.py --test-build --no-check-for-updates - xvfb-run python3 run.py --test-build --no-check-for-updates ./ci/test1.lpf - xvfb-run python3 run.py --test-build --no-check-for-updates ./ci/test2.lpf + - xvfb-run python3 run.py --test-build --no-check-for-updates ./ci/all.lpf + - xvfb-run python3 run.py --test-build --no-check-for-updates ./ci/magnitude.lpf + - xvfb-run python3 run.py --test-build --no-check-for-updates ./ci/phase.lpf + - xvfb-run python3 run.py --test-build --no-check-for-updates ./ci/stress.lpf when: event: [ push, tag ] diff --git a/ci/magnitude.lpf b/ci/magnitude.lpf new file mode 100644 index 0000000..35ac7ae --- /dev/null +++ b/ci/magnitude.lpf @@ -0,0 +1 @@ +LPFv1{"xzoom":120,"yzoom":10,"xmin":0.5,"ymax":25,"xaxisstep":"4","yaxisstep":"4","xaxislabel":"ω (rad/s)","yaxislabel":"G (dB)","logscalex":true,"linewidth":2,"showxgrad":false,"showygrad":true,"textsize":17,"history":[[["CreateNewObject",["ω","Point",["ω",true,"#94AE66","name","1","0","top","●"]]],["CreateNewObject",["G₀","Gain Bode",["G₀",true,"#94AE66","name + value","ω","high","20","below",1,false]]],["EditedProperty",["G₀","Gain Bode","gain","20","0",true]],["EditedProperty",["ω","Point","y","0","10",true]],["EditedVisibility",["ω","Point","visible"]],["EditedProperty",["G","Somme gains Bode","labelX",1,10,false]],["CreateNewObject",["ω₀","Point",["ω₀",true,"#A38B4D","name","1","0","top","●"]]],["CreateNewObject",["G₁","Gain Bode",["G₁",true,"#A38B4D","name + value","ω₀","high","20","below",1,false]]],["EditedProperty",["G₁","Gain Bode","pass","high","low",false]],["EditedProperty",["G₁","Gain Bode","gain","20","(-20)",true]],["EditedVisibility",["ω₀","Point","visible"]],["EditedProperty",["ω₁","Point","x","1","10",true]],["CreateNewObject",["ω₀","Point",["ω₀",true,"#5F04A2","name","1","0","top","●"]]],["CreateNewObject",["G₂","Gain Bode",["G₂",true,"#5F04A2","name + value","ω₀","high","20","below",1,false]]],["EditedVisibility",["ω₀","Point","visible"]],["EditedProperty",["G₂","Gain Bode","labelX",1,5,false]],["EditedProperty",["ω₂","Point","x","1","5",true]],["EditedProperty",["G₂","Gain Bode","pass","high","low",false]],["EditedProperty",["G₂","Gain Bode","gain","20","(-20)",true]],["EditedProperty",["ω₁","Point","x","10","13",true]],["EditedProperty",["ω₁","Point","x","13","30",true]],["EditedProperty",["G₀","Gain Bode","labelPosition","below","below",false]],["EditedProperty",["G₀","Gain Bode","labelX",1,2,false]],["EditedProperty",["G₀","Gain Bode","labelPosition","below","above",false]],["EditedProperty",["G₂","Gain Bode","labelX",5,40,false]],["EditedProperty",["G₂","Gain Bode","labelX",40,20,false]],["EditedProperty",["G₂","Gain Bode","labelX",20,10,false]],["EditedProperty",["G₁","Gain Bode","labelX",1,40,false]],["EditedProperty",["G₁","Gain Bode","labelPosition","below","above-left",false]],["EditedProperty",["G₁","Gain Bode","labelPosition","above-left","above-right",false]],["EditedProperty",["G₁","Gain Bode","labelX",40,45,false]],["EditedProperty",["G","Somme gains Bode","labelX",10,4,false]],["EditedProperty",["G₀","Gain Bode","labelX",2,20,false]],["EditedProperty",["G₁","Gain Bode","omGraduation",false,true,false]],["EditedProperty",["G₂","Gain Bode","omGraduation",false,true,false]],["EditedProperty",["G","Somme gains Bode","labelX",4,2,false]],["EditedProperty",["G","Somme gains Bode","labelPosition","above","below",false]],["EditedProperty",["G₁","Gain Bode","omGraduation",true,false,false]],["EditedProperty",["ω₁","Point","x","30","0",true]],["EditedVisibility",["ω₁","Point","visible"]],["EditedProperty",["G₁","Gain Bode","gain","(-20)","20",true]],["EditedProperty",["ω₁","Point","x","1","0.05",true]],["EditedProperty",["ω₁","Point","y","0","(-20)",true]],["EditedProperty",["ω₁","Point","x","0.05","0.1",true]],["EditedProperty",["G₁","Gain Bode","labelX",45,2,false]],["EditedProperty",["ω","Point","y","10","(-10)",true]],["EditedProperty",["ω","Point","y","(-10)","(-5)",true]],["EditedProperty",["G","Somme gains Bode","labelX",2,15,false]],["CreateNewObject",["X","X Cursor",["X",true,"#61AD9E","name + value","1",null,"left",true,3,"— — — — — — —","Next to target"]]],["EditedProperty",["X","X Cursor","x","1","50",true]],["EditedProperty",["G₂","Gain Bode","color","#5F04A2","#5f04a2",false]],["EditedProperty",["X","X Cursor","color","#61AD9E","#5f04a2",false]],["CreateNewObject",["text","Text",["text",true,"#242159","null","1","0","center","New text"]]],["EditedProperty",["text","Text","x","1","20",true]],["EditedProperty",["text","Text","x","20","50",true]],["EditedProperty",["text","Text","labelPosition","center","right",false]],["EditedProperty",["text","Text","labelPosition","right","left",false]],["EditedProperty",["text","Text","y","0","20",true]],["EditedProperty",["text","Text","text","New text","10",false]],["EditedProperty",["text","Text","text","10","10ω",false]],["EditedProperty",["text","Text","text","10ω","10ω₂",false]],["EditedProperty",["X","X Cursor","color","#5f04a2","#5f04a2",false]],["EditedProperty",["text","Text","color","#242159","#5f04a2",false]],["EditedProperty",["text","Text","disableLatex",false,true,false]],["EditedProperty",["G₁","Gain Bode","labelPosition","above-right","above-left",false]],["ColorChanged",["G₀","Gain Bode","#94AE66","#00aa00"]],["ColorChanged",["G₀","Gain Bode","#00aa00","#0000ff"]],["ColorChanged",["ω","Point","#94AE66","#0000ff"]],["EditedProperty",["ω₂","Point","labelPosition","top","above-left",false]],["EditedProperty",["ω₂","Point","labelPosition","above-left","below-left",false]],["EditedProperty",["ω₂","Point","labelPosition","below-left","above-right",false]],["EditedProperty",["text","Text","disableLatex",false,true,false]]],[]],"width":961,"height":500,"objects":{"Point":[["ω",false,"#0000ff","name","1","(-5)","top","●"],["ω₁",false,"#A38B4D","name","0.1","(-20)","top","●"],["ω₂",true,"#5F04A2","name","5","0","above-right","●"]],"Gain Bode":[["G₀",true,"#0000ff","name","ω","high","0","above",20,false],["G₁",true,"#A38B4D","name","ω₁","low","20","above-left",2,false],["G₂",true,"#5f04a2","name","ω₂","low","(-20)","below",10,true]],"Somme gains Bode":[["G",true,"#3E6E2A","name + value","below",15]],"X Cursor":[["X",true,"#5f04a2","null","50",null,"left",true,3,"— — — — — — —","Next to target"]],"Text":[["text",true,"#5f04a2","null","50","20","left","10ω₂",false]]},"type":"logplotv1"} diff --git a/ci/phase.lpf b/ci/phase.lpf new file mode 100644 index 0000000..361d157 --- /dev/null +++ b/ci/phase.lpf @@ -0,0 +1 @@ +LPFv1{"xzoom":100,"yzoom":100,"xmin":0.5,"ymax":2,"xaxisstep":"4","yaxisstep":"pi/4","xaxislabel":"ω (rad/s)","yaxislabel":"φ (rad)","logscalex":true,"linewidth":2,"showxgrad":true,"showygrad":true,"textsize":20,"history":[[["CreateNewObject",["f","Function",["f",true,"#989E2D","name + value","x","ℝ⁺*","ℝ","application","above",1,true,true]]],["EditedProperty",["f","Function","expression","x","(x ^ 20)",true]],["EditedProperty",["f","Function","expression","(x ^ 20)","(20 * (log10 x))",true]],["DeleteObject",["f","Function",["f",true,"#989E2D","name + value","(20 * (log10 x))","ℝ⁺*","ℝ","application","above",1,true,true]]],["CreateNewObject",["ω","Point",["ω",true,"#995178","name","1","0","bottom","●"]]],["CreateNewObject",["φ₀","Phase Bode",["φ₀",true,"#995178","name + value","ω","90","°","below",1]]],["EditedProperty",["φ₀","Phase Bode","phase","90","0",true]],["EditedProperty",["φ₀","Phase Bode","unit","°","rad",false]],["EditedProperty",["ω","Point","y","0","((-pi) / 2)",true]],["EditedVisibility",["ω","Point","visible"]],["EditedProperty",["φ₀","Phase Bode","labelX",1,10,false]],["CreateNewObject",["ω₀","Point",["ω₀",true,"#037753","name","1","0","bottom","●"]]],["CreateNewObject",["φ₁","Phase Bode",["φ₁",true,"#037753","name + value","ω₀","90","°","below",1]]],["EditedProperty",["ω₀","Point","x","1","10",true]],["EditedProperty",["φ₁","Phase Bode","unit","°","rad",false]],["EditedProperty",["φ₁","Phase Bode","phase","90","(pi / 2)",true]],["EditedProperty",["ω₀","Point","x","10","5",true]],["EditedProperty",["ω₀","Point","labelPosition","bottom","top-left",false]],["EditedProperty",["φ₁","Phase Bode","labelX",1,2,false]],["EditedProperty",["φ","Somme phases Bode","labelX",1,2,false]],["ColorChanged",["φ","Somme phases Bode","#665B74","#550000"]],["EditedProperty",["ω₀","Point","labelPosition","top-left","above-left",false]],["EditedProperty",["ω₀","Point","labelPosition","above-left","above-right",false]]],[]],"width":1000,"height":500,"objects":{"Function":[],"Point":[["ω",false,"#995178","name","1","((-pi) / 2)","below","●"],["ω₀",true,"#037753","name","5","0","above-right","●"]],"Phase Bode":[["φ₀",true,"#995178","name","ω","0","rad","below",10],["φ₁",true,"#037753","name","ω₀","(pi / 2)","rad","below",2]],"Somme phases Bode":[["φ",true,"#550000","name + value","above",2]]},"type":"logplotv1"} \ No newline at end of file diff --git a/ci/stress.lpf b/ci/stress.lpf new file mode 100644 index 0000000..05e171c --- /dev/null +++ b/ci/stress.lpf @@ -0,0 +1 @@ +LPFv1{"xzoom":150,"yzoom":10,"xmin":0.49556664658184385,"ymax":25.120703,"xaxisstep":"4","yaxisstep":"4","xaxislabel":"","yaxislabel":"","logscalex":true,"linewidth":1,"showxgrad":true,"showygrad":true,"textsize":18,"history":[[["CreateNewObject",["A","Point",["A",true,"#A35D32","name + value","1","0","above","●"]]],["CreateNewObject",["B","Point",["B",true,"#AF370C","name + value","1","0","above","●"]]],["CreateNewObject",["C","Point",["C",true,"#AB9221","name + value","1","0","above","●"]]],["CreateNewObject",["D","Point",["D",true,"#43A98E","name + value","1","0","above","●"]]],["CreateNewObject",["E","Point",["E",true,"#1F1C6A","name + value","1","0","above","●"]]],["CreateNewObject",["F","Point",["F",true,"#407099","name + value","1","0","above","●"]]],["CreateNewObject",["J","Point",["J",true,"#9B4B7A","name + value","1","0","above","●"]]],["CreateNewObject",["K","Point",["K",true,"#3B5698","name + value","1","0","above","●"]]],["CreateNewObject",["L","Point",["L",true,"#0C6A4D","name + value","1","0","above","●"]]],["CreateNewObject",["M","Point",["M",true,"#350945","name + value","1","0","above","●"]]],["CreateNewObject",["N","Point",["N",true,"#46511E","name + value","1","0","above","●"]]],["CreateNewObject",["O","Point",["O",true,"#0B318B","name + value","1","0","above","●"]]],["CreateNewObject",["P","Point",["P",true,"#354125","name + value","1","0","above","●"]]],["CreateNewObject",["Q","Point",["Q",true,"#598608","name + value","1","0","above","●"]]],["CreateNewObject",["R","Point",["R",true,"#733D64","name + value","1","0","above","●"]]],["CreateNewObject",["S","Point",["S",true,"#7477A8","name + value","1","0","above","●"]]],["CreateNewObject",["T","Point",["T",true,"#5B6034","name + value","1","0","above","●"]]],["CreateNewObject",["U","Point",["U",true,"#951A57","name + value","1","0","above","●"]]],["CreateNewObject",["V","Point",["V",true,"#72804E","name + value","1","0","above","●"]]],["CreateNewObject",["W","Point",["W",true,"#7B1070","name + value","1","0","above","●"]]],["CreateNewObject",["A₀","Point",["A₀",true,"#AFA71F","name + value","1","0","above","●"]]],["CreateNewObject",["B₀","Point",["B₀",true,"#121733","name + value","1","0","above","●"]]],["CreateNewObject",["C₀","Point",["C₀",true,"#363740","name + value","1","0","above","●"]]],["CreateNewObject",["D₀","Point",["D₀",true,"#96896E","name + value","1","0","above","●"]]],["CreateNewObject",["E₀","Point",["E₀",true,"#051126","name + value","1","0","above","●"]]],["CreateNewObject",["F₀","Point",["F₀",true,"#2F004D","name + value","1","0","above","●"]]],["CreateNewObject",["J₀","Point",["J₀",true,"#4B064D","name + value","1","0","above","●"]]],["CreateNewObject",["K₀","Point",["K₀",true,"#7D6527","name + value","1","0","above","●"]]],["CreateNewObject",["L₀","Point",["L₀",true,"#55725F","name + value","1","0","above","●"]]],["CreateNewObject",["M₀","Point",["M₀",true,"#A09E28","name + value","1","0","above","●"]]],["CreateNewObject",["N₀","Point",["N₀",true,"#3A7E1A","name + value","1","0","above","●"]]],["CreateNewObject",["O₀","Point",["O₀",true,"#905361","name + value","1","0","above","●"]]],["CreateNewObject",["P₀","Point",["P₀",true,"#824C96","name + value","1","0","above","●"]]],["CreateNewObject",["t","Text",["t",true,"#7F6A2B","null","1","0","center","New text",false]]],["CreateNewObject",["Q₀","Point",["Q₀",true,"#0B919F","name + value","1","0","above","●"]]],["CreateNewObject",["R₀","Point",["R₀",true,"#308188","name + value","1","0","above","●"]]],["CreateNewObject",["S₀","Point",["S₀",true,"#434DA2","name + value","1","0","above","●"]]],["CreateNewObject",["T₀","Point",["T₀",true,"#5A4455","name + value","1","0","above","●"]]],["CreateNewObject",["U₀","Point",["U₀",true,"#289954","name + value","1","0","above","●"]]],["CreateNewObject",["V₀","Point",["V₀",true,"#5D2371","name + value","1","0","above","●"]]],["CreateNewObject",["W₀","Point",["W₀",true,"#9E9F13","name + value","1","0","above","●"]]],["CreateNewObject",["A₁","Point",["A₁",true,"#6B8E7A","name + value","1","0","above","●"]]],["CreateNewObject",["B₁","Point",["B₁",true,"#25186C","name + value","1","0","above","●"]]],["CreateNewObject",["C₁","Point",["C₁",true,"#8FA8AD","name + value","1","0","above","●"]]],["CreateNewObject",["D₁","Point",["D₁",true,"#5D4528","name + value","1","0","above","●"]]],["CreateNewObject",["E₁","Point",["E₁",true,"#26435D","name + value","1","0","above","●"]]],["CreateNewObject",["F₁","Point",["F₁",true,"#6B7C9C","name + value","1","0","above","●"]]],["CreateNewObject",["J₁","Point",["J₁",true,"#96275E","name + value","1","0","above","●"]]],["CreateNewObject",["K₁","Point",["K₁",true,"#3DAF12","name + value","1","0","above","●"]]],["CreateNewObject",["L₁","Point",["L₁",true,"#1EA902","name + value","1","0","above","●"]]],["CreateNewObject",["t₀","Text",["t₀",true,"#511C6A","null","1","0","center","New text",false]]],["CreateNewObject",["M₁","Point",["M₁",true,"#515D07","name + value","1","0","above","●"]]],["CreateNewObject",["N₁","Point",["N₁",true,"#711764","name + value","1","0","above","●"]]],["CreateNewObject",["O₁","Point",["O₁",true,"#732C94","name + value","1","0","above","●"]]],["CreateNewObject",["P₁","Point",["P₁",true,"#66174C","name + value","1","0","above","●"]]],["CreateNewObject",["Q₁","Point",["Q₁",true,"#75816A","name + value","1","0","above","●"]]],["CreateNewObject",["R₁","Point",["R₁",true,"#AF8C59","name + value","1","0","above","●"]]],["CreateNewObject",["S₁","Point",["S₁",true,"#1E446B","name + value","1","0","above","●"]]],["CreateNewObject",["T₁","Point",["T₁",true,"#A58DA6","name + value","1","0","above","●"]]],["CreateNewObject",["U₁","Point",["U₁",true,"#912D54","name + value","1","0","above","●"]]],["CreateNewObject",["V₁","Point",["V₁",true,"#8E8886","name + value","1","0","above","●"]]],["CreateNewObject",["W₁","Point",["W₁",true,"#26602E","name + value","1","0","above","●"]]],["CreateNewObject",["A₂","Point",["A₂",true,"#8C6064","name + value","1","0","above","●"]]],["CreateNewObject",["B₂","Point",["B₂",true,"#431889","name + value","1","0","above","●"]]],["CreateNewObject",["C₂","Point",["C₂",true,"#8D6959","name + value","1","0","above","●"]]],["CreateNewObject",["D₂","Point",["D₂",true,"#A57776","name + value","1","0","above","●"]]],["CreateNewObject",["E₂","Point",["E₂",true,"#312374","name + value","1","0","above","●"]]],["CreateNewObject",["F₂","Point",["F₂",true,"#3D3150","name + value","1","0","above","●"]]],["CreateNewObject",["J₂","Point",["J₂",true,"#6F9C66","name + value","1","0","above","●"]]],["CreateNewObject",["t₁","Text",["t₁",true,"#84223B","null","1","0","center","New text",false]]],["CreateNewObject",["K₂","Point",["K₂",true,"#3C2899","name + value","1","0","above","●"]]],["CreateNewObject",["L₂","Point",["L₂",true,"#753355","name + value","1","0","above","●"]]],["CreateNewObject",["M₂","Point",["M₂",true,"#3F046A","name + value","1","0","above","●"]]],["CreateNewObject",["N₂","Point",["N₂",true,"#9E4B51","name + value","1","0","above","●"]]],["CreateNewObject",["O₂","Point",["O₂",true,"#199B64","name + value","1","0","above","●"]]],["CreateNewObject",["P₂","Point",["P₂",true,"#59893D","name + value","1","0","above","●"]]],["CreateNewObject",["Q₂","Point",["Q₂",true,"#944D3E","name + value","1","0","above","●"]]],["CreateNewObject",["R₂","Point",["R₂",true,"#8D8836","name + value","1","0","above","●"]]],["CreateNewObject",["S₂","Point",["S₂",true,"#A52589","name + value","1","0","above","●"]]],["CreateNewObject",["t₂","Text",["t₂",true,"#A10A90","null","1","0","center","New text",false]]],["CreateNewObject",["T₂","Point",["T₂",true,"#7F723D","name + value","1","0","above","●"]]],["CreateNewObject",["U₂","Point",["U₂",true,"#78AB96","name + value","1","0","above","●"]]],["CreateNewObject",["V₂","Point",["V₂",true,"#626A23","name + value","1","0","above","●"]]],["CreateNewObject",["W₂","Point",["W₂",true,"#401362","name + value","1","0","above","●"]]],["CreateNewObject",["A₃","Point",["A₃",true,"#9F0E30","name + value","1","0","above","●"]]],["CreateNewObject",["B₃","Point",["B₃",true,"#100C0E","name + value","1","0","above","●"]]],["CreateNewObject",["C₃","Point",["C₃",true,"#858161","name + value","1","0","above","●"]]],["CreateNewObject",["D₃","Point",["D₃",true,"#7482A8","name + value","1","0","above","●"]]],["CreateNewObject",["E₃","Point",["E₃",true,"#0D03A3","name + value","1","0","above","●"]]],["CreateNewObject",["F₃","Point",["F₃",true,"#652922","name + value","1","0","above","●"]]],["CreateNewObject",["J₃","Point",["J₃",true,"#39A671","name + value","1","0","above","●"]]],["CreateNewObject",["K₃","Point",["K₃",true,"#4E0481","name + value","1","0","above","●"]]],["CreateNewObject",["L₃","Point",["L₃",true,"#1F9239","name + value","1","0","above","●"]]],["CreateNewObject",["M₃","Point",["M₃",true,"#986A07","name + value","1","0","above","●"]]],["CreateNewObject",["N₃","Point",["N₃",true,"#4AAE1F","name + value","1","0","above","●"]]],["CreateNewObject",["O₃","Point",["O₃",true,"#3C0911","name + value","1","0","above","●"]]],["CreateNewObject",["P₃","Point",["P₃",true,"#400A42","name + value","1","0","above","●"]]],["CreateNewObject",["Q₃","Point",["Q₃",true,"#9A9C5F","name + value","1","0","above","●"]]],["CreateNewObject",["R₃","Point",["R₃",true,"#AB7FA9","name + value","1","0","above","●"]]],["CreateNewObject",["S₃","Point",["S₃",true,"#4E9D33","name + value","1","0","above","●"]]],["CreateNewObject",["T₃","Point",["T₃",true,"#564E4C","name + value","1","0","above","●"]]],["CreateNewObject",["U₃","Point",["U₃",true,"#674739","name + value","1","0","above","●"]]],["CreateNewObject",["V₃","Point",["V₃",true,"#5D689B","name + value","1","0","above","●"]]],["CreateNewObject",["W₃","Point",["W₃",true,"#6B8E57","name + value","1","0","above","●"]]],["CreateNewObject",["A₄","Point",["A₄",true,"#169C3E","name + value","1","0","above","●"]]],["CreateNewObject",["B₄","Point",["B₄",true,"#95104E","name + value","1","0","above","●"]]],["CreateNewObject",["C₄","Point",["C₄",true,"#73379E","name + value","1","0","above","●"]]],["CreateNewObject",["D₄","Point",["D₄",true,"#98143F","name + value","1","0","above","●"]]],["CreateNewObject",["E₄","Point",["E₄",true,"#A8926F","name + value","1","0","above","●"]]],["CreateNewObject",["F₄","Point",["F₄",true,"#3172AB","name + value","1","0","above","●"]]],["CreateNewObject",["J₄","Point",["J₄",true,"#8A9C96","name + value","1","0","above","●"]]],["CreateNewObject",["K₄","Point",["K₄",true,"#AF001D","name + value","1","0","above","●"]]],["CreateNewObject",["L₄","Point",["L₄",true,"#711495","name + value","1","0","above","●"]]],["CreateNewObject",["M₄","Point",["M₄",true,"#082241","name + value","1","0","above","●"]]],["CreateNewObject",["N₄","Point",["N₄",true,"#631582","name + value","1","0","above","●"]]],["CreateNewObject",["O₄","Point",["O₄",true,"#895378","name + value","1","0","above","●"]]],["CreateNewObject",["P₄","Point",["P₄",true,"#812404","name + value","1","0","above","●"]]],["CreateNewObject",["Q₄","Point",["Q₄",true,"#3B2755","name + value","1","0","above","●"]]],["CreateNewObject",["R₄","Point",["R₄",true,"#5B6E03","name + value","1","0","above","●"]]],["CreateNewObject",["S₄","Point",["S₄",true,"#AF4237","name + value","1","0","above","●"]]],["CreateNewObject",["T₄","Point",["T₄",true,"#9C75AC","name + value","1","0","above","●"]]],["CreateNewObject",["U₄","Point",["U₄",true,"#926178","name + value","1","0","above","●"]]],["CreateNewObject",["V₄","Point",["V₄",true,"#8C3DA7","name + value","1","0","above","●"]]],["CreateNewObject",["W₄","Point",["W₄",true,"#95843C","name + value","1","0","above","●"]]],["CreateNewObject",["A₅","Point",["A₅",true,"#022359","name + value","1","0","above","●"]]],["CreateNewObject",["B₅","Point",["B₅",true,"#8B906E","name + value","1","0","above","●"]]],["CreateNewObject",["C₅","Point",["C₅",true,"#317B9A","name + value","1","0","above","●"]]],["CreateNewObject",["D₅","Point",["D₅",true,"#559232","name + value","1","0","above","●"]]],["CreateNewObject",["E₅","Point",["E₅",true,"#9324A5","name + value","1","0","above","●"]]],["CreateNewObject",["F₅","Point",["F₅",true,"#574940","name + value","1","0","above","●"]]],["CreateNewObject",["J₅","Point",["J₅",true,"#A93968","name + value","1","0","above","●"]]],["CreateNewObject",["K₅","Point",["K₅",true,"#1F6266","name + value","1","0","above","●"]]],["CreateNewObject",["L₅","Point",["L₅",true,"#181928","name + value","1","0","above","●"]]],["CreateNewObject",["M₅","Point",["M₅",true,"#760C13","name + value","1","0","above","●"]]],["CreateNewObject",["N₅","Point",["N₅",true,"#366B7E","name + value","1","0","above","●"]]],["CreateNewObject",["O₅","Point",["O₅",true,"#8E6060","name + value","1","0","above","●"]]],["CreateNewObject",["P₅","Point",["P₅",true,"#A8158D","name + value","1","0","above","●"]]],["CreateNewObject",["Q₅","Point",["Q₅",true,"#1D206C","name + value","1","0","above","●"]]],["CreateNewObject",["R₅","Point",["R₅",true,"#9C6169","name + value","1","0","above","●"]]],["CreateNewObject",["S₅","Point",["S₅",true,"#6F412F","name + value","1","0","above","●"]]],["CreateNewObject",["T₅","Point",["T₅",true,"#0B2453","name + value","1","0","above","●"]]],["CreateNewObject",["U₅","Point",["U₅",true,"#04839E","name + value","1","0","above","●"]]],["CreateNewObject",["V₅","Point",["V₅",true,"#8B29A5","name + value","1","0","above","●"]]],["CreateNewObject",["W₅","Point",["W₅",true,"#491438","name + value","1","0","above","●"]]],["CreateNewObject",["A₆","Point",["A₆",true,"#00087B","name + value","1","0","above","●"]]],["CreateNewObject",["B₆","Point",["B₆",true,"#0F431C","name + value","1","0","above","●"]]],["CreateNewObject",["C₆","Point",["C₆",true,"#1D3B07","name + value","1","0","above","●"]]],["CreateNewObject",["D₆","Point",["D₆",true,"#7F695A","name + value","1","0","above","●"]]],["CreateNewObject",["E₆","Point",["E₆",true,"#AB4383","name + value","1","0","above","●"]]],["CreateNewObject",["F₆","Point",["F₆",true,"#9C9E78","name + value","1","0","above","●"]]],["CreateNewObject",["J₆","Point",["J₆",true,"#243945","name + value","1","0","above","●"]]],["CreateNewObject",["K₆","Point",["K₆",true,"#A49EAA","name + value","1","0","above","●"]]],["CreateNewObject",["L₆","Point",["L₆",true,"#822C32","name + value","1","0","above","●"]]],["CreateNewObject",["M₆","Point",["M₆",true,"#095D68","name + value","1","0","above","●"]]],["CreateNewObject",["N₆","Point",["N₆",true,"#AA361D","name + value","1","0","above","●"]]],["CreateNewObject",["O₆","Point",["O₆",true,"#045B40","name + value","1","0","above","●"]]],["CreateNewObject",["P₆","Point",["P₆",true,"#2B10AD","name + value","1","0","above","●"]]],["CreateNewObject",["Q₆","Point",["Q₆",true,"#8F0607","name + value","1","0","above","●"]]],["CreateNewObject",["R₆","Point",["R₆",true,"#953472","name + value","1","0","above","●"]]],["CreateNewObject",["S₆","Point",["S₆",true,"#7F7663","name + value","1","0","above","●"]]],["CreateNewObject",["T₆","Point",["T₆",true,"#9A4294","name + value","1","0","above","●"]]],["CreateNewObject",["U₆","Point",["U₆",true,"#924762","name + value","1","0","above","●"]]],["CreateNewObject",["V₆","Point",["V₆",true,"#006385","name + value","1","0","above","●"]]],["CreateNewObject",["W₆","Point",["W₆",true,"#8C0504","name + value","1","0","above","●"]]],["CreateNewObject",["A₇","Point",["A₇",true,"#337BA0","name + value","1","0","above","●"]]],["CreateNewObject",["B₇","Point",["B₇",true,"#970A47","name + value","1","0","above","●"]]],["CreateNewObject",["C₇","Point",["C₇",true,"#8D071F","name + value","1","0","above","●"]]],["CreateNewObject",["D₇","Point",["D₇",true,"#241417","name + value","1","0","above","●"]]],["CreateNewObject",["E₇","Point",["E₇",true,"#8DAB44","name + value","1","0","above","●"]]],["CreateNewObject",["F₇","Point",["F₇",true,"#555D7B","name + value","1","0","above","●"]]],["CreateNewObject",["J₇","Point",["J₇",true,"#537A31","name + value","1","0","above","●"]]],["CreateNewObject",["K₇","Point",["K₇",true,"#298D88","name + value","1","0","above","●"]]],["CreateNewObject",["L₇","Point",["L₇",true,"#55249C","name + value","1","0","above","●"]]],["CreateNewObject",["M₇","Point",["M₇",true,"#AB5E71","name + value","1","0","above","●"]]],["CreateNewObject",["N₇","Point",["N₇",true,"#834D89","name + value","1","0","above","●"]]],["CreateNewObject",["O₇","Point",["O₇",true,"#7B4EAC","name + value","1","0","above","●"]]],["CreateNewObject",["P₇","Point",["P₇",true,"#451133","name + value","1","0","above","●"]]],["CreateNewObject",["Q₇","Point",["Q₇",true,"#07410B","name + value","1","0","above","●"]]],["CreateNewObject",["R₇","Point",["R₇",true,"#5D0B61","name + value","1","0","above","●"]]],["CreateNewObject",["S₇","Point",["S₇",true,"#1F184F","name + value","1","0","above","●"]]],["CreateNewObject",["T₇","Point",["T₇",true,"#897283","name + value","1","0","above","●"]]],["CreateNewObject",["U₇","Point",["U₇",true,"#079906","name + value","1","0","above","●"]]],["CreateNewObject",["V₇","Point",["V₇",true,"#1DA545","name + value","1","0","above","●"]]],["CreateNewObject",["W₇","Point",["W₇",true,"#4E4A71","name + value","1","0","above","●"]]],["CreateNewObject",["A₈","Point",["A₈",true,"#563577","name + value","1","0","above","●"]]],["CreateNewObject",["B₈","Point",["B₈",true,"#6FA324","name + value","1","0","above","●"]]],["CreateNewObject",["C₈","Point",["C₈",true,"#099187","name + value","1","0","above","●"]]],["CreateNewObject",["D₈","Point",["D₈",true,"#0F976A","name + value","1","0","above","●"]]],["CreateNewObject",["E₈","Point",["E₈",true,"#525B2F","name + value","1","0","above","●"]]],["CreateNewObject",["F₈","Point",["F₈",true,"#249C5A","name + value","1","0","above","●"]]],["CreateNewObject",["J₈","Point",["J₈",true,"#359EAD","name + value","1","0","above","●"]]],["CreateNewObject",["K₈","Point",["K₈",true,"#014113","name + value","1","0","above","●"]]],["CreateNewObject",["L₈","Point",["L₈",true,"#992D2C","name + value","1","0","above","●"]]],["CreateNewObject",["M₈","Point",["M₈",true,"#2A9D50","name + value","1","0","above","●"]]],["CreateNewObject",["N₈","Point",["N₈",true,"#3BA6A8","name + value","1","0","above","●"]]],["CreateNewObject",["O₈","Point",["O₈",true,"#2F2BAB","name + value","1","0","above","●"]]],["CreateNewObject",["P₈","Point",["P₈",true,"#A35282","name + value","1","0","above","●"]]],["CreateNewObject",["Q₈","Point",["Q₈",true,"#346C86","name + value","1","0","above","●"]]],["CreateNewObject",["R₈","Point",["R₈",true,"#738755","name + value","1","0","above","●"]]],["CreateNewObject",["S₈","Point",["S₈",true,"#2E302D","name + value","1","0","above","●"]]],["CreateNewObject",["T₈","Point",["T₈",true,"#187E5B","name + value","1","0","above","●"]]],["CreateNewObject",["U₈","Point",["U₈",true,"#4B868E","name + value","1","0","above","●"]]],["CreateNewObject",["V₈","Point",["V₈",true,"#13937C","name + value","1","0","above","●"]]],["CreateNewObject",["W₈","Point",["W₈",true,"#938E72","name + value","1","0","above","●"]]]],[]],"width":1000,"height":500,"objects":{"Point":[["A",true,"#A35D32","name + value","1","0","above","●"],["B",true,"#AF370C","name + value","1","0","above","●"],["C",true,"#AB9221","name + value","1","0","above","●"],["D",true,"#43A98E","name + value","1","0","above","●"],["E",true,"#1F1C6A","name + value","1","0","above","●"],["F",true,"#407099","name + value","1","0","above","●"],["J",true,"#9B4B7A","name + value","1","0","above","●"],["K",true,"#3B5698","name + value","1","0","above","●"],["L",true,"#0C6A4D","name + value","1","0","above","●"],["M",true,"#350945","name + value","1","0","above","●"],["N",true,"#46511E","name + value","1","0","above","●"],["O",true,"#0B318B","name + value","1","0","above","●"],["P",true,"#354125","name + value","1","0","above","●"],["Q",true,"#598608","name + value","1","0","above","●"],["R",true,"#733D64","name + value","1","0","above","●"],["S",true,"#7477A8","name + value","1","0","above","●"],["T",true,"#5B6034","name + value","1","0","above","●"],["U",true,"#951A57","name + value","1","0","above","●"],["V",true,"#72804E","name + value","1","0","above","●"],["W",true,"#7B1070","name + value","1","0","above","●"],["A₀",true,"#AFA71F","name + value","1","0","above","●"],["B₀",true,"#121733","name + value","1","0","above","●"],["C₀",true,"#363740","name + value","1","0","above","●"],["D₀",true,"#96896E","name + value","1","0","above","●"],["E₀",true,"#051126","name + value","1","0","above","●"],["F₀",true,"#2F004D","name + value","1","0","above","●"],["J₀",true,"#4B064D","name + value","1","0","above","●"],["K₀",true,"#7D6527","name + value","1","0","above","●"],["L₀",true,"#55725F","name + value","1","0","above","●"],["M₀",true,"#A09E28","name + value","1","0","above","●"],["N₀",true,"#3A7E1A","name + value","1","0","above","●"],["O₀",true,"#905361","name + value","1","0","above","●"],["P₀",true,"#824C96","name + value","1","0","above","●"],["Q₀",true,"#0B919F","name + value","1","0","above","●"],["R₀",true,"#308188","name + value","1","0","above","●"],["S₀",true,"#434DA2","name + value","1","0","above","●"],["T₀",true,"#5A4455","name + value","1","0","above","●"],["U₀",true,"#289954","name + value","1","0","above","●"],["V₀",true,"#5D2371","name + value","1","0","above","●"],["W₀",true,"#9E9F13","name + value","1","0","above","●"],["A₁",true,"#6B8E7A","name + value","1","0","above","●"],["B₁",true,"#25186C","name + value","1","0","above","●"],["C₁",true,"#8FA8AD","name + value","1","0","above","●"],["D₁",true,"#5D4528","name + value","1","0","above","●"],["E₁",true,"#26435D","name + value","1","0","above","●"],["F₁",true,"#6B7C9C","name + value","1","0","above","●"],["J₁",true,"#96275E","name + value","1","0","above","●"],["K₁",true,"#3DAF12","name + value","1","0","above","●"],["L₁",true,"#1EA902","name + value","1","0","above","●"],["M₁",true,"#515D07","name + value","1","0","above","●"],["N₁",true,"#711764","name + value","1","0","above","●"],["O₁",true,"#732C94","name + value","1","0","above","●"],["P₁",true,"#66174C","name + value","1","0","above","●"],["Q₁",true,"#75816A","name + value","1","0","above","●"],["R₁",true,"#AF8C59","name + value","1","0","above","●"],["S₁",true,"#1E446B","name + value","1","0","above","●"],["T₁",true,"#A58DA6","name + value","1","0","above","●"],["U₁",true,"#912D54","name + value","1","0","above","●"],["V₁",true,"#8E8886","name + value","1","0","above","●"],["W₁",true,"#26602E","name + value","1","0","above","●"],["A₂",true,"#8C6064","name + value","1","0","above","●"],["B₂",true,"#431889","name + value","1","0","above","●"],["C₂",true,"#8D6959","name + value","1","0","above","●"],["D₂",true,"#A57776","name + value","1","0","above","●"],["E₂",true,"#312374","name + value","1","0","above","●"],["F₂",true,"#3D3150","name + value","1","0","above","●"],["J₂",true,"#6F9C66","name + value","1","0","above","●"],["K₂",true,"#3C2899","name + value","1","0","above","●"],["L₂",true,"#753355","name + value","1","0","above","●"],["M₂",true,"#3F046A","name + value","1","0","above","●"],["N₂",true,"#9E4B51","name + value","1","0","above","●"],["O₂",true,"#199B64","name + value","1","0","above","●"],["P₂",true,"#59893D","name + value","1","0","above","●"],["Q₂",true,"#944D3E","name + value","1","0","above","●"],["R₂",true,"#8D8836","name + value","1","0","above","●"],["S₂",true,"#A52589","name + value","1","0","above","●"],["T₂",true,"#7F723D","name + value","1","0","above","●"],["U₂",true,"#78AB96","name + value","1","0","above","●"],["V₂",true,"#626A23","name + value","1","0","above","●"],["W₂",true,"#401362","name + value","1","0","above","●"],["A₃",true,"#9F0E30","name + value","1","0","above","●"],["B₃",true,"#100C0E","name + value","1","0","above","●"],["C₃",true,"#858161","name + value","1","0","above","●"],["D₃",true,"#7482A8","name + value","1","0","above","●"],["E₃",true,"#0D03A3","name + value","1","0","above","●"],["F₃",true,"#652922","name + value","1","0","above","●"],["J₃",true,"#39A671","name + value","1","0","above","●"],["K₃",true,"#4E0481","name + value","1","0","above","●"],["L₃",true,"#1F9239","name + value","1","0","above","●"],["M₃",true,"#986A07","name + value","1","0","above","●"],["N₃",true,"#4AAE1F","name + value","1","0","above","●"],["O₃",true,"#3C0911","name + value","1","0","above","●"],["P₃",true,"#400A42","name + value","1","0","above","●"],["Q₃",true,"#9A9C5F","name + value","1","0","above","●"],["R₃",true,"#AB7FA9","name + value","1","0","above","●"],["S₃",true,"#4E9D33","name + value","1","0","above","●"],["T₃",true,"#564E4C","name + value","1","0","above","●"],["U₃",true,"#674739","name + value","1","0","above","●"],["V₃",true,"#5D689B","name + value","1","0","above","●"],["W₃",true,"#6B8E57","name + value","1","0","above","●"],["A₄",true,"#169C3E","name + value","1","0","above","●"],["B₄",true,"#95104E","name + value","1","0","above","●"],["C₄",true,"#73379E","name + value","1","0","above","●"],["D₄",true,"#98143F","name + value","1","0","above","●"],["E₄",true,"#A8926F","name + value","1","0","above","●"],["F₄",true,"#3172AB","name + value","1","0","above","●"],["J₄",true,"#8A9C96","name + value","1","0","above","●"],["K₄",true,"#AF001D","name + value","1","0","above","●"],["L₄",true,"#711495","name + value","1","0","above","●"],["M₄",true,"#082241","name + value","1","0","above","●"],["N₄",true,"#631582","name + value","1","0","above","●"],["O₄",true,"#895378","name + value","1","0","above","●"],["P₄",true,"#812404","name + value","1","0","above","●"],["Q₄",true,"#3B2755","name + value","1","0","above","●"],["R₄",true,"#5B6E03","name + value","1","0","above","●"],["S₄",true,"#AF4237","name + value","1","0","above","●"],["T₄",true,"#9C75AC","name + value","1","0","above","●"],["U₄",true,"#926178","name + value","1","0","above","●"],["V₄",true,"#8C3DA7","name + value","1","0","above","●"],["W₄",true,"#95843C","name + value","1","0","above","●"],["A₅",true,"#022359","name + value","1","0","above","●"],["B₅",true,"#8B906E","name + value","1","0","above","●"],["C₅",true,"#317B9A","name + value","1","0","above","●"],["D₅",true,"#559232","name + value","1","0","above","●"],["E₅",true,"#9324A5","name + value","1","0","above","●"],["F₅",true,"#574940","name + value","1","0","above","●"],["J₅",true,"#A93968","name + value","1","0","above","●"],["K₅",true,"#1F6266","name + value","1","0","above","●"],["L₅",true,"#181928","name + value","1","0","above","●"],["M₅",true,"#760C13","name + value","1","0","above","●"],["N₅",true,"#366B7E","name + value","1","0","above","●"],["O₅",true,"#8E6060","name + value","1","0","above","●"],["P₅",true,"#A8158D","name + value","1","0","above","●"],["Q₅",true,"#1D206C","name + value","1","0","above","●"],["R₅",true,"#9C6169","name + value","1","0","above","●"],["S₅",true,"#6F412F","name + value","1","0","above","●"],["T₅",true,"#0B2453","name + value","1","0","above","●"],["U₅",true,"#04839E","name + value","1","0","above","●"],["V₅",true,"#8B29A5","name + value","1","0","above","●"],["W₅",true,"#491438","name + value","1","0","above","●"],["A₆",true,"#00087B","name + value","1","0","above","●"],["B₆",true,"#0F431C","name + value","1","0","above","●"],["C₆",true,"#1D3B07","name + value","1","0","above","●"],["D₆",true,"#7F695A","name + value","1","0","above","●"],["E₆",true,"#AB4383","name + value","1","0","above","●"],["F₆",true,"#9C9E78","name + value","1","0","above","●"],["J₆",true,"#243945","name + value","1","0","above","●"],["K₆",true,"#A49EAA","name + value","1","0","above","●"],["L₆",true,"#822C32","name + value","1","0","above","●"],["M₆",true,"#095D68","name + value","1","0","above","●"],["N₆",true,"#AA361D","name + value","1","0","above","●"],["O₆",true,"#045B40","name + value","1","0","above","●"],["P₆",true,"#2B10AD","name + value","1","0","above","●"],["Q₆",true,"#8F0607","name + value","1","0","above","●"],["R₆",true,"#953472","name + value","1","0","above","●"],["S₆",true,"#7F7663","name + value","1","0","above","●"],["T₆",true,"#9A4294","name + value","1","0","above","●"],["U₆",true,"#924762","name + value","1","0","above","●"],["V₆",true,"#006385","name + value","1","0","above","●"],["W₆",true,"#8C0504","name + value","1","0","above","●"],["A₇",true,"#337BA0","name + value","1","0","above","●"],["B₇",true,"#970A47","name + value","1","0","above","●"],["C₇",true,"#8D071F","name + value","1","0","above","●"],["D₇",true,"#241417","name + value","1","0","above","●"],["E₇",true,"#8DAB44","name + value","1","0","above","●"],["F₇",true,"#555D7B","name + value","1","0","above","●"],["J₇",true,"#537A31","name + value","1","0","above","●"],["K₇",true,"#298D88","name + value","1","0","above","●"],["L₇",true,"#55249C","name + value","1","0","above","●"],["M₇",true,"#AB5E71","name + value","1","0","above","●"],["N₇",true,"#834D89","name + value","1","0","above","●"],["O₇",true,"#7B4EAC","name + value","1","0","above","●"],["P₇",true,"#451133","name + value","1","0","above","●"],["Q₇",true,"#07410B","name + value","1","0","above","●"],["R₇",true,"#5D0B61","name + value","1","0","above","●"],["S₇",true,"#1F184F","name + value","1","0","above","●"],["T₇",true,"#897283","name + value","1","0","above","●"],["U₇",true,"#079906","name + value","1","0","above","●"],["V₇",true,"#1DA545","name + value","1","0","above","●"],["W₇",true,"#4E4A71","name + value","1","0","above","●"],["A₈",true,"#563577","name + value","1","0","above","●"],["B₈",true,"#6FA324","name + value","1","0","above","●"],["C₈",true,"#099187","name + value","1","0","above","●"],["D₈",true,"#0F976A","name + value","1","0","above","●"],["E₈",true,"#525B2F","name + value","1","0","above","●"],["F₈",true,"#249C5A","name + value","1","0","above","●"],["J₈",true,"#359EAD","name + value","1","0","above","●"],["K₈",true,"#014113","name + value","1","0","above","●"],["L₈",true,"#992D2C","name + value","1","0","above","●"],["M₈",true,"#2A9D50","name + value","1","0","above","●"],["N₈",true,"#3BA6A8","name + value","1","0","above","●"],["O₈",true,"#2F2BAB","name + value","1","0","above","●"],["P₈",true,"#A35282","name + value","1","0","above","●"],["Q₈",true,"#346C86","name + value","1","0","above","●"],["R₈",true,"#738755","name + value","1","0","above","●"],["S₈",true,"#2E302D","name + value","1","0","above","●"],["T₈",true,"#187E5B","name + value","1","0","above","●"],["U₈",true,"#4B868E","name + value","1","0","above","●"],["V₈",true,"#13937C","name + value","1","0","above","●"],["W₈",true,"#938E72","name + value","1","0","above","●"]],"Text":[["t",true,"#7F6A2B","null","1","0","center","New text",false],["t₀",true,"#511C6A","null","1","0","center","New text",false],["t₁",true,"#84223B","null","1","0","center","New text",false],["t₂",true,"#A10A90","null","1","0","center","New text",false]]},"type":"logplotv1"} \ No newline at end of file From 45fef876ecca035d14955dee8319aaa8ebd20fe5 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Mon, 28 Oct 2024 19:09:25 +0100 Subject: [PATCH 079/104] Fixing issue with margins being shown despite an object not being displayed. --- .../qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml index c2a5a23..3b59e0a 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml @@ -56,7 +56,7 @@ ScrollView { property var editingRows: [] model: Modules.Objects.currentObjects[objType] width: objectsListView.width - height: contentItem.childrenRect.height + 10 + height: contentItem.childrenRect.height + (visible ? 10 : 0) visible: model != undefined && model.length > 0 interactive: false From 440575325e6d3e7934fa7b8362d546e783d55c97 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Mon, 28 Oct 2024 23:04:42 +0100 Subject: [PATCH 080/104] Fixing Helper version importing. --- runtime-pyside6/LogarithmPlotter/util/helper.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/runtime-pyside6/LogarithmPlotter/util/helper.py b/runtime-pyside6/LogarithmPlotter/util/helper.py index 7f7afb9..cc6bff4 100644 --- a/runtime-pyside6/LogarithmPlotter/util/helper.py +++ b/runtime-pyside6/LogarithmPlotter/util/helper.py @@ -16,10 +16,9 @@ * along with this program. If not, see . """ from PySide6.QtWidgets import QMessageBox, QApplication -from PySide6.QtCore import QRunnable, QThreadPool, QThread, QObject, Signal, Slot, QCoreApplication +from PySide6.QtCore import QRunnable, QThreadPool, QThread, QObject, Signal, Slot, QCoreApplication, __version__ as PySide6_version from PySide6.QtQml import QJSValue from PySide6.QtGui import QImage -from PySide6 import __version__ as PySide6_version from os import chdir, path from json import loads From 8429ff3739866dafffdbada43feddfdc60480db7 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Mon, 28 Oct 2024 23:05:55 +0100 Subject: [PATCH 081/104] Updating dependencies locK. --- common/package-lock.json | 4 +- runtime-pyside6/poetry.lock | 216 ++++++++++++++++++------------------ 2 files changed, 111 insertions(+), 109 deletions(-) diff --git a/common/package-lock.json b/common/package-lock.json index 5df6794..0e01b59 100644 --- a/common/package-lock.json +++ b/common/package-lock.json @@ -13,13 +13,13 @@ "@rollup/plugin-babel": "^6.0.4", "@rollup/plugin-commonjs": "^28.0.0", "@rollup/plugin-node-resolve": "^15.3.0", - "@types/chai-as-promised": "^8.0.1", "c8": "^10.1.2", "rollup": "^4.22.4", "rollup-plugin-cleanup": "^3.2.1" }, "devDependencies": { "@types/chai": "^5.0.0", + "@types/chai-as-promised": "^8.0.1", "@types/chai-spies": "^1.0.6", "@types/mocha": "^10.0.8", "chai": "^5.1.1", @@ -2199,12 +2199,14 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.0.0.tgz", "integrity": "sha512-+DwhEHAaFPPdJ2ral3kNHFQXnTfscEEFsUxzD+d7nlcLrFK23JtNjH71RGasTcHb88b4vVi4mTyfpf8u2L8bdA==", + "dev": true, "license": "MIT" }, "node_modules/@types/chai-as-promised": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-8.0.1.tgz", "integrity": "sha512-dAlDhLjJlABwAVYObo9TPWYTRg9NaQM5CXeaeJYcYAkvzUf0JRLIiog88ao2Wqy/20WUnhbbUZcgvngEbJ3YXQ==", + "dev": true, "license": "MIT", "dependencies": { "@types/chai": "*" diff --git a/runtime-pyside6/poetry.lock b/runtime-pyside6/poetry.lock index 07252a5..250fc64 100644 --- a/runtime-pyside6/poetry.lock +++ b/runtime-pyside6/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "altgraph" @@ -24,73 +24,73 @@ files = [ [[package]] name = "coverage" -version = "7.6.2" +version = "7.6.4" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" files = [ - {file = "coverage-7.6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c9df1950fb92d49970cce38100d7e7293c84ed3606eaa16ea0b6bc27175bb667"}, - {file = "coverage-7.6.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:24500f4b0e03aab60ce575c85365beab64b44d4db837021e08339f61d1fbfe52"}, - {file = "coverage-7.6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a663b180b6669c400b4630a24cc776f23a992d38ce7ae72ede2a397ce6b0f170"}, - {file = "coverage-7.6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfde025e2793a22efe8c21f807d276bd1d6a4bcc5ba6f19dbdfc4e7a12160909"}, - {file = "coverage-7.6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:087932079c065d7b8ebadd3a0160656c55954144af6439886c8bcf78bbbcde7f"}, - {file = "coverage-7.6.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9c6b0c1cafd96213a0327cf680acb39f70e452caf8e9a25aeb05316db9c07f89"}, - {file = "coverage-7.6.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6e85830eed5b5263ffa0c62428e43cb844296f3b4461f09e4bdb0d44ec190bc2"}, - {file = "coverage-7.6.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:62ab4231c01e156ece1b3a187c87173f31cbeee83a5e1f6dff17f288dca93345"}, - {file = "coverage-7.6.2-cp310-cp310-win32.whl", hash = "sha256:7b80fbb0da3aebde102a37ef0138aeedff45997e22f8962e5f16ae1742852676"}, - {file = "coverage-7.6.2-cp310-cp310-win_amd64.whl", hash = "sha256:d20c3d1f31f14d6962a4e2f549c21d31e670b90f777ef4171be540fb7fb70f02"}, - {file = "coverage-7.6.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bb21bac7783c1bf6f4bbe68b1e0ff0d20e7e7732cfb7995bc8d96e23aa90fc7b"}, - {file = "coverage-7.6.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a7b2e437fbd8fae5bc7716b9c7ff97aecc95f0b4d56e4ca08b3c8d8adcaadb84"}, - {file = "coverage-7.6.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:536f77f2bf5797983652d1d55f1a7272a29afcc89e3ae51caa99b2db4e89d658"}, - {file = "coverage-7.6.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f361296ca7054f0936b02525646b2731b32c8074ba6defab524b79b2b7eeac72"}, - {file = "coverage-7.6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7926d8d034e06b479797c199747dd774d5e86179f2ce44294423327a88d66ca7"}, - {file = "coverage-7.6.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0bbae11c138585c89fb4e991faefb174a80112e1a7557d507aaa07675c62e66b"}, - {file = "coverage-7.6.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fcad7d5d2bbfeae1026b395036a8aa5abf67e8038ae7e6a25c7d0f88b10a8e6a"}, - {file = "coverage-7.6.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f01e53575f27097d75d42de33b1b289c74b16891ce576d767ad8c48d17aeb5e0"}, - {file = "coverage-7.6.2-cp311-cp311-win32.whl", hash = "sha256:7781f4f70c9b0b39e1b129b10c7d43a4e0c91f90c60435e6da8288efc2b73438"}, - {file = "coverage-7.6.2-cp311-cp311-win_amd64.whl", hash = "sha256:9bcd51eeca35a80e76dc5794a9dd7cb04b97f0e8af620d54711793bfc1fbba4b"}, - {file = "coverage-7.6.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ebc94fadbd4a3f4215993326a6a00e47d79889391f5659bf310f55fe5d9f581c"}, - {file = "coverage-7.6.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9681516288e3dcf0aa7c26231178cc0be6cac9705cac06709f2353c5b406cfea"}, - {file = "coverage-7.6.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d9c5d13927d77af4fbe453953810db766f75401e764727e73a6ee4f82527b3e"}, - {file = "coverage-7.6.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b92f9ca04b3e719d69b02dc4a69debb795af84cb7afd09c5eb5d54b4a1ae2191"}, - {file = "coverage-7.6.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ff2ef83d6d0b527b5c9dad73819b24a2f76fdddcfd6c4e7a4d7e73ecb0656b4"}, - {file = "coverage-7.6.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:47ccb6e99a3031ffbbd6e7cc041e70770b4fe405370c66a54dbf26a500ded80b"}, - {file = "coverage-7.6.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a867d26f06bcd047ef716175b2696b315cb7571ccb951006d61ca80bbc356e9e"}, - {file = "coverage-7.6.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cdfcf2e914e2ba653101157458afd0ad92a16731eeba9a611b5cbb3e7124e74b"}, - {file = "coverage-7.6.2-cp312-cp312-win32.whl", hash = "sha256:f9035695dadfb397bee9eeaf1dc7fbeda483bf7664a7397a629846800ce6e276"}, - {file = "coverage-7.6.2-cp312-cp312-win_amd64.whl", hash = "sha256:5ed69befa9a9fc796fe015a7040c9398722d6b97df73a6b608e9e275fa0932b0"}, - {file = "coverage-7.6.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4eea60c79d36a8f39475b1af887663bc3ae4f31289cd216f514ce18d5938df40"}, - {file = "coverage-7.6.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa68a6cdbe1bc6793a9dbfc38302c11599bbe1837392ae9b1d238b9ef3dafcf1"}, - {file = "coverage-7.6.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ec528ae69f0a139690fad6deac8a7d33629fa61ccce693fdd07ddf7e9931fba"}, - {file = "coverage-7.6.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed5ac02126f74d190fa2cc14a9eb2a5d9837d5863920fa472b02eb1595cdc925"}, - {file = "coverage-7.6.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21c0ea0d4db8a36b275cb6fb2437a3715697a4ba3cb7b918d3525cc75f726304"}, - {file = "coverage-7.6.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:35a51598f29b2a19e26d0908bd196f771a9b1c5d9a07bf20be0adf28f1ad4f77"}, - {file = "coverage-7.6.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c9192925acc33e146864b8cf037e2ed32a91fdf7644ae875f5d46cd2ef086a5f"}, - {file = "coverage-7.6.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf4eeecc9e10f5403ec06138978235af79c9a79af494eb6b1d60a50b49ed2869"}, - {file = "coverage-7.6.2-cp313-cp313-win32.whl", hash = "sha256:e4ee15b267d2dad3e8759ca441ad450c334f3733304c55210c2a44516e8d5530"}, - {file = "coverage-7.6.2-cp313-cp313-win_amd64.whl", hash = "sha256:c71965d1ced48bf97aab79fad56df82c566b4c498ffc09c2094605727c4b7e36"}, - {file = "coverage-7.6.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7571e8bbecc6ac066256f9de40365ff833553e2e0c0c004f4482facb131820ef"}, - {file = "coverage-7.6.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:078a87519057dacb5d77e333f740708ec2a8f768655f1db07f8dfd28d7a005f0"}, - {file = "coverage-7.6.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5e92e3e84a8718d2de36cd8387459cba9a4508337b8c5f450ce42b87a9e760"}, - {file = "coverage-7.6.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebabdf1c76593a09ee18c1a06cd3022919861365219ea3aca0247ededf6facd6"}, - {file = "coverage-7.6.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12179eb0575b8900912711688e45474f04ab3934aaa7b624dea7b3c511ecc90f"}, - {file = "coverage-7.6.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:39d3b964abfe1519b9d313ab28abf1d02faea26cd14b27f5283849bf59479ff5"}, - {file = "coverage-7.6.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:84c4315577f7cd511d6250ffd0f695c825efe729f4205c0340f7004eda51191f"}, - {file = "coverage-7.6.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ff797320dcbff57caa6b2301c3913784a010e13b1f6cf4ab3f563f3c5e7919db"}, - {file = "coverage-7.6.2-cp313-cp313t-win32.whl", hash = "sha256:2b636a301e53964550e2f3094484fa5a96e699db318d65398cfba438c5c92171"}, - {file = "coverage-7.6.2-cp313-cp313t-win_amd64.whl", hash = "sha256:d03a060ac1a08e10589c27d509bbdb35b65f2d7f3f8d81cf2fa199877c7bc58a"}, - {file = "coverage-7.6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c37faddc8acd826cfc5e2392531aba734b229741d3daec7f4c777a8f0d4993e5"}, - {file = "coverage-7.6.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab31fdd643f162c467cfe6a86e9cb5f1965b632e5e65c072d90854ff486d02cf"}, - {file = "coverage-7.6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97df87e1a20deb75ac7d920c812e9326096aa00a9a4b6d07679b4f1f14b06c90"}, - {file = "coverage-7.6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:343056c5e0737487a5291f5691f4dfeb25b3e3c8699b4d36b92bb0e586219d14"}, - {file = "coverage-7.6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4ef1c56b47b6b9024b939d503ab487231df1f722065a48f4fc61832130b90e"}, - {file = "coverage-7.6.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7fca4a92c8a7a73dee6946471bce6d1443d94155694b893b79e19ca2a540d86e"}, - {file = "coverage-7.6.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:69f251804e052fc46d29d0e7348cdc5fcbfc4861dc4a1ebedef7e78d241ad39e"}, - {file = "coverage-7.6.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e8ea055b3ea046c0f66217af65bc193bbbeca1c8661dc5fd42698db5795d2627"}, - {file = "coverage-7.6.2-cp39-cp39-win32.whl", hash = "sha256:6c2ba1e0c24d8fae8f2cf0aeb2fc0a2a7f69b6d20bd8d3749fd6b36ecef5edf0"}, - {file = "coverage-7.6.2-cp39-cp39-win_amd64.whl", hash = "sha256:2186369a654a15628e9c1c9921409a6b3eda833e4b91f3ca2a7d9f77abb4987c"}, - {file = "coverage-7.6.2-pp39.pp310-none-any.whl", hash = "sha256:667952739daafe9616db19fbedbdb87917eee253ac4f31d70c7587f7ab531b4e"}, - {file = "coverage-7.6.2.tar.gz", hash = "sha256:a5f81e68aa62bc0cfca04f7b19eaa8f9c826b53fc82ab9e2121976dc74f131f3"}, + {file = "coverage-7.6.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f8ae553cba74085db385d489c7a792ad66f7f9ba2ee85bfa508aeb84cf0ba07"}, + {file = "coverage-7.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8165b796df0bd42e10527a3f493c592ba494f16ef3c8b531288e3d0d72c1f6f0"}, + {file = "coverage-7.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c8b95bf47db6d19096a5e052ffca0a05f335bc63cef281a6e8fe864d450a72"}, + {file = "coverage-7.6.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ed9281d1b52628e81393f5eaee24a45cbd64965f41857559c2b7ff19385df51"}, + {file = "coverage-7.6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0809082ee480bb8f7416507538243c8863ac74fd8a5d2485c46f0f7499f2b491"}, + {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d541423cdd416b78626b55f123412fcf979d22a2c39fce251b350de38c15c15b"}, + {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58809e238a8a12a625c70450b48e8767cff9eb67c62e6154a642b21ddf79baea"}, + {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c9b8e184898ed014884ca84c70562b4a82cbc63b044d366fedc68bc2b2f3394a"}, + {file = "coverage-7.6.4-cp310-cp310-win32.whl", hash = "sha256:6bd818b7ea14bc6e1f06e241e8234508b21edf1b242d49831831a9450e2f35fa"}, + {file = "coverage-7.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:06babbb8f4e74b063dbaeb74ad68dfce9186c595a15f11f5d5683f748fa1d172"}, + {file = "coverage-7.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:73d2b73584446e66ee633eaad1a56aad577c077f46c35ca3283cd687b7715b0b"}, + {file = "coverage-7.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51b44306032045b383a7a8a2c13878de375117946d68dcb54308111f39775a25"}, + {file = "coverage-7.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3fb02fe73bed561fa12d279a417b432e5b50fe03e8d663d61b3d5990f29546"}, + {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed8fe9189d2beb6edc14d3ad19800626e1d9f2d975e436f84e19efb7fa19469b"}, + {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b369ead6527d025a0fe7bd3864e46dbee3aa8f652d48df6174f8d0bac9e26e0e"}, + {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ade3ca1e5f0ff46b678b66201f7ff477e8fa11fb537f3b55c3f0568fbfe6e718"}, + {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:27fb4a050aaf18772db513091c9c13f6cb94ed40eacdef8dad8411d92d9992db"}, + {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4f704f0998911abf728a7783799444fcbbe8261c4a6c166f667937ae6a8aa522"}, + {file = "coverage-7.6.4-cp311-cp311-win32.whl", hash = "sha256:29155cd511ee058e260db648b6182c419422a0d2e9a4fa44501898cf918866cf"}, + {file = "coverage-7.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:8902dd6a30173d4ef09954bfcb24b5d7b5190cf14a43170e386979651e09ba19"}, + {file = "coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2"}, + {file = "coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117"}, + {file = "coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613"}, + {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27"}, + {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52"}, + {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2"}, + {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1"}, + {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5"}, + {file = "coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17"}, + {file = "coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08"}, + {file = "coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9"}, + {file = "coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba"}, + {file = "coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c"}, + {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06"}, + {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f"}, + {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b"}, + {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21"}, + {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a"}, + {file = "coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e"}, + {file = "coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963"}, + {file = "coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f"}, + {file = "coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806"}, + {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11"}, + {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3"}, + {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a"}, + {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc"}, + {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70"}, + {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef"}, + {file = "coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e"}, + {file = "coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1"}, + {file = "coverage-7.6.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9cb7fa111d21a6b55cbf633039f7bc2749e74932e3aa7cb7333f675a58a58bf3"}, + {file = "coverage-7.6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11a223a14e91a4693d2d0755c7a043db43d96a7450b4f356d506c2562c48642c"}, + {file = "coverage-7.6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a413a096c4cbac202433c850ee43fa326d2e871b24554da8327b01632673a076"}, + {file = "coverage-7.6.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00a1d69c112ff5149cabe60d2e2ee948752c975d95f1e1096742e6077affd376"}, + {file = "coverage-7.6.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f76846299ba5c54d12c91d776d9605ae33f8ae2b9d1d3c3703cf2db1a67f2c0"}, + {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fe439416eb6380de434886b00c859304338f8b19f6f54811984f3420a2e03858"}, + {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0294ca37f1ba500667b1aef631e48d875ced93ad5e06fa665a3295bdd1d95111"}, + {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6f01ba56b1c0e9d149f9ac85a2f999724895229eb36bd997b61e62999e9b0901"}, + {file = "coverage-7.6.4-cp39-cp39-win32.whl", hash = "sha256:bc66f0bf1d7730a17430a50163bb264ba9ded56739112368ba985ddaa9c3bd09"}, + {file = "coverage-7.6.4-cp39-cp39-win_amd64.whl", hash = "sha256:c481b47f6b5845064c65a7bc78bc0860e635a9b055af0df46fdf1c58cebf8e8f"}, + {file = "coverage-7.6.4-pp39.pp310-none-any.whl", hash = "sha256:3c65d37f3a9ebb703e710befdc489a38683a5b152242664b973a7b7b22348a4e"}, + {file = "coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73"}, ] [package.dependencies] @@ -174,13 +174,13 @@ files = [ [[package]] name = "pefile" -version = "2024.8.26" +version = "2023.2.7" description = "Python PE parsing module" optional = false python-versions = ">=3.6.0" files = [ - {file = "pefile-2024.8.26-py3-none-any.whl", hash = "sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f"}, - {file = "pefile-2024.8.26.tar.gz", hash = "sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632"}, + {file = "pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6"}, + {file = "pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc"}, ] [[package]] @@ -200,23 +200,23 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pyinstaller" -version = "6.10.0" +version = "6.11.0" description = "PyInstaller bundles a Python application and all its dependencies into a single package." optional = false python-versions = "<3.14,>=3.8" files = [ - {file = "pyinstaller-6.10.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:d60fb22859e11483af735aec115fdde09467cdbb29edd9844839f2c920b748c0"}, - {file = "pyinstaller-6.10.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:46d75359668993ddd98630a3669dc5249f3c446e35239b43bc7f4155bc574748"}, - {file = "pyinstaller-6.10.0-py3-none-manylinux2014_i686.whl", hash = "sha256:3398a98fa17d47ccb31f8779ecbdacec025f7adb2f22757a54b706ac8b4fe906"}, - {file = "pyinstaller-6.10.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e9989f354ae4ed8a3bec7bdb37ae0d170751d6520e500f049c7cd0632d31d5c3"}, - {file = "pyinstaller-6.10.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:b7c90c91921b3749083115b28f30f40abf2bb481ceff196d2b2ce0eaa2b3d429"}, - {file = "pyinstaller-6.10.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6cf876d7d93b8b4f28d1ad57fa24645cf43119c79e985dd5e5f7a801245e6f53"}, - {file = "pyinstaller-6.10.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:db05e3f2f10f9f78c56f1fb163d9cb453433429fe4281218ebaf1ebfd39ba942"}, - {file = "pyinstaller-6.10.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:28eca3817f176fdc19747e1afcf434f13bb9f17a644f611be2c5a61b1f498ed7"}, - {file = "pyinstaller-6.10.0-py3-none-win32.whl", hash = "sha256:703e041718987e46ba0568a2c71ecf2459fddef57cf9edf3efeed4a53e3dae3f"}, - {file = "pyinstaller-6.10.0-py3-none-win_amd64.whl", hash = "sha256:95b55966e563e8b8f31a43882aea10169e9a11fdf38e626d86a2907b640c0701"}, - {file = "pyinstaller-6.10.0-py3-none-win_arm64.whl", hash = "sha256:308e0a8670c9c9ac0cebbf1bbb492e71b6675606f2ec78bc4adfc830d209e087"}, - {file = "pyinstaller-6.10.0.tar.gz", hash = "sha256:143840f8056ff7b910bf8f16f6cd92cc10a6c2680bb76d0a25d558d543d21270"}, + {file = "pyinstaller-6.11.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:6fd68a3c1207635c49326c54881b89d5c3bd9ba061bbc9daa58c0902db1be39e"}, + {file = "pyinstaller-6.11.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:eddd53f231e51adc65088eac4f40057ca803a990239828d4a9229407fb866239"}, + {file = "pyinstaller-6.11.0-py3-none-manylinux2014_i686.whl", hash = "sha256:e6d229009e815542833fe00332b589aa6984a06f794dc16f2ce1acab1c567590"}, + {file = "pyinstaller-6.11.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:7d2cd2ebdcd6860f8a4abe2977264a7b6d260a7147047008971c7cfc66a656a4"}, + {file = "pyinstaller-6.11.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:d9ec6d4398b4eebc1d4c00437716264ba8406bc2746f594e253070a82378a584"}, + {file = "pyinstaller-6.11.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:04f71828aa9531ab18c9656985c1f09b83d10332c73a1f4a113a48b491906955"}, + {file = "pyinstaller-6.11.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:a843d470768d68b05684ccf4860c45b2eb13727f41667c0b2cd8f57ae231bd18"}, + {file = "pyinstaller-6.11.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:963dedc1f37144a4385f58f7f65f1c69c004a67faae522a2085b5ddb230c908b"}, + {file = "pyinstaller-6.11.0-py3-none-win32.whl", hash = "sha256:c71024c8a19c7b221b9152b2baff4c3ba849cada68dcdd34382ba09f0107451f"}, + {file = "pyinstaller-6.11.0-py3-none-win_amd64.whl", hash = "sha256:0e229610c22b96d741d905706f9496af472c1a9216a118988f393c98ecc3f51f"}, + {file = "pyinstaller-6.11.0-py3-none-win_arm64.whl", hash = "sha256:a5f716bb507517912fda39d109dead91fc0dd2e7b2859562522b63c61aa21676"}, + {file = "pyinstaller-6.11.0.tar.gz", hash = "sha256:cb4d433a3db30d9d17cf5f2cf7bb4df80a788d493c1d67dd822dc5791d9864af"}, ] [package.dependencies] @@ -224,7 +224,7 @@ altgraph = "*" importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} macholib = {version = ">=1.8", markers = "sys_platform == \"darwin\""} packaging = ">=22.0" -pefile = {version = ">=2022.5.30", markers = "sys_platform == \"win32\""} +pefile = {version = ">=2022.5.30,<2024.8.26 || >2024.8.26", markers = "sys_platform == \"win32\""} pyinstaller-hooks-contrib = ">=2024.8" pywin32-ctypes = {version = ">=0.2.1", markers = "sys_platform == \"win32\""} setuptools = ">=42.0.0" @@ -235,13 +235,13 @@ hook-testing = ["execnet (>=1.5.0)", "psutil", "pytest (>=2.7.3)"] [[package]] name = "pyinstaller-hooks-contrib" -version = "2024.8" +version = "2024.9" description = "Community maintained hooks for PyInstaller" optional = false python-versions = ">=3.8" files = [ - {file = "pyinstaller_hooks_contrib-2024.8-py3-none-any.whl", hash = "sha256:0057fe9a5c398d3f580e73e58793a1d4a8315ca91c3df01efea1c14ed557825a"}, - {file = "pyinstaller_hooks_contrib-2024.8.tar.gz", hash = "sha256:29b68d878ab739e967055b56a93eb9b58e529d5b054fbab7a2f2bacf80cef3e2"}, + {file = "pyinstaller_hooks_contrib-2024.9-py3-none-any.whl", hash = "sha256:1ddf9ba21d586afa84e505bb5c65fca10b22500bf3fdb89ee2965b99da53b891"}, + {file = "pyinstaller_hooks_contrib-2024.9.tar.gz", hash = "sha256:4793869f370d1dc4806c101efd2890e3c3e703467d8d27bb5a3db005ebfb008d"}, ] [package.dependencies] @@ -251,36 +251,36 @@ setuptools = ">=42.0.0" [[package]] name = "pyside6-addons" -version = "6.8.0" +version = "6.8.0.2" description = "Python bindings for the Qt cross-platform application and UI framework (Addons)" optional = false -python-versions = "<3.13,>=3.9" +python-versions = "<3.14,>=3.9" files = [ - {file = "PySide6_Addons-6.8.0-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:aebab1e4fe63ebceccae4068768bf20959ab78f7fe01af832458837241334b5c"}, - {file = "PySide6_Addons-6.8.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:4b3be260f9cc415d1a12b77a703ced18b8854f56985f4708cab5618a9554bbd6"}, - {file = "PySide6_Addons-6.8.0-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:7c153a685341683fac82d32926e2204747a83c13ef7b203db8ae9efe27f26a0f"}, - {file = "PySide6_Addons-6.8.0-cp39-abi3-win_amd64.whl", hash = "sha256:8f7f20fb3758995580f1fb8342df3479be51958eca36db2d6f6a3304f31471de"}, + {file = "PySide6_Addons-6.8.0.2-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:30c9ca570dd18ffbfd34ee95e0a319c34313a80425c4011d6ccc9f4cca0dc4c8"}, + {file = "PySide6_Addons-6.8.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:754a9822ab2dc313f9998edef69d8a12bc9fd61727543f8d30806ed272ae1e52"}, + {file = "PySide6_Addons-6.8.0.2-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:553f3fa412f423929b5cd8b7d43fd5f02161851f10a438174a198b0f1a044df7"}, + {file = "PySide6_Addons-6.8.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:ae4377a3e10fe720a9119677b31d8de13e2a5221c06b332df045af002f5f4c3d"}, ] [package.dependencies] -PySide6-Essentials = "6.8.0" -shiboken6 = "6.8.0" +PySide6-Essentials = "6.8.0.2" +shiboken6 = "6.8.0.2" [[package]] name = "pyside6-essentials" -version = "6.8.0" +version = "6.8.0.2" description = "Python bindings for the Qt cross-platform application and UI framework (Essentials)" optional = false -python-versions = "<3.13,>=3.9" +python-versions = "<3.14,>=3.9" files = [ - {file = "PySide6_Essentials-6.8.0-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:c2ad37de574ed911ac2dd392e95888ee7354c4bc475259dafc31978efb710a6a"}, - {file = "PySide6_Essentials-6.8.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:da99a94806416ec1e386426a474e7d1e514c1cdf8ad171c005376f4f633e7216"}, - {file = "PySide6_Essentials-6.8.0-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:ae0732228e93eb882c9a93fd510819fb64b7d09d8e500912b485a604537215d6"}, - {file = "PySide6_Essentials-6.8.0-cp39-abi3-win_amd64.whl", hash = "sha256:2ef7138dc7efb9f1153c1dda7a7bd6ac02badad1aa1971cc140d0b9bf962c3dc"}, + {file = "PySide6_Essentials-6.8.0.2-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:3df4ed75bbb74d74ac338b330819b1a272e7f5cec206765c7176a197c8bc9c79"}, + {file = "PySide6_Essentials-6.8.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:7df6d6c1da4858dbdea77c74d7270d9c68e8d1bbe3362892abd1a5ade3815a50"}, + {file = "PySide6_Essentials-6.8.0.2-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:cf490145d18812a6cff48b0b0afb0bfaf7066744bfbd09eb071c3323f1d6d00d"}, + {file = "PySide6_Essentials-6.8.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:d2f029b8c9f0106f57b26aa8c435435d7f509c80525075343e07177b283f862e"}, ] [package.dependencies] -shiboken6 = "6.8.0" +shiboken6 = "6.8.0.2" [[package]] name = "pytest" @@ -354,13 +354,13 @@ files = [ [[package]] name = "setuptools" -version = "75.1.0" +version = "75.2.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-75.1.0-py3-none-any.whl", hash = "sha256:35ab7fd3bcd95e6b7fd704e4a1539513edad446c097797f2985e0e4b960772f2"}, - {file = "setuptools-75.1.0.tar.gz", hash = "sha256:d59a21b17a275fb872a9c3dae73963160ae079f1049ed956880cd7c09b120538"}, + {file = "setuptools-75.2.0-py3-none-any.whl", hash = "sha256:a7fcb66f68b4d9e8e66b42f9876150a3371558f98fa32222ffaa5bced76406f8"}, + {file = "setuptools-75.2.0.tar.gz", hash = "sha256:753bb6ebf1f465a1912e19ed1d41f403a79173a9acf66a42e7e6aec45c3c16ec"}, ] [package.extras] @@ -374,15 +374,15 @@ type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11 [[package]] name = "shiboken6" -version = "6.8.0" +version = "6.8.0.2" description = "Python/C++ bindings helper module" optional = false -python-versions = "<3.13,>=3.9" +python-versions = "<3.14,>=3.9" files = [ - {file = "shiboken6-6.8.0-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:0d3171c496e7474ad29d73686e46e741317a9b29ae9fa30c421fa0360bc10af0"}, - {file = "shiboken6-6.8.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:ad88c0e73c9e4de3723c6e6b846e651729433ff9d9086bb2b4e6d49965477d97"}, - {file = "shiboken6-6.8.0-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:0f62ee7c34337e2c39fff0985694224f7503328c450245c399846b72cd71c410"}, - {file = "shiboken6-6.8.0-cp39-abi3-win_amd64.whl", hash = "sha256:cb98424a1f0c2d6ebf7f6be99660a121b9b22601a058e6b7efeadbc60bcd2182"}, + {file = "shiboken6-6.8.0.2-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:9019e1fcfeed8bb350222e981748ef05a2fec11e31ddf616657be702f0b7a468"}, + {file = "shiboken6-6.8.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:fa7d411c3c67b4296847b3f5f572268e219d947d029ff9d8bce72fe6982d92bc"}, + {file = "shiboken6-6.8.0.2-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:1aaa8b7f9138818322ef029b2c487d1c6e00dc3f53084e62e1d11bdea47e47c2"}, + {file = "shiboken6-6.8.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:b11e750e696bb565d897e0f5836710edfb86bd355f87b09988bd31b2aad404d3"}, ] [[package]] From f5b489ef4461f43e2996ee703a11c630cbd21e4f Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 29 Oct 2024 01:37:44 +0100 Subject: [PATCH 082/104] Fixing macOS build script. --- scripts/build-macosx.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/build-macosx.sh b/scripts/build-macosx.sh index 2ccd626..8f3f38d 100755 --- a/scripts/build-macosx.sh +++ b/scripts/build-macosx.sh @@ -27,9 +27,9 @@ rm $(find . -name "*.pyc") pyinstaller --add-data "LogarithmPlotter/qml:qml" \ --add-data "LogarithmPlotter/i18n:i18n" \ - --add-data "LICENSE.md:." \ - --add-data "../assets/native/mac/logarithmplotterfile.icns:." \ - --add-data "README.md:." \ + --add-data "../../LICENSE.md:." \ + --add-data "../../assets/native/mac/logarithmplotterfile.icns:." \ + --add-data "../../README.md:." \ --exclude-module "FixTk" \ --exclude-module "tcl" \ --exclude-module "tk" \ From da8aa59b0a069a20d51d175bd3d43c5b8c34ac3b Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 29 Oct 2024 02:50:11 +0100 Subject: [PATCH 083/104] Improving characters choosing popup. + No longer covering the input + No longer cut off when editing the name + Improved keyboard navigation. --- .../Popup/InsertCharacter.qml | 57 ++++++++++++------- .../Setting/ExpressionEditor.qml | 22 +++++-- .../LogarithmPlotter/Setting/TextSetting.qml | 22 +++++-- 3 files changed, 71 insertions(+), 30 deletions(-) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml index 7002539..8162b09 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml @@ -16,8 +16,9 @@ * along with this program. If not, see . */ -import QtQuick.Controls import QtQuick +import QtQuick.Controls +import QtQml.Models /*! \qmltype InsertCharacter @@ -42,15 +43,18 @@ Popup { */ property string category: 'all' - width: 280 - height: Math.ceil(insertGrid.insertChars.length/insertGrid.columns)*(width/insertGrid.columns)+5 + width: insertGrid.width + 10 + height: insertGrid.height + 10 modal: true closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent - Grid { + GridView { id: insertGrid - width: parent.width - columns: 7 + width: 280 + height: Math.ceil(model.count/columns)*cellHeight + property int columns: 7 + cellWidth: width/columns + cellHeight: cellWidth property var insertCharsExpression: [ "∞","π","¹","²","³","⁴","⁵", @@ -86,21 +90,34 @@ Popup { }[insertPopup.category] } - Repeater { - model: parent.insertChars.length - - Button { - id: insertBtn - width: insertGrid.width/insertGrid.columns - height: width - text: insertGrid.insertChars[modelData] - flat: text == " " - font.pixelSize: 18 - - onClicked: { - selected(text) - } + model: ListModel {} + + delegate: Button { + id: insertBtn + width: insertGrid.cellWidth + height: insertGrid.cellHeight + text: chr + flat: text == " " + font.pixelSize: 18 + + onClicked: { + insertPopup.selected(text) + insertPopup.close() + } + } + + Component.onCompleted: function() { + for(const chr of insertChars) { + console.log("Appending", chr) + model.append({ 'chr': chr }) } } } + + function setFocus() { + insertGrid.currentIndex = 0 + insertGrid.forceActiveFocus() + } + + Keys.onEscapePressed: close() } diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml index 8251a3f..af32b43 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml @@ -500,29 +500,41 @@ Item { Button { id: insertButton - text: "α" anchors.right: parent.right anchors.rightMargin: 5 anchors.verticalCenter: parent.verticalCenter width: 20 height: width + + Icon { + id: icon + width: 12 + height: 12 + anchors.centerIn: parent + + color: sysPalette.windowText + source: '../icons/properties/expression.svg' + } + onClicked: { insertPopup.open() - insertPopup.focus = true + insertPopup.setFocus() } } P.InsertCharacter { id: insertPopup - x: Math.round((parent.width - width) / 2) - y: Math.round((parent.height - height) / 2) + x: parent.width - width + y: parent.height category: "expression" onSelected: function(c) { editor.insert(editor.cursorPosition, c) - insertPopup.close() + } + + onClosed: function() { focus = false editor.focus = true } diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml index 3689dc1..8d1ca41 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml @@ -144,28 +144,40 @@ Item { Button { id: insertButton - text: "α" anchors.right: parent.right anchors.rightMargin: 5 anchors.verticalCenter: parent.verticalCenter width: 20 height: width visible: !isInt && !isDouble + + Icon { + id: icon + width: 12 + height: 12 + anchors.centerIn: parent + + color: sysPalette.windowText + source: '../icons/properties/expression.svg' + } + onClicked: { insertPopup.open() - insertPopup.focus = true + insertPopup.setFocus() } } Popup.InsertCharacter { id: insertPopup - x: Math.round((parent.width - width) / 2) - y: Math.round((parent.height - height) / 2) + x: parent.width - width + y: parent.height onSelected: function(c) { input.insert(input.cursorPosition, c) - insertPopup.close() + } + + onClosed: function() { focus = false input.focus = true } From fdcc8105babb8bd37fa2e577cb94861231691ac5 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 29 Oct 2024 02:58:32 +0100 Subject: [PATCH 084/104] Removing debug --- .../qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml index 8162b09..7ef1794 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml @@ -108,7 +108,6 @@ Popup { Component.onCompleted: function() { for(const chr of insertChars) { - console.log("Appending", chr) model.append({ 'chr': chr }) } } From 6025742e869323b11da537863d20a56b5c1c8cc8 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Mon, 6 Jan 2025 16:23:06 +0100 Subject: [PATCH 085/104] Fixing bugs. --- common/src/math/domain.mjs | 68 +++++---- common/test/math/domain.mjs | 130 ++++++++++++------ .../Popup/InsertCharacter.qml | 3 +- 3 files changed, 132 insertions(+), 69 deletions(-) diff --git a/common/src/math/domain.mjs b/common/src/math/domain.mjs index 48bf8ad..19586ee 100644 --- a/common/src/math/domain.mjs +++ b/common/src/math/domain.mjs @@ -24,6 +24,7 @@ import { Expression, executeExpression } from "./expression.mjs" */ export class Domain { constructor() { + this.latexMarkup = "#INVALID" } /** @@ -206,8 +207,8 @@ export class Range extends Domain { } includes(x) { - if(x instanceof Expression) x = x.execute() if(typeof x == "string") x = executeExpression(x) + if(x instanceof Expression) x = x.execute() return ((this.openBegin && x > this.begin.execute()) || (!this.openBegin && x >= this.begin.execute())) && ((this.openEnd && x < this.end.execute()) || (!this.openEnd && x <= this.end.execute())) } @@ -249,15 +250,17 @@ export class SpecialDomain extends Domain { /** * @constructs SpecialDomain * @param {string} displayName + * @param {string} latexMarkup - markup representing the domain. * @param {function} isValid - function returning true when number is in domain false when it isn't. * @param {function} next - function provides the next positive value in the domain after the one given. * @param {function} previous - function provides the previous positive value in the domain before the one given. * @param {boolean} moveSupported - Only true if next and previous functions are valid. */ - constructor(displayName, isValid, next = () => true, previous = () => true, + constructor(displayName, latexMarkup, isValid, next = () => true, previous = () => true, moveSupported = true) { super() this.displayName = displayName + this.latexMarkup = latexMarkup this.isValid = isValid this.nextValue = next this.prevValue = previous @@ -562,39 +565,54 @@ Domain.RPE.latexMarkup = "\\mathbb{R}^{+*}" Domain.RME = new Range(-Infinity, 0, true, true) Domain.RME.displayName = "ℝ⁻*" Domain.RME.latexMarkup = "\\mathbb{R}^{+*}" -Domain.N = new SpecialDomain("ℕ", x => x % 1 === 0 && x >= 0, +Domain.N = new SpecialDomain( + "ℕ", "\\mathbb{N}", + x => x % 1 === 0 && x >= 0, x => Math.max(Math.floor(x) + 1, 0), - x => Math.max(Math.ceil(x) - 1, 0)) -Domain.N.latexMarkup = "\\mathbb{N}" -Domain.NE = new SpecialDomain("ℕ*", x => x % 1 === 0 && x > 0, + x => Math.max(Math.ceil(x) - 1, 0) +) +Domain.NE = new SpecialDomain( + "ℕ*", "\\mathbb{N}^{*}", + x => x % 1 === 0 && x > 0, x => Math.max(Math.floor(x) + 1, 1), - x => Math.max(Math.ceil(x) - 1, 1)) -Domain.NE.latexMarkup = "\\mathbb{N}^{*}" -Domain.Z = new SpecialDomain("ℤ", x => x % 1 === 0, x => Math.floor(x) + 1, x => Math.ceil(x) - 1) -Domain.Z.latexMarkup = "\\mathbb{Z}" -Domain.ZE = new SpecialDomain("ℤ*", x => x % 1 === 0 && x !== 0, + x => Math.max(Math.ceil(x) - 1, 1) +) +Domain.Z = new SpecialDomain( + "ℤ", "\\mathbb{Z}", + x => x % 1 === 0, + x => Math.floor(x) + 1, + x => Math.ceil(x) - 1 +) +Domain.ZE = new SpecialDomain( + "ℤ*", "\\mathbb{Z}^{*}", + x => x % 1 === 0 && x !== 0, x => Math.floor(x) + 1 === 0 ? Math.floor(x) + 2 : Math.floor(x) + 1, - x => Math.ceil(x) - 1 === 0 ? Math.ceil(x) - 2 : Math.ceil(x) - 1) -Domain.ZE.latexMarkup = "\\mathbb{Z}^{*}" -Domain.ZM = new SpecialDomain("ℤ⁻", x => x % 1 === 0 && x <= 0, + x => Math.ceil(x) - 1 === 0 ? Math.ceil(x) - 2 : Math.ceil(x) - 1 +) +Domain.ZM = new SpecialDomain( + "ℤ⁻", "\\mathbb{Z}^{-}", + x => x % 1 === 0 && x <= 0, x => Math.min(Math.floor(x) + 1, 0), - x => Math.min(Math.ceil(x) - 1, 0)) -Domain.ZM.latexMarkup = "\\mathbb{Z}^{-}" -Domain.ZME = new SpecialDomain("ℤ⁻*", x => x % 1 === 0 && x < 0, + x => Math.min(Math.ceil(x) - 1, 0) +) +Domain.ZME = new SpecialDomain( + "ℤ⁻*", "\\mathbb{Z}^{-*}", + x => x % 1 === 0 && x < 0, x => Math.min(Math.floor(x) + 1, -1), - x => Math.min(Math.ceil(x) - 1, -1)) -Domain.ZME.latexMarkup = "\\mathbb{Z}^{-*}" -Domain.NLog = new SpecialDomain("ℕˡᵒᵍ", + x => Math.min(Math.ceil(x) - 1, -1) +) +Domain.NLog = new SpecialDomain( + "ℕˡᵒᵍ", "\\mathbb{N}^{log}", x => x / Math.pow(10, Math.ceil(Math.log10(x))) % 1 === 0 && x > 0, - function(x) { + x => { let x10pow = Math.pow(10, Math.ceil(Math.log10(x))) return Math.max(1, (Math.floor(x / x10pow) + 1) * x10pow) }, - function(x) { + x => { let x10pow = Math.pow(10, Math.ceil(Math.log10(x))) return Math.max(1, (Math.ceil(x / x10pow) - 1) * x10pow) - }) -Domain.NLog.latexMarkup = "\\mathbb{N}^{log}" + } +) let refedDomains = [] @@ -626,7 +644,7 @@ export function parseDomainSimple(domain) { if(domain.includes("U") || domain.includes("∪")) return UnionDomain.import(domain) if(domain.includes("∩")) return IntersectionDomain.import(domain) if(domain.includes("∖") || domain.includes("\\")) return MinusDomain.import(domain) - if(domain.charAt(0) === "{" && domain.charAt(domain.length - 1) === "}") return DomainSet.import(domain) + if(domain.at(0) === "{" && domain.at(-1) === "}") return DomainSet.import(domain) if(domain.includes("]") || domain.includes("[")) return Range.import(domain) if(["R", "ℝ", "N", "ℕ", "Z", "ℤ"].some(str => domain.toUpperCase().includes(str))) return Domain.import(domain) diff --git a/common/test/math/domain.mjs b/common/test/math/domain.mjs index e32dbd1..6c2b93e 100644 --- a/common/test/math/domain.mjs +++ b/common/test/math/domain.mjs @@ -19,46 +19,90 @@ import { describe, it } from "mocha" import { expect } from "chai" -// import { Domain, parseDomainSimple } from "../../src/math/domain.mjs" -// -// describe("math.domain", function() { -// describe("#parseDomainSimple", function() { -// it("returns predefined domains", function() { -// const predefinedToCheck = [ -// // Real domains -// { domain: Domain.R, shortcuts: ["R", "ℝ"] }, -// // Zero exclusive real domains -// { domain: Domain.RE, shortcuts: ["RE", "R*", "ℝ*"] }, -// // Real positive domains -// { domain: Domain.RP, shortcuts: ["RP", "R+", "ℝ⁺", "ℝ+"] }, -// // Zero-exclusive real positive domains -// { domain: Domain.RPE, shortcuts: ["RPE", "REP", "R+*", "R*+", "ℝ*⁺", "ℝ⁺*", "ℝ*+", "ℝ+*"] }, -// // Real negative domain -// { domain: Domain.RM, shortcuts: ["RM", "R-", "ℝ⁻", "ℝ-"] }, -// // Zero-exclusive real negative domains -// { domain: Domain.RME, shortcuts: ["RME", "REM", "R-*", "R*-", "ℝ⁻*", "ℝ*⁻", "ℝ-*", "ℝ*-"] }, -// // Natural integers domain -// { domain: Domain.N, shortcuts: ["ℕ", "N", "ZP", "Z+", "ℤ⁺", "ℤ+"] }, -// // Zero-exclusive natural integers domain -// { domain: Domain.NE, shortcuts: ["NE", "NP", "N*", "N+", "ℕ*", "ℕ⁺", "ℕ+", "ZPE", "ZEP", "Z+*", "Z*+", "ℤ⁺*", "ℤ*⁺", "ℤ+*", "ℤ*+"] }, -// // Logarithmic natural domains -// { domain: Domain.NLog, shortcuts: ["NLOG", "ℕˡᵒᵍ", "ℕLOG"] }, -// // All integers domains -// { domain: Domain.Z, shortcuts: ["Z", "ℤ"] }, -// // Zero-exclusive all integers domain -// { domain: Domain.ZE, shortcuts: ["ZE", "Z*", "ℤ*"] }, -// // Negative integers domain -// { domain: Domain.ZM, shortcuts: ["ZM", "Z-", "ℤ⁻", "ℤ-"] }, -// // Zero-exclusive negative integers domain -// { domain: Domain.ZME, shortcuts: ["ZME", "ZEM", "Z-*", "Z*-", "ℤ⁻*", "ℤ*⁻", "ℤ-*", "ℤ*-"] }, -// ] -// -// // Real domains -// for(const { domain, shortcuts } of predefinedToCheck) -// for(const shortcut of shortcuts) -// expect(parseDomainSimple(shortcut)).to.be.equal(domain) -// }) -// -// it("") -// }) -// }) +import { Domain, EmptySet, parseDomainSimple } from "../../src/math/domain.mjs" + +describe("math.domain", function() { + describe("#parseDomainSimple", function() { + it("returns empty sets when a domain cannot be parsed", function() { + expect(parseDomainSimple("∅")).to.be.an.instanceof(EmptySet) + expect(parseDomainSimple("O")).to.be.an.instanceof(EmptySet) + expect(parseDomainSimple("AAAAAAAAA")).to.be.an.instanceof(EmptySet) + expect(parseDomainSimple("???")).to.be.an.instanceof(EmptySet) + expect(parseDomainSimple("∅").latexMarkup).to.equal("\\emptyset") + expect(parseDomainSimple("???").toString()).to.equal("∅") + expect(parseDomainSimple("∅").includes(0)).to.be.false + expect(parseDomainSimple("∅").includes(Infinity)).to.be.false + expect(parseDomainSimple("∅").includes(-3)).to.be.false + + }) + + it("returns predefined domains", function() { + const predefinedToCheck = [ + // Real domains + { domain: Domain.R, shortcuts: ["R", "ℝ"] }, + // Zero exclusive real domains + { domain: Domain.RE, shortcuts: ["RE", "R*", "ℝ*"] }, + // Real positive domains + { domain: Domain.RP, shortcuts: ["RP", "R+", "ℝ⁺", "ℝ+"] }, + // Zero-exclusive real positive domains + { domain: Domain.RPE, shortcuts: ["RPE", "REP", "R+*", "R*+", "ℝ*⁺", "ℝ⁺*", "ℝ*+", "ℝ+*"] }, + // Real negative domain + { domain: Domain.RM, shortcuts: ["RM", "R-", "ℝ⁻", "ℝ-"] }, + // Zero-exclusive real negative domains + { domain: Domain.RME, shortcuts: ["RME", "REM", "R-*", "R*-", "ℝ⁻*", "ℝ*⁻", "ℝ-*", "ℝ*-"] }, + // Natural integers domain + { domain: Domain.N, shortcuts: ["ℕ", "N", "ZP", "Z+", "ℤ⁺", "ℤ+"] }, + // Zero-exclusive natural integers domain + { domain: Domain.NE, shortcuts: ["NE", "NP", "N*", "N+", "ℕ*", "ℕ⁺", "ℕ+", "ZPE", "ZEP", "Z+*", "Z*+", "ℤ⁺*", "ℤ*⁺", "ℤ+*", "ℤ*+"] }, + // Logarithmic natural domains + { domain: Domain.NLog, shortcuts: ["NLOG", "ℕˡᵒᵍ", "ℕLOG"] }, + // All integers domains + { domain: Domain.Z, shortcuts: ["Z", "ℤ"] }, + // Zero-exclusive all integers domain + { domain: Domain.ZE, shortcuts: ["ZE", "Z*", "ℤ*"] }, + // Negative integers domain + { domain: Domain.ZM, shortcuts: ["ZM", "Z-", "ℤ⁻", "ℤ-"] }, + // Zero-exclusive negative integers domain + { domain: Domain.ZME, shortcuts: ["ZME", "ZEM", "Z-*", "Z*-", "ℤ⁻*", "ℤ*⁻", "ℤ-*", "ℤ*-"] }, + ] + + // Real domains + for(const { domain, shortcuts } of predefinedToCheck) + for(const shortcut of shortcuts) + expect(parseDomainSimple(shortcut)).to.be.equal(domain) + }) + + it("returns parsed ranges", function() { + const parsedClosed = parseDomainSimple("[1;3]") + expect(parsedClosed.includes(1)).to.be.true + expect(parsedClosed.includes(2.4)).to.be.true + expect(parsedClosed.includes(3)).to.be.true + expect(parsedClosed.includes(3.01)).to.be.false + expect(parsedClosed.includes(0.99)).to.be.false + const parsedOpen = parseDomainSimple("]1;3[") + expect(parsedOpen.includes(1)).to.be.false + expect(parsedOpen.includes(3)).to.be.false + expect(parsedOpen.includes(2.4)).to.be.true + expect(parsedOpen.includes(1.01)).to.be.true + expect(parsedOpen.includes(2.99)).to.be.true + const parsedOpenBefore = parseDomainSimple("]1;3]") + expect(parsedOpenBefore.includes(1)).to.be.false + expect(parsedOpenBefore.includes(3)).to.be.true + expect(parsedOpenBefore.includes(2.4)).to.be.true + expect(parsedOpenBefore.includes(1.01)).to.be.true + expect(parsedOpenBefore.includes(3.01)).to.be.false + const parsedOpenAfter = parseDomainSimple("[1;3[") + expect(parsedOpenAfter.includes(1)).to.be.true + expect(parsedOpenAfter.includes(3)).to.be.false + expect(parsedOpenAfter.includes(2.4)).to.be.true + expect(parsedOpenAfter.includes(0.99)).to.be.false + expect(parsedOpenAfter.includes(2.99)).to.be.true + }) + + it("does not parse invalid ranges", function() { + expect(() => parseDomainSimple("]1;2;3[")).to.throw + expect(() => parseDomainSimple("]1,2;3[")).to.throw + expect(() => parseDomainSimple("](12);3[")).to.throw + }) + }) +}) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml index 7ef1794..9bf8f06 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml @@ -111,6 +111,8 @@ Popup { model.append({ 'chr': chr }) } } + + Keys.onEscapePressed: parent.close() } function setFocus() { @@ -118,5 +120,4 @@ Popup { insertGrid.forceActiveFocus() } - Keys.onEscapePressed: close() } From 004b3f5612e28caa50b6f710edc7587f638bf1f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=AE=A4=E0=AE=AE=E0=AE=BF=E0=AE=B4=E0=AF=8D=E0=AE=A8?= =?UTF-8?q?=E0=AF=87=E0=AE=B0=E0=AE=AE=E0=AF=8D?= Date: Sun, 12 Jan 2025 17:22:40 +0100 Subject: [PATCH 086/104] Added translation using Weblate (Tamil) --- assets/i18n/lp_ta.ts | 1563 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1563 insertions(+) create mode 100644 assets/i18n/lp_ta.ts diff --git a/assets/i18n/lp_ta.ts b/assets/i18n/lp_ta.ts new file mode 100644 index 0000000..780a6b9 --- /dev/null +++ b/assets/i18n/lp_ta.ts @@ -0,0 +1,1563 @@ + + + + + About + + + About LogarithmPlotter + + + + + LogarithmPlotter v%1 + + + + + 2D plotter software to make BODE plots, sequences and repartition functions. + + + + + Report a bug + + + + + Official website + + + + + AppMenuBar + + + &File + + + + + &Load... + + + + + &Save + + + + + Save &As... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + &Copy plot + + + + + &Preferences + + + + + &Create + + + + + &Help + + + + + &Source code + + + + + &Report a bug + + + + + &User manual + + + + + &Changelog + + + + + &Help translating! + + + + + &Thanks + + + + + &About + + + + + Save unsaved changes? + + + + + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? + + + + + BaseDialog + + + Close + + + + + Changelog + + + Fetching changelog... + + + + + Close + + + + + CustomPropertyList + + + + + Create new %1 + + + + + Pick on graph + + + + + Dialog + + + Edit properties of %1 %2 + + + + + LogarithmPlotter - Invalid object name + + + + + An object with the name '%1' already exists. + + + + + Name + + + + + null + + + + + name + + + + + name + value + + + + + ExpressionEditor + + + Object Properties + + + + + Variables + + + + + Constants + + + + + Functions + + + + + Executable Objects + + + + + Objects + + + + + FileDialog + + + Export Logarithm Plot file + + + + + Import Logarithm Plot file + + + + + GreetScreen + + + Welcome to LogarithmPlotter + + + + + Version %1 + + + + + User manual + + + + + Changelog + + + + + Preferences + + + + + Close + + + + + ListSetting + + + + Add Entry + + + + + LogarithmPlotter + + + Objects + + + + + Settings + + + + + History + + + + + Copied plot screenshot to clipboard! + + + + + &Update + + + + + &Update LogarithmPlotter + + + + + ObjectCreationGrid + + + + Create new: + + + + + ObjectLists + + + Hide all %1 + + + + + Show all %1 + + + + + ObjectRow + + + Hide %1 %2 + + + + + Show %1 %2 + + + + + Set %1 %2 position + + + + + Delete %1 %2 + + + + + Pick new color for %1 %2 + + + + + PickLocationOverlay + + + Pointer precision: + + + + + Snap to grid: + + + + + Pick X + + + + + Pick Y + + + + + Open picker settings + + + + + Hide picker settings + + + + + (no pick selected) + + + + + Preferences + + + Close + + + + + Settings + + + + X Zoom + + + + + + Y Zoom + + + + + + Min X + + + + + + Max Y + + + + + Max X + + + + + Min Y + + + + + + X Axis Step + + + + + + Y Axis Step + + + + + + Line width + + + + + + Text size (px) + + + + + + X Label + + + + + + Y Label + + + + + + X Log scale + + + + + + Show X graduation + + + + + + Show Y graduation + + + + + Copy to clipboard + + + + + Save plot + + + + + Save plot as + + + + + Load plot + + + + + ThanksTo + + + Thanks and Contributions - LogarithmPlotter + + + + + Source code + + + + + Original library by Raphael Graf + + + + + Source + + + + + Ported to Javascript by Matthew Crumley + + + + + + + Website + + + + + Ported to QMLJS by Ad5001 + + + + + Libraries included + + + + + Email + + + + + English + + + + + French + + + + + German + + + + + Hungarian + + + + + + + Github + + + + + Norwegian + + + + + Spanish + + + + + Translations included + + + + + Improve + + + + + bodemagnitude + + + Bode Magnitude + + + + + Bode Magnitudes + + + + + + low-pass + + + + + + high-pass + + + + + bodemagnitudesum + + + + Bode Magnitudes Sum + + + + + bodephase + + + Bode Phase + + + + + Bode Phases + + + + + bodephasesum + + + + Bode Phases Sum + + + + + changelog + + + Could not fetch changelog: Server error {}. + + + + + Could not fetch update: {}. + + + + + color + + + + %1 %2's color changed from %3 to %4. + + + + + comment + + + Ex: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ⁻*), ]0;1[, {3;4;5} + + + + + The following parameters are used when the definition domain is a non-continuous set. (Ex: ℕ, ℤ, sets like {0;3}...) + + + + + Note: Specify the probability for each value. + + + + + Note: Use %1[n] to refer to %1ₙ, %1[n+1] for %1ₙ₊₁... + + + + + If you have latex enabled, you can use use latex markup in between $$ to create equations. + + + + + control + + + + + + + %1: + + + + + create + + + + New %1 %2 created. + + + + + delete + + + + %1 %2 deleted. + + + + + distribution + + + Repartition + + + + + Repartition functions + + + + + editproperty + + + %1 of %2 %3 changed from "%4" to "%5". + + + + + %1 of %2 changed from %3 to %4. + + + + + error + + + No object found with names %1. + + + + + No object found with name %1. + + + + + Object cannot be dependent on itself. + + + + + Circular dependency detected. Object %1 depends on %2. + + + + + Circular dependency detected. Objects %1 depend on %2. + + + + + Error while parsing expression for property %1: +%2 + +Evaluated expression: %3 + + + + + Error while attempting to draw %1 %2: +%3 + +Undoing last change. + + + + + + Cannot find property %1 of object %2. + + + + + Undefined variable %1. + + + + + In order to be executed, object %1 must have at least one argument. + + + + + %1 cannot be executed. + + + + + + + Invalid expression. + + + + + Invalid expression (parity). + + + + + EOF + + + + + + Parse error [position %1]: %2 + + + + + Expected %1 + + + + + Unexpected %1 + + + + + Unexpected ".": member access is not permitted + + + + + Unexpected "[]": arrays are disabled. + + + + + Unexpected symbol: %1. + + + + + + Function %1 must have at least one argument. + + + + + First argument to map is not a function. + + + + + Second argument to map is not an array. + + + + + First argument to fold is not a function. + + + + + Second argument to fold is not an array. + + + + + First argument to filter is not a function. + + + + + Second argument to filter is not an array. + + + + + Second argument to indexOf is not a string or array. + + + + + Second argument to join is not an array. + + + + + Unknown character "%1". + + + + + + Illegal escape sequence: %1. + + + + + expression + + + + LogarithmPlotter - Parsing error + + + + + Error while parsing expression for property %1: +%2 + +Evaluated expression: %3 + + + + + LogarithmPlotter - Drawing error + + + + + Automatically close parenthesises and brackets + + + + + Enable syntax highlighting + + + + + Enable autocompletion + + + + + Color Scheme + + + + + function + + + Function + + + + + Functions + + + + + general + + + Check for updates on startup + + + + + Reset redo stack automaticly + + + + + Enable LaTeX rendering + + + + + io + + + Saved plot to '%1'. + + + + + Loading file '%1'. + + + + + Unknown object type: %1. + + + + + Invalid file provided. + + + + + Could not load file: + + + + + Loaded file '%1'. + + + + + latex + + + No Latex installation found. +If you already have a latex distribution installed, make sure it's installed on your path. +Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. + + + + + DVIPNG was not found. Make sure you include it from your Latex distribution. + + + + + An exception occured within the creation of the latex formula. +Process '{}' ended with a non-zero return code {}: + +{} +Please make sure your latex installation is correct and report a bug if so. + + + + + Your LaTeX installation does not include some required packages: + +- {} (https://ctan.org/pkg/{}) + +Make sure said package is installed, or disable the LaTeX rendering in LogarithmPlotter. + + + + + An exception occured within the creation of the latex formula. +Process '{}' took too long to finish: +{} +Please make sure your latex installation is correct and report a bug if so. + + + + + name + + + + %1 %2 renamed to %3. + + + + + parameters + + + above + + + + + below + + + + + + left + + + + + + right + + + + + above-left + + + + + above-right + + + + + below-left + + + + + below-right + + + + + center + + + + + top + + + + + bottom + + + + + top-left + + + + + top-right + + + + + bottom-left + + + + + bottom-right + + + + + application + + + + + function + + + + + high + + + + + low + + + + + Next to target + + + + + With label + + + + + Hidden + + + + + point + + + Point + + + + + Points + + + + + position + + + Position of %1 %2 set from "%3" to "%4". + + + + + Position of %1 set from %2 to %3. + + + + + prop + + + expression + + + + + definitionDomain + + + + + destinationDomain + + + + + displayMode + + + + + + + + + + + + + + labelPosition + + + + + + + + + + + labelX + + + + + + drawPoints + + + + + + drawDashedLines + + + + + + om_0 + + + + + pass + + + + + gain + + + + + omGraduation + + + + + phase + + + + + unit + + + + + + + x + + + + + + y + + + + + pointStyle + + + + + probabilities + + + + + defaultExpression + + + + + baseValues + + + + + text + + + + + disableLatex + + + + + targetElement + + + + + approximate + + + + + rounding + + + + + displayStyle + + + + + targetValuePosition + + + + + labelContent + + + + + sequence + + + Sequence + + + + + Sequences + + + + + settingCategory + + + general + + + + + editor + + + + + default + + + + + text + + + Text + + + + + Texts + + + + + update + + + An update for LogarithmPlotter (v{}) is available. + + + + + No update available. + + + + + Could not fetch update information: Server error {}. + + + + + Could not fetch update information: {}. + + + + + usage + + + integral(<from: number>, <to: number>, <f: ExecutableObject>) + + + + + + Usage: +%1 + + + + + + + Usage: +%1 +%2 + + + + + integral(<from: number>, <to: number>, <f: string>, <variable: string>) + + + + + derivative(<f: ExecutableObject>, <x: number>) + + + + + derivative(<f: string>, <variable: string>, <x: number>) + + + + + visibility + + + + %1 %2 shown. + + + + + + %1 %2 hidden. + + + + + xcursor + + + X Cursor + + + + + X Cursors + + + + From 3b244fad2c5f263c1ba951759b68670230d817a7 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sun, 12 Jan 2025 17:42:48 +0100 Subject: [PATCH 087/104] Updating translations + credits for Tamil. --- assets/i18n/lp_de.ts | 316 ++++++++++------ assets/i18n/lp_en.ts | 316 ++++++++++------ assets/i18n/lp_es.ts | 304 +++++++++------ assets/i18n/lp_fr.ts | 316 ++++++++++------ assets/i18n/lp_hu.ts | 316 ++++++++++------ assets/i18n/lp_nb_NO.ts | 352 ++++++++++-------- assets/i18n/lp_ta.ts | 298 +++++++-------- assets/i18n/lp_template.ts | 312 ++++++++-------- .../LogarithmPlotter/Popup/ThanksTo.qml | 10 + 9 files changed, 1539 insertions(+), 1001 deletions(-) diff --git a/assets/i18n/lp_de.ts b/assets/i18n/lp_de.ts index 7d66a7a..56a80ff 100644 --- a/assets/i18n/lp_de.ts +++ b/assets/i18n/lp_de.ts @@ -42,47 +42,47 @@ &Laden… - + &Save &Speichern - + Save &As... Speichern &Unter… - + &Quit &Ausfahrt - + &Edit &Bearbeiten - + &Undo &Lösen - + &Redo &Wiederherstellen - + &Copy plot Grafik &Kopieren - + &Preferences &Einstellung - + &Create &Erstellen @@ -123,52 +123,52 @@ Syntaktische Färbung - + &Help &Hilfe - + &Source code &Quellcode - + &Report a bug Fehler &Melden - + &User manual &Benutzerhandbuch - + &Changelog &Versionshinweise - + &Help translating! &Hilfe beim Übersetzen! - + &Thanks &Danksagungen - + &About &Übrigens - + Save unsaved changes? Änderungen speichern? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Diese Grafik enthält ungespeicherte Änderungen. Dadurch gehen alle ungespeicherten Daten verloren. Fortfahren? @@ -188,6 +188,29 @@ Beim Starten auf Updates prüfen + + Browser + + + Filter... + Filtern… + + + + Redo > + Wiederherstellen > + + + + > Now + > Aktueller Stand + + + + < Undo + < Rückgängig + + Changelog @@ -218,22 +241,22 @@ Dialog - + Edit properties of %1 %2 Eigenschaften von %1 %2 bearbeiten - + LogarithmPlotter - Invalid object name LogarithmPlotter - Ungültiger Objektname - + An object with the name '%1' already exists. Ein Objekt mit dem Namen '%1' existiert bereits. - + Name Name @@ -242,17 +265,17 @@ Etikett - + null leer - + name Name - + name + value Name + Wert @@ -428,20 +451,38 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" + Neuer Eintrag + + Loading + + + Loading... + + + + + Finished rendering of %1 + + + LogarithmPlotter - + + untitled + + + + Objects Objekte - + Settings Einstellungen - + History Verlauf @@ -470,17 +511,17 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" Geladene Datei '%1'. - + Copied plot screenshot to clipboard! Grafik in die Zwischenablage kopiert! - + &Update &Aktualisieren - + &Update LogarithmPlotter LogarithmPlotter &aktualisieren @@ -555,45 +596,76 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" - PickLocationOverlay + PickLocation - + Pointer precision: Genauigkeit des Zeigers: + + + Snap to grid: + Am Raster einrasten: + + + + Pick X + X nehmen + + + + Pick Y + Y nehmen + + + + Open picker settings + Zeigereinstellungen öffnen + + + + Hide picker settings + Zeigereinstellungen ausblenden + + + + (no pick selected) + (keine Auswahl ausgewählt) + + + + PickLocationOverlay + + Pointer precision: + Genauigkeit des Zeigers: + Snap to grid Am Gitter einrasten - Snap to grid: - Am Raster einrasten: + Am Raster einrasten: - Pick X - X nehmen + X nehmen - Pick Y - Y nehmen + Y nehmen - Open picker settings - Zeigereinstellungen öffnen + Zeigereinstellungen öffnen - Hide picker settings - Zeigereinstellungen ausblenden + Zeigereinstellungen ausblenden - (no pick selected) - (keine Auswahl ausgewählt) + (keine Auswahl ausgewählt) @@ -769,22 +841,22 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" E-Mail - + English Englisch - + French Französisch - + German Deutsch - + Hungarian Ungarisch @@ -792,26 +864,32 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" + Github GitHub - + Norwegian Norwegisch - + Spanish Spanisch - + + Tamil + + + + Translations included Einschließlich Übersetzungen - + Improve Verbessern @@ -875,12 +953,13 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" changelog - + Could not fetch changelog: Server error {}. Changelog konnte nicht geholt werden: Server-Fehler {}. - + + Could not fetch update: {}. Changelog konnte nicht geholt werden: {}. @@ -982,34 +1061,34 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" error - + Cannot find property %1 of object %2. Eigenschaft %1 von Objekt %2 kann nicht gefunden werden. - + Undefined variable %1. Die Variable %1 ist nicht definiert. - + In order to be executed, object %1 must have at least one argument. Um als Funktion verwendet zu werden, benötigt das Objekt %1 mindestens ein Parameter. - + %1 cannot be executed. %1 ist keine Formel. - - - + + + Invalid expression. Ungültiger Ausdruck. - + Invalid expression (parity). Ungültiger Ausdruck (Parität). @@ -1068,78 +1147,70 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" Unerwartetes Symbol: %1. - - + + Function %1 must have at least one argument. Die Funktion %1 benötigt mindestens ein Parameter. - First argument to map is not a function. - Der erste Parameter von map ist keine Formel. + Der erste Parameter von map ist keine Formel. - Second argument to map is not an array. - Der zweite Parameter von map ist kein Array. + Der zweite Parameter von map ist kein Array. - First argument to fold is not a function. - Der erste Parameter für fold ist keine Formel. + Der erste Parameter für fold ist keine Formel. - Second argument to fold is not an array. - Der zweite Parameter für fold ist kein Array. + Der zweite Parameter für fold ist kein Array. - First argument to filter is not a function. - Der erste Parameter für filter ist keine Formel. + Der erste Parameter für filter ist keine Formel. - Second argument to filter is not an array. - Der zweite Parameter von filter ist kein Array. + Der zweite Parameter von filter ist kein Array. - Second argument to indexOf is not a string or array. - Der zweite Parameter von indexOf ist kein String oder Array. + Der zweite Parameter von indexOf ist kein String oder Array. - Second argument to join is not an array. - Der zweite Parameter von join ist kein Array. + Der zweite Parameter von join ist kein Array. - + EOF Ende des Ausdrucks - + No object found with names %1. Kein Objekt mit Namen %1 gefunden. - + No object found with name %1. Kein Objekt mit dem Namen %1 gefunden. - + Object cannot be dependent on itself. Ein Objekt kann nicht von sich selbst abhängen. - + Circular dependency detected. Object %1 depends on %2. Zirkuläre Abhängigkeit entdeckt. Objekt %1 hängt von %2 ab. - + Circular dependency detected. Objects %1 depend on %2. Zirkuläre Abhängigkeit entdeckt. Objekte %1 hängen von %2 ab. @@ -1260,6 +1331,11 @@ Ausdruck analysiert: %3 Enable LaTeX rendering LaTeX-Rendering aktivieren + + + Enable threaded LaTeX renderer (experimental) + + historylib @@ -1303,38 +1379,32 @@ Ausdruck analysiert: %3 Verlauf - Saved plot to '%1'. - Gespeicherte Grafik auf '%1'. + Gespeicherte Grafik auf '%1'. - Loading file '%1'. - Laden der Datei '%1'. + Laden der Datei '%1'. - Unknown object type: %1. - Unbekannter Objekttyp: %1. + Unbekannter Objekttyp: %1. - Invalid file provided. - Ungültige Datei angegeben. + Ungültige Datei angegeben. - Could not load file: - Datei konnte nicht geladen werden: + Datei konnte nicht geladen werden: Could not save file: Die Datei konnte nicht gespeichert werden: - Loaded file '%1'. - Geladene Datei '%1'. + Geladene Datei '%1'. Copied plot screenshot to clipboard! @@ -1352,7 +1422,7 @@ Ausdruck analysiert: %3 latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. @@ -1361,12 +1431,12 @@ Wenn Sie bereits eine LaTeX-Distribution installiert haben, vergewissern Sie sic Andernfalls können Sie eine LaTeX-Distribution wie TeX Live unter https://tug.org/texlive/ herunterladen. - + DVIPNG was not found. Make sure you include it from your Latex distribution. DVIPNG wurde nicht gefunden. Stellen Sie sicher, dass Sie es aus Ihrer LaTeX-Distribution einbinden. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1379,7 +1449,7 @@ Der Prozess '{}' wurde mit einem Rückgabecode ungleich Null beendet { Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melden Sie einen Fehler, falls dies der Fall ist. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1392,7 +1462,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm Stellen Sie sicher, dass diese Pakete installiert sind, oder deaktivieren Sie das LaTeX-Rendering in LogarithmPlotter. - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1403,6 +1473,32 @@ Der Prozess '{}' brauchte zu lange, um beendet zu werden: Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melden Sie einen Fehler, falls dies der Fall ist. + + main + + + This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}. +Please update LogarithmPlotter to open this file. + + + + + Could not open file "{}": +{} + + + + + Could not open file: "{}" +File does not exist. + + + + + Built with PySide6 (Qt) v{} and python v{} + + + name @@ -1727,7 +1823,7 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde Farbe - + labelContent Etikett @@ -1804,22 +1900,22 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde update - + An update for LogarithmPlotter (v{}) is available. Ein Update für LogarithmPlotter (v{}) ist verfügbar. - + No update available. Keine Aktualisierung verfügbar. - + Could not fetch update information: Server error {}. Es konnten keine Aktualisierungsinformationen abgerufen werden: Server-Fehler {}. - + Could not fetch update information: {}. Es konnten keine Aktualisierungsinformationen abgerufen werden:{}. diff --git a/assets/i18n/lp_en.ts b/assets/i18n/lp_en.ts index 5f653a7..0f9b887 100644 --- a/assets/i18n/lp_en.ts +++ b/assets/i18n/lp_en.ts @@ -42,47 +42,47 @@ &Open… - + &Save &Save - + Save &As... Save &As… - + &Quit &Quit - + &Edit &Edit - + &Undo &Undo - + &Redo &Redo - + &Copy plot &Copy plot - + &Preferences &Preferences - + &Create &Create @@ -123,52 +123,52 @@ Color Scheme - + &Help &Help - + &Source code &Source code - + &Report a bug &Report a bug - + &User manual &User manual - + &Changelog &Changelog - + &Help translating! &Help translating! - + &Thanks &Thanks - + &About &About - + Save unsaved changes? Save unsaved changes? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? @@ -188,6 +188,29 @@ Check for updates on startup + + Browser + + + Filter... + Filter… + + + + Redo > + Redo > + + + + > Now + > Now + + + + < Undo + < Undo + + Changelog @@ -218,22 +241,22 @@ Dialog - + Edit properties of %1 %2 Edit properties of %1 %2 - + LogarithmPlotter - Invalid object name LogarithmPlotter - Invalid object name - + An object with the name '%1' already exists. An object with the name '%1' already exists. - + Name Name @@ -242,17 +265,17 @@ Label content - + null null - + name name - + name + value name + value @@ -428,20 +451,38 @@ These settings can be changed at any time from the "Settings" menu.+ Add Entry + + Loading + + + Loading... + + + + + Finished rendering of %1 + + + LogarithmPlotter - + + untitled + + + + Objects Objects - + Settings Settings - + History History @@ -470,17 +511,17 @@ These settings can be changed at any time from the "Settings" menu.Loaded file '%1'. - + Copied plot screenshot to clipboard! Copied plot screenshot to clipboard! - + &Update &Update - + &Update LogarithmPlotter &Update LogarithmPlotter @@ -555,45 +596,76 @@ These settings can be changed at any time from the "Settings" menu. - PickLocationOverlay + PickLocation - + Pointer precision: Pointer precision: + + + Snap to grid: + Snap to grid: + + + + Pick X + Pick X + + + + Pick Y + Pick Y + + + + Open picker settings + Open picker settings + + + + Hide picker settings + Hide picker settings + + + + (no pick selected) + (no pick selected) + + + + PickLocationOverlay + + Pointer precision: + Pointer precision: + Snap to grid Snap to grid - Snap to grid: - Snap to grid: + Snap to grid: - Pick X - Pick X + Pick X - Pick Y - Pick Y + Pick Y - Open picker settings - Open picker settings + Open picker settings - Hide picker settings - Hide picker settings + Hide picker settings - (no pick selected) - (no pick selected) + (no pick selected) @@ -769,22 +841,22 @@ These settings can be changed at any time from the "Settings" menu.Email - + English English - + French French - + German German - + Hungarian Hungarian @@ -792,26 +864,32 @@ These settings can be changed at any time from the "Settings" menu. + Github GitHub - + Norwegian Norwegian - + Spanish Spanish - + + Tamil + + + + Translations included Translations included - + Improve Improve @@ -875,12 +953,13 @@ These settings can be changed at any time from the "Settings" menu. changelog - + Could not fetch changelog: Server error {}. Could not fetch changelog: Server error {}. - + + Could not fetch update: {}. Could not fetch changelog: {}. @@ -982,34 +1061,34 @@ These settings can be changed at any time from the "Settings" menu.error - + Cannot find property %1 of object %2. Cannot find property %1 of object %2. - + Undefined variable %1. Undefined variable %1. - + In order to be executed, object %1 must have at least one argument. In order to be executed, object %1 must have at least one argument. - + %1 cannot be executed. %1 is not a function. - - - + + + Invalid expression. Invalid expression. - + Invalid expression (parity). Invalid expression (parity). @@ -1068,78 +1147,70 @@ These settings can be changed at any time from the "Settings" menu.Unexpected symbol: %1. - - + + Function %1 must have at least one argument. Function %1 must have at least one argument. - First argument to map is not a function. - First argument to map is not a function. + First argument to map is not a function. - Second argument to map is not an array. - Second argument to map is not an array. + Second argument to map is not an array. - First argument to fold is not a function. - First argument to fold is not a function. + First argument to fold is not a function. - Second argument to fold is not an array. - Second argument to fold is not an array. + Second argument to fold is not an array. - First argument to filter is not a function. - First argument to filter is not a function. + First argument to filter is not a function. - Second argument to filter is not an array. - Second argument to filter is not an array. + Second argument to filter is not an array. - Second argument to indexOf is not a string or array. - Second argument to indexOf is not a string or array. + Second argument to indexOf is not a string or array. - Second argument to join is not an array. - Second argument to join is not an array. + Second argument to join is not an array. - + EOF End of expression - + No object found with names %1. No object found with names %1. - + No object found with name %1. No object found with name %1. - + Object cannot be dependent on itself. Object cannot be dependent on itself. - + Circular dependency detected. Object %1 depends on %2. Circular dependency detected. Object %1 depends on %2. - + Circular dependency detected. Objects %1 depend on %2. Circular dependency detected. Objects %1 depend on %2. @@ -1260,6 +1331,11 @@ Evaluated expression: %3 Enable LaTeX rendering Enable LaTeX rendering + + + Enable threaded LaTeX renderer (experimental) + + historylib @@ -1303,38 +1379,32 @@ Evaluated expression: %3 History - Saved plot to '%1'. - Saved plot to '%1'. + Saved plot to '%1'. - Loading file '%1'. - Loading file '%1'. + Loading file '%1'. - Unknown object type: %1. - Unknown object type: %1. + Unknown object type: %1. - Invalid file provided. - Invalid file provided. + Invalid file provided. - Could not load file: - Could not load file: + Could not load file: Could not save file: Could not save file: - Loaded file '%1'. - Loaded file '%1'. + Loaded file '%1'. Copied plot screenshot to clipboard! @@ -1352,7 +1422,7 @@ Evaluated expression: %3 latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. @@ -1361,12 +1431,12 @@ If you already have a LaTeX distribution installed, make sure it's installe Otherwise, you can download a LaTeX distribution like TeX Live at https://tug.org/texlive/. - + DVIPNG was not found. Make sure you include it from your Latex distribution. DVIPNG was not found. Make sure you include it from your LaTeX distribution. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1379,7 +1449,7 @@ Process '{}' ended with a non-zero return code {}: Please make sure your LaTeX installation is correct and report a bug if so. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1392,7 +1462,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm Make sure said package is installed, or disable the LaTeX rendering in LogarithmPlotter. - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1403,6 +1473,32 @@ Process '{}' took too long to finish: Please make sure your LaTeX installation is correct and report a bug if so. + + main + + + This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}. +Please update LogarithmPlotter to open this file. + + + + + Could not open file "{}": +{} + + + + + Could not open file: "{}" +File does not exist. + + + + + Built with PySide6 (Qt) v{} and python v{} + + + name @@ -1727,7 +1823,7 @@ Please make sure your LaTeX installation is correct and report a bug if so.Color - + labelContent Label content @@ -1804,22 +1900,22 @@ Please make sure your LaTeX installation is correct and report a bug if so. update - + An update for LogarithmPlotter (v{}) is available. An update for LogarithmPlotter (v{}) is available. - + No update available. No update available. - + Could not fetch update information: Server error {}. Could not fetch update information: Server error {}. - + Could not fetch update information: {}. Could not fetch update information: {}. diff --git a/assets/i18n/lp_es.ts b/assets/i18n/lp_es.ts index 7a736b5..b1e5d0a 100644 --- a/assets/i18n/lp_es.ts +++ b/assets/i18n/lp_es.ts @@ -42,47 +42,47 @@ &Abrir… - + &Save &Guardar - + Save &As... Guardar &como… - + &Quit &Salida - + &Edit &Editar - + &Undo &Cancelar - + &Redo &Reiniciar - + &Copy plot &Copiar el gráfico - + &Preferences &Preferencias - + &Create &Crear @@ -119,52 +119,52 @@ Esquema de colores - + &Help &Ayuda - + &Source code &Código fuente - + &Report a bug &Informar de un error - + &User manual &Manual del usuario - + &Changelog &Registro de cambios - + &Help translating! &¡Ayuda a la traducción! - + &Thanks &Agradecimientos - + &About &Acerca de - + Save unsaved changes? ¿Guardar los cambios no guardados? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Este gráfico contiene cambios sin guardar. Al hacer esto, se perderán todos los datos no guardados. ¿Continuar? @@ -188,6 +188,29 @@ Comprobación de las actualizaciones al arrancar + + Browser + + + Filter... + + + + + Redo > + Rehacer > + + + + > Now + > Ahora + + + + < Undo + < Deshacer + + Changelog @@ -218,37 +241,37 @@ Dialog - + Edit properties of %1 %2 Editar las propiedades de %1 %2 - + LogarithmPlotter - Invalid object name LogarithmPlotter - Nombre de objeto no válido - + An object with the name '%1' already exists. Ya existe un objeto con el nombre '%1'. - + Name - + null - + name - + name + value nombre + valor @@ -420,35 +443,53 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes + Añadir entrada + + Loading + + + Loading... + + + + + Finished rendering of %1 + + + LogarithmPlotter - + + untitled + + + + Objects Objetos - + Settings Ajustes - + History Historial - + Copied plot screenshot to clipboard! ¡Captura de pantalla del gráfico copiada al portapapeles! - + &Update &Actualizar - + &Update LogarithmPlotter &Actualizar LogarithmPlotter @@ -547,42 +588,73 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes - PickLocationOverlay + PickLocation - + Pointer precision: Precisión del puntero: - + Snap to grid: Ajustar a la cuadrícula: - + Pick X Elige X - + Pick Y Elige Y - + Open picker settings Abrir los ajustes del selector - + Hide picker settings Ocultar ajustes del selector - + (no pick selected) (sin selección) + + + PickLocationOverlay + + Pointer precision: + Precisión del puntero: + + + Snap to grid: + Ajustar a la cuadrícula: + + + Pick X + Elige X + + + Pick Y + Elige Y + + + Open picker settings + Abrir los ajustes del selector + + + Hide picker settings + Ocultar ajustes del selector + + + (no pick selected) + (sin selección) + Snap to grid Ajustar a la cuadrícula @@ -761,22 +833,22 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes - + English - + French - + German - + Hungarian @@ -784,26 +856,32 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes + Github GitHub - + Norwegian - + Spanish Español - + + Tamil + + + + Translations included Traducciones incluidas - + Improve Mejorar @@ -867,12 +945,13 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes changelog - + Could not fetch changelog: Server error {}. No se ha podido recuperar el registro de cambios: Error del servidor {}. - + + Could not fetch update: {}. No se pudo obtener el registro de cambios: {}. @@ -974,34 +1053,34 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes error - + Cannot find property %1 of object %2. No se puede encontrar la propiedad %1 del objeto %2. - + Undefined variable %1. Variable %1 no definida. - + In order to be executed, object %1 must have at least one argument. Para ser ejecutado, el objeto %1 debe tener al menos un argumento. - + %1 cannot be executed. %1 no es una función. - - - + + + Invalid expression. Expresión incorrecta. - + Invalid expression (parity). Expresión no válida (paridad). @@ -1052,73 +1131,65 @@ Estos ajustes se pueden cambiar en cualquier momento desde el menú “Ajustes Símbolo inesperado: %1. - - + + Function %1 must have at least one argument. La función %1 debe tener al menos un argumento. - First argument to map is not a function. - El primer argumento de map no es una función. + El primer argumento de map no es una función. - Second argument to map is not an array. - El segundo argumento de map no es una matriz. + El segundo argumento de map no es una matriz. - First argument to fold is not a function. - El primer argumento de fold no es una función. + El primer argumento de fold no es una función. - Second argument to fold is not an array. - El segundo argumento de fold no es una matriz. + El segundo argumento de fold no es una matriz. - First argument to filter is not a function. - El primer argumento del filtro no es una función. + El primer argumento del filtro no es una función. - Second argument to filter is not an array. - El segundo argumento del filtro no es una matriz. + El segundo argumento del filtro no es una matriz. - Second argument to indexOf is not a string or array. - El segundo argumento de indexOf no es una cadena ni una matriz. + El segundo argumento de indexOf no es una cadena ni una matriz. - Second argument to join is not an array. - El segundo argumento para unirse no es una matriz. + El segundo argumento para unirse no es una matriz. - + No object found with names %1. No se ha encontrado ningún objeto con el nombre %1. - + No object found with name %1. Ningún objeto con el nombre %1 encontrado. - + Object cannot be dependent on itself. El objeto no puede depender de sí mismo. - + Circular dependency detected. Object %1 depends on %2. Dependencia circular detectada. El objeto %1 depende de %2. - + Circular dependency detected. Objects %1 depend on %2. Dependencia circular detectada. Los objetos %1 dependen de %2. @@ -1153,7 +1224,7 @@ Deshaciendo el último cambio. Variable de asignación esperada. - + EOF Fin de la expresión @@ -1252,6 +1323,11 @@ Expresión evaluada: %3 Enable LaTeX rendering Activar el renderizado de LaTeX + + + Enable threaded LaTeX renderer (experimental) + + historylib @@ -1307,44 +1383,38 @@ Expresión evaluada: %3 Objetos - Saved plot to '%1'. - Gráfico guardado en '%1'. + Gráfico guardado en '%1'. - Loading file '%1'. - Cargando el archivo '%1'. + Cargando el archivo '%1'. - Unknown object type: %1. - Tipo de objeto desconocido: %1 . + Tipo de objeto desconocido: %1 . - Invalid file provided. - Se ha proporcionado un archivo no válido. + Se ha proporcionado un archivo no válido. - Could not load file: - No se pudo cargar el archivo: + No se pudo cargar el archivo: Could not save file: No se ha podido guardar el archivo: - Loaded file '%1'. - Archivo cargado '%1'. + Archivo cargado '%1'. latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. @@ -1353,12 +1423,12 @@ Si ya tiene instalada una distribución de LaTeX, asegúrese de que está instal De lo contrario, puede descargar una distribución de LaTeX como TeX Live en https://tug.org/texlive/. - + DVIPNG was not found. Make sure you include it from your Latex distribution. No se ha encontrado DVIPNG. Asegúrese de incluirlo en tu distribución LaTeX. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1371,7 +1441,7 @@ El proceso '{}' terminó con un código de retorno distinto de cero {} Por favor, asegúrate de que tu instalación de LaTeX es correcta e informe de un error si es así. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1384,7 +1454,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm Asegúrate de que dicho paquete está instalado, o desactive el renderizado LaTeX en LogarithmPlotter. - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1395,6 +1465,32 @@ El proceso '{}' tardó demasiado en finalizar: Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de un error si es así. + + main + + + This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}. +Please update LogarithmPlotter to open this file. + + + + + Could not open file "{}": +{} + + + + + Could not open file: "{}" +File does not exist. + + + + + Built with PySide6 (Qt) v{} and python v{} + + + name @@ -1719,7 +1815,7 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u Valores de inicialización - + labelContent Contenido de la etiqueta @@ -1796,22 +1892,22 @@ Por favor, asegúrese de que su instalación de LaTeX es correcta e informe de u update - + An update for LogarithmPlotter (v{}) is available. Una actualización para LogarithmPlotter (v{}) está disponible. - + No update available. No hay ninguna actualización disponible. - + Could not fetch update information: Server error {}. No se ha podido obtener la información de la actualización: Error del servidor {}. - + Could not fetch update information: {}. No se pudo obtener información de la actualización: {}. diff --git a/assets/i18n/lp_fr.ts b/assets/i18n/lp_fr.ts index fd806a2..93fd60e 100644 --- a/assets/i18n/lp_fr.ts +++ b/assets/i18n/lp_fr.ts @@ -42,47 +42,47 @@ &Ouvrir… - + &Save &Sauvegarder - + Save &As... Sauvegarde &Sous… - + &Quit &Quitter - + &Edit &Édition - + &Undo &Annuler - + &Redo &Rétablir - + &Copy plot &Copier le graphe - + &Preferences &Préférences - + &Create &Créer @@ -124,52 +124,52 @@ Coloration Syntaxique - + &Help &Aide - + &Source code &Code source - + &Report a bug &Rapport de bug - + &User manual Manuel d'&utilisation - + &Changelog &Notes de version - + &Help translating! &Aider à la traduction ! - + &Thanks &Remerciements - + &About &À propos - + Save unsaved changes? Sauvegarder les modifications ? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Ce graphe contient des modifications non sauvegardées. En faisant cela, toutes les données non sauvegardées seront perdues. Continuer ? @@ -189,6 +189,29 @@ Vérifier la présence de mise à jour au démarrage + + Browser + + + Filter... + Filtrer… + + + + Redo > + Rétablir > + + + + > Now + > État actuel + + + + < Undo + < Annuler + + Changelog @@ -219,22 +242,22 @@ Dialog - + Edit properties of %1 %2 Changer les propriétés de %1 %2 - + LogarithmPlotter - Invalid object name LogarithmPlotter - Nom d'objet invalide - + An object with the name '%1' already exists. Un objet portant le nom '%1' existe déjà. - + Name Nom @@ -243,17 +266,17 @@ Étiquette - + null vide - + name nom - + name + value nom + valeur @@ -430,20 +453,38 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P + Nouvelle entrée + + Loading + + + Loading... + + + + + Finished rendering of %1 + + + LogarithmPlotter - + + untitled + + + + Objects Objets - + Settings Paramètres - + History Historique @@ -472,17 +513,17 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Fichier '%1' chargé. - + Copied plot screenshot to clipboard! Image du graphe copiée dans le presse-papiers ! - + &Update &Mise à jour - + &Update LogarithmPlotter &Mettre à jour LogarithmPlotter @@ -557,45 +598,76 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P - PickLocationOverlay + PickLocation - + Pointer precision: Précision du pointeur : + + + Snap to grid: + Placer sur la grille : + + + + Pick X + Prendre la position X + + + + Pick Y + Prendre la position Y + + + + Open picker settings + Ouvrir les paramètres du pointeur + + + + Hide picker settings + Cacher les paramètres du pointeur + + + + (no pick selected) + (aucun axe sélectionné) + + + + PickLocationOverlay + + Pointer precision: + Précision du pointeur : + Snap to grid Placement sur la grille - Snap to grid: - Placer sur la grille : + Placer sur la grille : - Pick X - Prendre la position X + Prendre la position X - Pick Y - Prendre la position Y + Prendre la position Y - Open picker settings - Ouvrir les paramètres du pointeur + Ouvrir les paramètres du pointeur - Hide picker settings - Cacher les paramètres du pointeur + Cacher les paramètres du pointeur - (no pick selected) - (aucun axe sélectionné) + (aucun axe sélectionné) @@ -771,22 +843,22 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Email - + English Anglais - + French Français - + German Allemand - + Hungarian Hongrois @@ -794,26 +866,32 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P + Github GitHub - + Norwegian Norvégien - + Spanish Espagnol - + + Tamil + + + + Translations included Traductions incluses - + Improve Améliorer @@ -877,12 +955,13 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P changelog - + Could not fetch changelog: Server error {}. Impossible de récupérer les notes de version : Erreur de serveur {}. - + + Could not fetch update: {}. Impossible de récupérer les notes de version : {}. @@ -985,34 +1064,34 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P error - + Cannot find property %1 of object %2. Impossible de trouver la propriété %1 de l'objet %2. - + Undefined variable %1. La variable %1 n'est pas définie. - + In order to be executed, object %1 must have at least one argument. Pour être utilisé comme fonction, l'objet %1 nécessite au moins un argument. - + %1 cannot be executed. %1 n'est pas une fonction. - - - + + + Invalid expression. Formule invalide. - + Invalid expression (parity). Formule invalide (parité). @@ -1071,78 +1150,70 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Symbole inconnu : %1. - - + + Function %1 must have at least one argument. La fonction %1 nécessite au moins un argument. - First argument to map is not a function. - Le premier argument de map n'est pas une fonction. + Le premier argument de map n'est pas une fonction. - Second argument to map is not an array. - Le deuxième argument de map n'est pas un tableau. + Le deuxième argument de map n'est pas un tableau. - First argument to fold is not a function. - Le premier argument de fold n'est pas une fonction. + Le premier argument de fold n'est pas une fonction. - Second argument to fold is not an array. - Le deuxième argument de fold n'est pas un tableau. + Le deuxième argument de fold n'est pas un tableau. - First argument to filter is not a function. - Le premier argument de filter n'est pas une fonction. + Le premier argument de filter n'est pas une fonction. - Second argument to filter is not an array. - Le deuxième argument de filter n'est pas un tableau. + Le deuxième argument de filter n'est pas un tableau. - Second argument to indexOf is not a string or array. - Le deuxième argument de indexOf n'est ni chaîne de caractères ni un tableau. + Le deuxième argument de indexOf n'est ni chaîne de caractères ni un tableau. - Second argument to join is not an array. - Le deuxième argument de join n'est pas un tableau. + Le deuxième argument de join n'est pas un tableau. - + EOF Fin de la formule - + No object found with names %1. Aucun objet trouvé ayant pour noms %1. - + No object found with name %1. Aucun objet avec le nom %1 n'a été trouvé. - + Object cannot be dependent on itself. Un objet ne peut pas dépendre de lui-même. - + Circular dependency detected. Object %1 depends on %2. Dépendance circulaire détectée. L'objet %1 dépend de %2. - + Circular dependency detected. Objects %1 depend on %2. Dépendance circulaire détectée. Les objets %1 dépendent de %2. @@ -1263,6 +1334,11 @@ Formule analysée : %3 Enable LaTeX rendering Activer le rendu LaTeX + + + Enable threaded LaTeX renderer (experimental) + + historylib @@ -1318,44 +1394,38 @@ Formule analysée : %3 &Mettre à jour LogarithmPlotter - Saved plot to '%1'. - Graphe sauvegardé dans '%1'. + Graphe sauvegardé dans '%1'. - Loading file '%1'. - Chargement du fichier '%1'. + Chargement du fichier '%1'. - Unknown object type: %1. - Type d'objet inconnu : %1. + Type d'objet inconnu : %1. - Invalid file provided. - Fichier fourni invalide. + Fichier fourni invalide. - Could not load file: - Impossible de charger le fichier : + Impossible de charger le fichier : Could not save file: Impossible de sauvegarder le fichier : - Loaded file '%1'. - Fichier '%1' chargé. + Fichier '%1' chargé. latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. @@ -1364,12 +1434,12 @@ Si vous avez déjà installé une distribution LaTeX, assurez-vous qu'elle Sinon, vous pouvez télécharger une distribution LaTeX comme TeX Live à l'adresse https://tug.org/texlive/. - + DVIPNG was not found. Make sure you include it from your Latex distribution. DVIPNG n'a pas été trouvé. Assurez-vous de l'inclure dans votre distribution LaTeX. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1382,7 +1452,7 @@ Le processus '{}' s'est terminé par un code de retour non nul {} Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c'est le cas. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1395,7 +1465,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm Assurez-vous que ce paquetage est installé, ou désactivez le rendu LaTeX dans LogarithmPlotter. - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1406,6 +1476,32 @@ Le processus '{}' a mis trop de temps à se terminer : Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c'est le cas. + + main + + + This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}. +Please update LogarithmPlotter to open this file. + + + + + Could not open file "{}": +{} + + + + + Could not open file: "{}" +File does not exist. + + + + + Built with PySide6 (Qt) v{} and python v{} + + + name @@ -1730,7 +1826,7 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c Couleur - + labelContent Étiquette @@ -1807,22 +1903,22 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c update - + An update for LogarithmPlotter (v{}) is available. Une mise à jour de LogarithmPlotter (v{}) est disponible. - + No update available. À jour. - + Could not fetch update information: Server error {}. Impossible de récupérer les informations de mise à jour. Erreur du serveur {}. - + Could not fetch update information: {}. Impossible de récupérer les informations de mise à jour. {}. diff --git a/assets/i18n/lp_hu.ts b/assets/i18n/lp_hu.ts index ac521eb..bff8a44 100644 --- a/assets/i18n/lp_hu.ts +++ b/assets/i18n/lp_hu.ts @@ -42,47 +42,47 @@ &Megnyitás… - + &Save &Mentés - + Save &As... Me&ntés másként… - + &Quit &Kilépés - + &Edit S&zerkesztés - + &Undo &Visszavonás - + &Redo &Ismétlés - + &Copy plot Ábra má&solása - + &Preferences &Beállítások - + &Create &Létrehozás @@ -123,52 +123,52 @@ Színséma - + &Help &Súgó - + &Source code &Forráskód - + &Report a bug &Hiba bejelentése - + &User manual &Használati utasítás - + &Changelog &Változásnapló - + &Help translating! &Segítség a fordításban! - + &Thanks &Köszönjük - + &About &Névjegy - + Save unsaved changes? Menti a változtatásokat? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Ez az ábra nem mentett változtatásokat tartalmaz. Ezzel az összes nem mentett adat elveszik. Folytatja? @@ -188,6 +188,29 @@ Frissítések keresése indításkor + + Browser + + + Filter... + Szűrő… + + + + Redo > + Ismétlés > + + + + > Now + > Most + + + + < Undo + < Visszavonás + + Changelog @@ -218,22 +241,22 @@ Dialog - + Edit properties of %1 %2 %1 %2 tulajdonságainak szerkesztése - + LogarithmPlotter - Invalid object name LogarithmPlotter - Érvénytelen objektumnév - + An object with the name '%1' already exists. A(z) „%1” nevű objektum már létezik. - + Name Név @@ -242,17 +265,17 @@ Címketartalom - + null üres - + name név - + name + value név + érték @@ -428,20 +451,38 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. + Bejegyzés hozzáadása + + Loading + + + Loading... + + + + + Finished rendering of %1 + + + LogarithmPlotter - + + untitled + + + + Objects Tárgyak - + Settings Beállítások - + History Előzmények @@ -470,17 +511,17 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. A(z) „%1” fájl betöltve. - + Copied plot screenshot to clipboard! Ábra képernyőkép vágólapra másolva! - + &Update &Frissítés - + &Update LogarithmPlotter A LogarithmPlotter &frissítése @@ -555,45 +596,76 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. - PickLocationOverlay + PickLocation - + Pointer precision: Mutató pontossága: + + + Snap to grid: + Rácshoz igazítás: + + + + Pick X + X kijelölése + + + + Pick Y + Y kijelölése + + + + Open picker settings + Kijelölési beállítások megnyitása + + + + Hide picker settings + Kijelölési beállítások elrejtése + + + + (no pick selected) + (nincs kijelölés kiválasztva) + + + + PickLocationOverlay + + Pointer precision: + Mutató pontossága: + Snap to grid Rácshoz illesztés - Snap to grid: - Rácshoz igazítás: + Rácshoz igazítás: - Pick X - X kijelölése + X kijelölése - Pick Y - Y kijelölése + Y kijelölése - Open picker settings - Kijelölési beállítások megnyitása + Kijelölési beállítások megnyitása - Hide picker settings - Kijelölési beállítások elrejtése + Kijelölési beállítások elrejtése - (no pick selected) - (nincs kijelölés kiválasztva) + (nincs kijelölés kiválasztva) @@ -769,22 +841,22 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. E-mail - + English angol - + French francia - + German német - + Hungarian magyar @@ -792,26 +864,32 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. + Github GitHub - + Norwegian norvég - + Spanish spanyol - + + Tamil + + + + Translations included A felhasználói felület nyelvei - + Improve Fejlesztés @@ -875,12 +953,13 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. changelog - + Could not fetch changelog: Server error {}. Nem sikerült lekérni a változásnaplót: Kiszolgálóhiba: {}. - + + Could not fetch update: {}. Nem sikerült lekérni a változásnaplót: {}. @@ -982,34 +1061,34 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. error - + Cannot find property %1 of object %2. A(z) %2 objektum %1 tulajdonsága nem található. - + Undefined variable %1. A(z) %1 változó nincs meghatározva. - + In order to be executed, object %1 must have at least one argument. A végrehajtáshoz a(z) %1 objektumnak legalább egy argumentummal kell rendelkeznie. - + %1 cannot be executed. A(z) %1 nem függvény. - - - + + + Invalid expression. Érvénytelen kifejezés. - + Invalid expression (parity). Érvénytelen kifejezés (paritás). @@ -1068,78 +1147,70 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. Váratlan szimbólum: %1. - - + + Function %1 must have at least one argument. A(z) %1 függvénynek legalább egy argumentumnak kell lennie. - First argument to map is not a function. - Az első leképezési argumentum nem függvény. + Az első leképezési argumentum nem függvény. - Second argument to map is not an array. - A második leképezési argumentum nem tömb. + A második leképezési argumentum nem tömb. - First argument to fold is not a function. - Az első behajtási argumentum nem függvény. + Az első behajtási argumentum nem függvény. - Second argument to fold is not an array. - A második behajtási argumentum nem tömb. + A második behajtási argumentum nem tömb. - First argument to filter is not a function. - Az első szűrési argumentum nem függvény. + Az első szűrési argumentum nem függvény. - Second argument to filter is not an array. - A második szűrési argumentum nem tömb. + A második szűrési argumentum nem tömb. - Second argument to indexOf is not a string or array. - Az indexOf második argumentuma nem karakterlánc vagy tömb. + Az indexOf második argumentuma nem karakterlánc vagy tömb. - Second argument to join is not an array. - A második csatlakozási argumentum nem tömb. + A második csatlakozási argumentum nem tömb. - + EOF Kifejezés vége - + No object found with names %1. A(z) %1 nevű objektum nem található. - + No object found with name %1. A(z) %1 nevű objektum nem található. - + Object cannot be dependent on itself. Az objektum nem függhet önmagától. - + Circular dependency detected. Object %1 depends on %2. Körkörös függőség észlelve. A(z) %1-objektum a(z) %2-objektumtól függ. - + Circular dependency detected. Objects %1 depend on %2. Körkörös függőség észlelve. A(z) %1-objektumok a(z) %2-objektumtól függenek. @@ -1260,6 +1331,11 @@ Kiértékelt kifejezés: %3 Enable LaTeX rendering LaTeX-megjelenítés engedélyezése + + + Enable threaded LaTeX renderer (experimental) + + historylib @@ -1299,38 +1375,32 @@ Kiértékelt kifejezés: %3 Előzmények - Saved plot to '%1'. - Ábra mentve ide: „%1”. + Ábra mentve ide: „%1”. - Loading file '%1'. - A(z) „%1” fájl betöltése folyamatban van. + A(z) „%1” fájl betöltése folyamatban van. - Unknown object type: %1. - Ismeretlen objektumtípus: %1. + Ismeretlen objektumtípus: %1. - Invalid file provided. - A megadott fájl érvénytelen. + A megadott fájl érvénytelen. - Could not load file: - Nem sikerült betölteni a fájlt: + Nem sikerült betölteni a fájlt: Could not save file: A fájl mentése nem sikerült: - Loaded file '%1'. - A(z) „%1” fájl betöltve. + A(z) „%1” fájl betöltve. Copied plot screenshot to clipboard! @@ -1352,7 +1422,7 @@ Kiértékelt kifejezés: %3 latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. @@ -1361,12 +1431,12 @@ Ha már telepítve van egy LaTeX disztribúció, győződjön meg arról, hogy a Egyébként letölthet egy LaTeX disztribúciót, például a TeX Live-t a https://tug.org/texlive/ címről. - + DVIPNG was not found. Make sure you include it from your Latex distribution. DVIPNG nem található. Ügyeljen arra, hogy a LaTeX disztribúciójából tartalmazza. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1379,7 +1449,7 @@ A(z) „{}” folyamat nullától eltérő visszatérési kóddal ({}) végződ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelentse a hibát. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1392,7 +1462,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm Győződjön meg arról, hogy az említett csomag telepítve van, vagy tiltsa le a LaTeX megjelenítést a LogarithmPlotterben. - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1403,6 +1473,32 @@ A(z) „{}” folyamat túl sokáig tartott a befejezéshez: Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelentse a hibát. + + main + + + This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}. +Please update LogarithmPlotter to open this file. + + + + + Could not open file "{}": +{} + + + + + Could not open file: "{}" +File does not exist. + + + + + Built with PySide6 (Qt) v{} and python v{} + + + name @@ -1727,7 +1823,7 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents Szín - + labelContent Címketartalom @@ -1804,22 +1900,22 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents update - + An update for LogarithmPlotter (v{}) is available. Elérhető a Logaritmus-ábrázoló ({} verzió) frissítése. - + No update available. Nincs telepíthető frissítés. - + Could not fetch update information: Server error {}. Nem sikerült lekérni a frissítési adatokat: Kiszolgálóhiba: {}. - + Could not fetch update information: {}. Nem sikerült lekérni a frissítési adatokat: {}. diff --git a/assets/i18n/lp_nb_NO.ts b/assets/i18n/lp_nb_NO.ts index 79657f6..97799c6 100644 --- a/assets/i18n/lp_nb_NO.ts +++ b/assets/i18n/lp_nb_NO.ts @@ -42,47 +42,47 @@ &Last inn … - + &Save &Lagre - + Save &As... Lagre &som … - + &Quit &Avslutt - + &Edit &Rediger - + &Undo &Angre - + &Redo &Gjenta - + &Copy plot &Kopier plott - + &Preferences - + &Create &Opprett @@ -99,52 +99,52 @@ Tilbakestill angrehistorikk automatisk - + &Help &Hjelp - + &Source code - + &Report a bug &Rapporter en feil - + &User manual - + &Changelog &Endringslogg - + &Help translating! &Hjelp til å oversette! - + &Thanks &Erkjennelser - + &About &Om - + Save unsaved changes? Lagre ikke-lagrede endringer? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? Dette plottet inneholder ikke-lagrede endringer. Hvis du gjør dette, vil alle ikke-lagrede data gå tapt. Fortsette? @@ -164,6 +164,29 @@ Se etter nye versjoner ved programstart + + Browser + + + Filter... + + + + + Redo > + Angre > + + + + > Now + > Nå + + + + < Undo + < Angre + + Changelog @@ -194,22 +217,22 @@ Dialog - + Edit properties of %1 %2 Rediger egenskaper for %1 %2 - + LogarithmPlotter - Invalid object name LogarithmPlotter - Ugyldig objektnavn - + An object with the name '%1' already exists. Et objekt med navnet '%1' finnes allerede. - + Name Navn @@ -218,17 +241,17 @@ Etikett-innhold - + null NULL - + name navn - + name + value navn + veri @@ -380,20 +403,38 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. + + Loading + + + Loading... + + + + + Finished rendering of %1 + + + LogarithmPlotter - + + untitled + + + + Objects Objekter - + Settings Innstillinger - + History Historikk @@ -422,17 +463,17 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen.Lastet inn filen «%1». - + Copied plot screenshot to clipboard! Kopierte plott-skjermavbildning til utklippstavlen! - + &Update &Oppdater - + &Update LogarithmPlotter &Installer ny versjon av LogartimePlotter @@ -507,46 +548,53 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. - PickLocationOverlay + PickLocation - + Pointer precision: Peker-presisjon: + + + Snap to grid: + + + + + Pick X + + + + + Pick Y + + + + + Open picker settings + + + + + Hide picker settings + + + + + (no pick selected) + + + + + PickLocationOverlay + + Pointer precision: + Peker-presisjon: + Snap to grid Fest til rutenett - - - Snap to grid: - - - - - Pick X - - - - - Pick Y - - - - - Open picker settings - - - - - Hide picker settings - - - - - (no pick selected) - - Preferences @@ -654,17 +702,17 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. Save plot - Lagre plott + Lagre plott Save plot as - Lagre plott som + Lagre plott som Load plot - Last inn plott + Last inn plott @@ -717,22 +765,22 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. - + English - + French - + German - + Hungarian @@ -740,26 +788,32 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. + Github GitHub - + Norwegian - + Spanish - + + Tamil + + + + Translations included - + Improve @@ -823,12 +877,13 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. changelog - + Could not fetch changelog: Server error {}. - + + Could not fetch update: {}. @@ -929,27 +984,27 @@ Disse innstillingene kan endres når som helst fra «Innstillinger»-menyen. error - + No object found with names %1. - + No object found with name %1. - + Object cannot be dependent on itself. - + Circular dependency detected. Object %1 depends on %2. - + Circular dependency detected. Objects %1 depend on %2. @@ -971,39 +1026,39 @@ Undoing last change. - + Cannot find property %1 of object %2. - + Undefined variable %1. - + In order to be executed, object %1 must have at least one argument. - + %1 cannot be executed. - - - + + + Invalid expression. - + Invalid expression (parity). - + EOF @@ -1039,51 +1094,11 @@ Undoing last change. - - + + Function %1 must have at least one argument. - - - First argument to map is not a function. - - - - - Second argument to map is not an array. - - - - - First argument to fold is not a function. - - - - - Second argument to fold is not an array. - - - - - First argument to filter is not a function. - - - - - Second argument to filter is not an array. - - - - - Second argument to indexOf is not a string or array. - - - - - Second argument to join is not an array. - - Unknown character "%1". @@ -1187,6 +1202,11 @@ Evaluated expression: %3 Enable LaTeX rendering + + + Enable threaded LaTeX renderer (experimental) + + historylib @@ -1226,38 +1246,28 @@ Evaluated expression: %3 Historikk - Saved plot to '%1'. - Lagret plott i «%1». + Lagret plott i «%1». - Loading file '%1'. - Laster inn «%1»-fil. + Laster inn «%1»-fil. - Unknown object type: %1. - Ukjent objekttype: %1. + Ukjent objekttype: %1. - Invalid file provided. - Ugyldig fil angitt. - - - - Could not load file: - + Ugyldig fil angitt. Could not save file: Kunne ikke lagre fil: - Loaded file '%1'. - Lastet inn filen «%1». + Lastet inn filen «%1». Copied plot screenshot to clipboard! @@ -1275,19 +1285,19 @@ Evaluated expression: %3 latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. - + DVIPNG was not found. Make sure you include it from your Latex distribution. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1296,7 +1306,7 @@ Please make sure your latex installation is correct and report a bug if so. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1305,7 +1315,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1313,6 +1323,32 @@ Please make sure your latex installation is correct and report a bug if so. + + main + + + This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}. +Please update LogarithmPlotter to open this file. + + + + + Could not open file "{}": +{} + + + + + Could not open file: "{}" +File does not exist. + + + + + Built with PySide6 (Qt) v{} and python v{} + + + name @@ -1633,7 +1669,7 @@ Please make sure your latex installation is correct and report a bug if so. - + labelContent Etikett-innhold @@ -1710,22 +1746,22 @@ Please make sure your latex installation is correct and report a bug if so. update - + An update for LogarithmPlotter (v{}) is available. En ny versjon av LogartimePlotter (v{}) er tilgjengelig. - + No update available. Ingen nye versjoner. - + Could not fetch update information: Server error {}. Fant ikke ut om det er noen nye versjoner. Tjenerfeil {}. - + Could not fetch update information: {}. Kunne ikke hente info om hvorvidt det er nye versjoner: {}. diff --git a/assets/i18n/lp_ta.ts b/assets/i18n/lp_ta.ts index 780a6b9..89125eb 100644 --- a/assets/i18n/lp_ta.ts +++ b/assets/i18n/lp_ta.ts @@ -42,97 +42,97 @@ - + &Save - + Save &As... - + &Quit - + &Edit - + &Undo - + &Redo - + &Copy plot - + &Preferences - + &Create - + &Help - + &Source code - + &Report a bug - + &User manual - + &Changelog - + &Help translating! - + &Thanks - + &About - + Save unsaved changes? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? @@ -145,6 +145,29 @@ + + Browser + + + Filter... + + + + + Redo > + + + + + > Now + + + + + < Undo + + + Changelog @@ -175,37 +198,37 @@ Dialog - + Edit properties of %1 %2 - + LogarithmPlotter - Invalid object name - + An object with the name '%1' already exists. - + Name - + null - + name - + name + value @@ -297,35 +320,53 @@ + + Loading + + + Loading... + + + + + Finished rendering of %1 + + + LogarithmPlotter - + + untitled + + + + Objects - + Settings - + History - + Copied plot screenshot to clipboard! - + &Update - + &Update LogarithmPlotter @@ -380,39 +421,39 @@ - PickLocationOverlay + PickLocation - + Pointer precision: - + Snap to grid: - + Pick X - + Pick Y - + Open picker settings - + Hide picker settings - + (no pick selected) @@ -586,22 +627,22 @@ - + English - + French - + German - + Hungarian @@ -609,26 +650,32 @@ + Github - + Norwegian - + Spanish - + + Tamil + + + + Translations included - + Improve @@ -692,12 +739,13 @@ changelog - + Could not fetch changelog: Server error {}. - + + Could not fetch update: {}. @@ -798,27 +846,27 @@ error - + No object found with names %1. - + No object found with name %1. - + Object cannot be dependent on itself. - + Circular dependency detected. Object %1 depends on %2. - + Circular dependency detected. Objects %1 depend on %2. @@ -840,39 +888,39 @@ Undoing last change. - + Cannot find property %1 of object %2. - + Undefined variable %1. - + In order to be executed, object %1 must have at least one argument. - + %1 cannot be executed. - - - + + + Invalid expression. - + Invalid expression (parity). - + EOF @@ -908,51 +956,11 @@ Undoing last change. - - + + Function %1 must have at least one argument. - - - First argument to map is not a function. - - - - - Second argument to map is not an array. - - - - - First argument to fold is not a function. - - - - - Second argument to fold is not an array. - - - - - First argument to filter is not a function. - - - - - Second argument to filter is not an array. - - - - - Second argument to indexOf is not a string or array. - - - - - Second argument to join is not an array. - - Unknown character "%1". @@ -1037,56 +1045,28 @@ Evaluated expression: %3 Enable LaTeX rendering - - - io - - Saved plot to '%1'. - - - - - Loading file '%1'. - - - - - Unknown object type: %1. - - - - - Invalid file provided. - - - - - Could not load file: - - - - - Loaded file '%1'. + + Enable threaded LaTeX renderer (experimental) latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. - + DVIPNG was not found. Make sure you include it from your Latex distribution. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1095,7 +1075,7 @@ Please make sure your latex installation is correct and report a bug if so. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1104,7 +1084,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1112,6 +1092,32 @@ Please make sure your latex installation is correct and report a bug if so. + + main + + + This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}. +Please update LogarithmPlotter to open this file. + + + + + Could not open file "{}": +{} + + + + + Could not open file: "{}" +File does not exist. + + + + + Built with PySide6 (Qt) v{} and python v{} + + + name @@ -1421,7 +1427,7 @@ Please make sure your latex installation is correct and report a bug if so. - + labelContent @@ -1473,22 +1479,22 @@ Please make sure your latex installation is correct and report a bug if so. update - + An update for LogarithmPlotter (v{}) is available. - + No update available. - + Could not fetch update information: Server error {}. - + Could not fetch update information: {}. diff --git a/assets/i18n/lp_template.ts b/assets/i18n/lp_template.ts index 81221dd..7f1bc28 100644 --- a/assets/i18n/lp_template.ts +++ b/assets/i18n/lp_template.ts @@ -42,97 +42,97 @@ - + &Save - + Save &As... - + &Quit - + &Edit - + &Undo - + &Redo - + &Copy plot - + &Preferences - + &Create - + &Help - + &Source code - + &Report a bug - + &User manual - + &Changelog - + &Help translating! - + &Thanks - + &About - + Save unsaved changes? - + This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? @@ -145,6 +145,29 @@ + + Browser + + + Filter... + + + + + Redo > + + + + + > Now + + + + + < Undo + + + Changelog @@ -175,37 +198,37 @@ Dialog - + Edit properties of %1 %2 - + LogarithmPlotter - Invalid object name - + An object with the name '%1' already exists. - + Name - + null - + name - + name + value @@ -297,35 +320,53 @@ + + Loading + + + Loading... + + + + + Finished rendering of %1 + + + LogarithmPlotter - + + untitled + + + + Objects - + Settings - + History - + Copied plot screenshot to clipboard! - + &Update - + &Update LogarithmPlotter @@ -380,41 +421,41 @@ - PickLocationOverlay + PickLocation - + Pointer precision: - + - + Snap to grid: - + - + Pick X - + - + Pick Y - + - + Open picker settings - + - + Hide picker settings - + - + (no pick selected) - + @@ -586,22 +627,22 @@ - + English - + French - + German - + Hungarian @@ -609,26 +650,32 @@ + Github - + Norwegian - + Spanish - + + Tamil + + + + Translations included - + Improve @@ -692,12 +739,13 @@ changelog - + Could not fetch changelog: Server error {}. - + + Could not fetch update: {}. @@ -798,27 +846,27 @@ error - + No object found with names %1. - + No object found with name %1. - + Object cannot be dependent on itself. - + Circular dependency detected. Object %1 depends on %2. - + Circular dependency detected. Objects %1 depend on %2. @@ -840,39 +888,39 @@ Undoing last change. - + Cannot find property %1 of object %2. - + Undefined variable %1. - + In order to be executed, object %1 must have at least one argument. - + %1 cannot be executed. - - - + + + Invalid expression. - + Invalid expression (parity). - + EOF @@ -908,51 +956,11 @@ Undoing last change. - - + + Function %1 must have at least one argument. - - - First argument to map is not a function. - - - - - Second argument to map is not an array. - - - - - First argument to fold is not a function. - - - - - Second argument to fold is not an array. - - - - - First argument to filter is not a function. - - - - - Second argument to filter is not an array. - - - - - Second argument to indexOf is not a string or array. - - - - - Second argument to join is not an array. - - Unknown character "%1". @@ -1037,56 +1045,28 @@ Evaluated expression: %3 Enable LaTeX rendering - - - io - - Saved plot to '%1'. - - - - - Loading file '%1'. - - - - - Unknown object type: %1. - - - - - Invalid file provided. - - - - - Could not load file: - - - - - Loaded file '%1'. + + Enable threaded LaTeX renderer (experimental) latex - + No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. - + DVIPNG was not found. Make sure you include it from your Latex distribution. - + An exception occured within the creation of the latex formula. Process '{}' ended with a non-zero return code {}: @@ -1095,7 +1075,7 @@ Please make sure your latex installation is correct and report a bug if so. - + Your LaTeX installation does not include some required packages: - {} (https://ctan.org/pkg/{}) @@ -1104,7 +1084,7 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm - + An exception occured within the creation of the latex formula. Process '{}' took too long to finish: {} @@ -1112,6 +1092,32 @@ Please make sure your latex installation is correct and report a bug if so. + + main + + + This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}. +Please update LogarithmPlotter to open this file. + + + + + Could not open file "{}": +{} + + + + + Could not open file: "{}" +File does not exist. + + + + + Built with PySide6 (Qt) v{} and python v{} + + + name @@ -1421,7 +1427,7 @@ Please make sure your latex installation is correct and report a bug if so. - + labelContent @@ -1473,22 +1479,22 @@ Please make sure your latex installation is correct and report a bug if so. update - + An update for LogarithmPlotter (v{}) is available. - + No update available. - + Could not fetch update information: Server error {}. - + Could not fetch update information: {}. diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/ThanksTo.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/ThanksTo.qml index 107eac5..c2001a2 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/ThanksTo.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/ThanksTo.qml @@ -232,6 +232,11 @@ BaseDialog { authorLine: 'gallegonovato', website: '', websiteName: '' + }, + TamilNeram: { + authorLine: 'தமிழ் நேரம்', + website: 'https://github.com/TamilNeram', + websiteName: qsTr('Github') } } @@ -265,6 +270,11 @@ BaseDialog { link: 'https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/', authors: [authors.IngrownMink4, authors.gallegonovato] }) + append({ + tranName: '🇱🇰 ' + qsTr('Tamil'), + link: 'https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/ta/', + authors: [authors.TamilNeram] + }) } } From b673038b1592d946fda7189e8374e131442e5a6f Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sun, 12 Jan 2025 16:44:21 +0000 Subject: [PATCH 088/104] Translated using Weblate (English) Currently translated at 100.0% (264 of 264 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/ --- assets/i18n/lp_en.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/assets/i18n/lp_en.ts b/assets/i18n/lp_en.ts index 0f9b887..68590af 100644 --- a/assets/i18n/lp_en.ts +++ b/assets/i18n/lp_en.ts @@ -456,12 +456,12 @@ These settings can be changed at any time from the "Settings" menu. Loading... - + Loading… Finished rendering of %1 - + Finished rendering of %1 @@ -469,7 +469,7 @@ These settings can be changed at any time from the "Settings" menu. untitled - + untitled @@ -881,7 +881,7 @@ These settings can be changed at any time from the "Settings" menu. Tamil - + Tamil @@ -1334,7 +1334,7 @@ Evaluated expression: %3 Enable threaded LaTeX renderer (experimental) - + Enable threaded LaTeX renderer (experimental) @@ -1479,24 +1479,27 @@ Please make sure your LaTeX installation is correct and report a bug if so. This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}. Please update LogarithmPlotter to open this file. - + This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}. +Please update LogarithmPlotter to open this file. Could not open file "{}": {} - + Could not open file "{}": +{} Could not open file: "{}" File does not exist. - + Could not open file: "{}" +File does not exist. Built with PySide6 (Qt) v{} and python v{} - + Built with PySide6 (Qt) v{} and python v{} From 6101c0c6451d308d214873013e59afbd9c511f7f Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sun, 12 Jan 2025 17:07:29 +0000 Subject: [PATCH 089/104] Translated using Weblate (German) Currently translated at 100.0% (264 of 264 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/ --- assets/i18n/lp_de.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/assets/i18n/lp_de.ts b/assets/i18n/lp_de.ts index 56a80ff..9ed0e8c 100644 --- a/assets/i18n/lp_de.ts +++ b/assets/i18n/lp_de.ts @@ -456,12 +456,12 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" Loading... - + Laden… Finished rendering of %1 - + Beendetes Rendering von %1 @@ -469,7 +469,7 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" untitled - + unbetitelt @@ -881,7 +881,7 @@ Diese Einstellungen können jederzeit über das Menü "Einstellungen" Tamil - + Tamil @@ -1334,7 +1334,7 @@ Ausdruck analysiert: %3 Enable threaded LaTeX renderer (experimental) - + LaTeX-Renderer mit Threads aktivieren (experimentell) @@ -1479,24 +1479,27 @@ Bitte vergewissern Sie sich, dass Ihre LaTeX-Installation korrekt ist, und melde This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}. Please update LogarithmPlotter to open this file. - + Diese Datei wurde mit einer neueren Version von LogarithmPlotter erstellt und kann nicht in LogarithmPlotter v{} zurückgeladen werden. +Bitte aktualisieren Sie LogarithmPlotter, um diese Datei zu öffnen. Could not open file "{}": {} - + Die Datei „{}“ konnte nicht geöffnet werden: +{} Could not open file: "{}" File does not exist. - + Die Datei „{}“ konnte nicht geöffnet werden: +Die Datei existiert nicht. Built with PySide6 (Qt) v{} and python v{} - + Kompiliert mit PySide6 (Qt) v{} und python v{} From 54f82eab92723aa41ba5db76b77fc4a6b8cab4b4 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sun, 12 Jan 2025 16:58:58 +0000 Subject: [PATCH 090/104] Translated using Weblate (French) Currently translated at 100.0% (264 of 264 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/ --- assets/i18n/lp_fr.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/assets/i18n/lp_fr.ts b/assets/i18n/lp_fr.ts index 93fd60e..d2e6380 100644 --- a/assets/i18n/lp_fr.ts +++ b/assets/i18n/lp_fr.ts @@ -458,12 +458,12 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Loading... - + Chargement… Finished rendering of %1 - + Rendu de %1 terminé @@ -471,7 +471,7 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P untitled - + sans titre @@ -883,7 +883,7 @@ Ces paramètres peuvent être modifiés à tout moment à partir du menu "P Tamil - + Tamoul @@ -1337,7 +1337,7 @@ Formule analysée : %3 Enable threaded LaTeX renderer (experimental) - + Activer le moteur de rendu LaTeX asynchrone (expérimental) @@ -1482,24 +1482,27 @@ Vérifiez que votre installation de LaTeX est correcte et signalez un bogue si c This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}. Please update LogarithmPlotter to open this file. - + Ce fichier a été créé par une version plus récente de LogarithmPlotter et ne peut pas être rechargé dans LogarithmPlotter v{}. +Veuillez mettre à jour LogarithmPlotter pour ouvrir ce fichier. Could not open file "{}": {} - + Impossible d'ouvrir le fichier "{}": +{} Could not open file: "{}" File does not exist. - + Impossible d'ouvrir le fichier "{}": +Le fichier n'existe pas. Built with PySide6 (Qt) v{} and python v{} - + Compilé avec PySide6 (Qt) v{} et python v{} From 2c8011056de43b28b8be01274dcbff8efd120fa2 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sun, 12 Jan 2025 18:08:44 +0100 Subject: [PATCH 091/104] Fixing not recreating canvas context if it already exists. --- common/src/module/canvas.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/src/module/canvas.mjs b/common/src/module/canvas.mjs index dcc3f33..22166d5 100644 --- a/common/src/module/canvas.mjs +++ b/common/src/module/canvas.mjs @@ -212,8 +212,9 @@ class CanvasAPI extends Module { */ redraw() { if(!this.initialized) throw new Error("Attempting redraw before initialize!") + if(this.#ctx == null) + this.#ctx = this.#canvas.getContext("2d") this.#redrawCount = (this.#redrawCount + 1) % 10000 - this.#ctx = this.#canvas.getContext("2d") this._computeAxes() this._reset() this._drawGrid() From 5fa118233c1db0e000dca68a3778c0c61ef9eab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=AE=A4=E0=AE=AE=E0=AE=BF=E0=AE=B4=E0=AF=8D=E0=AE=A8?= =?UTF-8?q?=E0=AF=87=E0=AE=B0=E0=AE=AE=E0=AF=8D?= Date: Mon, 13 Jan 2025 00:23:27 +0000 Subject: [PATCH 092/104] Translated using Weblate (Tamil) Currently translated at 99.6% (263 of 264 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/ta/ --- assets/i18n/lp_ta.ts | 556 +++++++++++++++++++++++-------------------- 1 file changed, 292 insertions(+), 264 deletions(-) diff --git a/assets/i18n/lp_ta.ts b/assets/i18n/lp_ta.ts index 89125eb..2f3048c 100644 --- a/assets/i18n/lp_ta.ts +++ b/assets/i18n/lp_ta.ts @@ -6,27 +6,27 @@ About LogarithmPlotter - + மடக்கை பற்றி LogarithmPlotter v%1 - + மடக்கை சதித்திட்டம் வி 1 2D plotter software to make BODE plots, sequences and repartition functions. - + போட் அடுக்கு, காட்சிகள் மற்றும் விநியோக செயல்பாடுகளை உருவாக்க 2 டி ப்ளாட்டர் மென்பொருள். Report a bug - + ஒரு பிழையைப் புகாரளிக்கவும் Official website - + அதிகாரப்பூர்வ வலைத்தளம் @@ -34,107 +34,107 @@ &File - + கோப்பு (&f) &Load... - + & திறந்த… &Save - + சேமி (&s) Save &As... - + சேமிக்கவும்… &Quit - + &வெளியேறு &Edit - + திருத்து (&e) &Undo - + செயல்தவிர் (&u) &Redo - + மீண்டும்செய் (&r) &Copy plot - + & சூழ்ச்சி நகலெடுக்கவும் &Preferences - + &விருப்பத்தேர்வுகள் &Create - + & உருவாக்கு &Help - + உதவி (&h) &Source code - + & மூலக் குறியீடு &Report a bug - + ஒரு பிழையைப் புகாரளிக்கவும் &User manual - + & பயனர் கையேடு &Changelog - + & சேஞ்ச்லாக் &Help translating! - + & மொழிபெயர்க்க உதவுங்கள்! &Thanks - + & நன்றி &About - + &பற்றி Save unsaved changes? - + சேமிக்கப்படாத மாற்றங்களைச் சேமிக்கவா? This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue? - + இந்த சதித்திட்டத்தில் சேமிக்கப்படாத மாற்றங்கள் உள்ளன. இதைச் செய்வதன் மூலம், சேமிக்கப்படாத அனைத்து தரவும் இழக்கப்படும். தொடரவா? @@ -142,7 +142,7 @@ Close - + மூடு @@ -150,22 +150,22 @@ Filter... - + வடிகட்டி… Redo > - + மீண்டும்> > Now - + > இப்போது < Undo - + <செயல்தவிர்க்கவும் @@ -173,12 +173,12 @@ Fetching changelog... - + சேஞ்ச்லாக் பெறுதல்… Close - + மூடு @@ -187,12 +187,12 @@ + Create new %1 - + + புதிய %1 ஐ உருவாக்கவும் Pick on graph - + வரைபடத்தைத் தேர்ந்தெடுங்கள் @@ -200,37 +200,37 @@ Edit properties of %1 %2 - + %1 %2 இன் பண்புகளைத் திருத்தவும் LogarithmPlotter - Invalid object name - + மடக்கை - தவறான பொருள் பெயர் An object with the name '%1' already exists. - + '%1' என்ற பெயரைக் கொண்ட ஒரு பொருள் ஏற்கனவே உள்ளது. Name - + பெயர் null - + சுழியம் name - + பெயர் name + value - + பெயர் + மதிப்பு @@ -238,32 +238,32 @@ Object Properties - + பொருள் பண்புகள் Variables - + மாறிகள் Constants - + மாறிலிகள் Functions - + செயல்பாடுகள் Executable Objects - + செயல்பாடு பொருள்கள் Objects - + பொருள்கள் @@ -271,12 +271,12 @@ Export Logarithm Plot file - + மடக்கை சூழ்ச்சி கோப்பை ஏற்றுமதி செய்யுங்கள் Import Logarithm Plot file - + மடக்கை சூழ்ச்சி கோப்பை இறக்குமதி செய்க @@ -284,32 +284,32 @@ Welcome to LogarithmPlotter - + மடக்கை பிளாட்டருக்கு வருக Version %1 - + பதிப்பு %1 User manual - + பயனர் கையேடு Changelog - + மாற்றபதிவு Preferences - + விருப்பத்தேர்வுகள் Close - + மூடு @@ -317,7 +317,7 @@ + Add Entry - + + உள்ளீட்டைச் சேர்க்கவும் @@ -325,12 +325,12 @@ Loading... - + ஏற்றுகிறது… Finished rendering of %1 - + %1 இன் வழங்குதல் முடிந்தது @@ -338,37 +338,37 @@ untitled - + தலைப்பிடப்படாத Objects - + பொருள்கள் Settings - + அமைப்புகள் History - + வரலாறு Copied plot screenshot to clipboard! - + இடைநிலைப்பலகைக்கு சூழ்ச்சி திரை சாட்டை நகலெடுத்தது! &Update - + & புதுப்பிக்கவும் &Update LogarithmPlotter - + & மடக்கை புதுப்பிக்கவும் @@ -376,7 +376,7 @@ + Create new: - + + புதியதை உருவாக்கு: @@ -384,12 +384,12 @@ Hide all %1 - + அனைத்து %1 ஐ மறைக்கவும் Show all %1 - + அனைத்து %1 ஐக் காட்டு @@ -397,27 +397,27 @@ Hide %1 %2 - + %1 %2 ஐ மறைக்கவும் Show %1 %2 - + %1 %2 ஐக் காட்டு Set %1 %2 position - + %1 %2 நிலையை அமைக்கவும் Delete %1 %2 - + %1 %2 ஐ நீக்கு Pick new color for %1 %2 - + %1 %2 க்கு புதிய வண்ணத்தைத் தேர்ந்தெடுங்கள் @@ -425,37 +425,37 @@ Pointer precision: - + சுட்டிக்காட்டி துல்லியம்: Snap to grid: - + கட்டம் வரை: Pick X - + ஃச் பிக் Pick Y - + ஒய் ஐ தேர்வு செய்யுங்கள் Open picker settings - + திறந்த பிக்கர் அமைப்புகள் Hide picker settings - + பிக்கர் அமைப்புகளை மறைக்கவும் (no pick selected) - + (தேர்ந்தெடுக்கப்பட்ட தேர்வு இல்லை) @@ -463,7 +463,7 @@ Close - + மூடு @@ -472,109 +472,109 @@ X Zoom - + ஃச் சூம் Y Zoom - + மற்றும் பெரிதாக்கு Min X - + என் ஃச் Max Y - + அதிகபட்சம் மற்றும் Max X - + அதிகபட்ச ஃச் Min Y - + Min ஒய் X Axis Step - + ஃச் அச்சு படி Y Axis Step - + ஒய் அச்சு படி Line width - + வரி அகலம் Text size (px) - + உரை அளவு (பிஎக்ச்) X Label - + ஃச் சிட்டை Y Label - + ஒய் சிட்டை X Log scale - + ஃச் பதிவு அளவுகோல் Show X graduation - + ஃச் பட்டப்படிப்பைக் காட்டு Show Y graduation - + ஒய் பட்டப்படிப்பைக் காட்டு Copy to clipboard - + இடைநிலைப்பலகைக்கு நகலெடுக்கவும் Save plot - + சதித்திட்டத்தை சேமிக்கவும்… Save plot as - + சூழ்ச்சி சேமிக்கவும்… Load plot - + திறந்த சதி… @@ -582,69 +582,69 @@ Thanks and Contributions - LogarithmPlotter - + நன்றி மற்றும் பங்களிப்புகள் - மடக்கை Source code - + மூலக் குறியீடு Original library by Raphael Graf - + ரபேல் கிராஃப் எழுதிய அசல் நூலகம் Source - + மூலம் Ported to Javascript by Matthew Crumley - + மத்தேயு க்ரம்லி எழுதிய சாவாச்கிரிப்டுக்கு அனுப்பப்பட்டது Website - + வலைத்தளம் Ported to QMLJS by Ad5001 - + AD5001 ஆல் QMLJS க்கு அனுப்பப்பட்டது Libraries included - + நூலகங்கள் சேர்க்கப்பட்டுள்ளன Email - + மின்னஞ்சல் English - + ஆங்கிலம் French - + பிரஞ்சு German - + செர்மன் Hungarian - + அங்கேரியன் @@ -652,32 +652,32 @@ Github - + கிரப் Norwegian - + நோர்வே Spanish - + ச்பானிச் Tamil - + தமிழ் Translations included - + மொழிபெயர்ப்புகள் சேர்க்கப்பட்டுள்ளன Improve - + மேம்படுத்தவும் @@ -685,24 +685,24 @@ Bode Magnitude - + போட் அளவு Bode Magnitudes - + போட் அளவுகள் low-pass - + குறைந்த பாச் high-pass - + உயர்-பாச் @@ -711,7 +711,7 @@ Bode Magnitudes Sum - + போட் அளவு தொகை @@ -719,12 +719,12 @@ Bode Phase - + போட் கட்டம் Bode Phases - + போட் கட்டங்கள் @@ -733,7 +733,7 @@ Bode Phases Sum - + போட் கட்டங்கள் தொகை @@ -741,13 +741,13 @@ Could not fetch changelog: Server error {}. - + சேஞ்ச்லாக் பெற முடியவில்லை: சேவையக பிழை {}. Could not fetch update: {}. - + சேஞ்ச்லாக் பெற முடியவில்லை: {}. @@ -756,7 +756,7 @@ %1 %2's color changed from %3 to %4. - + %1 %2 இன் நிறம் %3 முதல் %4 வரை மாற்றப்பட்டது. @@ -764,27 +764,27 @@ Ex: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ⁻*), ]0;1[, {3;4;5} - + Ex: r+* (ℝ⁺*), n (ℕ), z-* (ℤ⁻*),] 0; 1 [, {3; 4; 5} The following parameters are used when the definition domain is a non-continuous set. (Ex: ℕ, ℤ, sets like {0;3}...) - + டொமைன் ஒரு தொடர்ச்சியான தொகுப்பாக இருக்கும்போது பின்வரும் அளவுருக்கள் பயன்படுத்தப்படுகின்றன. (எ.கா: ℕ, ℤ, {0; 3}…) Note: Specify the probability for each value. - + குறிப்பு: ஒவ்வொரு மதிப்புக்கும் நிகழ்தகவைக் குறிப்பிடவும். Note: Use %1[n] to refer to %1ₙ, %1[n+1] for %1ₙ₊₁... - + குறிப்பு: %1ₙ, %1 [n+1] ஐ %1ₙ₊₁ க்கு குறிக்க %1 [n] ஐப் பயன்படுத்தவும்… If you have latex enabled, you can use use latex markup in between $$ to create equations. - + நீங்கள் லேடெக்ச் இயக்கப்பட்டிருந்தால், சமன்பாடுகளை உருவாக்க லேடெக்ச் மார்க்அப்பைப் பயன்படுத்தலாம். @@ -796,7 +796,7 @@ %1: - + %1: @@ -805,7 +805,7 @@ New %1 %2 created. - + புதிய %1 %2 உருவாக்கப்பட்டது. @@ -814,7 +814,7 @@ %1 %2 deleted. - + %1 %2 நீக்கப்பட்டது. @@ -822,12 +822,12 @@ Repartition - + பரவல் Repartition functions - + விநியோக செயல்பாடுகள் @@ -835,12 +835,12 @@ %1 of %2 %3 changed from "%4" to "%5". - + %2 %3 இல் %1 " %4" இலிருந்து " %5" ஆக மாற்றப்பட்டது. %1 of %2 changed from %3 to %4. - + %2 இல் %1 %3 முதல் %4 வரை மாற்றப்பட்டது. @@ -848,27 +848,27 @@ No object found with names %1. - + %1 பெயர்களைக் கொண்ட எந்த பொருளும் காணப்படவில்லை. No object found with name %1. - + %1 என்ற பெயருடன் எந்த பொருளும் காணப்படவில்லை. Object cannot be dependent on itself. - + பொருள் தன்னைச் சார்ந்து இருக்க முடியாது. Circular dependency detected. Object %1 depends on %2. - + வட்ட சார்பு கண்டறியப்பட்டது. பொருள் %1 %2 ஐப் பொறுத்தது. Circular dependency detected. Objects %1 depend on %2. - + வட்ட சார்பு கண்டறியப்பட்டது. பொருள்கள் %1 %2 ஐ சார்ந்துள்ளது. @@ -876,7 +876,10 @@ %2 Evaluated expression: %3 - + சொத்து %1 க்கான வெளிப்பாட்டை பாகுபடுத்தும்போது பிழை: + %2 + + மதிப்பீடு செய்யப்பட்ட வெளிப்பாடு: %3 @@ -884,93 +887,96 @@ Evaluated expression: %3 %3 Undoing last change. - + %1 %2 ஐ வரைய முயற்சிக்கும் போது பிழை: + %3 + + கடைசி மாற்றத்தை செயல்தவிர்க்கவும். Cannot find property %1 of object %2. - + பொருள் %2 இன் சொத்து %1 ஐக் கண்டுபிடிக்க முடியாது. Undefined variable %1. - + வரையறுக்கப்படாத மாறி %1. In order to be executed, object %1 must have at least one argument. - + செயல்படுத்தப்படுவதற்கு, பொருள் %1 க்கு குறைந்தது ஒரு உரையாடல் இருக்க வேண்டும். %1 cannot be executed. - + %1 ஒரு செயல்பாடு அல்ல. Invalid expression. - + தவறான வெளிப்பாடு. Invalid expression (parity). - + தவறான வெளிப்பாடு (சமநிலை). EOF - + வெளிப்பாட்டின் முடிவு Parse error [position %1]: %2 - + பாகுபடுத்தும் பிழை [நிலை %1]: %2 Expected %1 - + எதிர்பார்க்கப்படும் %1 Unexpected %1 - + எதிர்பாராத %1 Unexpected ".": member access is not permitted - + எதிர்பாராதது ".": உறுப்பினர் அணுகல் அனுமதிக்கப்படவில்லை Unexpected "[]": arrays are disabled. - + எதிர்பாராத "[]": வரிசைகள் முடக்கப்பட்டுள்ளன. Unexpected symbol: %1. - + எதிர்பாராத சின்னம்: %1. Function %1 must have at least one argument. - + செயல்பாடு %1 க்கு குறைந்தது ஒரு உரையாடல் இருக்க வேண்டும். Unknown character "%1". - + அறியப்படாத எழுத்து "%1". Illegal escape sequence: %1. - + சட்டவிரோத தப்பிக்கும் வரிசை: %1. @@ -979,7 +985,7 @@ Undoing last change. LogarithmPlotter - Parsing error - + மடக்கை பிளாட்டர் - பாகுபடுத்தும் பிழை @@ -987,32 +993,35 @@ Undoing last change. %2 Evaluated expression: %3 - + சொத்து %1 க்கான வெளிப்பாட்டை பாகுபடுத்தும்போது பிழை: + %2 + + மதிப்பீடு செய்யப்பட்ட வெளிப்பாடு: %3 LogarithmPlotter - Drawing error - + மடக்கை - வரைதல் பிழை Automatically close parenthesises and brackets - + தானாகவே அடைப்புக்குறிப்புகள் மற்றும் அடைப்புக்குறிகளை மூடு Enable syntax highlighting - + தொடரியல் சிறப்பம்சத்தை இயக்கவும் Enable autocompletion - + தன்னியக்கவியல் இயக்கவும் Color Scheme - + வண்ணத் திட்டம் @@ -1020,12 +1029,12 @@ Evaluated expression: %3 Function - + சார்பு Functions - + செயல்பாடுகள் @@ -1033,22 +1042,22 @@ Evaluated expression: %3 Check for updates on startup - + தொடக்கத்தின் புதுப்பிப்புகளைச் சரிபார்க்கவும் Reset redo stack automaticly - + மீண்டும் அடுக்கை மீட்டமைக்கவும் Enable LaTeX rendering - + லேடெக்ச் வழங்குதல் இயக்கவும் Enable threaded LaTeX renderer (experimental) - + திரிக்கப்பட்ட லேடெக்ச் ரெண்டரரை இயக்கவும் (சோதனை) @@ -1058,12 +1067,14 @@ Evaluated expression: %3 No Latex installation found. If you already have a latex distribution installed, make sure it's installed on your path. Otherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/. - + லேடெக்ச் நிறுவல் எதுவும் கிடைக்கவில்லை. + உங்களிடம் ஏற்கனவே லேடெக்ச் வழங்கல் நிறுவப்பட்டிருந்தால், அது உங்கள் பாதையில் நிறுவப்பட்டுள்ளதா என்பதை உறுதிப்படுத்திக் கொள்ளுங்கள். + இல்லையெனில், டெக்ச் லைவ் போன்ற லேடெக்ச் விநியோகத்தை https://tug.org/texlive/ இல் பதிவிறக்கம் செய்யலாம். DVIPNG was not found. Make sure you include it from your Latex distribution. - + Dvipng கண்டுபிடிக்கப்படவில்லை. உங்கள் லேடெக்ச் விநியோகத்திலிருந்து இதைச் சேர்த்துள்ளீர்கள் என்பதை உறுதிப்படுத்திக் கொள்ளுங்கள். @@ -1072,7 +1083,11 @@ Process '{}' ended with a non-zero return code {}: {} Please make sure your latex installation is correct and report a bug if so. - + லேடெக்ச் சூத்திரத்தை உருவாக்குவதற்குள் விதிவிலக்கு ஏற்பட்டது. + '{}' ஐ பூச்சியமற்ற வருவாய் குறியீட்டோடு முடிந்தது {}: + + {} + உங்கள் லேடெக்ச் நிறுவல் சரியானது என்பதை உறுதிப்படுத்தவும், அப்படியானால் ஒரு பிழையைப் புகாரளிக்கவும். @@ -1081,7 +1096,11 @@ Please make sure your latex installation is correct and report a bug if so. - + உங்கள் லேடெக்ச் நிறுவலில் தேவையான சில தொகுப்புகள் இல்லை: + + - {} (https://ctan.org/pkg/ {}) + + தொகுப்பு நிறுவப்பட்டிருப்பதை உறுதிசெய்து கொள்ளுங்கள், அல்லது லோகரிதம்லட்டரில் லேடெக்ச் வழங்குதல் முடக்கவும். @@ -1089,7 +1108,10 @@ Make sure said package is installed, or disable the LaTeX rendering in Logarithm Process '{}' took too long to finish: {} Please make sure your latex installation is correct and report a bug if so. - + லேடெக்ச் சூத்திரத்தை உருவாக்குவதற்குள் விதிவிலக்கு ஏற்பட்டது. + '{}' செயல்முறை முடிக்க அதிக நேரம் எடுத்தது: + {} + உங்கள் லேடெக்ச் நிறுவல் சரியானது என்பதை உறுதிப்படுத்தவும், அப்படியானால் ஒரு பிழையைப் புகாரளிக்கவும். @@ -1098,24 +1120,27 @@ Please make sure your latex installation is correct and report a bug if so. This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}. Please update LogarithmPlotter to open this file. - + இந்த கோப்பு மடக்கை படத்தின் மிக அண்மைக் கால பதிப்பால் உருவாக்கப்பட்டது, மேலும் லோகரிதம் பிளாட்டர் v {fol இல் பின்வாங்க முடியாது. + இந்த கோப்பைத் திறக்க லோகரிதில் பிளாட்டரைப் புதுப்பிக்கவும். Could not open file "{}": {} - + "{}" கோப்பைத் திறக்க முடியவில்லை: + {} Could not open file: "{}" File does not exist. - + கோப்பைத் திறக்க முடியவில்லை: "{}" + கோப்பு இல்லை. Built with PySide6 (Qt) v{} and python v{} - + Pyside6 (qt) V {} மற்றும் பைதான் V {with உடன் கட்டப்பட்டுள்ளது @@ -1124,7 +1149,7 @@ File does not exist. %1 %2 renamed to %3. - + %1 %2 %3 என மறுபெயரிடப்பட்டது. @@ -1132,114 +1157,114 @@ File does not exist. above - + மேலே below - + கீழே left - + . இடது right - + சரி above-left - + இடதுபுறம் மேலே above-right - + ↗ மேலே வலதுபுறம் below-left - + இடதுபுறமாக கீழே below-right - + ↘ கீழே வலது கீழே center - + > | <மையம் top - + . மேல் bottom - + கீழே top-left - + ↖ மேல் இடது top-right - + ↗ மேல் வலது bottom-left - + ↙ கீழ் இடது bottom-right - + வலது வலது application - + பயன்பாடு function - + சார்பு high - + உயர்ந்த low - + குறைந்த Next to target - + இலக்கு அடுத்து With label - + லேபிளுடன் Hidden - + மறைக்கப்பட்ட @@ -1247,12 +1272,12 @@ File does not exist. Point - + புள்ளியம் Points - + பிரிவகம் @@ -1260,12 +1285,12 @@ File does not exist. Position of %1 %2 set from "%3" to "%4". - + %1%2 "%3" இலிருந்து "%4" க்கு நகர்ந்தது. Position of %1 set from %2 to %3. - + %1 %2 முதல் %3 வரை நகர்ந்தது. @@ -1273,22 +1298,22 @@ File does not exist. expression - + கோவை definitionDomain - + டொமைன் destinationDomain - + வீச்சு displayMode - + காட்சி முறை @@ -1302,7 +1327,7 @@ File does not exist. labelPosition - + சிட்டை நிலை @@ -1313,123 +1338,123 @@ File does not exist. labelX - + லேபிளின் ஃச் நிலை drawPoints - + புள்ளிகளைக் காட்டு drawDashedLines - + கோடு கோடுகளைக் காட்டு om_0 - + pass - + கணவாய் gain - + அளவு ஆதாயம் omGraduation - + Ω₀ இல் பட்டப்படிப்பைக் காட்டு phase - + கட்டம் unit - + பயன்படுத்த அலகு x - + ஃச் y - + ஒய் pointStyle - + புள்ளி நடை probabilities - + நிகழ்தகவுகள் பட்டியல் defaultExpression - + இயல்புநிலை வெளிப்பாடு baseValues - + துவக்க மதிப்புகள் text - + உள்ளடக்கம் disableLatex - + இந்த உரைக்கு லேடெக்ச் வழங்குதல் முடக்கு targetElement - + இலக்கை எதிர்க்கவும் approximate - + வட்டமான கணக்கிடப்பட்ட மதிப்பைக் காட்டு rounding - + சுற்று displayStyle - + காட்சி நடை targetValuePosition - + இலக்கின் மதிப்பு நிலை labelContent - + சிட்டை உள்ளடக்கம் @@ -1437,12 +1462,12 @@ File does not exist. Sequence - + வரிசை Sequences - + வரிசைகள் @@ -1450,17 +1475,17 @@ File does not exist. general - + பொது editor - + வெளிப்பாடு ஆசிரியர் default - + இயல்புநிலை அமைப்புகள் @@ -1468,12 +1493,12 @@ File does not exist. Text - + உரை Texts - + நூல்கள் @@ -1481,22 +1506,22 @@ File does not exist. An update for LogarithmPlotter (v{}) is available. - + மடக்கை (v {}) க்கான புதுப்பிப்பு கிடைக்கிறது. No update available. - + புதுப்பிப்பு எதுவும் கிடைக்கவில்லை. Could not fetch update information: Server error {}. - + புதுப்பிப்பு தகவலைப் பெற முடியவில்லை: சேவையக பிழை {}. Could not fetch update information: {}. - + புதுப்பிப்பு தகவல்களைப் பெற முடியவில்லை: {}. @@ -1504,14 +1529,15 @@ File does not exist. integral(<from: number>, <to: number>, <f: ExecutableObject>) - + ஒருங்கிணைந்த (<இலிருந்து: எண்>, <க்கு: எண்>, <f: செயல்பாடு போன்ற பொருள்>) Usage: %1 - + பயன்பாடு: + %1 @@ -1520,22 +1546,24 @@ File does not exist. Usage: %1 %2 - + பயன்பாடு: + %1 + %2 integral(<from: number>, <to: number>, <f: string>, <variable: string>) - + ஒருங்கிணைந்த (<இலிருந்து: எண்>, <க்கு: எண்>, <f: சரம்>, <மாறி: சரம்>) derivative(<f: ExecutableObject>, <x: number>) - + வழித்தோன்றல் (<f: செயல்பாடு போன்ற பொருள்>, <x: எண்>) derivative(<f: string>, <variable: string>, <x: number>) - + வழித்தோன்றல் (<f: சரம்>, <மாறி: சரம்>, <x: எண்>) @@ -1544,13 +1572,13 @@ File does not exist. %1 %2 shown. - + %1 %2 காட்டப்பட்டுள்ளது. %1 %2 hidden. - + %1 %2 மறைக்கப்பட்டுள்ளது. @@ -1558,12 +1586,12 @@ File does not exist. X Cursor - + ஃச் கர்சர் X Cursors - + ஃச் கர்சர்கள் From 310afa5672660b64b6e8bf62901e333cc03c1e08 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 6 Feb 2025 19:08:39 +0100 Subject: [PATCH 093/104] Disabling experimental threaded rendering by default for now. --- runtime-pyside6/LogarithmPlotter/util/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime-pyside6/LogarithmPlotter/util/config.py b/runtime-pyside6/LogarithmPlotter/util/config.py index 020569a..a7b2ffb 100644 --- a/runtime-pyside6/LogarithmPlotter/util/config.py +++ b/runtime-pyside6/LogarithmPlotter/util/config.py @@ -28,7 +28,7 @@ DEFAULT_SETTINGS = { "reset_redo_stack": True, "last_install_greet": "0", "enable_latex": which("latex") is not None and which("dvipng") is not None, - "enable_latex_threaded": True, + "enable_latex_threaded": False, "expression_editor": { "autoclose": True, "colorize": True, From fbef5dc28aa566bd1250a94ad4805575bfdfaf91 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Thu, 6 Feb 2025 19:14:00 +0100 Subject: [PATCH 094/104] Updating copyrights to 2025. --- README.md | 2 +- assets/native/linux/eu.ad5001.LogarithmPlotter.metainfo.xml | 2 +- assets/native/win/installer.nsi | 2 +- common/rollup.config.mjs | 2 +- common/src/events.mjs | 2 +- common/src/history/color.mjs | 2 +- common/src/history/common.mjs | 2 +- common/src/history/create.mjs | 2 +- common/src/history/delete.mjs | 2 +- common/src/history/editproperty.mjs | 2 +- common/src/history/index.mjs | 2 +- common/src/history/name.mjs | 2 +- common/src/history/position.mjs | 2 +- common/src/history/visibility.mjs | 2 +- common/src/index.mjs | 2 +- common/src/lib/expr-eval/expression.mjs | 2 +- common/src/lib/expr-eval/instruction.mjs | 2 +- common/src/lib/expr-eval/parser.mjs | 2 +- common/src/lib/expr-eval/parserstate.mjs | 2 +- common/src/lib/expr-eval/polyfill.mjs | 2 +- common/src/lib/expr-eval/tokens.mjs | 2 +- common/src/lib/polyfills/js.mjs | 4 ++-- common/src/lib/polyfills/qt.mjs | 2 +- common/src/math/domain.mjs | 2 +- common/src/math/expression.mjs | 2 +- common/src/math/index.mjs | 2 +- common/src/math/sequence.mjs | 2 +- common/src/module/canvas.mjs | 2 +- common/src/module/common.mjs | 2 +- common/src/module/expreval.mjs | 2 +- common/src/module/history.mjs | 2 +- common/src/module/index.mjs | 2 +- common/src/module/interface.mjs | 2 +- common/src/module/io.mjs | 2 +- common/src/module/latex.mjs | 2 +- common/src/module/objects.mjs | 2 +- common/src/module/preferences.mjs | 2 +- common/src/module/settings.mjs | 2 +- common/src/objs/autoload.mjs | 2 +- common/src/objs/bodemagnitude.mjs | 2 +- common/src/objs/bodemagnitudesum.mjs | 2 +- common/src/objs/bodephase.mjs | 2 +- common/src/objs/bodephasesum.mjs | 2 +- common/src/objs/common.mjs | 2 +- common/src/objs/distribution.mjs | 2 +- common/src/objs/function.mjs | 2 +- common/src/objs/point.mjs | 2 +- common/src/objs/sequence.mjs | 2 +- common/src/objs/text.mjs | 2 +- common/src/objs/xcursor.mjs | 2 +- common/src/parameters.mjs | 2 +- common/src/parsing/common.mjs | 2 +- common/src/parsing/index.mjs | 2 +- common/src/parsing/reference.mjs | 2 +- common/src/parsing/tokenizer.mjs | 2 +- common/src/preferences/common.mjs | 2 +- common/src/preferences/default.mjs | 2 +- common/src/preferences/expression.mjs | 2 +- common/src/preferences/general.mjs | 2 +- common/src/utils/expression.mjs | 2 +- common/src/utils/index.mjs | 2 +- common/src/utils/other.mjs | 2 +- common/src/utils/prototype.mjs | 2 +- common/src/utils/subsup.mjs | 2 +- common/test/basics/events.mjs | 2 +- common/test/basics/interface.mjs | 2 +- common/test/basics/polyfill.mjs | 2 +- common/test/basics/utils.mjs | 2 +- common/test/hooks.mjs | 2 +- common/test/math/domain.mjs | 2 +- common/test/math/expression.mjs | 2 +- common/test/mock/canvas.mjs | 2 +- common/test/mock/dialog.mjs | 2 +- common/test/mock/fs.mjs | 2 +- common/test/mock/helper.mjs | 2 +- common/test/mock/latex.mjs | 2 +- common/test/mock/qt.mjs | 2 +- common/test/mock/root.mjs | 2 +- common/test/module/base.mjs | 2 +- common/test/module/expreval.mjs | 2 +- common/test/module/latex.mjs | 2 +- common/test/module/objects.mjs | 2 +- common/test/module/settings.mjs | 2 +- run.py | 2 +- runtime-pyside6/LogarithmPlotter/__init__.py | 2 +- runtime-pyside6/LogarithmPlotter/logarithmplotter.py | 2 +- .../qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/History/Browser.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/History/SingleItem.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml | 2 +- .../ObjectLists/Editor/CustomPropertyList.qml | 2 +- .../eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml | 2 +- .../LogarithmPlotter/ObjectLists/ObjectCreationGrid.qml | 2 +- .../eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Overlay/Loading.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Overlay/PickLocation.qml | 2 +- .../eu/ad5001/LogarithmPlotter/Overlay/ViewPositionChange.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Popup/About.qml | 4 ++-- .../qml/eu/ad5001/LogarithmPlotter/Popup/Alert.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Popup/BaseDialog.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Popup/Changelog.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Popup/FileDialog.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Popup/GreetScreen.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Popup/Preferences.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Popup/ThanksTo.qml | 2 +- .../LogarithmPlotter/Setting/AutocompletionCategory.qml | 2 +- .../eu/ad5001/LogarithmPlotter/Setting/ComboBoxSetting.qml | 2 +- .../eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Setting/Icon.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Setting/ListSetting.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml | 2 +- .../qml/eu/ad5001/LogarithmPlotter/Settings.qml | 2 +- runtime-pyside6/LogarithmPlotter/util/config.py | 2 +- runtime-pyside6/LogarithmPlotter/util/debug.py | 2 +- runtime-pyside6/LogarithmPlotter/util/helper.py | 2 +- runtime-pyside6/LogarithmPlotter/util/js.py | 2 +- runtime-pyside6/LogarithmPlotter/util/latex.py | 2 +- runtime-pyside6/LogarithmPlotter/util/native.py | 2 +- runtime-pyside6/LogarithmPlotter/util/promise.py | 2 +- runtime-pyside6/LogarithmPlotter/util/update.py | 2 +- runtime-pyside6/setup.py | 2 +- runtime-pyside6/tests/globals.py | 2 +- runtime-pyside6/tests/plugins/natural/__init__.py | 2 +- runtime-pyside6/tests/plugins/natural/interfaces/assertion.py | 2 +- runtime-pyside6/tests/plugins/natural/interfaces/base.py | 2 +- runtime-pyside6/tests/plugins/natural/interfaces/basic.py | 2 +- runtime-pyside6/tests/plugins/natural/interfaces/int.py | 2 +- runtime-pyside6/tests/plugins/natural/interfaces/spy.py | 2 +- runtime-pyside6/tests/plugins/natural/interfaces/utils.py | 2 +- runtime-pyside6/tests/plugins/natural/spy.py | 2 +- runtime-pyside6/tests/plugins/natural/that.py | 2 +- runtime-pyside6/tests/plugins/tests/test_natural.py | 2 +- runtime-pyside6/tests/test_config.py | 2 +- runtime-pyside6/tests/test_debug.py | 2 +- runtime-pyside6/tests/test_helper.py | 2 +- runtime-pyside6/tests/test_latex.py | 2 +- runtime-pyside6/tests/test_main.py | 2 +- runtime-pyside6/tests/test_native.py | 2 +- runtime-pyside6/tests/test_promise.py | 2 +- runtime-pyside6/tests/test_pyjs.py | 2 +- runtime-pyside6/tests/test_update.py | 2 +- scripts/build.sh | 2 +- 145 files changed, 147 insertions(+), 147 deletions(-) diff --git a/README.md b/README.md index 976df53..f06d009 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ Finally, to actually run the tests: ## Legal notice LogarithmPlotter - 2D plotter software to make Bode plots, sequences and repartition functions. - Copyright (C) 2021-2024 Ad5001 + Copyright (C) 2021-2025 Ad5001 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/assets/native/linux/eu.ad5001.LogarithmPlotter.metainfo.xml b/assets/native/linux/eu.ad5001.LogarithmPlotter.metainfo.xml index a9dbded..f7e4c9d 100644 --- a/assets/native/linux/eu.ad5001.LogarithmPlotter.metainfo.xml +++ b/assets/native/linux/eu.ad5001.LogarithmPlotter.metainfo.xml @@ -1,5 +1,5 @@ - + eu.ad5001.LogarithmPlotter logarithmplotter.desktop diff --git a/assets/native/win/installer.nsi b/assets/native/win/installer.nsi index ebb84c9..bf38199 100644 --- a/assets/native/win/installer.nsi +++ b/assets/native/win/installer.nsi @@ -13,7 +13,7 @@ Unicode True !define WEBSITE "https://apps.ad5001.eu/logarithmplotter" !define VERSION_SHORT "0.6.0" !define APP_VERSION "${VERSION_SHORT}.0" -!define COPYRIGHT "Ad5001 (c) 2021-2024" +!define COPYRIGHT "Ad5001 (c) 2021-2025" !define DESCRIPTION "Create graphs with logarithmic scales." !define REG_UNINSTALL "Software\Microsoft\Windows\CurrentVersion\Uninstall\LogarithmPlotter" diff --git a/common/rollup.config.mjs b/common/rollup.config.mjs index 6156873..5c4d38a 100644 --- a/common/rollup.config.mjs +++ b/common/rollup.config.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/events.mjs b/common/src/events.mjs index 75a7a52..1ef3777 100644 --- a/common/src/events.mjs +++ b/common/src/events.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/history/color.mjs b/common/src/history/color.mjs index 1d395ed..0efa29d 100644 --- a/common/src/history/color.mjs +++ b/common/src/history/color.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/history/common.mjs b/common/src/history/common.mjs index e8e5795..8c46757 100644 --- a/common/src/history/common.mjs +++ b/common/src/history/common.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/history/create.mjs b/common/src/history/create.mjs index 1308d9e..fb27f62 100644 --- a/common/src/history/create.mjs +++ b/common/src/history/create.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/history/delete.mjs b/common/src/history/delete.mjs index f9674c5..2f8d8fe 100644 --- a/common/src/history/delete.mjs +++ b/common/src/history/delete.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/history/editproperty.mjs b/common/src/history/editproperty.mjs index 886f100..2a81e7a 100644 --- a/common/src/history/editproperty.mjs +++ b/common/src/history/editproperty.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/history/index.mjs b/common/src/history/index.mjs index aa57307..a2ef1ea 100644 --- a/common/src/history/index.mjs +++ b/common/src/history/index.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/history/name.mjs b/common/src/history/name.mjs index 5c5b397..61bb6b5 100644 --- a/common/src/history/name.mjs +++ b/common/src/history/name.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/history/position.mjs b/common/src/history/position.mjs index 3bf2fe8..2b9c0ff 100644 --- a/common/src/history/position.mjs +++ b/common/src/history/position.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/history/visibility.mjs b/common/src/history/visibility.mjs index e911c1b..9254d67 100644 --- a/common/src/history/visibility.mjs +++ b/common/src/history/visibility.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/index.mjs b/common/src/index.mjs index 9b5684c..57efb01 100644 --- a/common/src/index.mjs +++ b/common/src/index.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/lib/expr-eval/expression.mjs b/common/src/lib/expr-eval/expression.mjs index f782fa3..45854e8 100644 --- a/common/src/lib/expr-eval/expression.mjs +++ b/common/src/lib/expr-eval/expression.mjs @@ -7,7 +7,7 @@ * * Ported to QMLJS with modifications done accordingly done by Ad5001 (https://ad5001.eu) * - * Copyright (c) 2015 Matthew Crumley, 2021-2024 Ad5001 + * Copyright (c) 2015 Matthew Crumley, 2021-2025 Ad5001 * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, diff --git a/common/src/lib/expr-eval/instruction.mjs b/common/src/lib/expr-eval/instruction.mjs index df0e2d7..9157fea 100644 --- a/common/src/lib/expr-eval/instruction.mjs +++ b/common/src/lib/expr-eval/instruction.mjs @@ -7,7 +7,7 @@ * * Ported to QMLJS with modifications done accordingly done by Ad5001 (https://ad5001.eu) * - * Copyright (c) 2015 Matthew Crumley, 2021-2024 Ad5001 + * Copyright (c) 2015 Matthew Crumley, 2021-2025 Ad5001 * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, diff --git a/common/src/lib/expr-eval/parser.mjs b/common/src/lib/expr-eval/parser.mjs index e27d512..98f4539 100644 --- a/common/src/lib/expr-eval/parser.mjs +++ b/common/src/lib/expr-eval/parser.mjs @@ -7,7 +7,7 @@ * * Ported to QMLJS with modifications done accordingly done by Ad5001 (https://ad5001.eu) * - * Copyright (c) 2015 Matthew Crumley, 2021-2024 Ad5001 + * Copyright (c) 2015 Matthew Crumley, 2021-2025 Ad5001 * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, diff --git a/common/src/lib/expr-eval/parserstate.mjs b/common/src/lib/expr-eval/parserstate.mjs index 801c424..d4b3a3b 100644 --- a/common/src/lib/expr-eval/parserstate.mjs +++ b/common/src/lib/expr-eval/parserstate.mjs @@ -7,7 +7,7 @@ * * Ported to QMLJS with modifications done accordingly done by Ad5001 (https://ad5001.eu) * - * Copyright (c) 2015 Matthew Crumley, 2021-2024 Ad5001 + * Copyright (c) 2015 Matthew Crumley, 2021-2025 Ad5001 * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, diff --git a/common/src/lib/expr-eval/polyfill.mjs b/common/src/lib/expr-eval/polyfill.mjs index a15c741..65f05c7 100644 --- a/common/src/lib/expr-eval/polyfill.mjs +++ b/common/src/lib/expr-eval/polyfill.mjs @@ -7,7 +7,7 @@ * * Ported to QMLJS with modifications done accordingly done by Ad5001 (https://ad5001.eu) * - * Copyright (c) 2015 Matthew Crumley, 2021-2024 Ad5001 + * Copyright (c) 2015 Matthew Crumley, 2021-2025 Ad5001 * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, diff --git a/common/src/lib/expr-eval/tokens.mjs b/common/src/lib/expr-eval/tokens.mjs index bfaad39..254d30a 100644 --- a/common/src/lib/expr-eval/tokens.mjs +++ b/common/src/lib/expr-eval/tokens.mjs @@ -7,7 +7,7 @@ * * Ported to QMLJS with modifications done accordingly done by Ad5001 (https://ad5001.eu) * - * Copyright (c) 2015 Matthew Crumley, 2021-2024 Ad5001 + * Copyright (c) 2015 Matthew Crumley, 2021-2025 Ad5001 * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, diff --git a/common/src/lib/polyfills/js.mjs b/common/src/lib/polyfills/js.mjs index f8b910b..75d149c 100644 --- a/common/src/lib/polyfills/js.mjs +++ b/common/src/lib/polyfills/js.mjs @@ -1,6 +1,6 @@ /*! * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -119,7 +119,7 @@ const polyfills = { [Array.prototype, "toSpliced", notPolyfilled("Array.prototype.toSpliced")], [Array.prototype, "with", notPolyfilled("Array.prototype.with")] ], - 2024: [ + 2025: [ [Object, "groupBy", notPolyfilled("Object.groupBy")], [Map, "groupBy", notPolyfilled("Map.groupBy")] ] diff --git a/common/src/lib/polyfills/qt.mjs b/common/src/lib/polyfills/qt.mjs index 6559423..0e9a9b5 100644 --- a/common/src/lib/polyfills/qt.mjs +++ b/common/src/lib/polyfills/qt.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/math/domain.mjs b/common/src/math/domain.mjs index 19586ee..b81e527 100644 --- a/common/src/math/domain.mjs +++ b/common/src/math/domain.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/math/expression.mjs b/common/src/math/expression.mjs index 7c7170b..2502110 100644 --- a/common/src/math/expression.mjs +++ b/common/src/math/expression.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/math/index.mjs b/common/src/math/index.mjs index 27be49e..c517958 100644 --- a/common/src/math/index.mjs +++ b/common/src/math/index.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/math/sequence.mjs b/common/src/math/sequence.mjs index b295708..6049e53 100644 --- a/common/src/math/sequence.mjs +++ b/common/src/math/sequence.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/module/canvas.mjs b/common/src/module/canvas.mjs index 22166d5..1137ae5 100644 --- a/common/src/module/canvas.mjs +++ b/common/src/module/canvas.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/module/common.mjs b/common/src/module/common.mjs index 4cd7993..f5fa8aa 100644 --- a/common/src/module/common.mjs +++ b/common/src/module/common.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/module/expreval.mjs b/common/src/module/expreval.mjs index 8440282..dd89f4d 100644 --- a/common/src/module/expreval.mjs +++ b/common/src/module/expreval.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/module/history.mjs b/common/src/module/history.mjs index 4b07095..45a37f0 100644 --- a/common/src/module/history.mjs +++ b/common/src/module/history.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/module/index.mjs b/common/src/module/index.mjs index 2530a00..6fdff97 100644 --- a/common/src/module/index.mjs +++ b/common/src/module/index.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/module/interface.mjs b/common/src/module/interface.mjs index a96621c..6947acd 100644 --- a/common/src/module/interface.mjs +++ b/common/src/module/interface.mjs @@ -3,7 +3,7 @@ * * @author Ad5001 * @license GPL-3.0-or-later - * @copyright (C) 2021-2024 Ad5001 + * @copyright (C) 2021-2025 Ad5001 * @preserve * * This program is free software: you can redistribute it and/or modify diff --git a/common/src/module/io.mjs b/common/src/module/io.mjs index 1ac6e58..4887954 100644 --- a/common/src/module/io.mjs +++ b/common/src/module/io.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/module/latex.mjs b/common/src/module/latex.mjs index 3b48ebc..27fbdd4 100644 --- a/common/src/module/latex.mjs +++ b/common/src/module/latex.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/module/objects.mjs b/common/src/module/objects.mjs index 979dba4..e98a15f 100644 --- a/common/src/module/objects.mjs +++ b/common/src/module/objects.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/module/preferences.mjs b/common/src/module/preferences.mjs index dea8677..5d20f92 100644 --- a/common/src/module/preferences.mjs +++ b/common/src/module/preferences.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/module/settings.mjs b/common/src/module/settings.mjs index d630e7a..c740383 100644 --- a/common/src/module/settings.mjs +++ b/common/src/module/settings.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/objs/autoload.mjs b/common/src/objs/autoload.mjs index 26a6003..7ecac04 100644 --- a/common/src/objs/autoload.mjs +++ b/common/src/objs/autoload.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/objs/bodemagnitude.mjs b/common/src/objs/bodemagnitude.mjs index 82d9728..4dbcd28 100644 --- a/common/src/objs/bodemagnitude.mjs +++ b/common/src/objs/bodemagnitude.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/objs/bodemagnitudesum.mjs b/common/src/objs/bodemagnitudesum.mjs index eb81663..701a4b9 100644 --- a/common/src/objs/bodemagnitudesum.mjs +++ b/common/src/objs/bodemagnitudesum.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/objs/bodephase.mjs b/common/src/objs/bodephase.mjs index 800671e..75776b1 100644 --- a/common/src/objs/bodephase.mjs +++ b/common/src/objs/bodephase.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/objs/bodephasesum.mjs b/common/src/objs/bodephasesum.mjs index 90864d7..55b3b6c 100644 --- a/common/src/objs/bodephasesum.mjs +++ b/common/src/objs/bodephasesum.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/objs/common.mjs b/common/src/objs/common.mjs index 380ac5d..602856a 100644 --- a/common/src/objs/common.mjs +++ b/common/src/objs/common.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/objs/distribution.mjs b/common/src/objs/distribution.mjs index 16aa4d4..b63717c 100644 --- a/common/src/objs/distribution.mjs +++ b/common/src/objs/distribution.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/objs/function.mjs b/common/src/objs/function.mjs index 70d0b69..fec90ac 100644 --- a/common/src/objs/function.mjs +++ b/common/src/objs/function.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/objs/point.mjs b/common/src/objs/point.mjs index d179481..841308e 100644 --- a/common/src/objs/point.mjs +++ b/common/src/objs/point.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/objs/sequence.mjs b/common/src/objs/sequence.mjs index 0328041..b424ac0 100644 --- a/common/src/objs/sequence.mjs +++ b/common/src/objs/sequence.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/objs/text.mjs b/common/src/objs/text.mjs index af79824..f4dd993 100644 --- a/common/src/objs/text.mjs +++ b/common/src/objs/text.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/objs/xcursor.mjs b/common/src/objs/xcursor.mjs index 11f6a5a..4ad511c 100644 --- a/common/src/objs/xcursor.mjs +++ b/common/src/objs/xcursor.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/parameters.mjs b/common/src/parameters.mjs index 1078518..0da11a8 100644 --- a/common/src/parameters.mjs +++ b/common/src/parameters.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/parsing/common.mjs b/common/src/parsing/common.mjs index 72a9a4b..998f038 100644 --- a/common/src/parsing/common.mjs +++ b/common/src/parsing/common.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/parsing/index.mjs b/common/src/parsing/index.mjs index 6d0de80..f0fde37 100644 --- a/common/src/parsing/index.mjs +++ b/common/src/parsing/index.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/parsing/reference.mjs b/common/src/parsing/reference.mjs index 36d4c8c..80365aa 100644 --- a/common/src/parsing/reference.mjs +++ b/common/src/parsing/reference.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/parsing/tokenizer.mjs b/common/src/parsing/tokenizer.mjs index a8552fc..8725bf3 100644 --- a/common/src/parsing/tokenizer.mjs +++ b/common/src/parsing/tokenizer.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/preferences/common.mjs b/common/src/preferences/common.mjs index 812263c..4e3ecc8 100644 --- a/common/src/preferences/common.mjs +++ b/common/src/preferences/common.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/preferences/default.mjs b/common/src/preferences/default.mjs index 1d7e4bd..c6864d1 100644 --- a/common/src/preferences/default.mjs +++ b/common/src/preferences/default.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/preferences/expression.mjs b/common/src/preferences/expression.mjs index 85e1fbe..bda6899 100644 --- a/common/src/preferences/expression.mjs +++ b/common/src/preferences/expression.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/preferences/general.mjs b/common/src/preferences/general.mjs index a00a813..093afaf 100644 --- a/common/src/preferences/general.mjs +++ b/common/src/preferences/general.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/utils/expression.mjs b/common/src/utils/expression.mjs index ef20b27..2caf5ea 100644 --- a/common/src/utils/expression.mjs +++ b/common/src/utils/expression.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/utils/index.mjs b/common/src/utils/index.mjs index 02adfd6..2c11c1b 100644 --- a/common/src/utils/index.mjs +++ b/common/src/utils/index.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/utils/other.mjs b/common/src/utils/other.mjs index bcafd6b..50f84f4 100644 --- a/common/src/utils/other.mjs +++ b/common/src/utils/other.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/utils/prototype.mjs b/common/src/utils/prototype.mjs index cb2cc15..b0fd27f 100644 --- a/common/src/utils/prototype.mjs +++ b/common/src/utils/prototype.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/src/utils/subsup.mjs b/common/src/utils/subsup.mjs index ff6ed50..6eb4280 100644 --- a/common/src/utils/subsup.mjs +++ b/common/src/utils/subsup.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/basics/events.mjs b/common/test/basics/events.mjs index 092f037..7dac6e2 100644 --- a/common/test/basics/events.mjs +++ b/common/test/basics/events.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/basics/interface.mjs b/common/test/basics/interface.mjs index aaf512e..48af62e 100644 --- a/common/test/basics/interface.mjs +++ b/common/test/basics/interface.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/basics/polyfill.mjs b/common/test/basics/polyfill.mjs index 4c44514..1fc9599 100644 --- a/common/test/basics/polyfill.mjs +++ b/common/test/basics/polyfill.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/basics/utils.mjs b/common/test/basics/utils.mjs index 42adead..66ecd92 100644 --- a/common/test/basics/utils.mjs +++ b/common/test/basics/utils.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/hooks.mjs b/common/test/hooks.mjs index 66e9da9..39a25d7 100644 --- a/common/test/hooks.mjs +++ b/common/test/hooks.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/math/domain.mjs b/common/test/math/domain.mjs index 6c2b93e..b9161c8 100644 --- a/common/test/math/domain.mjs +++ b/common/test/math/domain.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/math/expression.mjs b/common/test/math/expression.mjs index 0c15f9c..588480c 100644 --- a/common/test/math/expression.mjs +++ b/common/test/math/expression.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/mock/canvas.mjs b/common/test/mock/canvas.mjs index e770e10..82bcbff 100644 --- a/common/test/mock/canvas.mjs +++ b/common/test/mock/canvas.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/mock/dialog.mjs b/common/test/mock/dialog.mjs index 3ff118f..ec8628d 100644 --- a/common/test/mock/dialog.mjs +++ b/common/test/mock/dialog.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/mock/fs.mjs b/common/test/mock/fs.mjs index bccb71f..7cb00dd 100644 --- a/common/test/mock/fs.mjs +++ b/common/test/mock/fs.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/mock/helper.mjs b/common/test/mock/helper.mjs index b912b44..9186947 100644 --- a/common/test/mock/helper.mjs +++ b/common/test/mock/helper.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/mock/latex.mjs b/common/test/mock/latex.mjs index 2d6fb5f..54d427d 100644 --- a/common/test/mock/latex.mjs +++ b/common/test/mock/latex.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/mock/qt.mjs b/common/test/mock/qt.mjs index 58ceae0..46f5b3d 100644 --- a/common/test/mock/qt.mjs +++ b/common/test/mock/qt.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/mock/root.mjs b/common/test/mock/root.mjs index 51807e2..0539342 100644 --- a/common/test/mock/root.mjs +++ b/common/test/mock/root.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/module/base.mjs b/common/test/module/base.mjs index be035c0..0cc73ea 100644 --- a/common/test/module/base.mjs +++ b/common/test/module/base.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/module/expreval.mjs b/common/test/module/expreval.mjs index 2d075f6..c04290e 100644 --- a/common/test/module/expreval.mjs +++ b/common/test/module/expreval.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/module/latex.mjs b/common/test/module/latex.mjs index e038e63..6581850 100644 --- a/common/test/module/latex.mjs +++ b/common/test/module/latex.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/module/objects.mjs b/common/test/module/objects.mjs index d598097..73b9e25 100644 --- a/common/test/module/objects.mjs +++ b/common/test/module/objects.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/common/test/module/settings.mjs b/common/test/module/settings.mjs index 7ad439a..b266bb2 100644 --- a/common/test/module/settings.mjs +++ b/common/test/module/settings.mjs @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/run.py b/run.py index 783e23b..058ca94 100644 --- a/run.py +++ b/run.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/__init__.py b/runtime-pyside6/LogarithmPlotter/__init__.py index 0c5cbbb..08914d3 100644 --- a/runtime-pyside6/LogarithmPlotter/__init__.py +++ b/runtime-pyside6/LogarithmPlotter/__init__.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/logarithmplotter.py b/runtime-pyside6/LogarithmPlotter/logarithmplotter.py index 8940e56..562231a 100644 --- a/runtime-pyside6/LogarithmPlotter/logarithmplotter.py +++ b/runtime-pyside6/LogarithmPlotter/logarithmplotter.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml index 79fa6b0..d271cb6 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/Browser.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/Browser.qml index 645916c..09b6feb 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/Browser.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/Browser.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/SingleItem.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/SingleItem.qml index bffdb9b..fac19e3 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/SingleItem.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/History/SingleItem.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml index e1583f6..30bf6ca 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml index 064a0be..ddbd2bd 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml index e688202..6e33b71 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml index ced0cdd..d762da2 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectCreationGrid.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectCreationGrid.qml index e3894cd..21559a9 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectCreationGrid.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectCreationGrid.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml index 3b59e0a..d37a015 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml index 5812252..0f7003f 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/Loading.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/Loading.qml index 6aec616..10f3665 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/Loading.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/Loading.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/PickLocation.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/PickLocation.qml index 60eb90e..6ba8bb6 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/PickLocation.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/PickLocation.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/ViewPositionChange.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/ViewPositionChange.qml index 41ce60a..78329a7 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/ViewPositionChange.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Overlay/ViewPositionChange.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/About.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/About.qml index d74c101..e82f39c 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/About.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/About.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -102,7 +102,7 @@ BaseDialog { wrapMode: Text.WordWrap textFormat: Text.RichText font.pixelSize: 13 - text: "Copyright © 2021-2024 Ad5001 <mail@ad5001.eu>
+ text: "Copyright © 2021-2025 Ad5001 <mail@ad5001.eu>

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Alert.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Alert.qml index 0220956..98e37d4 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Alert.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Alert.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/BaseDialog.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/BaseDialog.qml index 10fe87e..a9c73a6 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/BaseDialog.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/BaseDialog.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Changelog.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Changelog.qml index 93d76db..1797b9d 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Changelog.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Changelog.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/FileDialog.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/FileDialog.qml index 4b7ff8a..00dbdae 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/FileDialog.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/FileDialog.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/GreetScreen.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/GreetScreen.qml index 5a1ff21..a083d64 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/GreetScreen.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/GreetScreen.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml index 9bf8f06..8111f85 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/InsertCharacter.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Preferences.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Preferences.qml index 70d77a9..9ed40c8 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Preferences.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Preferences.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/ThanksTo.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/ThanksTo.qml index c2001a2..85e4a64 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/ThanksTo.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/ThanksTo.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/AutocompletionCategory.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/AutocompletionCategory.qml index 304b704..897af70 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/AutocompletionCategory.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/AutocompletionCategory.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ComboBoxSetting.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ComboBoxSetting.qml index d29ab7c..a4dc93b 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ComboBoxSetting.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ComboBoxSetting.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml index af32b43..35bba0a 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/Icon.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/Icon.qml index aeffe53..6ba76aa 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/Icon.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/Icon.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ListSetting.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ListSetting.qml index 221b3a3..daad433 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ListSetting.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ListSetting.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml index 8d1ca41..bc105aa 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml index 3f17ea3..58db0e9 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml @@ -1,6 +1,6 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/util/config.py b/runtime-pyside6/LogarithmPlotter/util/config.py index a7b2ffb..2cce4dc 100644 --- a/runtime-pyside6/LogarithmPlotter/util/config.py +++ b/runtime-pyside6/LogarithmPlotter/util/config.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/util/debug.py b/runtime-pyside6/LogarithmPlotter/util/debug.py index ef02d62..c977253 100644 --- a/runtime-pyside6/LogarithmPlotter/util/debug.py +++ b/runtime-pyside6/LogarithmPlotter/util/debug.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/util/helper.py b/runtime-pyside6/LogarithmPlotter/util/helper.py index cc6bff4..8adb81e 100644 --- a/runtime-pyside6/LogarithmPlotter/util/helper.py +++ b/runtime-pyside6/LogarithmPlotter/util/helper.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/util/js.py b/runtime-pyside6/LogarithmPlotter/util/js.py index 944c2b0..380ab97 100644 --- a/runtime-pyside6/LogarithmPlotter/util/js.py +++ b/runtime-pyside6/LogarithmPlotter/util/js.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/util/latex.py b/runtime-pyside6/LogarithmPlotter/util/latex.py index 570e083..b446295 100644 --- a/runtime-pyside6/LogarithmPlotter/util/latex.py +++ b/runtime-pyside6/LogarithmPlotter/util/latex.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/util/native.py b/runtime-pyside6/LogarithmPlotter/util/native.py index aefc310..3adf153 100644 --- a/runtime-pyside6/LogarithmPlotter/util/native.py +++ b/runtime-pyside6/LogarithmPlotter/util/native.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/util/promise.py b/runtime-pyside6/LogarithmPlotter/util/promise.py index f4f21c2..8e17651 100644 --- a/runtime-pyside6/LogarithmPlotter/util/promise.py +++ b/runtime-pyside6/LogarithmPlotter/util/promise.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/LogarithmPlotter/util/update.py b/runtime-pyside6/LogarithmPlotter/util/update.py index 1d2ecec..e18b93e 100644 --- a/runtime-pyside6/LogarithmPlotter/util/update.py +++ b/runtime-pyside6/LogarithmPlotter/util/update.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/setup.py b/runtime-pyside6/setup.py index 524ad29..4100042 100644 --- a/runtime-pyside6/setup.py +++ b/runtime-pyside6/setup.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/globals.py b/runtime-pyside6/tests/globals.py index def1415..67a1356 100644 --- a/runtime-pyside6/tests/globals.py +++ b/runtime-pyside6/tests/globals.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/plugins/natural/__init__.py b/runtime-pyside6/tests/plugins/natural/__init__.py index 4cfe179..180969f 100644 --- a/runtime-pyside6/tests/plugins/natural/__init__.py +++ b/runtime-pyside6/tests/plugins/natural/__init__.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/assertion.py b/runtime-pyside6/tests/plugins/natural/interfaces/assertion.py index e1e43c4..b81d0e5 100644 --- a/runtime-pyside6/tests/plugins/natural/interfaces/assertion.py +++ b/runtime-pyside6/tests/plugins/natural/interfaces/assertion.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/base.py b/runtime-pyside6/tests/plugins/natural/interfaces/base.py index 0786285..c96c146 100644 --- a/runtime-pyside6/tests/plugins/natural/interfaces/base.py +++ b/runtime-pyside6/tests/plugins/natural/interfaces/base.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/basic.py b/runtime-pyside6/tests/plugins/natural/interfaces/basic.py index 25d45cb..85720da 100644 --- a/runtime-pyside6/tests/plugins/natural/interfaces/basic.py +++ b/runtime-pyside6/tests/plugins/natural/interfaces/basic.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/int.py b/runtime-pyside6/tests/plugins/natural/interfaces/int.py index 75bd8b8..b282e4d 100644 --- a/runtime-pyside6/tests/plugins/natural/interfaces/int.py +++ b/runtime-pyside6/tests/plugins/natural/interfaces/int.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/spy.py b/runtime-pyside6/tests/plugins/natural/interfaces/spy.py index 524fd71..ce0b8ff 100644 --- a/runtime-pyside6/tests/plugins/natural/interfaces/spy.py +++ b/runtime-pyside6/tests/plugins/natural/interfaces/spy.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/plugins/natural/interfaces/utils.py b/runtime-pyside6/tests/plugins/natural/interfaces/utils.py index 50e3777..5200975 100644 --- a/runtime-pyside6/tests/plugins/natural/interfaces/utils.py +++ b/runtime-pyside6/tests/plugins/natural/interfaces/utils.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/plugins/natural/spy.py b/runtime-pyside6/tests/plugins/natural/spy.py index 2f9211a..4026b20 100644 --- a/runtime-pyside6/tests/plugins/natural/spy.py +++ b/runtime-pyside6/tests/plugins/natural/spy.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/plugins/natural/that.py b/runtime-pyside6/tests/plugins/natural/that.py index 05a3e31..60ad4b6 100644 --- a/runtime-pyside6/tests/plugins/natural/that.py +++ b/runtime-pyside6/tests/plugins/natural/that.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/plugins/tests/test_natural.py b/runtime-pyside6/tests/plugins/tests/test_natural.py index f381639..31f85c0 100644 --- a/runtime-pyside6/tests/plugins/tests/test_natural.py +++ b/runtime-pyside6/tests/plugins/tests/test_natural.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/test_config.py b/runtime-pyside6/tests/test_config.py index cef3673..a95a9d9 100644 --- a/runtime-pyside6/tests/test_config.py +++ b/runtime-pyside6/tests/test_config.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/test_debug.py b/runtime-pyside6/tests/test_debug.py index 4799024..467e5b8 100644 --- a/runtime-pyside6/tests/test_debug.py +++ b/runtime-pyside6/tests/test_debug.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/test_helper.py b/runtime-pyside6/tests/test_helper.py index 6bc1f0d..f2f6d70 100644 --- a/runtime-pyside6/tests/test_helper.py +++ b/runtime-pyside6/tests/test_helper.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/test_latex.py b/runtime-pyside6/tests/test_latex.py index ee87fa5..4ffbc6c 100644 --- a/runtime-pyside6/tests/test_latex.py +++ b/runtime-pyside6/tests/test_latex.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/test_main.py b/runtime-pyside6/tests/test_main.py index 6b161ad..1595236 100644 --- a/runtime-pyside6/tests/test_main.py +++ b/runtime-pyside6/tests/test_main.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/test_native.py b/runtime-pyside6/tests/test_native.py index 3ca4834..d60b907 100644 --- a/runtime-pyside6/tests/test_native.py +++ b/runtime-pyside6/tests/test_native.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/test_promise.py b/runtime-pyside6/tests/test_promise.py index 30f0a1e..ef71a55 100644 --- a/runtime-pyside6/tests/test_promise.py +++ b/runtime-pyside6/tests/test_promise.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/test_pyjs.py b/runtime-pyside6/tests/test_pyjs.py index 95c3cf6..9177b4e 100644 --- a/runtime-pyside6/tests/test_pyjs.py +++ b/runtime-pyside6/tests/test_pyjs.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/runtime-pyside6/tests/test_update.py b/runtime-pyside6/tests/test_update.py index ff71e61..16b562e 100644 --- a/runtime-pyside6/tests/test_update.py +++ b/runtime-pyside6/tests/test_update.py @@ -1,6 +1,6 @@ """ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 + * Copyright (C) 2021-2025 Ad5001 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/scripts/build.sh b/scripts/build.sh index b63d7f6..257b2c4 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # # LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. -# Copyright (C) 2021-2024 Ad5001 +# Copyright (C) 2021-2025 Ad5001 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by From a2f8a924e0a9812e054e61051e0a94649af80ce1 Mon Sep 17 00:00:00 2001 From: ovari Date: Thu, 13 Mar 2025 05:57:01 +0100 Subject: [PATCH 095/104] Translated using Weblate (Hungarian) Currently translated at 100.0% (264 of 264 strings) Translation: LogarithmPlotter/LogarithmPlotter Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/ --- assets/i18n/lp_hu.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/assets/i18n/lp_hu.ts b/assets/i18n/lp_hu.ts index bff8a44..7e2856d 100644 --- a/assets/i18n/lp_hu.ts +++ b/assets/i18n/lp_hu.ts @@ -456,12 +456,12 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. Loading... - + Betöltés… Finished rendering of %1 - + %1 renderelése befejeződött
@@ -469,7 +469,7 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. untitled - + névtelen @@ -881,7 +881,7 @@ Ezek a beállítások bármikor módosíthatók a „Beállítások” menüben. Tamil - + Tamil @@ -1334,7 +1334,7 @@ Kiértékelt kifejezés: %3 Enable threaded LaTeX renderer (experimental) - + A szálas LaTeX renderer engedélyezése (kísérleti) @@ -1479,24 +1479,27 @@ Kérjük, ellenőrizze, hogy a LaTeX telepítése helyes-e, és ha igen, jelents This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}. Please update LogarithmPlotter to open this file. - + Ezt a fájlt a LogarithmPlotter egy újabb verziója hozta létre, és nem tölthető vissza a LogarithmPlotter v{} alkalmazásban. +Kérjük, frissítse a LogarithmPlottert a fájl megnyitásához. Could not open file "{}": {} - + Nem sikerült megnyitni a(z) „{}”-fájlt: +{} Could not open file: "{}" File does not exist. - + Nem sikerült megnyitni a(z) „{}”-fájlt: +A fájl nem létezik. Built with PySide6 (Qt) v{} and python v{} - + PySide6 (Qt) v{} és python v{} segítségével épült From abd7d6a550134314f8c2581077f016bc9603d1f2 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 22 Apr 2025 04:06:12 +0200 Subject: [PATCH 096/104] Creating changelog for v0.6.0. --- CHANGELOG.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4b7c6d..4a756a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,55 @@ # Changelog +## v0.6.0 (?? Apr 2025) + +**New** + + * Revamped the update greet screan. + * Settings now have their dedicated configuration screen. + * Default settings for graphs can now be configured. + * LaTeX rendering now support both concurent and (experimental) threaded rendering, making graph render up to 20x times faster. + * Added a loading screen for the threaded LaTeX renderer. + +**Changes** + + * Settings menu removed, use `Edit > Preferences` to access LogarithmPlotter's settings. + * Logarithmic graduation limit upped from 10^20 to 10^309 (and conversively). + * Error messages should now all be properly translated. + * LaTeX renders are now persistantly cached. Closing and reopening files will be instantaneous. + * Special character choosing popup is now keyboard navigable and no longer covers the input. + * Domains are now rendered with LaTeX. + +**Fixed bugs** + + * Fixed sequence rendering method. + * Picker's 'snap to grid' option caused issues when picking. + * Outzooming with mousescroll no longer prevents you from being able to zoom back in. + * Several bugs related to X Cursors, namely certain function causing LogarithmPlotter to crash, and rounding errors. + * When using derivatives, the value passed as parameter is now properly rendered instead of a placeholder `x`. + * LaTeX renderer now uses native square root function look instead of `sqrt` function. + * LaTeX renderer now properly renders pi as π. + * Improved the stability of complex function drawing. + * (Linux) Certain links in 'About' were broken. + +**Translations** + + * New translation in Tamil (thanks @TamilNeram!) + * Completed Spanish translation (thanks @gallegonovato and @IngrownMink4!) + * We're still looking for Norwegian speakers who could help complete the [translation](https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/nb_NO/). + * If your language is not yet supported by LogarithmPlotter, feel free to add it on [Weblate](https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/)! + +**Internal changes** + + * The near entirety of the logic was refractored from QML JS to modern ECMAScript (added Babel and rollup as dependancies). + * PySide6 and ES codebases were completely separated (in preparation of a web-based renderer). + * Added Python unit tests (complete). + * Added ES unit tests (WIP). + * Internal tooling for translations was overalled to allow lupdate to parse newer ES syntax. + * Flushed a great many deals of hacks and bugs this way. + * Type safety is now properly enforced at every step of IO. + * Several new test files were added in the `ci` folder. + * Updated to PySide6 v6.9.0 + ## v0.5.0 (11 Jan 2024) **New** From b90c72c0b1d7f57d1ad180350cb1db36748db024 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 22 Apr 2025 04:13:09 +0200 Subject: [PATCH 097/104] Updating ES locks. --- common/package-lock.json | 1974 ++++++++++++++++---------------------- 1 file changed, 804 insertions(+), 1170 deletions(-) diff --git a/common/package-lock.json b/common/package-lock.json index 0e01b59..9ca31b3 100644 --- a/common/package-lock.json +++ b/common/package-lock.json @@ -44,12 +44,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", - "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "license": "MIT", "dependencies": { - "@babel/highlight": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -57,31 +58,31 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.7.tgz", - "integrity": "sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.7.tgz", - "integrity": "sha512-yJ474Zv3cwiSOO9nXJuqzvwEeM+chDuQ8GJirw+pZ91sCGCyOZ3dJkVE09fTV0VEVzXyLWhh3G/AolYTPX7Mow==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "license": "MIT", "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.25.7", - "@babel/generator": "^7.25.7", - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helpers": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/template": "^7.25.7", - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -97,12 +98,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", - "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.7", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -112,38 +114,25 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", - "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.7.tgz", - "integrity": "sha512-12xfNeKNH7jubQNm7PAkzlLwEmCs1tfuX3UjIw6vP6QXi+leKh6+LyC/+Ed4EIQermwd58wsyh070yjDHFlNGg==", - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", - "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", + "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.7", - "@babel/helper-validator-option": "^7.25.7", + "@babel/compat-data": "^7.26.8", + "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -153,17 +142,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.7.tgz", - "integrity": "sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz", + "integrity": "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-member-expression-to-functions": "^7.25.7", - "@babel/helper-optimise-call-expression": "^7.25.7", - "@babel/helper-replace-supers": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", - "@babel/traverse": "^7.25.7", + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.27.0", "semver": "^6.3.1" }, "engines": { @@ -174,13 +163,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.7.tgz", - "integrity": "sha512-byHhumTj/X47wJ6C6eLpK7wW/WBEcnUeb7D0FNc/jFQnQVw7DOso3Zz5u9x/zLrFVkHa89ZGDbkAa1D54NdrCQ==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.0.tgz", + "integrity": "sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "regexpu-core": "^6.1.1", + "@babel/helper-annotate-as-pure": "^7.25.9", + "regexpu-core": "^6.2.0", "semver": "^6.3.1" }, "engines": { @@ -191,9 +180,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.4.tgz", + "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==", "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", @@ -207,41 +196,40 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.7.tgz", - "integrity": "sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", - "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", - "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.7", - "@babel/helper-simple-access": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -251,35 +239,35 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.7.tgz", - "integrity": "sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", - "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.7.tgz", - "integrity": "sha512-kRGE89hLnPfcz6fTrlNU+uhgcwv0mBE4Gv3P9Ke9kLVJYpi4AMVVEElXvB5CabrPZW4nCM8P8UyyjrzCM0O2sw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", + "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-wrap-function": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -289,14 +277,14 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.7.tgz", - "integrity": "sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", + "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.25.7", - "@babel/helper-optimise-call-expression": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -305,109 +293,81 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", - "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.7.tgz", - "integrity": "sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", - "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", - "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", - "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.7.tgz", - "integrity": "sha512-MA0roW3JF2bD1ptAaJnvcabsVlNQShUaThyJbCDD4bCp8NEgiFvpoqRI2YS22hHlc2thjO/fTg2ShLMC3jygAg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", + "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", "license": "MIT", "dependencies": { - "@babel/template": "^7.25.7", - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", - "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", "license": "MIT", "peer": true, "dependencies": { - "@babel/template": "^7.25.7", - "@babel/types": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", - "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", - "integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.7" + "@babel/types": "^7.27.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -417,13 +377,13 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.7.tgz", - "integrity": "sha512-UV9Lg53zyebzD1DwQoT9mzkEKa922LNUp5YkTJ6Uta0RbyXaQNUgcvSt7qIu1PpPzVb6rd10OVNTzkyBGeVmxQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", + "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -433,12 +393,12 @@ } }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.7.tgz", - "integrity": "sha512-GDDWeVLNxRIkQTnJn2pDOM1pkCgYdSqPeT1a9vh9yIqu2uzzgw1zcqEb+IJOhy+dTBMlNdThrDIksr2o09qrrQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", + "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -448,12 +408,12 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.7.tgz", - "integrity": "sha512-wxyWg2RYaSUYgmd9MR0FyRGyeOMQE/Uzr1wzd/g5cf5bwi9A4v6HFdDm7y1MgDtod/fLOSTZY6jDgV0xU9d5bA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", + "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -463,14 +423,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.7.tgz", - "integrity": "sha512-Xwg6tZpLxc4iQjorYsyGMyfJE7nP5MV8t/Ka58BgiA7Jw0fRqQNcANlLfdJ/yvBt9z9LD2We+BEkT7vLqZRWng==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", - "@babel/plugin-transform-optional-chaining": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -480,13 +440,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.7.tgz", - "integrity": "sha512-UVATLMidXrnH+GMUIuxq55nejlj02HP7F5ETyBONzP6G87fPBogG4CH6kxrSrdIuAjdwNO9VzyaYsrZPscWUrw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", + "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -507,76 +467,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.7.tgz", - "integrity": "sha512-ZvZQRmME0zfJnDQnVBKYzHxXT7lYBB3Revz1GuS7oLXWMgqUPX4G+DDbT30ICClht9WKV34QVrZhSw6WdklwZQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", + "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -586,138 +483,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", - "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -743,12 +514,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.7.tgz", - "integrity": "sha512-EJN2mKxDwfOUCPxMO6MUI58RN3ganiRAG/MS/S3HfB6QFNjroAMelQo/gybyYq97WerCBAZoyrAoW8Tzdq2jWg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", + "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -758,15 +529,14 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.7.tgz", - "integrity": "sha512-4B6OhTrwYKHYYgcwErvZjbmH9X5TxQBsaBHdzEIB4l71gR5jh/tuHGlb9in47udL2+wVUcOz5XXhhfhVJwEpEg==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz", + "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-remap-async-to-generator": "^7.25.7", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/traverse": "^7.25.7" + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.26.8" }, "engines": { "node": ">=6.9.0" @@ -776,14 +546,14 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.7.tgz", - "integrity": "sha512-ZUCjAavsh5CESCmi/xCpX1qcCaAglzs/7tmuvoFnJgA1dM7gQplsguljoTg+Ru8WENpX89cQyAtWoaE0I3X3Pg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-remap-async-to-generator": "^7.25.7" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -793,12 +563,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.7.tgz", - "integrity": "sha512-xHttvIM9fvqW+0a3tZlYcZYSBpSWzGBFIt/sYG3tcdSzBB8ZeVgz2gBP7Df+sM0N1850jrviYSSeUuc+135dmQ==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz", + "integrity": "sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -808,12 +578,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.7.tgz", - "integrity": "sha512-ZEPJSkVZaeTFG/m2PARwLZQ+OG0vFIhPlKHK/JdIMy8DbRJ/htz6LRrTFtdzxi9EHmcwbNPAKDnadpNSIW+Aow==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.0.tgz", + "integrity": "sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -823,13 +593,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.7.tgz", - "integrity": "sha512-mhyfEW4gufjIqYFo9krXHJ3ElbFLIze5IDp+wQTxoPd+mwFb1NxatNAwmv8Q8Iuxv7Zc+q8EkiMQwc9IhyGf4g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", + "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -839,14 +609,13 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.7.tgz", - "integrity": "sha512-rvUUtoVlkDWtDWxGAiiQj0aNktTPn3eFynBcMC2IhsXweehwgdI9ODe+XjWw515kEmv22sSOTp/rxIRuTiB7zg==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", + "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-class-static-block": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -856,16 +625,16 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.7.tgz", - "integrity": "sha512-9j9rnl+YCQY0IGoeipXvnk3niWicIB6kCsWRGLwX241qSXpbA4MKxtp/EdvFxsc4zI5vqfLxzOd0twIJ7I99zg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", + "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-replace-supers": "^7.25.7", - "@babel/traverse": "^7.25.7", + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/traverse": "^7.25.9", "globals": "^11.1.0" }, "engines": { @@ -876,13 +645,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.7.tgz", - "integrity": "sha512-QIv+imtM+EtNxg/XBKL3hiWjgdLjMOmZ+XzQwSgmBfKbfxUjBzGgVPklUuE55eq5/uVoh8gg3dqlrwR/jw3ZeA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", + "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/template": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/template": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -892,12 +661,12 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.7.tgz", - "integrity": "sha512-xKcfLTlJYUczdaM1+epcdh1UGewJqr9zATgrNHcLBcV2QmfvPPEixo/sK/syql9cEmbr7ulu5HMFG5vbbt/sEA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", + "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -907,13 +676,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.7.tgz", - "integrity": "sha512-kXzXMMRzAtJdDEgQBLF4oaiT6ZCU3oWHgpARnTKDAqPkDJ+bs3NrZb310YYevR5QlRo3Kn7dzzIdHbZm1VzJdQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", + "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -923,12 +692,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.7.tgz", - "integrity": "sha512-by+v2CjoL3aMnWDOyCIg+yxU9KXSRa9tN6MbqggH5xvymmr9p4AMjYkNlQy4brMceBnUyHZ9G8RnpvT8wP7Cfg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", + "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -938,13 +707,13 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.7.tgz", - "integrity": "sha512-HvS6JF66xSS5rNKXLqkk7L9c/jZ/cdIVIcoPVrnl8IsVpLggTjXs8OWekbLHs/VtYDDh5WXnQyeE3PPUGm22MA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -954,13 +723,12 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.7.tgz", - "integrity": "sha512-UvcLuual4h7/GfylKm2IAA3aph9rwvAM2XBA0uPKU3lca+Maai4jBjjEVUS568ld6kJcgbouuumCBhMd/Yz17w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", + "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -970,13 +738,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.7.tgz", - "integrity": "sha512-yjqtpstPfZ0h/y40fAXRv2snciYr0OAoMXY/0ClC7tm4C/nG5NJKmIItlaYlLbIVAWNfrYuy9dq1bE0SbX0PEg==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", + "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", "license": "MIT", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -986,13 +753,12 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.7.tgz", - "integrity": "sha512-h3MDAP5l34NQkkNulsTNyjdaR+OiB0Im67VU//sFupouP8Q6m9Spy7l66DcaAQxtmCqGdanPByLsnwFttxKISQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", + "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1002,13 +768,13 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.7.tgz", - "integrity": "sha512-n/TaiBGJxYFWvpJDfsxSj9lEEE44BFM1EPGz4KEiTipTgkoFVVcCmzAL3qA7fdQU96dpo4gGf5HBx/KnDvqiHw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz", + "integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1018,14 +784,14 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.7.tgz", - "integrity": "sha512-5MCTNcjCMxQ63Tdu9rxyN6cAWurqfrDZ76qvVPrGYdBxIj+EawuuxTu/+dgJlhK5eRz3v1gLwp6XwS8XaX2NiQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", + "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1035,13 +801,12 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.7.tgz", - "integrity": "sha512-Ot43PrL9TEAiCe8C/2erAjXMeVSnE/BLEx6eyrKLNFCCw5jvhTHKyHxdI1pA0kz5njZRYAnMO2KObGqOCRDYSA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", + "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-json-strings": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1051,12 +816,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.7.tgz", - "integrity": "sha512-fwzkLrSu2fESR/cm4t6vqd7ebNIopz2QHGtjoU+dswQo/P6lwAG04Q98lliE3jkz/XqnbGFLnUcE0q0CVUf92w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", + "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1066,13 +831,12 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.7.tgz", - "integrity": "sha512-iImzbA55BjiovLyG2bggWS+V+OLkaBorNvc/yJoeeDQGztknRnDdYfp2d/UPmunZYEnZi6Lg8QcTmNMHOB0lGA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", + "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1082,12 +846,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.7.tgz", - "integrity": "sha512-Std3kXwpXfRV0QtQy5JJcRpkqP8/wG4XL7hSKZmGlxPlDqmpXtEPRmhF7ztnlTCtUN3eXRUJp+sBEZjaIBVYaw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", + "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1097,13 +861,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.7.tgz", - "integrity": "sha512-CgselSGCGzjQvKzghCvDTxKHP3iooenLpJDO842ehn5D2G5fJB222ptnDwQho0WjEvg7zyoxb9P+wiYxiJX5yA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", + "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1113,14 +877,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.7.tgz", - "integrity": "sha512-L9Gcahi0kKFYXvweO6n0wc3ZG1ChpSFdgG+eV1WYZ3/dGbJK7vvk91FgGgak8YwRgrCuihF8tE/Xg07EkL5COg==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", + "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-simple-access": "^7.25.7" + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1130,15 +893,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.7.tgz", - "integrity": "sha512-t9jZIvBmOXJsiuyOwhrIGs8dVcD6jDyg2icw1VL4A/g+FnWyJKwUfSSU2nwJuMV2Zqui856El9u+ElB+j9fV1g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", + "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1148,13 +911,13 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.7.tgz", - "integrity": "sha512-p88Jg6QqsaPh+EB7I9GJrIqi1Zt4ZBHUQtjw3z1bzEXcLh6GfPqzZJ6G+G1HBGKUNukT58MnKG7EN7zXQBCODw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", + "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1164,13 +927,13 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.7.tgz", - "integrity": "sha512-BtAT9LzCISKG3Dsdw5uso4oV1+v2NlVXIIomKJgQybotJY3OwCwJmkongjHgwGKoZXd0qG5UZ12JUlDQ07W6Ow==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1180,12 +943,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.7.tgz", - "integrity": "sha512-CfCS2jDsbcZaVYxRFo2qtavW8SpdzmBXC2LOI4oO0rP+JSRDxxF3inF4GcPsLgfb5FjkhXG5/yR/lxuRs2pySA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", + "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1195,13 +958,12 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.7.tgz", - "integrity": "sha512-FbuJ63/4LEL32mIxrxwYaqjJxpbzxPVQj5a+Ebrc8JICV6YX8nE53jY+K0RZT3um56GoNWgkS2BQ/uLGTjtwfw==", + "version": "7.26.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz", + "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1211,13 +973,12 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.7.tgz", - "integrity": "sha512-8CbutzSSh4hmD+jJHIA8vdTNk15kAzOnFLVVgBSMGr28rt85ouT01/rezMecks9pkU939wDInImwCKv4ahU4IA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", + "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1227,15 +988,14 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.7.tgz", - "integrity": "sha512-1JdVKPhD7Y5PvgfFy0Mv2brdrolzpzSoUq2pr6xsR+m+3viGGeHEokFKsCgOkbeFOQxfB1Vt2F0cPJLRpFI4Zg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", + "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.25.7" + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1245,13 +1005,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.7.tgz", - "integrity": "sha512-pWT6UXCEW3u1t2tcAGtE15ornCBvopHj9Bps9D2DsH15APgNVOTwwczGckX+WkAvBmuoYKRCFa4DK+jM8vh5AA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", + "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-replace-supers": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1261,13 +1021,12 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.7.tgz", - "integrity": "sha512-m9obYBA39mDPN7lJzD5WkGGb0GO54PPLXsbcnj1Hyeu8mSRz7Gb4b1A6zxNX32ZuUySDK4G6it8SDFWD1nCnqg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", + "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1277,14 +1036,13 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.7.tgz", - "integrity": "sha512-h39agClImgPWg4H8mYVAbD1qP9vClFbEjqoJmt87Zen8pjqK8FTPUwrOXAvqu5soytwxrLMd2fx2KSCp2CHcNg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1294,12 +1052,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.7.tgz", - "integrity": "sha512-FYiTvku63me9+1Nz7TOx4YMtW3tWXzfANZtrzHhUZrz4d47EEtMQhzFoZWESfXuAMMT5mwzD4+y1N8ONAX6lMQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", + "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1309,13 +1067,13 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz", - "integrity": "sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", + "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1325,15 +1083,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.7.tgz", - "integrity": "sha512-LzA5ESzBy7tqj00Yjey9yWfs3FKy4EmJyKOSWld144OxkTji81WWnUT8nkLUn+imN/zHL8ZQlOu/MTUAhHaX3g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", + "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1343,12 +1100,12 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.7.tgz", - "integrity": "sha512-lQEeetGKfFi0wHbt8ClQrUSUMfEeI3MMm74Z73T9/kuz990yYVtfofjf3NuA42Jy3auFOpbjDyCSiIkTs1VIYw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", + "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1358,12 +1115,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.7.tgz", - "integrity": "sha512-mgDoQCRjrY3XK95UuV60tZlFCQGXEtMg8H+IsW72ldw1ih1jZhzYXbJvghmAEpg5UVhhnCeia1CkGttUvCkiMQ==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.0.tgz", + "integrity": "sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-plugin-utils": "^7.26.5", "regenerator-transform": "^0.15.2" }, "engines": { @@ -1373,13 +1130,29 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.7.tgz", - "integrity": "sha512-3OfyfRRqiGeOvIWSagcwUTVk2hXBsr/ww7bLn6TRTuXnexA+Udov2icFOxFX9abaj4l96ooYkcNN1qi2Zvqwng==", + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", + "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", + "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1389,12 +1162,12 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.7.tgz", - "integrity": "sha512-uBbxNwimHi5Bv3hUccmOFlUy3ATO6WagTApenHz9KzoIdn0XeACdB12ZJ4cjhuB2WSi80Ez2FWzJnarccriJeA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", + "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1404,13 +1177,13 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.7.tgz", - "integrity": "sha512-Mm6aeymI0PBh44xNIv/qvo8nmbkpZze1KvR8MkEqbIREDxoiWTi18Zr2jryfRMwDfVZF9foKh060fWgni44luw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", + "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1420,12 +1193,12 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.7.tgz", - "integrity": "sha512-ZFAeNkpGuLnAQ/NCsXJ6xik7Id+tHuS+NT+ue/2+rn/31zcdnupCdmunOizEaP0JsUmTFSTOPoQY7PkK2pttXw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", + "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1435,12 +1208,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.7.tgz", - "integrity": "sha512-SI274k0nUsFFmyQupiO7+wKATAmMFf8iFgq2O+vVFXZ0SV9lNfT1NGzBEhjquFmD8I9sqHLguH+gZVN3vww2AA==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz", + "integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1450,12 +1223,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.7.tgz", - "integrity": "sha512-OmWmQtTHnO8RSUbL0NTdtpbZHeNTnm68Gj5pA4Y2blFNh+V4iZR68V1qL9cI37J21ZN7AaCnkfdHtLExQPf2uA==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.0.tgz", + "integrity": "sha512-+LLkxA9rKJpNoGsbLnAgOCdESl73vwYn+V6b+5wHbrE7OGKVDPHIQvbFSzqE6rwqaCw2RE+zdJrlLkcf8YOA0w==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1465,12 +1238,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.7.tgz", - "integrity": "sha512-BN87D7KpbdiABA+t3HbVqHzKWUDN3dymLaTnPFAMyc8lV+KN3+YzNhVRNdinaCPA4AUqx7ubXbQ9shRjYBl3SQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", + "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1480,13 +1253,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.7.tgz", - "integrity": "sha512-IWfR89zcEPQGB/iB408uGtSPlQd3Jpq11Im86vUgcmSTcoWAiQMCTOa2K2yNNqFJEBVICKhayctee65Ka8OB0w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", + "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1496,13 +1269,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.7.tgz", - "integrity": "sha512-8JKfg/hiuA3qXnlLx8qtv5HWRbgyFx2hMMtpDDuU2rTckpKkGu4ycK5yYHwuEa16/quXfoxHBIApEsNyMWnt0g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", + "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1512,13 +1285,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.7.tgz", - "integrity": "sha512-YRW8o9vzImwmh4Q3Rffd09bH5/hvY0pxg+1H1i0f7APoUeg12G7+HhLj9ZFNIrYkgBXhIijPJ+IXypN0hLTIbw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", + "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1528,93 +1301,79 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.7.tgz", - "integrity": "sha512-Gibz4OUdyNqqLj+7OAvBZxOD7CklCtMA5/j0JgUEwOnaRULsPDXmic2iKxL2DX2vQduPR5wH2hjZas/Vr/Oc0g==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz", + "integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.7", - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-validator-option": "^7.25.7", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.7", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.7", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.7", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.7", + "@babel/compat-data": "^7.26.8", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.25.7", - "@babel/plugin-syntax-import-attributes": "^7.25.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.25.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.7", - "@babel/plugin-transform-async-to-generator": "^7.25.7", - "@babel/plugin-transform-block-scoped-functions": "^7.25.7", - "@babel/plugin-transform-block-scoping": "^7.25.7", - "@babel/plugin-transform-class-properties": "^7.25.7", - "@babel/plugin-transform-class-static-block": "^7.25.7", - "@babel/plugin-transform-classes": "^7.25.7", - "@babel/plugin-transform-computed-properties": "^7.25.7", - "@babel/plugin-transform-destructuring": "^7.25.7", - "@babel/plugin-transform-dotall-regex": "^7.25.7", - "@babel/plugin-transform-duplicate-keys": "^7.25.7", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.7", - "@babel/plugin-transform-dynamic-import": "^7.25.7", - "@babel/plugin-transform-exponentiation-operator": "^7.25.7", - "@babel/plugin-transform-export-namespace-from": "^7.25.7", - "@babel/plugin-transform-for-of": "^7.25.7", - "@babel/plugin-transform-function-name": "^7.25.7", - "@babel/plugin-transform-json-strings": "^7.25.7", - "@babel/plugin-transform-literals": "^7.25.7", - "@babel/plugin-transform-logical-assignment-operators": "^7.25.7", - "@babel/plugin-transform-member-expression-literals": "^7.25.7", - "@babel/plugin-transform-modules-amd": "^7.25.7", - "@babel/plugin-transform-modules-commonjs": "^7.25.7", - "@babel/plugin-transform-modules-systemjs": "^7.25.7", - "@babel/plugin-transform-modules-umd": "^7.25.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.7", - "@babel/plugin-transform-new-target": "^7.25.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.7", - "@babel/plugin-transform-numeric-separator": "^7.25.7", - "@babel/plugin-transform-object-rest-spread": "^7.25.7", - "@babel/plugin-transform-object-super": "^7.25.7", - "@babel/plugin-transform-optional-catch-binding": "^7.25.7", - "@babel/plugin-transform-optional-chaining": "^7.25.7", - "@babel/plugin-transform-parameters": "^7.25.7", - "@babel/plugin-transform-private-methods": "^7.25.7", - "@babel/plugin-transform-private-property-in-object": "^7.25.7", - "@babel/plugin-transform-property-literals": "^7.25.7", - "@babel/plugin-transform-regenerator": "^7.25.7", - "@babel/plugin-transform-reserved-words": "^7.25.7", - "@babel/plugin-transform-shorthand-properties": "^7.25.7", - "@babel/plugin-transform-spread": "^7.25.7", - "@babel/plugin-transform-sticky-regex": "^7.25.7", - "@babel/plugin-transform-template-literals": "^7.25.7", - "@babel/plugin-transform-typeof-symbol": "^7.25.7", - "@babel/plugin-transform-unicode-escapes": "^7.25.7", - "@babel/plugin-transform-unicode-property-regex": "^7.25.7", - "@babel/plugin-transform-unicode-regex": "^7.25.7", - "@babel/plugin-transform-unicode-sets-regex": "^7.25.7", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.26.8", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.26.5", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.26.3", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.26.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.26.8", + "@babel/plugin-transform-typeof-symbol": "^7.26.7", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-corejs3": "^0.11.0", "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.38.1", + "core-js-compat": "^3.40.0", "semver": "^6.3.1" }, "engines": { @@ -1639,9 +1398,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", - "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -1651,30 +1410,30 @@ } }, "node_modules/@babel/template": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", - "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", - "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/generator": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/template": "^7.25.7", - "@babel/types": "^7.25.7", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -1683,24 +1442,26 @@ } }, "node_modules/@babel/types": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", - "integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "license": "MIT" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -1808,9 +1569,9 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", @@ -1892,18 +1653,18 @@ } }, "node_modules/@rollup/plugin-commonjs": { - "version": "28.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.0.tgz", - "integrity": "sha512-BJcu+a+Mpq476DMXG+hevgPSl56bkUoi88dKT8t3RyUp8kGuOh+2bU8Gs7zXDlu+fyZggnJ+iOBGrb/O1SorYg==", + "version": "28.0.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.3.tgz", + "integrity": "sha512-pyltgilam1QPdn+Zd9gaCfOLcnjMEJ9gV+bTw6/r73INdvzf1ah9zLIJBm+kW7R6IUFIQ1YO+VqZtYxZNWFPEQ==", "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", - "fdir": "^6.1.1", + "fdir": "^6.2.0", "is-reference": "1.2.1", "magic-string": "^0.30.3", - "picomatch": "^2.3.1" + "picomatch": "^4.0.2" }, "engines": { "node": ">=16.0.0 || 14 >= 14.17" @@ -1917,22 +1678,10 @@ } } }, - "node_modules/@rollup/plugin-commonjs/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/@rollup/plugin-node-resolve": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz", - "integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==", + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz", + "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.0.1", @@ -1954,14 +1703,14 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz", - "integrity": "sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", + "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" + "picomatch": "^4.0.2" }, "engines": { "node": ">=14.0.0" @@ -1975,22 +1724,10 @@ } } }, - "node_modules/@rollup/pluginutils/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", - "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz", + "integrity": "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==", "cpu": [ "arm" ], @@ -2001,9 +1738,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", - "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.0.tgz", + "integrity": "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==", "cpu": [ "arm64" ], @@ -2014,9 +1751,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", - "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.0.tgz", + "integrity": "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==", "cpu": [ "arm64" ], @@ -2027,9 +1764,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", - "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.0.tgz", + "integrity": "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==", "cpu": [ "x64" ], @@ -2039,10 +1776,36 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.0.tgz", + "integrity": "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.0.tgz", + "integrity": "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", - "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.0.tgz", + "integrity": "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==", "cpu": [ "arm" ], @@ -2053,9 +1816,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", - "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.0.tgz", + "integrity": "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==", "cpu": [ "arm" ], @@ -2066,9 +1829,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", - "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.0.tgz", + "integrity": "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==", "cpu": [ "arm64" ], @@ -2079,9 +1842,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", - "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.0.tgz", + "integrity": "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==", "cpu": [ "arm64" ], @@ -2091,10 +1854,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.0.tgz", + "integrity": "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", - "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.0.tgz", + "integrity": "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==", "cpu": [ "ppc64" ], @@ -2105,9 +1881,22 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", - "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.0.tgz", + "integrity": "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.0.tgz", + "integrity": "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==", "cpu": [ "riscv64" ], @@ -2118,9 +1907,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", - "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.0.tgz", + "integrity": "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==", "cpu": [ "s390x" ], @@ -2131,9 +1920,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", - "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz", + "integrity": "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==", "cpu": [ "x64" ], @@ -2144,9 +1933,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", - "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.0.tgz", + "integrity": "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==", "cpu": [ "x64" ], @@ -2157,9 +1946,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", - "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.0.tgz", + "integrity": "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==", "cpu": [ "arm64" ], @@ -2170,9 +1959,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", - "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.0.tgz", + "integrity": "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==", "cpu": [ "ia32" ], @@ -2183,9 +1972,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", - "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.0.tgz", + "integrity": "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==", "cpu": [ "x64" ], @@ -2196,16 +1985,19 @@ ] }, "node_modules/@types/chai": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.0.0.tgz", - "integrity": "sha512-+DwhEHAaFPPdJ2ral3kNHFQXnTfscEEFsUxzD+d7nlcLrFK23JtNjH71RGasTcHb88b4vVi4mTyfpf8u2L8bdA==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.1.tgz", + "integrity": "sha512-iu1JLYmGmITRzUgNiLMZD3WCoFzpYtueuyAgHTXqgwSRAMIlFTnZqG6/xenkpUGRJEzSfklUTI4GNSzks/dc0w==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*" + } }, "node_modules/@types/chai-as-promised": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-8.0.1.tgz", - "integrity": "sha512-dAlDhLjJlABwAVYObo9TPWYTRg9NaQM5CXeaeJYcYAkvzUf0JRLIiog88ao2Wqy/20WUnhbbUZcgvngEbJ3YXQ==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-8.0.2.tgz", + "integrity": "sha512-meQ1wDr1K5KRCSvG2lX7n7/5wf70BeptTKst0axGvnN6zqaVpRqegoIbugiAPSqOW9K9aL8gDVrm7a2LXOtn2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2222,10 +2014,17 @@ "@types/chai": "*" } }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "license": "MIT" }, "node_modules/@types/istanbul-lib-coverage": { @@ -2235,9 +2034,9 @@ "license": "MIT" }, "node_modules/@types/mocha": { - "version": "10.0.9", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.9.tgz", - "integrity": "sha512-sicdRoWtYevwxjOHNMPTl3vSfJM6oyW8o1wXeI7uww6b6xHg8eBznQDNSGBCDJmsE8UMxP05JgZRtsKbTqt//Q==", + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", + "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", "dev": true, "license": "MIT" }, @@ -2267,15 +2066,18 @@ } }, "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", "dependencies": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/anymatch": { @@ -2323,13 +2125,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.13.tgz", + "integrity": "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==", "license": "MIT", "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", + "@babel/helper-define-polyfill-provider": "^0.6.4", "semver": "^6.3.1" }, "peerDependencies": { @@ -2337,25 +2139,25 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", - "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", + "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2", - "core-js-compat": "^3.38.0" + "@babel/helper-define-polyfill-provider": "^0.6.3", + "core-js-compat": "^3.40.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", - "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.4.tgz", + "integrity": "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==", "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2" + "@babel/helper-define-polyfill-provider": "^0.6.4" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -2410,9 +2212,9 @@ "license": "ISC" }, "node_modules/browserslist": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", - "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "funding": [ { "type": "opencollective", @@ -2429,10 +2231,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001663", - "electron-to-chromium": "^1.5.28", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -2442,12 +2244,12 @@ } }, "node_modules/c8": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.2.tgz", - "integrity": "sha512-Qr6rj76eSshu5CgRYvktW0uM0CFY0yi4Fd5D0duDXO6sYinyopmftUiJVuzBQxQcwQLor7JWDVRP+dUfCmzgJw==", + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.3.tgz", + "integrity": "sha512-LvcyrOAaOnrrlMpW22n690PUvxiq4Uf9WMhQwNJ9vgagkL/ph1+D4uvjvDA5XCbykrc0sx+ay6pVi9YZ1GnhyA==", "license": "ISC", "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", + "@bcoe/v8-coverage": "^1.0.1", "@istanbuljs/schema": "^0.1.3", "find-up": "^5.0.0", "foreground-child": "^3.1.1", @@ -2488,9 +2290,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001667", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz", - "integrity": "sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==", + "version": "1.0.30001715", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001715.tgz", + "integrity": "sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==", "funding": [ { "type": "opencollective", @@ -2508,9 +2310,9 @@ "license": "CC-BY-4.0" }, "node_modules/chai": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", - "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", + "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", "dev": true, "license": "MIT", "dependencies": { @@ -2525,11 +2327,11 @@ } }, "node_modules/chai-as-promised": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-8.0.0.tgz", - "integrity": "sha512-sMsGXTrS3FunP/wbqh/KxM8Kj/aLPXQGkNtvE5wPfSToq8wkkvBpTZo1LIiEVmC4BwkKpag+l5h/20lBMk6nUg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-8.0.1.tgz", + "integrity": "sha512-OIEJtOL8xxJSH8JJWbIoRjybbzR52iFuDHuF8eb+nTPD6tgXLjRqsgnUGqQfFODxYvq5QdirT0pN9dZ0+Gz6rA==", "dev": true, - "license": "WTFPL", + "license": "MIT", "dependencies": { "check-error": "^2.0.0" }, @@ -2551,17 +2353,20 @@ } }, "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/check-error": { @@ -2614,18 +2419,21 @@ } }, "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, "node_modules/commondir": { @@ -2641,12 +2449,12 @@ "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", - "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "version": "3.41.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.41.0.tgz", + "integrity": "sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==", "license": "MIT", "dependencies": { - "browserslist": "^4.23.3" + "browserslist": "^4.24.4" }, "funding": { "type": "opencollective", @@ -2654,9 +2462,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -2668,9 +2476,9 @@ } }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2733,9 +2541,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.34", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.34.tgz", - "integrity": "sha512-/TZAiChbAflBNjCg+VvstbcwAtIL/VdMFO3NgRFIzBjpvPzWOTIbbO8kNb6RwU4bt9TP7K+3KqBKw/lOU+Y+GA==", + "version": "1.5.140", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.140.tgz", + "integrity": "sha512-o82Rj+ONp4Ip7Cl1r7lrqx/pXhbp/lh9DpKcMNscFJdh8ebyRofnc7Sh01B4jx403RI0oqTBvlZ7OBIZLMr2+Q==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -2754,12 +2562,16 @@ } }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/esm": { @@ -2788,9 +2600,9 @@ } }, "node_modules/fdir": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.0.tgz", - "integrity": "sha512-3oB133prH1o4j/L5lLW7uOCF1PlD+/It2L0eL/iAqWMB91RBbqTewABqxhj0ibBd90EEmWZq7ntIWzVaWcXTGQ==", + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", "license": "MIT", "peerDependencies": { "picomatch": "^3 || ^4" @@ -2841,12 +2653,12 @@ } }, "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -2949,12 +2761,12 @@ } }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/hasown": { @@ -3018,9 +2830,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -3141,27 +2953,6 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/istanbul-reports": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", @@ -3233,9 +3024,9 @@ } }, "node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -3295,86 +3086,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/loupe": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", - "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", "dev": true, "license": "MIT" }, @@ -3388,9 +3103,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" @@ -3412,9 +3127,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -3446,9 +3161,9 @@ } }, "node_modules/mocha": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz", - "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", "dev": true, "license": "MIT", "dependencies": { @@ -3493,29 +3208,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -3568,9 +3260,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "license": "MIT" }, "node_modules/normalize-path": { @@ -3695,9 +3387,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { @@ -3705,8 +3397,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "license": "MIT", - "optional": true, - "peer": true, "engines": { "node": ">=12" }, @@ -3784,15 +3474,15 @@ } }, "node_modules/regexpu-core": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", - "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", + "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", "license": "MIT", "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.0", "regjsgen": "^0.8.0", - "regjsparser": "^0.11.0", + "regjsparser": "^0.12.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" }, @@ -3807,9 +3497,9 @@ "license": "MIT" }, "node_modules/regjsparser": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.1.tgz", - "integrity": "sha512-1DHODs4B8p/mQHU9kr+jv8+wIC9mtG4eBHxWxIq5mhjE3D5oORhCc6deRKzTjs9DcfRFmj9BHSDguZklqCGFWQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", + "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", "license": "BSD-2-Clause", "dependencies": { "jsesc": "~3.0.2" @@ -3818,6 +3508,18 @@ "regjsparser": "bin/parser" } }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3828,29 +3530,32 @@ } }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/rollup": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", - "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.0.tgz", + "integrity": "sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==", "license": "MIT", "dependencies": { - "@types/estree": "1.0.6" + "@types/estree": "1.0.7" }, "bin": { "rollup": "dist/bin/rollup" @@ -3860,22 +3565,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.24.0", - "@rollup/rollup-android-arm64": "4.24.0", - "@rollup/rollup-darwin-arm64": "4.24.0", - "@rollup/rollup-darwin-x64": "4.24.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", - "@rollup/rollup-linux-arm-musleabihf": "4.24.0", - "@rollup/rollup-linux-arm64-gnu": "4.24.0", - "@rollup/rollup-linux-arm64-musl": "4.24.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", - "@rollup/rollup-linux-riscv64-gnu": "4.24.0", - "@rollup/rollup-linux-s390x-gnu": "4.24.0", - "@rollup/rollup-linux-x64-gnu": "4.24.0", - "@rollup/rollup-linux-x64-musl": "4.24.0", - "@rollup/rollup-win32-arm64-msvc": "4.24.0", - "@rollup/rollup-win32-ia32-msvc": "4.24.0", - "@rollup/rollup-win32-x64-msvc": "4.24.0", + "@rollup/rollup-android-arm-eabi": "4.40.0", + "@rollup/rollup-android-arm64": "4.40.0", + "@rollup/rollup-darwin-arm64": "4.40.0", + "@rollup/rollup-darwin-x64": "4.40.0", + "@rollup/rollup-freebsd-arm64": "4.40.0", + "@rollup/rollup-freebsd-x64": "4.40.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.40.0", + "@rollup/rollup-linux-arm-musleabihf": "4.40.0", + "@rollup/rollup-linux-arm64-gnu": "4.40.0", + "@rollup/rollup-linux-arm64-musl": "4.40.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.40.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.40.0", + "@rollup/rollup-linux-riscv64-gnu": "4.40.0", + "@rollup/rollup-linux-riscv64-musl": "4.40.0", + "@rollup/rollup-linux-s390x-gnu": "4.40.0", + "@rollup/rollup-linux-x64-gnu": "4.40.0", + "@rollup/rollup-linux-x64-musl": "4.40.0", + "@rollup/rollup-win32-arm64-msvc": "4.40.0", + "@rollup/rollup-win32-ia32-msvc": "4.40.0", + "@rollup/rollup-win32-x64-msvc": "4.40.0", "fsevents": "~2.3.2" } }, @@ -4067,15 +3776,15 @@ } }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -4139,15 +3848,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4202,9 +3902,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "funding": [ { "type": "opencollective", @@ -4222,7 +3922,7 @@ "license": "MIT", "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -4302,72 +4002,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", From 70333a4e4145bbc3e60ca55610699c19f0b9aeea Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 22 Apr 2025 04:47:27 +0200 Subject: [PATCH 098/104] Fixing opening files on Windows (regression) --- .../qml/eu/ad5001/LogarithmPlotter/Settings.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml index 58db0e9..64e9f61 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml @@ -130,7 +130,9 @@ ScrollView { Popup.FileDialog { id: fdiag onAccepted: { - var filePath = fdiag.currentFile.toString().substr(7) + let filePath = fdiag.currentFile.toString().substr(7) + if(filePath.at(2) === ":") // Windows path, remove the leading slash. + filePath = filePath.substr(1) Modules.Settings.set("saveFilename", filePath) if(exportMode) { Modules.IO.saveDiagram(filePath) From 04e070058ebae83561edaa402836068b9ae03bec Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 22 Apr 2025 04:49:47 +0200 Subject: [PATCH 099/104] Fixing LaTeX rendering on windows. --- runtime-pyside6/LogarithmPlotter/util/latex.py | 4 ++-- runtime-pyside6/tests/test_latex.py | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/runtime-pyside6/LogarithmPlotter/util/latex.py b/runtime-pyside6/LogarithmPlotter/util/latex.py index b446295..5b127dc 100644 --- a/runtime-pyside6/LogarithmPlotter/util/latex.py +++ b/runtime-pyside6/LogarithmPlotter/util/latex.py @@ -195,7 +195,7 @@ class Latex(QObject): # self.convert_dvi_to_png(latex_path, export_path+"@4", font_size*4, color) img = QImage(export_path) # Small hack, not very optimized since we load the image twice, but you can't pass a QImage to QML and expect it to be loaded - return f'{export_path}.png,{img.width()},{img.height()}' + return f'file:///{export_path}.png,{img.width()},{img.height()}' @Slot(str, float, QColor, result=str) def findPrerendered(self, latex_markup: str, font_size: float, color: QColor) -> str: @@ -206,7 +206,7 @@ class Latex(QObject): data = "" if path.exists(export_path + ".png"): img = QImage(export_path) - data = f'{export_path}.png,{img.width()},{img.height()}' + data = f'file:///{export_path}.png,{img.width()},{img.height()}' return data def create_export_path(self, latex_markup: str, font_size: float, color: QColor): diff --git a/runtime-pyside6/tests/test_latex.py b/runtime-pyside6/tests/test_latex.py index 4ffbc6c..e410995 100644 --- a/runtime-pyside6/tests/test_latex.py +++ b/runtime-pyside6/tests/test_latex.py @@ -47,7 +47,8 @@ def check_render_results(result): result = result.toVariant() assert type(result) == str [path, width, height] = result.split(",") - assert exists(path) + assert path.startswith("file:///") + assert exists(path[len("file:///"):]) assert match(r"\d+", width) assert match(r"\d+", height) return True @@ -92,10 +93,7 @@ class TestLatex: latex_obj.renderSync(*args) prerendered = latex_obj.findPrerendered(*args) assert type(prerendered) == str - [path, width, height] = prerendered.split(",") - assert exists(path) - assert match(r"\d+", width) - assert match(r"\d+", height) + check_render_results(prerendered) prerendered2 = latex_obj.findPrerendered(args[0], args[1]+2, args[2]) assert prerendered2 == "" From 5586f0c21432eb2b9a67331d795117afef21d146 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 22 Apr 2025 05:08:19 +0200 Subject: [PATCH 100/104] Fixing issue with Repeater refusing to use ES classes as values. --- common/src/parameters.mjs | 2 +- .../ObjectLists/Editor/CustomPropertyList.qml | 12 +++++++++--- .../LogarithmPlotter/ObjectLists/Editor/Dialog.qml | 5 +++-- .../LogarithmPlotter/ObjectLists/ObjectLists.qml | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/common/src/parameters.mjs b/common/src/parameters.mjs index 0da11a8..755d4aa 100644 --- a/common/src/parameters.mjs +++ b/common/src/parameters.mjs @@ -377,4 +377,4 @@ export function serializesByPropertyType(propertyType, value) { } else throw new TypeError(`Exportation error: Unknown property type ${propertyType}.`) return result -} \ No newline at end of file +} diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml index 6e33b71..113b8bd 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml @@ -41,6 +41,12 @@ Repeater { Object whose properties to list and edit. */ property var obj + + /*! + \qmlproperty var CustomPropertyList::objPropertyTypes + Record containing the properties types of the object mapped by their name. + */ + property var objPropertyTypes /*! \qmlproperty var CustomPropertyList::positionPicker Reference to the global PositionPicker QML object. @@ -280,15 +286,15 @@ Repeater { Loader { id: propertyEditor width: dlgProperties.width - pointerButton.width - property string propertyName: modelData[0] - property var propertyType: modelData[1] + property string propertyName: modelData + property var propertyType: objPropertyTypes[modelData] property string propertyLabel: qsTranslate('prop',propertyName) property string propertyIcon: propertyName sourceComponent: { if(propertyName.startsWith('comment')) return commentComponent - else if(propertyType == 'boolean') + else if(propertyType === 'boolean') return checkboxComponent else if(paramTypeIn(propertyType, ['Expression'])) return expressionEditorComponent diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml index d762da2..a5352d4 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml @@ -164,8 +164,9 @@ Popup.BaseDialog { */ function open() { dlgCustomProperties.model = [] // Reset - let objProps = Modules.Objects.types[objEditor.objType].properties() - dlgCustomProperties.model = Object.keys(objProps).map(prop => [prop, objProps[prop]]) // Converted to 2-dimentional array. + const objProps = Modules.Objects.types[objEditor.objType].properties() + dlgCustomProperties.objPropertyTypes = objProps + dlgCustomProperties.model = Object.keys(objProps) objEditor.show() } } diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml index d37a015..8047573 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml @@ -140,7 +140,7 @@ ScrollView { */ function paramTypeIn(parameter, types = []) { if(types.includes(parameter.toString())) return true - if(typeof parameter == 'object' && 'type' in parameter) + if(typeof parameter === 'object' && 'type' in parameter) return types.includes(parameter.type) return false } From 45f01a9871b71fd55c0b3742400548cbf4044253 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 22 Apr 2025 05:20:50 +0200 Subject: [PATCH 101/104] Fixing crash when X Cursor's calculated target number is an integer. --- common/src/objs/xcursor.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/objs/xcursor.mjs b/common/src/objs/xcursor.mjs index 4ad511c..63fd182 100644 --- a/common/src/objs/xcursor.mjs +++ b/common/src/objs/xcursor.mjs @@ -78,7 +78,7 @@ export default class XCursor extends DrawableObject { if(this.approximate) { approx = (this.targetElement.execute(this.x.execute())) let intLength = Math.round(approx).toString().length - let rounding = Math.min(this.rounding, approx.toString().length - intLength - 1) + let rounding = Math.max(0, Math.min(this.rounding, approx.toString().length - intLength - 1)) approx = approx.toPrecision(rounding + intLength) } return approx From fea081045b9b1e4be7bbd44edb66f687bd5ce930 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 22 Apr 2025 22:02:20 +0200 Subject: [PATCH 102/104] Updating pyside6 version dependency. --- runtime-pyside6/pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime-pyside6/pyproject.toml b/runtime-pyside6/pyproject.toml index cafc0cb..ef68cb8 100644 --- a/runtime-pyside6/pyproject.toml +++ b/runtime-pyside6/pyproject.toml @@ -9,8 +9,8 @@ package-mode = false [tool.poetry.dependencies] python = ">=3.9,<3.13" -PySide6-Essentials = "^6.8" -PySide6-Addons = "^6.8" +PySide6-Essentials = "^6.9" +PySide6-Addons = "^6.9" [tool.poetry.group.packaging.dependencies] pyinstaller = "^6.10.0" From 328ac2b877540a3ed084d5f5ee33f65a4eb1ece0 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 22 Apr 2025 22:25:09 +0200 Subject: [PATCH 103/104] Replacing symlink by icon directly during build process (avoids symlink related bugs) --- assets/icons/logarithmplotter.svg | 1 - scripts/build.sh | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 120000 assets/icons/logarithmplotter.svg diff --git a/assets/icons/logarithmplotter.svg b/assets/icons/logarithmplotter.svg deleted file mode 120000 index 0497bab..0000000 --- a/assets/icons/logarithmplotter.svg +++ /dev/null @@ -1 +0,0 @@ -../../../../../logarithmplotter.svg \ No newline at end of file diff --git a/scripts/build.sh b/scripts/build.sh index 257b2c4..8d170bf 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -52,4 +52,5 @@ mkdir -p "$BUILD_DIR/LogarithmPlotter/i18n" && cp assets/i18n/*.qm "$BUILD_DIR/L box "Building icons..." cp -r assets/icons "$BUILD_QML_DIR" +cp assets/logarithmplotter.svg "$BUILD_QML_DIR/icons/" cp assets/logarithmplotter.svg "$BUILD_DIR/LogarithmPlotter/" From 4549257109d3f0ef7a3c457402503ed6cbb31359 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 22 Apr 2025 22:26:55 +0200 Subject: [PATCH 104/104] Updating locked pagaes. --- runtime-pyside6/poetry.lock | 296 ++++++++++++++++++++---------------- 1 file changed, 165 insertions(+), 131 deletions(-) diff --git a/runtime-pyside6/poetry.lock b/runtime-pyside6/poetry.lock index 250fc64..9a66e3e 100644 --- a/runtime-pyside6/poetry.lock +++ b/runtime-pyside6/poetry.lock @@ -24,73 +24,74 @@ files = [ [[package]] name = "coverage" -version = "7.6.4" +version = "7.8.0" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" files = [ - {file = "coverage-7.6.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f8ae553cba74085db385d489c7a792ad66f7f9ba2ee85bfa508aeb84cf0ba07"}, - {file = "coverage-7.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8165b796df0bd42e10527a3f493c592ba494f16ef3c8b531288e3d0d72c1f6f0"}, - {file = "coverage-7.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c8b95bf47db6d19096a5e052ffca0a05f335bc63cef281a6e8fe864d450a72"}, - {file = "coverage-7.6.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ed9281d1b52628e81393f5eaee24a45cbd64965f41857559c2b7ff19385df51"}, - {file = "coverage-7.6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0809082ee480bb8f7416507538243c8863ac74fd8a5d2485c46f0f7499f2b491"}, - {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d541423cdd416b78626b55f123412fcf979d22a2c39fce251b350de38c15c15b"}, - {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58809e238a8a12a625c70450b48e8767cff9eb67c62e6154a642b21ddf79baea"}, - {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c9b8e184898ed014884ca84c70562b4a82cbc63b044d366fedc68bc2b2f3394a"}, - {file = "coverage-7.6.4-cp310-cp310-win32.whl", hash = "sha256:6bd818b7ea14bc6e1f06e241e8234508b21edf1b242d49831831a9450e2f35fa"}, - {file = "coverage-7.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:06babbb8f4e74b063dbaeb74ad68dfce9186c595a15f11f5d5683f748fa1d172"}, - {file = "coverage-7.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:73d2b73584446e66ee633eaad1a56aad577c077f46c35ca3283cd687b7715b0b"}, - {file = "coverage-7.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51b44306032045b383a7a8a2c13878de375117946d68dcb54308111f39775a25"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3fb02fe73bed561fa12d279a417b432e5b50fe03e8d663d61b3d5990f29546"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed8fe9189d2beb6edc14d3ad19800626e1d9f2d975e436f84e19efb7fa19469b"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b369ead6527d025a0fe7bd3864e46dbee3aa8f652d48df6174f8d0bac9e26e0e"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ade3ca1e5f0ff46b678b66201f7ff477e8fa11fb537f3b55c3f0568fbfe6e718"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:27fb4a050aaf18772db513091c9c13f6cb94ed40eacdef8dad8411d92d9992db"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4f704f0998911abf728a7783799444fcbbe8261c4a6c166f667937ae6a8aa522"}, - {file = "coverage-7.6.4-cp311-cp311-win32.whl", hash = "sha256:29155cd511ee058e260db648b6182c419422a0d2e9a4fa44501898cf918866cf"}, - {file = "coverage-7.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:8902dd6a30173d4ef09954bfcb24b5d7b5190cf14a43170e386979651e09ba19"}, - {file = "coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2"}, - {file = "coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5"}, - {file = "coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17"}, - {file = "coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08"}, - {file = "coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9"}, - {file = "coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a"}, - {file = "coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e"}, - {file = "coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963"}, - {file = "coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f"}, - {file = "coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef"}, - {file = "coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e"}, - {file = "coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1"}, - {file = "coverage-7.6.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9cb7fa111d21a6b55cbf633039f7bc2749e74932e3aa7cb7333f675a58a58bf3"}, - {file = "coverage-7.6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11a223a14e91a4693d2d0755c7a043db43d96a7450b4f356d506c2562c48642c"}, - {file = "coverage-7.6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a413a096c4cbac202433c850ee43fa326d2e871b24554da8327b01632673a076"}, - {file = "coverage-7.6.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00a1d69c112ff5149cabe60d2e2ee948752c975d95f1e1096742e6077affd376"}, - {file = "coverage-7.6.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f76846299ba5c54d12c91d776d9605ae33f8ae2b9d1d3c3703cf2db1a67f2c0"}, - {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fe439416eb6380de434886b00c859304338f8b19f6f54811984f3420a2e03858"}, - {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0294ca37f1ba500667b1aef631e48d875ced93ad5e06fa665a3295bdd1d95111"}, - {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6f01ba56b1c0e9d149f9ac85a2f999724895229eb36bd997b61e62999e9b0901"}, - {file = "coverage-7.6.4-cp39-cp39-win32.whl", hash = "sha256:bc66f0bf1d7730a17430a50163bb264ba9ded56739112368ba985ddaa9c3bd09"}, - {file = "coverage-7.6.4-cp39-cp39-win_amd64.whl", hash = "sha256:c481b47f6b5845064c65a7bc78bc0860e635a9b055af0df46fdf1c58cebf8e8f"}, - {file = "coverage-7.6.4-pp39.pp310-none-any.whl", hash = "sha256:3c65d37f3a9ebb703e710befdc489a38683a5b152242664b973a7b7b22348a4e"}, - {file = "coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73"}, + {file = "coverage-7.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2931f66991175369859b5fd58529cd4b73582461877ecfd859b6549869287ffe"}, + {file = "coverage-7.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52a523153c568d2c0ef8826f6cc23031dc86cffb8c6aeab92c4ff776e7951b28"}, + {file = "coverage-7.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c8a5c139aae4c35cbd7cadca1df02ea8cf28a911534fc1b0456acb0b14234f3"}, + {file = "coverage-7.8.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a26c0c795c3e0b63ec7da6efded5f0bc856d7c0b24b2ac84b4d1d7bc578d676"}, + {file = "coverage-7.8.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:821f7bcbaa84318287115d54becb1915eece6918136c6f91045bb84e2f88739d"}, + {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a321c61477ff8ee705b8a5fed370b5710c56b3a52d17b983d9215861e37b642a"}, + {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ed2144b8a78f9d94d9515963ed273d620e07846acd5d4b0a642d4849e8d91a0c"}, + {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:042e7841a26498fff7a37d6fda770d17519982f5b7d8bf5278d140b67b61095f"}, + {file = "coverage-7.8.0-cp310-cp310-win32.whl", hash = "sha256:f9983d01d7705b2d1f7a95e10bbe4091fabc03a46881a256c2787637b087003f"}, + {file = "coverage-7.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a570cd9bd20b85d1a0d7b009aaf6c110b52b5755c17be6962f8ccd65d1dbd23"}, + {file = "coverage-7.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7ac22a0bb2c7c49f441f7a6d46c9c80d96e56f5a8bc6972529ed43c8b694e27"}, + {file = "coverage-7.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf13d564d310c156d1c8e53877baf2993fb3073b2fc9f69790ca6a732eb4bfea"}, + {file = "coverage-7.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5761c70c017c1b0d21b0815a920ffb94a670c8d5d409d9b38857874c21f70d7"}, + {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ff52d790c7e1628241ffbcaeb33e07d14b007b6eb00a19320c7b8a7024c040"}, + {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d39fc4817fd67b3915256af5dda75fd4ee10621a3d484524487e33416c6f3543"}, + {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b44674870709017e4b4036e3d0d6c17f06a0e6d4436422e0ad29b882c40697d2"}, + {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8f99eb72bf27cbb167b636eb1726f590c00e1ad375002230607a844d9e9a2318"}, + {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b571bf5341ba8c6bc02e0baeaf3b061ab993bf372d982ae509807e7f112554e9"}, + {file = "coverage-7.8.0-cp311-cp311-win32.whl", hash = "sha256:e75a2ad7b647fd8046d58c3132d7eaf31b12d8a53c0e4b21fa9c4d23d6ee6d3c"}, + {file = "coverage-7.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:3043ba1c88b2139126fc72cb48574b90e2e0546d4c78b5299317f61b7f718b78"}, + {file = "coverage-7.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bbb5cc845a0292e0c520656d19d7ce40e18d0e19b22cb3e0409135a575bf79fc"}, + {file = "coverage-7.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4dfd9a93db9e78666d178d4f08a5408aa3f2474ad4d0e0378ed5f2ef71640cb6"}, + {file = "coverage-7.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f017a61399f13aa6d1039f75cd467be388d157cd81f1a119b9d9a68ba6f2830d"}, + {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0915742f4c82208ebf47a2b154a5334155ed9ef9fe6190674b8a46c2fb89cb05"}, + {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a40fcf208e021eb14b0fac6bdb045c0e0cab53105f93ba0d03fd934c956143a"}, + {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a1f406a8e0995d654b2ad87c62caf6befa767885301f3b8f6f73e6f3c31ec3a6"}, + {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:77af0f6447a582fdc7de5e06fa3757a3ef87769fbb0fdbdeba78c23049140a47"}, + {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f2d32f95922927186c6dbc8bc60df0d186b6edb828d299ab10898ef3f40052fe"}, + {file = "coverage-7.8.0-cp312-cp312-win32.whl", hash = "sha256:769773614e676f9d8e8a0980dd7740f09a6ea386d0f383db6821df07d0f08545"}, + {file = "coverage-7.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:e5d2b9be5b0693cf21eb4ce0ec8d211efb43966f6657807f6859aab3814f946b"}, + {file = "coverage-7.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ac46d0c2dd5820ce93943a501ac5f6548ea81594777ca585bf002aa8854cacd"}, + {file = "coverage-7.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:771eb7587a0563ca5bb6f622b9ed7f9d07bd08900f7589b4febff05f469bea00"}, + {file = "coverage-7.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42421e04069fb2cbcbca5a696c4050b84a43b05392679d4068acbe65449b5c64"}, + {file = "coverage-7.8.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:554fec1199d93ab30adaa751db68acec2b41c5602ac944bb19187cb9a41a8067"}, + {file = "coverage-7.8.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aaeb00761f985007b38cf463b1d160a14a22c34eb3f6a39d9ad6fc27cb73008"}, + {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:581a40c7b94921fffd6457ffe532259813fc68eb2bdda60fa8cc343414ce3733"}, + {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f319bae0321bc838e205bf9e5bc28f0a3165f30c203b610f17ab5552cff90323"}, + {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04bfec25a8ef1c5f41f5e7e5c842f6b615599ca8ba8391ec33a9290d9d2db3a3"}, + {file = "coverage-7.8.0-cp313-cp313-win32.whl", hash = "sha256:dd19608788b50eed889e13a5d71d832edc34fc9dfce606f66e8f9f917eef910d"}, + {file = "coverage-7.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:a9abbccd778d98e9c7e85038e35e91e67f5b520776781d9a1e2ee9d400869487"}, + {file = "coverage-7.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:18c5ae6d061ad5b3e7eef4363fb27a0576012a7447af48be6c75b88494c6cf25"}, + {file = "coverage-7.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:95aa6ae391a22bbbce1b77ddac846c98c5473de0372ba5c463480043a07bff42"}, + {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e013b07ba1c748dacc2a80e69a46286ff145935f260eb8c72df7185bf048f502"}, + {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d766a4f0e5aa1ba056ec3496243150698dc0481902e2b8559314368717be82b1"}, + {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad80e6b4a0c3cb6f10f29ae4c60e991f424e6b14219d46f1e7d442b938ee68a4"}, + {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b87eb6fc9e1bb8f98892a2458781348fa37e6925f35bb6ceb9d4afd54ba36c73"}, + {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d1ba00ae33be84066cfbe7361d4e04dec78445b2b88bdb734d0d1cbab916025a"}, + {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f3c38e4e5ccbdc9198aecc766cedbb134b2d89bf64533973678dfcf07effd883"}, + {file = "coverage-7.8.0-cp313-cp313t-win32.whl", hash = "sha256:379fe315e206b14e21db5240f89dc0774bdd3e25c3c58c2c733c99eca96f1ada"}, + {file = "coverage-7.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2e4b6b87bb0c846a9315e3ab4be2d52fac905100565f4b92f02c445c8799e257"}, + {file = "coverage-7.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa260de59dfb143af06dcf30c2be0b200bed2a73737a8a59248fcb9fa601ef0f"}, + {file = "coverage-7.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:96121edfa4c2dfdda409877ea8608dd01de816a4dc4a0523356067b305e4e17a"}, + {file = "coverage-7.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b8af63b9afa1031c0ef05b217faa598f3069148eeee6bb24b79da9012423b82"}, + {file = "coverage-7.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89b1f4af0d4afe495cd4787a68e00f30f1d15939f550e869de90a86efa7e0814"}, + {file = "coverage-7.8.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ec0be97723ae72d63d3aa41961a0b9a6f5a53ff599813c324548d18e3b9e8c"}, + {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a1d96e780bdb2d0cbb297325711701f7c0b6f89199a57f2049e90064c29f6bd"}, + {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f1d8a2a57b47142b10374902777e798784abf400a004b14f1b0b9eaf1e528ba4"}, + {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cf60dd2696b457b710dd40bf17ad269d5f5457b96442f7f85722bdb16fa6c899"}, + {file = "coverage-7.8.0-cp39-cp39-win32.whl", hash = "sha256:be945402e03de47ba1872cd5236395e0f4ad635526185a930735f66710e1bd3f"}, + {file = "coverage-7.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:90e7fbc6216ecaffa5a880cdc9c77b7418c1dcb166166b78dbc630d07f278cc3"}, + {file = "coverage-7.8.0-pp39.pp310.pp311-none-any.whl", hash = "sha256:b8194fb8e50d556d5849753de991d390c5a1edeeba50f68e3a9253fbd8bf8ccd"}, + {file = "coverage-7.8.0-py3-none-any.whl", hash = "sha256:dbf364b4c5e7bae9250528167dfe40219b62e2d573c854d74be213e1e52069f7"}, + {file = "coverage-7.8.0.tar.gz", hash = "sha256:7a3d62b3b03b4b6fd41a085f3574874cf946cb4604d2b4d3e8dca8cd570ca501"}, ] [package.dependencies] @@ -115,13 +116,13 @@ test = ["pytest (>=6)"] [[package]] name = "importlib-metadata" -version = "8.5.0" +version = "8.6.1" description = "Read metadata from Python packages" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, - {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, + {file = "importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e"}, + {file = "importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580"}, ] [package.dependencies] @@ -133,18 +134,18 @@ cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] perf = ["ipython"] -test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +test = ["flufl.flake8", "importlib_resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] type = ["pytest-mypy"] [[package]] name = "iniconfig" -version = "2.0.0" +version = "2.1.0" description = "brain-dead simple config-ini parsing" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, ] [[package]] @@ -163,13 +164,13 @@ altgraph = ">=0.17" [[package]] name = "packaging" -version = "24.1" +version = "25.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, + {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, + {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, ] [[package]] @@ -200,32 +201,32 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pyinstaller" -version = "6.11.0" +version = "6.13.0" description = "PyInstaller bundles a Python application and all its dependencies into a single package." optional = false python-versions = "<3.14,>=3.8" files = [ - {file = "pyinstaller-6.11.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:6fd68a3c1207635c49326c54881b89d5c3bd9ba061bbc9daa58c0902db1be39e"}, - {file = "pyinstaller-6.11.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:eddd53f231e51adc65088eac4f40057ca803a990239828d4a9229407fb866239"}, - {file = "pyinstaller-6.11.0-py3-none-manylinux2014_i686.whl", hash = "sha256:e6d229009e815542833fe00332b589aa6984a06f794dc16f2ce1acab1c567590"}, - {file = "pyinstaller-6.11.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:7d2cd2ebdcd6860f8a4abe2977264a7b6d260a7147047008971c7cfc66a656a4"}, - {file = "pyinstaller-6.11.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:d9ec6d4398b4eebc1d4c00437716264ba8406bc2746f594e253070a82378a584"}, - {file = "pyinstaller-6.11.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:04f71828aa9531ab18c9656985c1f09b83d10332c73a1f4a113a48b491906955"}, - {file = "pyinstaller-6.11.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:a843d470768d68b05684ccf4860c45b2eb13727f41667c0b2cd8f57ae231bd18"}, - {file = "pyinstaller-6.11.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:963dedc1f37144a4385f58f7f65f1c69c004a67faae522a2085b5ddb230c908b"}, - {file = "pyinstaller-6.11.0-py3-none-win32.whl", hash = "sha256:c71024c8a19c7b221b9152b2baff4c3ba849cada68dcdd34382ba09f0107451f"}, - {file = "pyinstaller-6.11.0-py3-none-win_amd64.whl", hash = "sha256:0e229610c22b96d741d905706f9496af472c1a9216a118988f393c98ecc3f51f"}, - {file = "pyinstaller-6.11.0-py3-none-win_arm64.whl", hash = "sha256:a5f716bb507517912fda39d109dead91fc0dd2e7b2859562522b63c61aa21676"}, - {file = "pyinstaller-6.11.0.tar.gz", hash = "sha256:cb4d433a3db30d9d17cf5f2cf7bb4df80a788d493c1d67dd822dc5791d9864af"}, + {file = "pyinstaller-6.13.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:aa404f0b02cd57948098055e76ee190b8e65ccf7a2a3f048e5000f668317069f"}, + {file = "pyinstaller-6.13.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:92efcf2f09e78f07b568c5cb7ed48c9940f5dad627af4b49bede6320fab2a06e"}, + {file = "pyinstaller-6.13.0-py3-none-manylinux2014_i686.whl", hash = "sha256:9f82f113c463f012faa0e323d952ca30a6f922685d9636e754bd3a256c7ed200"}, + {file = "pyinstaller-6.13.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:db0e7945ebe276f604eb7c36e536479556ab32853412095e19172a5ec8fca1c5"}, + {file = "pyinstaller-6.13.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:92fe7337c5aa08d42b38d7a79614492cb571489f2cb0a8f91dc9ef9ccbe01ed3"}, + {file = "pyinstaller-6.13.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:bc09795f5954135dd4486c1535650958c8218acb954f43860e4b05fb515a21c0"}, + {file = "pyinstaller-6.13.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:589937548d34978c568cfdc39f31cf386f45202bc27fdb8facb989c79dfb4c02"}, + {file = "pyinstaller-6.13.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:b7260832f7501ba1d2ce1834d4cddc0f2b94315282bc89c59333433715015447"}, + {file = "pyinstaller-6.13.0-py3-none-win32.whl", hash = "sha256:80c568848529635aa7ca46d8d525f68486d53e03f68b7bb5eba2c88d742e302c"}, + {file = "pyinstaller-6.13.0-py3-none-win_amd64.whl", hash = "sha256:8d4296236b85aae570379488c2da833b28828b17c57c2cc21fccd7e3811fe372"}, + {file = "pyinstaller-6.13.0-py3-none-win_arm64.whl", hash = "sha256:d9f21d56ca2443aa6a1e255e7ad285c76453893a454105abe1b4d45e92bb9a20"}, + {file = "pyinstaller-6.13.0.tar.gz", hash = "sha256:38911feec2c5e215e5159a7e66fdb12400168bd116143b54a8a7a37f08733456"}, ] [package.dependencies] altgraph = "*" -importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} +importlib_metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} macholib = {version = ">=1.8", markers = "sys_platform == \"darwin\""} packaging = ">=22.0" pefile = {version = ">=2022.5.30,<2024.8.26 || >2024.8.26", markers = "sys_platform == \"win32\""} -pyinstaller-hooks-contrib = ">=2024.8" +pyinstaller-hooks-contrib = ">=2025.2" pywin32-ctypes = {version = ">=0.2.1", markers = "sys_platform == \"win32\""} setuptools = ">=42.0.0" @@ -235,62 +236,64 @@ hook-testing = ["execnet (>=1.5.0)", "psutil", "pytest (>=2.7.3)"] [[package]] name = "pyinstaller-hooks-contrib" -version = "2024.9" +version = "2025.3" description = "Community maintained hooks for PyInstaller" optional = false python-versions = ">=3.8" files = [ - {file = "pyinstaller_hooks_contrib-2024.9-py3-none-any.whl", hash = "sha256:1ddf9ba21d586afa84e505bb5c65fca10b22500bf3fdb89ee2965b99da53b891"}, - {file = "pyinstaller_hooks_contrib-2024.9.tar.gz", hash = "sha256:4793869f370d1dc4806c101efd2890e3c3e703467d8d27bb5a3db005ebfb008d"}, + {file = "pyinstaller_hooks_contrib-2025.3-py3-none-any.whl", hash = "sha256:70cba46b1a6b82ae9104f074c25926e31f3dde50ff217434d1d660355b949683"}, + {file = "pyinstaller_hooks_contrib-2025.3.tar.gz", hash = "sha256:af129da5cd6219669fbda360e295cc822abac55b7647d03fec63a8fcf0a608cf"}, ] [package.dependencies] -importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} +importlib_metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} packaging = ">=22.0" setuptools = ">=42.0.0" [[package]] name = "pyside6-addons" -version = "6.8.0.2" +version = "6.9.0" description = "Python bindings for the Qt cross-platform application and UI framework (Addons)" optional = false python-versions = "<3.14,>=3.9" files = [ - {file = "PySide6_Addons-6.8.0.2-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:30c9ca570dd18ffbfd34ee95e0a319c34313a80425c4011d6ccc9f4cca0dc4c8"}, - {file = "PySide6_Addons-6.8.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:754a9822ab2dc313f9998edef69d8a12bc9fd61727543f8d30806ed272ae1e52"}, - {file = "PySide6_Addons-6.8.0.2-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:553f3fa412f423929b5cd8b7d43fd5f02161851f10a438174a198b0f1a044df7"}, - {file = "PySide6_Addons-6.8.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:ae4377a3e10fe720a9119677b31d8de13e2a5221c06b332df045af002f5f4c3d"}, + {file = "PySide6_Addons-6.9.0-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:98f9ad4b65820736e12d49c18db2e570eac63727407fbb59a62ac753e89dc201"}, + {file = "PySide6_Addons-6.9.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:fc9dcd63a0ce7565f238cb11c44494435a50eb6cb72b8dbce3b709618989c3dc"}, + {file = "PySide6_Addons-6.9.0-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:d8a650644e0b9d1e7a092f6bcd11f25a63706d12f77d442b6ace75d346ab5d30"}, + {file = "PySide6_Addons-6.9.0-cp39-abi3-win_amd64.whl", hash = "sha256:8cf54065b3d1b4698448fad825378a25c10ef52017d9dff48cead03200636d8d"}, + {file = "PySide6_Addons-6.9.0-cp39-abi3-win_arm64.whl", hash = "sha256:260a56da59539f476c1635a3ff13591e10f1b04d92155c0617129bc53ca8b5f8"}, ] [package.dependencies] -PySide6-Essentials = "6.8.0.2" -shiboken6 = "6.8.0.2" +PySide6-Essentials = "6.9.0" +shiboken6 = "6.9.0" [[package]] name = "pyside6-essentials" -version = "6.8.0.2" +version = "6.9.0" description = "Python bindings for the Qt cross-platform application and UI framework (Essentials)" optional = false python-versions = "<3.14,>=3.9" files = [ - {file = "PySide6_Essentials-6.8.0.2-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:3df4ed75bbb74d74ac338b330819b1a272e7f5cec206765c7176a197c8bc9c79"}, - {file = "PySide6_Essentials-6.8.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:7df6d6c1da4858dbdea77c74d7270d9c68e8d1bbe3362892abd1a5ade3815a50"}, - {file = "PySide6_Essentials-6.8.0.2-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:cf490145d18812a6cff48b0b0afb0bfaf7066744bfbd09eb071c3323f1d6d00d"}, - {file = "PySide6_Essentials-6.8.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:d2f029b8c9f0106f57b26aa8c435435d7f509c80525075343e07177b283f862e"}, + {file = "PySide6_Essentials-6.9.0-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:b18e3e01b507e8a57481fe19792eb373d5f10a23a50702ce540da1435e722f39"}, + {file = "PySide6_Essentials-6.9.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:45eaf7f17688d1991f39680dbfd3c41674f3cbb78f278aa10fe0b5f2f31c1989"}, + {file = "PySide6_Essentials-6.9.0-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:69aedfad77119c5bec0005ca31d5620e9bac8ba5ae66c7389160530cfd698ed8"}, + {file = "PySide6_Essentials-6.9.0-cp39-abi3-win_amd64.whl", hash = "sha256:94a0096d6bb1d3e5cef29ca4a5366d0f229d42480fbb17aa25ad85d72b1b7947"}, + {file = "PySide6_Essentials-6.9.0-cp39-abi3-win_arm64.whl", hash = "sha256:d2dc45536f2269ad111991042e81257124f1cd1c9ed5ea778d7224fd65dc9e2b"}, ] [package.dependencies] -shiboken6 = "6.8.0.2" +shiboken6 = "6.9.0" [[package]] name = "pytest" -version = "8.3.3" +version = "8.3.5" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, - {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, + {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, + {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, ] [package.dependencies] @@ -354,35 +357,36 @@ files = [ [[package]] name = "setuptools" -version = "75.2.0" +version = "75.9.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "setuptools-75.2.0-py3-none-any.whl", hash = "sha256:a7fcb66f68b4d9e8e66b42f9876150a3371558f98fa32222ffaa5bced76406f8"}, - {file = "setuptools-75.2.0.tar.gz", hash = "sha256:753bb6ebf1f465a1912e19ed1d41f403a79173a9acf66a42e7e6aec45c3c16ec"}, + {file = "setuptools-75.9.1-py3-none-any.whl", hash = "sha256:0a6f876d62f4d978ca1a11ab4daf728d1357731f978543ff18ecdbf9fd071f73"}, + {file = "setuptools-75.9.1.tar.gz", hash = "sha256:b6eca2c3070cdc82f71b4cb4bb2946bc0760a210d11362278cf1ff394e6ea32c"}, ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] -core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.8.0)"] +core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"] [[package]] name = "shiboken6" -version = "6.8.0.2" +version = "6.9.0" description = "Python/C++ bindings helper module" optional = false python-versions = "<3.14,>=3.9" files = [ - {file = "shiboken6-6.8.0.2-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:9019e1fcfeed8bb350222e981748ef05a2fec11e31ddf616657be702f0b7a468"}, - {file = "shiboken6-6.8.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:fa7d411c3c67b4296847b3f5f572268e219d947d029ff9d8bce72fe6982d92bc"}, - {file = "shiboken6-6.8.0.2-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:1aaa8b7f9138818322ef029b2c487d1c6e00dc3f53084e62e1d11bdea47e47c2"}, - {file = "shiboken6-6.8.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:b11e750e696bb565d897e0f5836710edfb86bd355f87b09988bd31b2aad404d3"}, + {file = "shiboken6-6.9.0-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:c4d8e3a5907154ac4789e52c77957db95bcf584238c244d7743cb39e9b66dd26"}, + {file = "shiboken6-6.9.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3f585caae5b814a7e23308db0a077355a7dc20c34d58ca4c339ff7625e9a1936"}, + {file = "shiboken6-6.9.0-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:b61579b90bf9c53ecc174085a69429166dfe57a0b8b894f933d1281af9df6568"}, + {file = "shiboken6-6.9.0-cp39-abi3-win_amd64.whl", hash = "sha256:121ea290ed1afa5ad6abf690b377612693436292b69c61b0f8e10b1f0850f935"}, + {file = "shiboken6-6.9.0-cp39-abi3-win_arm64.whl", hash = "sha256:24f53857458881b54798d7e35704611d07f6b6885bcdf80f13a4c8bb485b8df2"}, ] [[package]] @@ -408,24 +412,54 @@ files = [ [[package]] name = "tomli" -version = "2.0.2" +version = "2.2.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" files = [ - {file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"}, - {file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] [[package]] name = "zipp" -version = "3.20.2" +version = "3.21.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"}, - {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"}, + {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, + {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, ] [package.extras] @@ -439,4 +473,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.13" -content-hash = "fad810a5ba9b4cb5ab759c9b5641ccba2b735e12064e510c0bfe0f4766c576f1" +content-hash = "b0920ba14495c199b201802e11473e624a133c5b7b97d2e96ba5744b8bc0e4c4"