Compare commits

..

458 commits

Author SHA1 Message Date
fdcc8105ba
Removing debug
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-29 02:58:32 +01:00
da8aa59b0a
Improving characters choosing popup.
All checks were successful
continuous-integration/drone/push Build is passing
+ No longer covering the input
+ No longer cut off when editing the name
+ Improved keyboard navigation.
2024-10-29 02:50:11 +01:00
f5b489ef44
Fixing macOS build script. 2024-10-29 01:37:44 +01:00
8429ff3739
Updating dependencies locK.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-28 23:05:55 +01:00
440575325e
Fixing Helper version importing. 2024-10-28 23:04:42 +01:00
45fef876ec
Fixing issue with margins being shown despite an object not being displayed.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-28 19:09:25 +01:00
43e41a5da4
Adding new test files
All checks were successful
continuous-integration/drone/push Build is passing
Including:
- magnitude.lpf & phase.lpf: regular use case magnitude and phase
- all.lpf: tests all objects
- stress.lpf: over 200 objects to be rendered
2024-10-28 18:51:13 +01:00
687b14429a
Improving reliability of threaded rendering, separating JS Utils into separate files.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-28 18:47:55 +01:00
ovari
49e94317d4
Translated using Weblate (Hungarian)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (265 of 265 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/
2024-10-28 09:17:49 +01:00
727dda2623
Adding loading screen for rendering LaTeX formula when threaded setting is enabled.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-27 02:40:42 +02:00
27c9fe0473
Fixing newly made issue with PickLocation. 2024-10-27 00:46:42 +02:00
e6de739d0c
Rewirring paths to improve import names and such. 2024-10-27 00:45:04 +02:00
f52ee65c56
Improving stability of Function drawing. 2024-10-26 23:37:20 +02:00
8da10497d2
Adding different revisions for different debian packages depending on their dependencies
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-26 22:46:41 +02:00
5d0542ffcc
Ensuring app icons are white. 2024-10-26 22:46:22 +02:00
90f4691c54
Updating icons to comply with KDE HIG. 2024-10-26 22:44:18 +02:00
c39498c60f
Finally got rid of the camelCase2Readable Utils function.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-26 05:55:34 +02:00
2594fd6844
Adding new expression tests.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-26 01:06:24 +02:00
a01b7a17ef
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-22 02:51:42 +02:00
67799e9908
Removing debug from python. 2024-10-22 02:50:56 +02:00
d53f50193a
Finishing latex and polyfill tests. 2024-10-22 02:50:24 +02:00
14e8cef6af
Fixing issues with LaTeX and rendering variable pi. 2024-10-22 02:50:00 +02:00
b989a685e9
Fixing issue with LaTeX sqrt. 2024-10-22 01:05:06 +02:00
e35f6cebec
Starting Latex tests. 2024-10-20 00:11:35 +02:00
6251835aa0
Translated using Weblate (German)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (265 of 265 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2024-10-18 16:09:36 +02:00
14c092b9fa
Fixing tests
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-17 05:28:03 +02:00
811262b1fb
Changing lupdate and lrelease to use pyside6 versions, updating images so I no longer have to install node to build.
Some checks failed
continuous-integration/drone/push Build is failing
2024-10-17 05:09:33 +02:00
3c0d99d9c0
Exiting when not all tests are fulfilled.
Some checks failed
continuous-integration/drone/push Build is failing
2024-10-17 03:44:35 +02:00
2899ac6cde
Fixing unit testing importing unexpected and unused libraries.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-17 03:41:41 +02:00
a182c703f4
Finishing testing promises.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-17 03:38:36 +02:00
ef465b34e7
Finishing natural language plugin. 2024-10-17 02:08:24 +02:00
8fab9d8e52
Starting natural language plugin. 2024-10-16 22:18:53 +02:00
34caf20593
Fixing LaTeX tests, adding new sexy natural language method spy, started testing Promises. 2024-10-16 05:38:49 +02:00
a85a4721e3
Fixing double redraw when opening a file.
Some checks failed
continuous-integration/drone/push Build is failing
2024-10-15 20:39:03 +02:00
aeaaba759f
Starting latex render locking. 2024-10-15 19:21:40 +02:00
ccddb068a6
Fixing tests for Promises (new ones need to be written) 2024-10-15 18:06:24 +02:00
37ac400f23
Enabling latex async generation by default, default LaTeX setting now depends on state of installation.
Some checks failed
continuous-integration/drone/push Build is failing
2024-10-15 03:52:47 +02:00
5313428250
Improving stability of asynchronous LaTeX renderer. 2024-10-15 03:52:06 +02:00
cf73b35a9a
Adding experimental async LaTeX renderer (speeds up rendering ridiculously, but causes instability) 2024-10-15 03:01:27 +02:00
f734e40ad9
Starting PyPromise 2024-10-15 02:28:27 +02:00
b33e1329db
Removing typed config functions in Helper.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-14 23:22:57 +02:00
2995b2271a
Fixing mind-bogingingly strange issue causing Qt crash when attempting to set WeakSet during mouse move events.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-14 17:55:53 +02:00
a26dbc8a00
Getting rid of Qt5Compat, ridding dependency on PySide6-Addons
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-14 17:39:02 +02:00
89e78913de
Adding dependencies for Ubuntu 24.10.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-14 17:28:43 +02:00
c03afdf4ee
Upgrading deb packaging
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-14 17:18:58 +02:00
3a81441d0b
Finished expr-eval testing
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-13 00:33:22 +02:00
edf4518494
Starting expr-eval's tests. 2024-10-12 20:37:16 +02:00
345458f453
Adding new test for Settings Module
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-12 06:19:30 +02:00
974baa6cc2
Adding base module tests
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-12 05:31:42 +02:00
4c1b705240
Mocking interfaces (+adding new method to canvas to make it more JS-like)
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-12 04:57:07 +02:00
885d1f5dc3
Adding test for Utils
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-12 03:22:49 +02:00
0abb22130f
Disable domain tests, started base tests. 2024-10-12 00:40:46 +02:00
42d5add810
Fixing tests and LaTeX
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-11 22:33:57 +02:00
e2d259f866
Fixing French localization.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-11 22:18:35 +02:00
8a878b4cc1
Storing LaTeX renders in cache directory instead of temporary to store them for later use.
All checks were successful
continuous-integration/drone/push Build is passing
+ Makes reponening files instantaneous.
+ Improves performance of 'base state' objects (e.g. A = (1, 0) or f(x) = x).
2024-10-11 22:04:12 +02:00
07e58a3a55
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (265 of 265 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2024-10-11 22:00:30 +02:00
c592b92212
Translated using Weblate (Spanish)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (265 of 265 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2024-10-11 19:18:30 +02:00
7935d0134d
Fixing wrap on Greet Screen buttons in certain locales.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-11 19:06:33 +02:00
5745587c72
Fixing git version detection. 2024-10-11 19:06:15 +02:00
84adc787e5
Fixing typo in Spanish translation 2024-10-11 19:05:53 +02:00
f3307b47d9
Fixing bug with saving files 2024-10-11 19:05:34 +02:00
9017f84c06
Updating metadata and python package lock. 2024-10-11 18:21:03 +02:00
00ab895b21
Adding x value as argument for derivative objects.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-11 02:38:11 +02:00
82e6d2ffe3
Removing HistoryInterface (no longer needed)
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-11 02:35:13 +02:00
b91dbfb311
Finishing touches on putting History off QML.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-11 02:14:42 +02:00
448d94fee3
Fixed many issues with new History module, including saved status.
+ Fixed (old) bug that label content wasn't being saved.
2024-10-11 02:03:27 +02:00
2dc9234b22
Decoupled History from QML 2024-10-11 01:14:52 +02:00
54363b25bc
Fixing issue with Replace All when replacement string includes source string.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-10 23:56:42 +02:00
52f859349a
Converting actual settings to new Settings module. 2024-10-10 23:28:25 +02:00
d1ac70a946
Switching a lot of stuff to new Settings module
+ Fixing a bug that did not load the showygrad setting properly.
2024-10-10 19:15:46 +02:00
f4920aadb6
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-10 06:50:08 +02:00
af2950c3d2
Starting Settings modules + implemented basic events for ECMAScript <=> Qt compat. 2024-10-10 06:49:14 +02:00
gallegonovato
bd346240bd
Translated using Weblate (Spanish)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (269 of 269 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2024-10-10 03:34:21 +00:00
9663c33563
Improving MJS lupdate hacky script to take private fields into account.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-10 05:33:01 +02:00
934dd3ea1b
Adding private fields for Modules 2024-10-10 05:25:34 +02:00
b02ed87a29
Updating package-lock 2024-10-10 04:56:09 +02:00
40d86c8f82
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (269 of 269 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2024-10-09 20:22:37 +02:00
6b3cce4252
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/
2024-10-09 20:22:36 +02:00
8c273f4220
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/
2024-10-09 20:22:36 +02:00
a60ac79d83
Updating translations to new folder structure.
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-09 20:15:27 +02:00
23c3b771c2
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-09 20:04:07 +02:00
041d4f424e
Reorganisation du projet pour séparer le module ECMAScript du reste de l'application.
Merge branch 'rollup-js'
2024-10-09 20:02:53 +02:00
1fc19f6ba3
Adding rebuild to scripts
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2024-10-01 21:50:10 +02:00
ovari
7ef55e48e8
Translated using Weblate (Hungarian)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (269 of 269 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/
2024-10-01 17:23:20 +02:00
07e556da56
Removing building when testing current build.
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-30 01:45:02 +02:00
cd6f258720
Fixing CI
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-30 01:39:59 +02:00
1c7e9d627d
Updating tests
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-30 01:35:24 +02:00
e2841c0129
Updating remaining paths in scripts 2024-09-30 01:27:30 +02:00
ca5c7492dc
Fixing deb building 2024-09-30 00:54:30 +02:00
34cb856dd4
Reorganizing paths 2024-09-30 00:23:39 +02:00
e9d204daab
Code coverage for JS
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-28 03:49:14 +02:00
a2443d7915
Adding coverage 2024-09-28 03:46:16 +02:00
56a0817960
Testing!
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-28 03:32:51 +02:00
c74c2fb747
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-27 22:30:36 +02:00
c2eae30bd6
Updating qmldirs 2024-09-27 22:26:15 +02:00
80cea6d280
Translated using Weblate (Hungarian)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 95.1% (256 of 269 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/
2024-09-27 18:16:19 +02:00
f8ce98d4ad
Removing logplotter.svg file (duplicate) + adding PySide6-Addons as dependency 2024-09-27 04:15:34 +02:00
c806f09b10
Improving translations update script.
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-27 03:02:55 +02:00
c32d70e9ed
Reformatting JS files
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-27 02:54:20 +02:00
8cefc56ac7
Adding JS polyfills to avoid issues because core-js does not deal well with the environment it's given. 2024-09-27 02:34:42 +02:00
850d076268
Using more modern ECMAScript 2024-09-26 23:16:58 +02:00
95b47effdf
Removing unique file dependencies in QML, removing comments from JS Builds (except first one, ~-30% build size)
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-26 22:36:42 +02:00
49aa23de92
Removing the need for releasing translations after building
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-26 03:28:41 +02:00
4a1b333198
Updating APT before installing in CI
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-26 03:26:41 +02:00
b5bdbb6294
Adding building for JS
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-26 03:24:57 +02:00
309b0fafb0
Adding tests for debug
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-26 00:01:30 +02:00
fbb85083c1
Translated using Weblate (German)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (269 of 269 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2024-09-25 22:15:42 +02:00
f9af0c34dd
Source mapping and debugging 2024-09-25 19:18:04 +02:00
gallegonovato
17b6e40d60
Translated using Weblate (Spanish)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (269 of 269 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2024-09-24 19:15:41 +02:00
937cb07d0b
Working mjs building 2024-09-24 05:23:12 +02:00
6a1f01ba1f
Better interfaces!
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-24 00:04:11 +02:00
4c1403c983
Implementing modules requiring interfaces 2024-09-23 20:55:48 +02:00
8c8964e75e
Renaming internal ExprEval Expression class to ExprEvalExpression
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-23 18:37:57 +02:00
45dff33bb5
Moving mathlib and historylib into math/index and history/index
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-23 18:32:11 +02:00
bac802ec5b
Using translated property name in usage error messages.
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-23 18:23:45 +02:00
34a436fe49
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-23 18:19:09 +02:00
cb2ffcf77a
Translated using Weblate (Hungarian)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 94.7% (255 of 269 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/
2024-09-23 18:19:00 +02:00
a27d3109ed
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/
2024-09-23 18:19:00 +02:00
a998c52eec
Translated using Weblate (Spanish)
Currently translated at 98.8% (266 of 269 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2024-09-23 18:19:00 +02:00
8b8a280b37
Translated using Weblate (German)
Currently translated at 99.6% (268 of 269 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2024-09-23 18:19:00 +02:00
3befff41fa
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/
2024-09-23 18:18:59 +02:00
9810435456
Updating usages 2024-09-23 18:18:56 +02:00
84a65cd1fc
Testing the Helper.
All checks were successful
continuous-integration/drone/push Build is passing
We're now getting to 88% coverage on python. I don't think I can get it much higher between the statements that pytest doesn't count,
the ones which aren't easy to reproduce in test env (eg no internet connection), and the ones essential to the app's startup workflow.
2024-09-23 05:58:29 +02:00
5bdf81b2ed
Adding new python 2024-09-23 04:35:10 +02:00
c66d08b352
Moving Modules to separate directory
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-22 21:59:11 +02:00
a4e9ad7f5a
Removing usage of "Modules" to refer to modules in JavaScript (using imports instead) 2024-09-22 19:35:40 +02:00
a88be86350
Adding translations to current branch
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-22 19:18:18 +02:00
4baf4f8aa6
Updating some keys (should be the last time) 2024-09-22 19:17:24 +02:00
1f2b8e5c4b
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (269 of 269 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2024-09-22 19:13:12 +02:00
gallegonovato
8eac624bb2
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/
2024-09-22 19:13:12 +02:00
976088ad03
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/
2024-09-22 19:13:12 +02:00
dcb63c48e9
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/
2024-09-22 19:13:12 +02:00
dcc47104ef
Changing all JS qsTr to qsTranslate (better compatibility moving forward) 2024-09-22 19:10:23 +02:00
a32d480b43
Renaming objects to their proper english names. 2024-09-22 18:58:19 +02:00
e0601379ba
Update README
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-22 18:44:45 +02:00
3c42cbb6d0
Updating translations for new expr-eval
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-22 18:28:36 +02:00
cc0f277da7
Nearly rewrote expr-eval to be compatible as an ECMAScript module, the last blocker for many bugs and JS tests!
All checks were successful
continuous-integration/drone/push Build is passing
commit f91538de446ef0e497ec7e87e2729f504a4172cb
Author: Ad5001 <mail@ad5001.eu>
Date:   Sun Sep 22 05:55:12 2024 +0200

    Converted expr-eval back to regular JS!

commit 23c346f6c65b5b5c4bb4ad610f0554bd1d9a3700
Author: Ad5001 <mail@ad5001.eu>
Date:   Sun Sep 22 05:06:59 2024 +0200

    Reformatting

commit 66608c980fd44f26ae8e6855ecd5fc3e7db55a7b
Author: Ad5001 <mail@ad5001.eu>
Date:   Sun Sep 22 05:04:27 2024 +0200

    Removed all 'var's

commit 545886fd38c99cf11bc576caa40bec0d7fe0ac30
Author: Ad5001 <mail@ad5001.eu>
Date:   Sun Sep 22 04:53:32 2024 +0200

    Removing function definition

commit 489602b24bb70cb6ad782871e269a22c92fcf072
Author: Ad5001 <mail@ad5001.eu>
Date:   Sun Sep 22 04:51:21 2024 +0200

    Removing semicolons

commit 3ee069edbeb8ebfb5c7d15d319014f7a085ff623
Author: Ad5001 <mail@ad5001.eu>
Date:   Sun Sep 22 04:49:32 2024 +0200

    Converting all classes to ECMAScript classes
2024-09-22 05:57:36 +02:00
1299fe469d
Updating README
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-21 03:21:49 +02:00
5d0f3eec56
Translated using Weblate (Hungarian)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 95.9% (258 of 269 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/
2024-09-21 02:47:17 +02:00
gallegonovato
c8ada79776
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/
2024-09-21 02:47:17 +02:00
43a0aa3529
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/
2024-09-21 02:47:17 +02:00
9c76d469d6
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-20 23:59:56 +02:00
3c57f207b6
Translated using Weblate (Hungarian)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 96.2% (259 of 269 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/
2024-09-20 23:59:20 +02:00
77d03e5837
Translated using Weblate (Norwegian Bokmål)
Currently translated at 71.7% (193 of 269 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/nb_NO/
2024-09-20 23:59:20 +02:00
ed5b7e95a6
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/
2024-09-20 23:59:20 +02:00
2bf7df12a8
Translated using Weblate (Spanish)
Currently translated at 98.5% (265 of 269 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2024-09-20 23:59:20 +02:00
0e23d9181e
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/
2024-09-20 23:59:20 +02:00
7e698eda32
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/
2024-09-20 23:59:20 +02:00
6e92c428f9
Removing vanished translation from Spanish file 2024-09-20 23:52:05 +02:00
b18e1ca56e
Update translation files
All checks were successful
continuous-integration/drone/push Build is passing
Updated by "Cleanup translation files" hook in Weblate.

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/
2024-09-20 23:51:37 +02:00
1ef1d27452
Translated using Weblate (Hungarian)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 96.1% (298 of 310 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/
2024-09-20 23:51:00 +02:00
7c12b757ee
Translated using Weblate (Norwegian Bokmål)
Currently translated at 68.0% (211 of 310 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/nb_NO/
2024-09-20 23:51:00 +02:00
484888f80f
Translated using Weblate (French)
Currently translated at 100.0% (310 of 310 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2024-09-20 23:51:00 +02:00
4e265b66c2
Translated using Weblate (Spanish)
Currently translated at 98.3% (305 of 310 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2024-09-20 23:50:59 +02:00
6d3f4ba372
Translated using Weblate (German)
Currently translated at 100.0% (310 of 310 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2024-09-20 23:50:56 +02:00
2321a1076c
Translated using Weblate (English)
Currently translated at 100.0% (310 of 310 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2024-09-20 23:50:14 +02:00
dd2ae7a2c8
Implemented workaround for QTBUG-123819 (lupdate not parsing *.mjs files)
All checks were successful
continuous-integration/drone/push Build is passing
Woohoo! No longer any duplicate and vanished translations (might cause a few that need to be checked, but translations should be properlerly reused).
2024-09-20 23:44:29 +02:00
2fc9bdee86
Fixing import of Objects
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-20 22:58:37 +02:00
67190e1b4c
Fixing rendering of LaTeX for position changing.
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-20 22:14:52 +02:00
8ab461ff72
Removing ObjectsCommon tests
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-20 19:29:02 +02:00
9b5356f8e7
Fixing another bug with X Cursor relating to rounding to a superior precision than what the number originally has.
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-20 19:28:11 +02:00
370402f303
Fixing a particularly smelly bug in regard to X Cursor targetting causing issues with certain functions. 2024-09-20 19:02:10 +02:00
7f57ed13c7
Removing ObjectsCommon API 2024-09-20 17:56:59 +02:00
325eef57e2
Fixing ES flag in Thanks 2024-09-20 17:40:42 +02:00
956de5f9e3
FIxing building location
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-19 21:57:41 +02:00
48427b7923
Fixing lrelease installation
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-19 21:33:29 +02:00
fceb5e711c
Upgrading CI images
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-19 20:21:04 +02:00
836d13386e
Adding building translations in CI.
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-19 18:19:35 +02:00
c3daa92280
Testing for modules existance in globals.
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-19 02:34:49 +02:00
d566c285fd
Adding values and types to PyJS 2024-09-19 02:20:42 +02:00
a9e47dbc17
Adding main tests (note: full main app may not be completely tested though) 2024-09-19 01:52:23 +02:00
4a5756f24d
Update translation files
All checks were successful
continuous-integration/drone/push Build is passing
Updated by "Cleanup translation files" hook in Weblate.

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/
2024-09-18 22:57:16 +00:00
a250f532d9
Adding pyside6-addons as dependency until https://bugreports.qt.io/browse/PYSIDE-2871 is resolved.
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-19 00:51:28 +02:00
e68411e93c
Fixing typos 2024-09-19 00:51:16 +02:00
b55b2a11fe
Starting main tests 2024-09-19 00:50:47 +02:00
7dd64c8e31
Fixing issue with Settings no longer being translated.
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-19 00:22:03 +02:00
8f95479689
Making pyinstaller command multiline. 2024-09-18 23:26:07 +02:00
9712ff15bb
Giving script a GUI env lest Qt dumps
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-18 23:20:00 +02:00
a3cf99f3af
Filtering report paths
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-18 23:19:00 +02:00
2ee7da7995
Fixing CI building
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-18 23:11:44 +02:00
3104dea918
Trying to fix building
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-18 23:03:44 +02:00
cb0db7fae1
Running tests from script
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-18 22:52:53 +02:00
4ac7de48b0
Latex tests 2024-09-18 22:51:23 +02:00
5211821a84
Setting up Poetry for dependency management.
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-18 18:15:30 +02:00
29e48e284c
Adding pytest to drone ci
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-18 18:01:51 +02:00
4759bdcd33
Continuing python tests
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-18 00:31:17 +02:00
9072e94d14
Starting python tests
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-18 00:30:58 +02:00
b50d56d511
Improving python coding format 2024-09-17 22:43:24 +02:00
1bf175b09c
Adding type hints 2024-09-17 22:26:17 +02:00
52fd95551c
Adding translations (again)
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-17 22:02:19 +02:00
769ad22ea6
Cleaning up and update Linux data
+ Removing (no longer working) local install for linux.

+ Moving appstream changelog generation to scripts.

+ Updating debian package information.
2024-09-17 21:58:12 +02:00
gallegonovato
8b36ad81ab
Translated using Weblate (Spanish)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (309 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2024-09-17 21:38:38 +02:00
1e32faa1d1
Adding translations
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-17 20:38:01 +02:00
78d7e6f310
Bumping required Python version to v3.9 + adding new Polyfills for IDEs. 2024-09-17 20:36:46 +02:00
ab45109206
Fixing typos. 2024-09-17 19:21:29 +02:00
12b48a2e74
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (309 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2024-09-17 02:20:41 +02:00
1bc3aaf53b
Translated using Weblate (Spanish)
Currently translated at 99.6% (308 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2024-09-17 02:20:40 +02:00
b52cc1de29
Translated using Weblate (German)
Currently translated at 100.0% (309 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2024-09-17 02:20:40 +02:00
214dd687b1
Translated using Weblate (Hungarian)
Currently translated at 98.0% (303 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/
2024-09-17 02:19:33 +02:00
6b4da2b061
Translated using Weblate (French)
Currently translated at 100.0% (309 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2024-09-17 02:19:33 +02:00
gallegonovato
bcf76dcd28
Translated using Weblate (Spanish)
Currently translated at 100.0% (309 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2024-09-17 02:19:33 +02:00
207a2254f3
Translated using Weblate (German)
Currently translated at 100.0% (309 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2024-09-17 02:19:32 +02:00
0f39930b88
Translated using Weblate (English)
Currently translated at 100.0% (309 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2024-09-17 02:19:32 +02:00
d4e97f2860
Moving last methods from LogGraphCanvas to Canvas JS module. 2024-09-17 02:14:47 +02:00
a2fa16949a
Fixing some bugs, including outzooming too much. 2024-09-17 01:58:34 +02:00
91e4220397
Upping logarithmic graduation limit to 309 (maximum before Infinity, probably some dragons to be had there) 2024-09-17 01:35:47 +02:00
d7fe760900
Slightly improving phases sum cleanness.
Didn't have quite as many bugs, but isn't quite as clean as the magnitude one as of now
2024-09-17 01:01:46 +02:00
a16f02fd5f
Refractoring the magnitude sum object cache calculation which should (hopefully) reduce bugs and improve maintainability. 2024-09-17 00:44:14 +02:00
601efc6122
Fixing issue with LocationPickOverlay snap to grid. 2024-09-16 23:52:42 +02:00
51807a80d0
Fixing position of filter item 2024-09-16 23:41:34 +02:00
ef14db8bbb
Fixing issue with object's execution category 2024-09-16 23:33:59 +02:00
7e0262e4fe
Making Objects List Latex render async 2024-09-16 23:33:08 +02:00
70f1c03cb6
Making history items being rendered with LaTeX (e.g. positions and properties) asynchronous. 2024-09-16 22:56:54 +02:00
8d6891c4f0
Starting async LaTeX rendering. 2024-09-16 22:05:17 +02:00
c9a597ea82
Translated using Weblate (Norwegian Bokmål)
Currently translated at 69.2% (214 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/nb_NO/
2024-09-16 21:17:26 +02:00
c1a468148d
Translated using Weblate (French)
Currently translated at 100.0% (309 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2024-09-16 21:17:26 +02:00
59d4d2f728
Translated using Weblate (Spanish)
Currently translated at 80.5% (249 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2024-09-16 21:17:26 +02:00
gallegonovato
9ca48bbcfa
Translated using Weblate (Spanish)
Currently translated at 80.5% (249 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2024-09-16 21:17:25 +02:00
3994d8d49d
Translated using Weblate (German)
Currently translated at 100.0% (309 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2024-09-16 21:17:25 +02:00
53124fc8d7
Translated using Weblate (Norwegian Bokmål)
Currently translated at 69.9% (216 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/nb_NO/
2024-09-16 21:01:51 +02:00
35fef4cb1e
Translated using Weblate (French)
Currently translated at 100.0% (309 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2024-09-16 21:01:51 +02:00
f1e2278695
Translated using Weblate (Spanish)
Currently translated at 75.7% (234 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2024-09-16 21:01:51 +02:00
gallegonovato
6a1f0013d6
Translated using Weblate (Spanish)
Currently translated at 75.7% (234 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2024-09-16 21:01:51 +02:00
6626362d23
Translated using Weblate (German)
Currently translated at 99.6% (308 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2024-09-16 21:01:51 +02:00
107cea1308
Translated using Weblate (English)
Currently translated at 100.0% (309 of 309 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2024-09-16 21:01:51 +02:00
7b0bc4469f
Improving message for missing packages in LaTeX. 2024-09-16 20:15:57 +02:00
e3eea751cb
Improving ThanksTo (to add scrolling) 2024-09-16 20:05:57 +02:00
7b76a8fe08
Improving testing of LaTeX configuration. 2024-09-16 20:01:35 +02:00
4b1cf2cd9d
Improving linux metainfo generation. 2024-09-16 20:00:56 +02:00
88797d00be
Adding new translations for v0.6.0 + adding Spanish credits 2024-09-16 19:34:35 +02:00
f98852c336
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter 2024-09-15 21:34:50 +02:00
606ec428ab
Fixing issue with setting JS objects being serialized into ListViews.
+ Fixing broken links on Linux
2024-09-15 21:30:44 +02:00
ovari
136ac4c7bc
Translated using Weblate (Hungarian)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (304 of 304 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/
2024-04-21 08:07:05 +02:00
gallegonovato
87d8882db1
Translated using Weblate (Spanish)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 80.2% (244 of 304 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2024-04-03 23:01:47 +02:00
915c6b5246
Setting version to v0.6.0
All checks were successful
continuous-integration/drone/push Build is passing
2024-04-03 22:05:57 +02:00
54f9802975
Adding default canvas settings
All checks were successful
continuous-integration/drone/push Build is passing
+ Getting rid of Qt5COmpat for Icon.
+ Fixing some (non production) bugs.
2024-04-03 21:39:06 +02:00
997a1645a0
Removing Settings submenu.
All checks were successful
continuous-integration/drone/push Build is passing
2024-04-02 22:50:43 +02:00
fefb0f92b0
New, rewamped Greet Screen. 2024-04-02 22:49:56 +02:00
665906ecb3
New preferences panel. 2024-04-02 22:11:54 +02:00
781a0f4aae
Enforcing type safety at export
All checks were successful
continuous-integration/drone/push Build is passing
2024-04-02 00:11:56 +02:00
5f8c756dc7
Enforcing type safety at import. 2024-04-01 23:48:57 +02:00
8e75f13e9a
Removing vanished translations.
All checks were successful
continuous-integration/drone/push Build is passing
2024-03-29 17:56:09 +01:00
82e8413e56
Creating IO JS module.
All checks were successful
continuous-integration/drone/push Build is passing
2024-03-29 17:53:10 +01:00
73cba85592
Creating Canvas JS Module.
All checks were successful
continuous-integration/drone/push Build is passing
2024-03-29 01:55:13 +01:00
861bb001c9
Changing version, making Helper objects globals, adding their polyfills.
All checks were successful
continuous-integration/drone/push Build is passing
2024-03-28 22:52:14 +01:00
08fea34366
Converting as many JS libraries to ECMAScript modules.
All checks were successful
continuous-integration/drone/push Build is passing
2024-03-28 03:09:37 +01:00
a6fcf6da19
Fixing sequence no longer working with current rendering method.
All checks were successful
continuous-integration/drone/push Build is passing
2024-03-25 18:58:07 +01:00
f730121047
Fixing the icon on wayland, building on MacOS, and date on changelog
All checks were successful
continuous-integration/drone/push Build is passing
2024-03-06 18:52:58 +01:00
80f1077b35
Updating snapcraft
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-11 23:28:42 +01:00
33c790b113
Updating debian information
Some checks reported errors
continuous-integration/drone/push Build encountered an error
continuous-integration/drone Build is failing
2024-01-11 21:20:23 +01:00
f9b0bb99ce
Updating appstream
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2024-01-11 20:15:25 +01:00
557592708f
Fixing building for debian 2024-01-11 19:56:25 +01:00
1f72c76fb4
Releasing v0.5.0
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2024-01-11 19:24:06 +01:00
66b4c8df90
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2024-01-11 02:13:44 +01:00
70b1ac09f7
Translated using Weblate (German)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (271 of 271 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2024-01-11 02:13:33 +01:00
2d6389bfd5
Updating images for CI 2024-01-11 01:49:29 +01:00
d0851b819f
Updating windows installer
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-11 01:15:43 +01:00
cff994d9d7
Fixing macos building
Some checks failed
continuous-integration/drone/push Build is failing
2024-01-11 00:59:01 +01:00
fde2526c54
Updating copyrights
Some checks failed
continuous-integration/drone/push Build is failing
2024-01-11 00:11:09 +01:00
e5fe8afd06
Fixing issue with derivative and integrals
Some checks failed
continuous-integration/drone/push Build is failing
2024-01-11 00:09:35 +01:00
f9a7443631
New icons for macos and windows
Some checks failed
continuous-integration/drone/push Build is failing
2024-01-10 23:42:17 +01:00
874046960f
Changing linux descriptions
Some checks failed
continuous-integration/drone/push Build is failing
2024-01-10 23:32:47 +01:00
d53573d468
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
Some checks failed
continuous-integration/drone/push Build is failing
2024-01-10 22:57:33 +01:00
1da1221c51
Updating icons 2024-01-10 22:57:18 +01:00
ovari
8bb147cbee
Translated using Weblate (Hungarian)
Some checks failed
continuous-integration/drone/push Build is failing
Currently translated at 100.0% (271 of 271 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/
2023-10-20 04:11:48 +00:00
bd2e692285
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
Some checks failed
continuous-integration/drone/push Build is failing
2023-10-18 16:06:26 +02:00
298acaace2
Reworking SVG object icons to use default system sans-serif font.
Provides better native integration at the cost of uniformisation.
2023-10-18 16:06:11 +02:00
5284c71ee7
Translated using Weblate (French)
Some checks failed
continuous-integration/drone/push Build is failing
Currently translated at 100.0% (271 of 271 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2023-10-11 15:01:31 +00:00
b8d679e118
Translated using Weblate (English)
Currently translated at 100.0% (271 of 271 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2023-10-11 15:01:30 +00:00
22106f97b5
Adding new strings
Some checks failed
continuous-integration/drone/push Build is failing
2023-10-10 02:13:17 +02:00
bf211df67d
Adding function usage to auto complete.
Some checks failed
continuous-integration/drone/push Build is failing
2023-10-10 01:58:55 +02:00
803416d08d
New system for integrals the same as for derivatives.
Some checks failed
continuous-integration/drone/push Build is failing
2023-10-10 01:33:57 +02:00
d991deee7b
Reworking the derivative function, removed assignement in parser.
The new derivative now supports executable elements.
2023-10-10 00:53:35 +02:00
ed4d30573c
Adding usage for functions. 2023-10-10 00:05:19 +02:00
3f1d089a78
Minor modifications, adding usage to derivative. 2023-10-09 23:28:29 +02:00
4b692894f2
Removing old and unused bits for previously planned new parser, that would have remained unused.
Some checks failed
continuous-integration/drone/push Build is failing
Some bits (like the tokenizer and the reference) are still used for the syntax highlighting and autocomplete though.
2023-10-09 23:27:30 +02:00
062fde6b16
Updating build script for newest pyinstaller version. 2023-10-09 22:26:50 +02:00
2b5d442d3a
Changing v0.4.1 to v0.5.0 considering the number of changes.
Some checks failed
continuous-integration/drone/push Build is failing
2023-10-09 20:29:21 +02:00
038dd9f4a8
Fixing the (previously very broken) text renderer when using symbols.
Some checks failed
continuous-integration/drone/push Build is failing
2023-10-09 18:50:34 +02:00
cf754a7a34
Better handling of constants in simplified expressions. 2023-10-09 18:37:28 +02:00
bc35b18da0
Insert character popup's characters are now contextually aware.
Some checks failed
continuous-integration/drone/push Build is failing
2023-10-09 17:55:06 +02:00
7542d63121
Adding new characters to insert chars popup. 2023-10-09 17:20:32 +02:00
4fe1086d68
Adding new behavior for object creation to default on picker when pickable.
Some checks failed
continuous-integration/drone/push Build is failing
2023-10-08 22:36:23 +02:00
a66ccd1319
Changing version to v0.4.1
Some checks failed
continuous-integration/drone/push Build is failing
2023-10-08 18:34:51 +02:00
9879e7fbc9
Fixing changelog 2023-10-08 18:34:09 +02:00
999999832a
Taking edge cases into account into new drawing system.
Some checks failed
continuous-integration/drone/push Build is failing
2023-10-08 17:22:21 +02:00
7408520819
Reworking continuous functions' rendering to make it faster.
Some checks failed
continuous-integration/drone/push Build is failing
+ Diminishing pixel precision from 1 to 10.
+ The change is barely noticable by the human eye in most functions.
+ Reworked domain checking to keep the pixel perfect precision.

The only visual degradations are functions with very high y variations for very small x variations (like cos and sin on log scale).
2023-10-08 17:00:12 +02:00
9f2b08b938
Fixing "Unknown variable ∞." message.
It occured when using a domain with the infinity symbol.
2023-10-08 16:31:01 +02:00
3039aade29
Fixing some issues with infinity in domains. 2023-10-08 16:24:16 +02:00
d6a83b0f4b
Adding the ability to scroll to zoom.
Some checks failed
continuous-integration/drone/push Build is failing
2023-10-07 23:38:51 +02:00
0b5aa36c23
Adding view position changer overlay. 2023-10-07 19:11:19 +02:00
25347a8eff
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
Some checks failed
continuous-integration/drone/push Build is failing
2023-10-07 02:54:36 +02:00
ovari
d6d7f3a511
Translated using Weblate (Hungarian)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (267 of 267 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/
2023-06-11 06:48:17 +02:00
e67619771b
Fixing macOS building script. 2023-05-27 11:09:13 +02:00
df3e7d4796
I thought I pushed the updated script for macOS, but it looks like I didn't.
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-27 10:36:37 +02:00
19e403ce98
Forgot to remove auto reappearance from greet screen.
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-27 10:11:42 +02:00
273d5539ec
Forgot to update the debian changelog. 2023-05-27 10:11:19 +02:00
5e7dbb8fa6
Adding changelog 2023-05-27 10:07:40 +02:00
1e30bee220
Updating snapcraft building
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-26 20:11:41 +02:00
ebf07dccfa
Disabling interactive thanks dialog.
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-26 18:05:05 +02:00
95546bd14e
Qt6 testing and porting on macOS.
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-26 14:54:28 +02:00
59145905ea
Changing dependencies to only PySide6's essentials.
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-26 08:16:48 +02:00
66da751b36
Updating windows builders for pyside6 (halving the bundled installer size)
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-26 06:25:29 +02:00
deb4355756
Preparing debian package for PySide6
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-25 19:40:06 +02:00
8358cc142c
Fixing localisation issue on position picker
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-25 15:08:12 +02:00
62e70885e0
Changing default themes for the ones available in Qt6
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-25 12:15:35 +02:00
6fa0aea0e5
Disabling auto detect of qtquick style if manual set.
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-25 10:27:27 +02:00
08edd7be14
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-24 11:49:59 +02:00
16effe064c
Disabling generation of HDPI latex pngs, as they aren't used in PySide6. 2023-05-24 11:49:45 +02:00
98f01845e1
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (267 of 267 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2023-05-24 10:13:06 +02:00
87b4787a2b
Translated using Weblate (German)
Currently translated at 100.0% (267 of 267 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2023-05-24 10:13:05 +02:00
a610d0949e
Translated using Weblate (English)
Currently translated at 100.0% (267 of 267 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2023-05-24 10:13:05 +02:00
803670635b
Forgot to disable Greet Screen seen saving.
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-24 10:00:47 +02:00
09c1a44150
Adding escape shortcut for base dialog.
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-24 09:58:58 +02:00
40743e54c3
Allow the user to choose what he wants to pick.
All checks were successful
continuous-integration/drone/push Build is passing
Updating translations.
2023-05-24 08:00:58 +02:00
9239eac78a
Fixing several function calls with no argument errors.
All checks were successful
continuous-integration/drone/push Build is passing
+ Functions max and min now throw an error if no arguments are provided.
+ Objects called now throw an error if no argument is provided.
+ Fixing tokenizer's seek error reporting system (leads to very rare types of errors).
+ Removing expression simplifications that could make the app freeze when no arguments are provided to a function.
2023-05-24 07:43:40 +02:00
35ce1c4824
Adding error handling for function argument errors. 2023-05-24 07:03:12 +02:00
75e70903f1
Fixing coloration in dark theme of autocomplete categories. 2023-05-24 06:47:34 +02:00
016a21ecb4
Adding new translations
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-24 04:18:55 +02:00
f7dd40d2f5
Changing omega zero icon file name to fix issue with finding it.
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-24 04:00:09 +02:00
d1843b455a
Fixing issue with sums & latex variables. 2023-05-24 03:58:13 +02:00
6abbbe5e61
Adding picker for properties (x,y,labelX)
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-24 03:51:42 +02:00
5cef8e23fa
Fixing several issues with repartition
+ Underscores being automatically removed from the name the moment it's edited.
+ Fixing issue with function name change.
2023-05-24 03:17:21 +02:00
d6dee6a2be
Fixing color picker not working
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-24 02:48:35 +02:00
3da51430f1
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (258 of 258 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2023-05-23 14:13:36 +02:00
ae930be621
Translated using Weblate (German)
Currently translated at 100.0% (258 of 258 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2023-05-23 14:13:35 +02:00
abae3ef94b
Translated using Weblate (English)
Currently translated at 100.0% (258 of 258 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2023-05-23 14:13:35 +02:00
82d53748b3
Forgot to change shiboken2 to shiboken6 in windows installer.
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-23 13:03:00 +02:00
fce2a5ba0d
Adding version freeze for changelog
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-23 12:51:47 +02:00
3904dc0217
Removing last instances of PySide2, updating copyrights & version to v0.4
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-23 12:42:43 +02:00
7a80455e25
Fixing the usage of symbols in text.
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-22 11:02:34 +02:00
20c1ed005e
Removing warning
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-22 09:49:20 +02:00
d8534d1e0d
Adding bottom borders to dialogs 2023-05-22 09:31:43 +02:00
4be92a07e3
Adding revision to CI building image.
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-22 07:43:44 +02:00
b143f7e10d
Disable Windows testing (issue between PySide6, wine & Xvfb).
Some checks failed
continuous-integration/drone/push Build is failing
Reinstating windows building.
2023-05-22 07:29:15 +02:00
0ac690d0c1
Fixing cursor from expression editor.
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-22 07:22:33 +02:00
37150b5823
Fixing CI image
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-22 06:18:03 +02:00
0539f988e2
Adding new strings
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2023-05-22 06:17:08 +02:00
bf067b7e7c
Fixing object edition dialog height
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2023-05-22 06:11:15 +02:00
9f20a80228
Merge branch 'qt6' 2023-05-22 05:57:03 +02:00
5ef8cac1c0
Adding color schemes for expressions 2023-05-22 05:56:34 +02:00
7ec80e6682
Custom color schemes! 2023-05-22 05:17:12 +02:00
43d78e17e5
Improving LaTeX rendering DPI. 2023-05-22 04:21:53 +02:00
93308f2bfa
Forgot adding setting icon 2023-05-22 03:41:50 +02:00
508f316bc5
Better pick location settings overlay 2023-05-22 03:41:20 +02:00
424eef6e17
Fixing opening file in settings, updating CI images to PySide6. 2023-05-22 01:50:22 +02:00
f40c242877
Bumping copyright 2023-05-22 00:19:58 +02:00
aecc02c606
Updating to Qt6 2023-05-22 00:15:09 +02:00
78ffc8c645
Changing RegExpValidator to RegularExpressionValidator. 2023-05-21 22:32:49 +02:00
98f26d4919
Removing unclosed tag.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-28 22:02:52 +02:00
65c42abd26
Updating metadata images for the future.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-28 21:53:19 +02:00
ba98fc3611
Fixing appstream data.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-28 19:26:00 +02:00
839f8e9f36
Updating changelog to not overflow the popup.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-28 18:15:10 +02:00
fe13351e99
Removing flatpak submodule.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-28 17:38:41 +02:00
225ae67834
Releasing v0.3.0!
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-28 16:41:20 +02:00
6307855b87
Adding v0.3.0 changelog.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-28 16:36:18 +02:00
3a36e41738
Fixing MacOS building version string.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-24 04:51:25 +02:00
ee26bc04c5
Fixing syntax error.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-23 23:26:34 +02:00
ovari
02c7cb8afc
Translated using Weblate (Hungarian)
Some checks failed
continuous-integration/drone/push Build is failing
Currently translated at 100.0% (253 of 253 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/
2022-10-23 10:05:26 +02:00
0a064694f5
Adding new functions for autocomplete, and disabling the ones not implemented in expr-eval.
Some checks failed
continuous-integration/drone/push Build is failing
2022-10-22 18:26:36 +02:00
b0b77834a8
Fixing inability to open and load files due to greet screen fixes. 2022-10-22 14:17:52 +02:00
fb1c4c0de7
Using Screen.devicePixelRatio as image depth.
Fixes bluriness of images on HDPI screens and disabling it on those who don't need it.
2022-10-22 14:16:15 +02:00
d969661b33
Fixing autocompletion in case object does not exist.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-21 15:40:01 +02:00
86656fe46c
Bumping version to 0.3.0, removing GreetScreen debug.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-20 22:05:45 +02:00
4b6d333cee
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (253 of 253 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2022-10-20 21:54:21 +02:00
9ca8903a3e
Translated using Weblate (German)
Currently translated at 100.0% (253 of 253 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2022-10-20 21:54:20 +02:00
a3faeeb7d0
Translated using Weblate (English)
Currently translated at 100.0% (253 of 253 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2022-10-20 21:54:20 +02:00
244935d7e2
Adding settings for editor.
All checks were successful
continuous-integration/drone/push Build is passing
Also fixing bug with GreetScreen not setting settings in the menu bar, and adding translations.
2022-10-20 21:44:08 +02:00
677d13278d
Removing debug that made functions crash
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-20 18:11:40 +02:00
7241add9e5
Recursive dependencies & fixing some bugs related to dependencies themselves.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-20 18:10:49 +02:00
356169c749
Fixing expression being set even if errors are found.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-20 17:39:36 +02:00
7e427e5bb9
Fixing history rendering of expressions
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-20 16:44:11 +02:00
3cd4ad6a20
Object properties for autocompletion!
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-20 16:23:12 +02:00
0e41c12e03
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (244 of 244 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2022-10-20 01:44:18 +02:00
fc68d3da6a
Translated using Weblate (German)
Currently translated at 100.0% (244 of 244 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2022-10-20 01:44:18 +02:00
0561782293
Translated using Weblate (English)
Currently translated at 100.0% (244 of 244 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2022-10-20 01:44:18 +02:00
47a9f63d66
Adding new category for object properties unpopulated
All checks were successful
continuous-integration/drone/push Build is passing
Adding new translations
2022-10-20 01:35:14 +02:00
7f548796f2
Slight change for Repartition for the name to be prefixed by F_ on creation.
All checks were successful
continuous-integration/drone/push Build is passing
This makes it better when using it in tooltips for autocompletion.
2022-10-20 01:25:55 +02:00
15b87fc15d
Variables & objects (+ their type) in autocompletion. 2022-10-20 01:14:09 +02:00
77ae54fa18
More autocompletion! 2022-10-20 00:37:02 +02:00
5da8dcefe5
First crack at autocompletion. 2022-10-19 23:44:04 +02:00
16efe31b5f
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (238 of 238 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2022-10-19 19:47:15 +02:00
6e21f2eea1
Translated using Weblate (German)
Currently translated at 100.0% (238 of 238 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2022-10-19 19:47:15 +02:00
c85dba737d
Translated using Weblate (English)
Currently translated at 100.0% (238 of 238 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2022-10-19 19:47:15 +02:00
218c55b491
Fixing Expression and text not saving changes when having used the input character popup.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-19 17:37:38 +02:00
e98be96b0d
Latex rendering for property edition history action!
Some checks failed
continuous-integration/drone/push Build is failing
2022-10-19 17:29:35 +02:00
c5851e6d95
Adding new 'Position setting' history action.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-19 17:11:54 +02:00
de1be925b0
Removing unneeded and buggy simplifications.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-19 02:55:23 +02:00
ddb5156396
Fixing mistranslated string.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-19 02:49:43 +02:00
7686204786
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (236 of 236 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2022-10-19 02:45:17 +02:00
acadad2bd1
Translated using Weblate (German)
Currently translated at 100.0% (236 of 236 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2022-10-19 02:45:16 +02:00
1ceccc15cf
Translated using Weblate (English)
Currently translated at 100.0% (236 of 236 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2022-10-19 02:45:16 +02:00
97338506a4
Adding new translation strings (errors with syntax)
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-19 02:00:22 +02:00
e7ba1d9ff5
Disabling font properties to reactivate native OS font size.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-19 01:53:53 +02:00
b519e34016
Fixed bugs.
All checks were successful
continuous-integration/drone/push Build is passing
1. X Cursors pointing to an object when LaTeX is enabled make LogarithmPlotter crash due to invalid LaTeX.
2. Invalid class-property types are now directly generated from the static instance.
3. Sequences didn't include sequence value properly anymore.
2022-10-19 01:49:30 +02:00
dc532fcd19
Forgot to add the parsing javascript module.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-19 01:19:52 +02:00
971a9d10d2
Reverting not swapping the sidebar at load.
Some checks failed
continuous-integration/drone/push Build is failing
As the bug is *still* very much present.
Notably when you load a graph from command line arguments.
2022-10-19 01:18:25 +02:00
4564d5446f
Syntax coloration first attempt!
Currently, when there are two many styles, the text is *slightly* offset from the normal one.
2022-10-19 01:16:54 +02:00
32db56304b
Expression editor!
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-18 23:24:58 +02:00
64d1419452
Fixing bugs in recursive object deletion and dependency. 2022-10-18 22:40:49 +02:00
fcf5ef9539
Fixing a few bugs related to dependency and text. 2022-10-18 22:17:10 +02:00
6116ffe4e7
Removing tab switch on file open due to previous fix about first tab length.
Some checks failed
continuous-integration/drone/push Build is failing
2022-10-18 18:31:42 +02:00
2a8cab9398
Proper error handling and reporting for expressions!
Only remaining non convered case is recursive dependencies, but I'm not willing to tackle that yet.
2022-10-18 18:31:04 +02:00
29e62fee6e
Trying to fix deb build
Some checks failed
continuous-integration/drone/push Build is failing
2022-10-18 17:49:49 +02:00
d65f343b60
Reworking the Editor dialog to be much faster and cleaner.
All checks were successful
continuous-integration/drone/push Build is passing
By using Components and Loader instead of instantiating each type of editor for every property, the whole operation becomes much faster, cleaner, and streamlined.
Visible (admittedly unmeasured) boosts in speed with it.
Preparing the groundwork for new editors.
2022-10-18 16:43:39 +02:00
f76b601139
Fixing tons of bugs.
All checks were successful
continuous-integration/drone/push Build is passing
1. Height of object list items should be adaptable to image's heights.
2. Fixed object positioning
3. Buttons of object rows are now vertically centered.
4. Fixing expr-eval not recognizing certain characters as part of the variable.
5. Fixing silent error when misentering variables preventing you from changing the expression again.
6. Fixing points in gains and phases having name-related issues.
7. (in the previous commit) Fixing invisible buttons at the end of the object row when not changing tabs.
2022-10-18 02:55:15 +02:00
9facc2389c
Attempting to fix blurry icons and Latex renders in the objects tab. 2022-10-18 02:00:56 +02:00
15fd660e0c
Adding support for latex images in the objects tab. 2022-10-18 01:47:49 +02:00
dfdd576296
Componentizing the object's row. 2022-10-18 01:12:24 +02:00
b8d312bb23
Fixing build²
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-18 00:49:15 +02:00
8c6784663e
Fixing build
Some checks failed
continuous-integration/drone/push Build is failing
2022-10-18 00:47:27 +02:00
1a433eba27
Propagated property updates to dependent objects.
Some checks failed
continuous-integration/drone/push Build is failing
+ Fixing object expression dependency at setup.
+ Fixing function calls in utils
+ Removing some unnecessary comments
2022-10-18 00:45:53 +02:00
1ba594c4f7
Fixing executing function in expression. 2022-10-17 22:54:02 +02:00
6b535dd8a2
Adding object properties usable in expressions 2022-10-17 22:30:59 +02:00
fad5325501
Better handling of Object names in a separate dictionary. 2022-10-17 20:25:29 +02:00
3dc69cc9ba
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
All checks were successful
continuous-integration/drone/push Build is passing
2022-05-15 00:28:18 +02:00
2d46de35d2
Fixing snap 2022-05-15 00:28:11 +02:00
Sergio Varela
ef04b2aa58
Translated using Weblate (Spanish)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 13.6% (28 of 205 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2022-05-11 15:15:45 +02:00
ovari
876ea1eaa8
Translated using Weblate (Hungarian)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (205 of 205 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/
2022-05-02 04:11:17 +02:00
20f8d68f13
Starting v0.2.1
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-23 02:17:34 +02:00
a5ce17e7f3
Updating appstream images 2022-04-23 02:14:26 +02:00
cf3e775834
Fixing LaTeX disabling for texts not being saved.
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-23 01:40:47 +02:00
cb733a556c
Releasing v0.2.0
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-22 17:05:15 +02:00
22c9151e0c
Adding changelog for v0.2.0
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-22 16:53:48 +02:00
871630ef0b
Last fix for appstream generation script.
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-22 16:32:56 +02:00
6b2afd3a1b
Fixing generation script MacOS link.
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-22 16:25:20 +02:00
b496807576
Disabling LaTeX integration by default.
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-22 15:28:02 +02:00
b45e105202
Disabling LaTeX popup if LaTeX support is disabled.
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-04-22 15:14:52 +02:00
6129bcf928
Translated using Weblate (French)
Some checks reported errors
continuous-integration/drone/push Build was killed
Currently translated at 100.0% (205 of 205 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2022-04-16 20:03:39 +02:00
b69aaa2d7a
Translated using Weblate (German)
Currently translated at 100.0% (205 of 205 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2022-04-16 20:03:39 +02:00
1b91176f2d
Translated using Weblate (English)
Currently translated at 100.0% (205 of 205 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2022-04-16 20:03:39 +02:00
3a2fcb1be1
Adding new translations strings.
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-04-16 19:25:01 +02:00
836e6d8922
Merge branch 'latex-rendering' 2022-04-16 19:18:31 +02:00
eef42655e5
Trying to fix build
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-04-02 18:20:04 +02:00
1f581c46ec
Adding thanks to popup
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-02 18:17:09 +02:00
f77b1ce331
Fixing snapcraft
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-04-02 16:39:21 +02:00
86f3399a53
Fixing a lot of snap issues, updating translations
Some checks reported errors
continuous-integration/drone/push Build was killed
- Files are now properly opened in snapcraft
- Added latex dependencies to snapcraft (tho it's buggy atm)
- Added changelog to snapcraft
2022-03-09 00:28:42 +01:00
3e7b36a420
Changing version to v0.2.0 instead of v0.1.9
Due to Latex being a big change.
2022-03-07 20:40:37 +01:00
27759362cb
Toggle for latex setting
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-03-07 20:28:50 +01:00
7120e3a781
Fixing timeout on build.
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-03-07 17:25:30 +01:00
166d1a2485
X Cursor Latex implementation
Some checks reported errors
continuous-integration/drone/push Build was killed
Also a few bugfixes and added documentation
2022-03-07 17:20:24 +01:00
2691ba687f
Changed a few serif text to sans serif. 2022-03-07 15:06:40 +01:00
4c9c9668bb
Adding comment to disableLatex, allowing for symbols in content.
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-03-07 03:10:51 +01:00
b72bbeab4f
Translated using Weblate (French)
Some checks reported errors
continuous-integration/drone/push Build was killed
Currently translated at 100.0% (184 of 184 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2022-03-07 02:58:47 +01:00
7723107ff6
Translated using Weblate (English)
Currently translated at 100.0% (184 of 184 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2022-03-07 02:58:46 +01:00
6539ca8caa
Fixing linux tests
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-03-07 02:50:50 +01:00
12ecf3b19b
Adding LatexExpression, LaTeX integration for texts (needs a comment tho)
Some checks failed
continuous-integration/drone/push Build is failing
- Simplified label rendering for both Latex and normal mode
- Texts now can integrate latex expressions in latex mode
- There is now a toggle for texts to use normal fonts or integrate latex
- Updated translation sources.
2022-03-07 02:47:58 +01:00
07ae71de36
DVI files are no longer remade unless there is a change in the formula
Some checks failed
continuous-integration/drone/push Build is failing
2022-03-07 01:37:23 +01:00
06bb00cc17
Latex for sums, fixing bugs related to expression simplification.
Some checks failed
continuous-integration/drone/push Build is failing
Also removing some debug and unused code.
2022-03-07 00:11:12 +01:00
ec90779912
Changing build process to reflect changes.
Some checks failed
continuous-integration/drone/push Build is failing
2022-03-06 23:36:10 +01:00
2ce66df4dd
Removed dependency on Sympy for subprocesses directly.
New dependencies: latex, dvipng.

Slight changes to default for fonts to avoid too many anti aliasing issues.
Also adds proper checks for latex installation.
2022-03-06 23:34:59 +01:00
8251504fbe
Latex markup for sequences and bode phases 2022-03-06 18:31:03 +01:00
650e43894c
Merging label drawing functions, adding comments to common objects, adding bode magnitude.
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-03-06 17:44:31 +01:00
de0220fecf
Implemented latex for distributions 2022-03-06 01:13:20 +01:00
c4ffcdaa35
Removing custom copyrights from license in order to have better referencing.
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-03-06 01:01:12 +01:00
0975189615
A lot of changes related to latex:
Some checks reported errors
continuous-integration/drone/push Build was killed
- Implemented latex for functions
- Fixed Points with greek variable names
- Small changes to test1 to fit latex better
- History re/undos only redraw the graph every 4 change in order to speed up the process when re/undoing a lot of changes.
- Removing some debug related to latex
- Added latexMarkup property for domains, allowing them to be integrated into objects latex.
- Fixed issues related to derivatives and integrals on latex
- Fully fixed variable substitution for latex
- Fixed sequence crashing
- Adding getLatexLabel method for objects that have a latex label.
2022-03-06 00:55:32 +01:00
ccf3de5783
Fixing typos
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-03-05 21:00:29 +01:00
b5600046e9
Fixing build to add sympy.
Some checks failed
continuous-integration/drone/push Build is failing
2022-03-05 20:58:38 +01:00
387 changed files with 39056 additions and 18244 deletions

37
.gitignore vendored
View file

@ -1,33 +1,46 @@
# Building
build/
dist/
deb_dist/
linux/flatpak/AppDir
linux/flatpak/repo
linux/flatpak/build-dir
linux/flatpak/.flatpak-builder
assets/linux/flatpak/AppDir
assets/linux/flatpak/repo
assets/linux/flatpak/build-dir
assets/linux/flatpak/.flatpak-builder
*.snap
*.spec
*.zip
*.tar.gz
*.spec
*.egg-info/
# Runtime data
**/**.qmlc
**/**.jsc
**/**.pyc
**/**.qm
**/**.log
*.jsc
*.qmlc
*.log
**/*.dxvk-cache
.DS_Store
**/.DS_Store
**/__pycache__/
# IDE Data
.ropeproject
.vscode
build
*.kdev4
.kdev4
docs/html
.directory
*.kdev4
*.lpf
*.lgg
*.spec
.kdev4
AccountFree.pro
AccountFree.pro.user
*.egg-info/
*.tar.gz
# Tests
common/coverage/
**/.coverage
# npm
common/node_modules
runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/index.mjs*

7
.gitmodules vendored
View file

@ -1,6 +1,3 @@
[submodule "LogarithmPlotter/qml/eu/ad5001/MixedMenu"]
path = LogarithmPlotter/qml/eu/ad5001/MixedMenu
[submodule "runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/MixedMenu"]
path = runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/MixedMenu
url = https://git.ad5001.eu/Ad5001/MixedMenu
[submodule "linux/flatpak"]
path = linux/flatpak
url = https://github.com/Ad5001/eu.ad5001.LogarithmPlotter

View file

@ -1,5 +1,162 @@
# Changelog
## v0.5.0 (11 Jan 2024)
**New**
* New, reworked application icon.
* Graph is now mouse interactive:
* You can now drag to move and scroll to zoom!
* Builtin functions now provide usage when used in the autocomplete of the expression editor.
**Changes**
* When creating an object that can be positioned, new default behavior is to pick first instead of opening object settings.
* Icons with text now use the SVG's text element, allowing them to integrate better with the system's default font.
* Special characters popup is now context aware (e.g. no sub/supscript symbols in expressions).
* New symbols in special characters popup.
* Integrals and derivatives can now be provided with an executable object (e.g. Functions) instead of strings as function.
* New description on Linux.
**Fixed bugs**
* Fixing ∞ 'variable' in domains and expressions.
* Several other bugs related to constants in expresions were fixed as well.
* Builtin functions now send an error message when not provided with the proper arguments.
**Internal changes**
* Updated to PySide6 v6.6.1.
* Reworked continuous functions' rendering to make it faster.
* Removed old bits from an unfinished new parser that weren't used.
## v0.4.0 (27 May 2023)
**Changes**
* Fully ported to PySide6 (Qt6).
* Greet screen settings are now scrollable.
* Changelog is now freezed to current version.
**New**
* Customizable color schemes for expressions.
* New, rewamped and improved picked location overlay settings:
* It's now possible to disable picking x or y when setting a location.
* Properties which are related to positioning (X, Y, Label's X position) can now be set using the picker.
* Visual redesign that enhances readability of settings.
* There is now a button to hide picker settings.
**Fixed bugs**
* Cursors in expression are now easier to see.
* Symbols in LaTeX rendered Texts cause the LaTeX renderer to crash.
* Underscores in distribution names are automatically removed if the name is modified.
* Autocomplete categories now properly respect theme colors.
* Functions in expressions (like indexOf, map...) now properly send errors when the arguments are of the wrong type or count.
* Executable Objects called (like functions, bode magnitures, phases...) now send an error if provided with no arguments.
* Function calls with no argument no longer make LogarithmPlotter crash under certain circumstances.
* Thank you dialog's lists are no longer draggable.
**Internal changes**
* A lot of inner changes led by porting to Qt6, fixing a lot of bugs at the same time.
* Disabled auto detect of visual theme if the `QT_QUICK_CONTROLS_STYLE` environment variable is set.
* (macOS, Windows, Flatpak) Drastically reducing installer sizes (more than halved).
* (Launchpad/Ubuntu) Using custom built packages of PySide6, meaning smaller installation and distro dependency.
## v0.3.0 (28 Oct 2022)
**New**
* New completely revamped expression editor:
* Automatic closing of parentheses and brackets (can be disabled in settings).
* Syntax highlighting (can be disabled in the settings).
* Autocompletion is now available (for functions, variables and constants, object names and properties) (can be disabled in the settings).
* Object properties can now be used in expressions (e.g. if you have a point named A, you can use A.x to access its x value).
* Executable objects can be now be used in expressions (e.g. if you have a function named 'f', it's accessible using `f(<value>)`).
* LaTeX-rendered formulas are now used in the Objects and History tabs when LaTeX rendering is enabled.
* Errors in formulas are now reported in message boxes.
**Changes**
* The Object Editor dialog has been completely reworked internally, resulting in notable performance improvements.
* Vast improvements to the objects system: names can no longer be shared amongst different objects.
* Disabled access to custom variable and function definition in expressions (can cause issues and vulnerabilities)
* When using the set position cursor, the position change is now saved a single history action.
* Distribution are now prefixed with an 'F_' to prevent confusion with X Cursors.
**Added translations**
* Autocompletion categories (English, French, German, Hungarian).
* Expression editor settings (English, French, German, Hungarian).
* Expression syntax errors (English, French, German, Hungarian).
* On top of the above:
* Hungarian: v0.2.0 added text (thanks @ovari!)
* Spanish: Menu bars (thanks @Sergio Varela)
* You can contribute to translation on [Weblate](https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/#repository).
**Fixed bugs**
* Fixing Texts not being properly recognized as texts when saving.
* Text's 'Disable LaTeX' property is now properly saved.
* X Cursors LaTeX rendering made the app crash.
* Attempting to insert special character no longer automatically saves the expression you're editing.
* Proper HDPI support for icons and buttons (note: HDPI is not available for the rendered canvas yet).
* Support for non-latin characters in variables (e.g. greek letters, subtext, suptext)
* Silent error when misentering variable names in the expression editor causing internal issues.
* Fixing some utils function simplifying parentheses when they shouldn't have.
* (flatpak and KDE SDK) Fixing the sometimes invisible buttons on the objects tab on startup.
* (macos) Application string version does not match LogarithmPlotter's version.
* (debian) (Normally) Fixing deb building.
**Internal changes**
* Object dependencies are now registered on both the dependant object, and the object it's depending on.
* Objects now have a proper per-name registry.
* Object Editor Dialog has been reworked to use loaders insteads.
* Reworked the file loading system to be able to load dependencies properly.
## v0.2.0 (22 Apr 2022)
**New**
* (EXPERIMENTAL) LogarithmPlotter now has an optional LaTeX integration.
* It requires a LaTeX installation, including `latexmk` and `dvipng` available in the PATH.
* NOTE: LaTeX support is disabled by default and is only for working for the rendering on the graph.
* NOTE: The objects and history tab still use the legacy text based expression rendering.
* Thanks and contributions dialog, showing included libraries and translations, their license and author(s).
* LaTeX rendering can be disabled for texts, even if LaTeX is enabled.
**Changes**
* History re/undos only redraw the graph every 4 change at most in order to speed up the process when re/undoing a lot of changes.
* Gradients are no longer hidden when filtered out in the history tab.
**Added translations**
* LaTeX options and error messages
* Thanks and contribution dialog
* New option for text.
* Fixed translation of "repartition" which should be "distribution" in certain remaining strings.
**Fixed bugs**
* (macos) #1 - Opening files don't work on compiled versions of LogarithmPlotter on MacOS
* (snapcraft) Fixed bug preventing from launching LogarithmPlotter. This fix has been backported to v0.1.8.
* (snapcraft) Files are now properly opened.
* (snapcraft) Added changelog support.
**Internal changes**
* Moved python modules to "util" directory for more clarity.
* Moved flatpak metainfo to eu.ad5001.LogarithmPlotter repository.
* Componented the Mathlib library in order to have a more readable source.
* Added documentation for most internal JavaScript modules.
* Merge label drawing methods due to it's complexity.
* (flatpak) Updated SDK version to v5.15-21.08.
## v0.1.8 (19 Feb 2022)
**New**

View file

@ -630,8 +630,8 @@ attach them to the start of each source file to most effectively state
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
LogarithmPlotter - Create graphs with logarithm scales.
Copyright (C) 2021 Ad5001
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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
@ -652,7 +652,7 @@ mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
LogarithmPlotter Copyright (C) 2021 Ad5001
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@ -673,4 +673,3 @@ library, you may consider it more useful to permit linking proprietary
applications with the library. If this is what you want to do, use the
GNU Lesser General Public License instead of this License. But first,
please read <https://www.gnu.org/licenses/why-not-lgpl.html>.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,2 +0,0 @@
#!/bin/bash
lrelease *.ts

View file

@ -1,2 +0,0 @@
#!/bin/bash
lupdate -extensions js,qs,qml,py -recursive .. -ts lp_*.ts

View file

@ -1,149 +0,0 @@
"""
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
"""
from time import time
start_time = time()
from PySide2.QtWidgets import QApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCore import QTranslator, QLocale
from PySide2.QtGui import QIcon
from tempfile import TemporaryDirectory
from os import getcwd, chdir, environ, path, remove, close
from platform import release as os_release
from sys import platform, argv, version as sys_version, exit
# Create the temporary directory for saving copied screenshots and latex files
tempdir = TemporaryDirectory()
tmpfile = path.join(tempdir.name, 'graph.png')
pwd = getcwd()
chdir(path.dirname(path.realpath(__file__)))
from sys import path as sys_path
if path.realpath(path.join(getcwd(), "..")) not in sys_path:
sys_path.append(path.realpath(path.join(getcwd(), "..")))
from LogarithmPlotter import __VERSION__
from LogarithmPlotter.util import config, native
from LogarithmPlotter.util.update import check_for_updates
from LogarithmPlotter.util.helper import Helper
from LogarithmPlotter.util.latex import Latex
config.init()
def get_linux_theme():
des = {
"KDE": "org.kde.desktop",
"gnome": "default",
"lxqt": "fusion",
"mate": "fusion",
}
if "XDG_SESSION_DESKTOP" in environ:
return des[environ["XDG_SESSION_DESKTOP"]] if environ["XDG_SESSION_DESKTOP"] in des else "fusion"
else:
# Android
return "Material"
def run():
environ["QT_QUICK_CONTROLS_STYLE"] = {
"linux": get_linux_theme(),
"freebsd": get_linux_theme(),
"win32": "universal" if os_release == "10" else "fusion",
"cygwin": "fusion",
"darwin": "default"
}[platform]
dep_time = time()
print("Loaded dependencies in " + str((dep_time - start_time)*1000) + "ms.")
icon_fallbacks = QIcon.fallbackSearchPaths();
base_icon_path = path.join(getcwd(), "qml", "eu", "ad5001", "LogarithmPlotter", "icons")
icon_fallbacks.append(path.realpath(path.join(base_icon_path, "common")))
icon_fallbacks.append(path.realpath(path.join(base_icon_path, "objects")))
icon_fallbacks.append(path.realpath(path.join(base_icon_path, "history")))
icon_fallbacks.append(path.realpath(path.join(base_icon_path, "settings")))
icon_fallbacks.append(path.realpath(path.join(base_icon_path, "settings", "custom")))
QIcon.setFallbackSearchPaths(icon_fallbacks);
app = QApplication(argv)
app.setApplicationName("LogarithmPlotter")
app.setOrganizationName("Ad5001")
app.styleHints().setShowShortcutsInContextMenus(True)
app.setWindowIcon(QIcon(path.realpath(path.join(getcwd(), "logarithmplotter.svg"))))
# Installing translators
translator = QTranslator()
# Check if lang is forced.
forcedlang = [p for p in argv if p[:7]=="--lang="]
locale = QLocale(forcedlang[0][7:]) if len(forcedlang) > 0 else QLocale()
if (translator.load(locale, "lp", "_", path.realpath(path.join(getcwd(), "i18n")))):
app.installTranslator(translator);
# Installing macOS file handler.
macOSFileOpenHandler = None
if platform == "darwin":
macOSFileOpenHandler = native.MacOSFileOpenHandler()
app.installEventFilter(macOSFileOpenHandler)
engine = QQmlApplicationEngine()
global tmpfile
helper = Helper(pwd, tmpfile)
latex = Latex(tempdir, app.palette())
engine.rootContext().setContextProperty("Helper", helper)
engine.rootContext().setContextProperty("Latex", latex)
engine.rootContext().setContextProperty("TestBuild", "--test-build" in argv)
engine.rootContext().setContextProperty("StartTime", dep_time)
app.translate("About","About LogarithmPlotter") # FOR SOME REASON, if this isn't included, Qt refuses to load the QML file.
engine.addImportPath(path.realpath(path.join(getcwd(), "qml")))
engine.load(path.realpath(path.join(getcwd(), "qml", "eu", "ad5001", "LogarithmPlotter", "LogarithmPlotter.qml")))
if not engine.rootObjects():
print("No root object", path.realpath(path.join(getcwd(), "qml")))
print(path.realpath(path.join(getcwd(), "qml", "eu", "ad5001", "LogarithmPlotter", "LogarithmPlotter.qml")))
exit(-1)
# Open the current diagram
chdir(pwd)
if len(argv) > 0 and path.exists(argv[-1]) and argv[-1].split('.')[-1] in ['lpf']:
engine.rootObjects()[0].loadDiagram(argv[-1])
chdir(path.dirname(path.realpath(__file__)))
if platform == "darwin":
macOSFileOpenHandler.init_graphics(engine.rootObjects()[0])
# Check for updates
if config.getSetting("check_for_updates"):
check_for_updates(__VERSION__, engine.rootObjects()[0])
exit_code = app.exec_()
tempdir.cleanup()
config.save()
exit(exit_code)
if __name__ == "__main__":
run()

View file

@ -1,9 +0,0 @@
<svg id="SVGRoot" width="48" height="48" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
<title>LogarithmPlotter Icon v1.0</title>
<g fill-rule="evenodd" stroke-width="2">
<rect width="48" height="48" ry="6" fill="#fff"/>
<rect x="2" y="38" width="44" height="4" stroke-opacity="0"/>
<rect x="18" y="2" width="4" height="44" stroke-opacity="0"/>
</g>
<path d="M 42.05,2 A 40.05,36.05 0 0 1 2,38.05" fill="none" stroke="#f00" stroke-width="3.9012"/>
</svg>

Before

Width:  |  Height:  |  Size: 488 B

View file

@ -1,215 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.12
import QtQml 2.12
import "../js/objects.js" as Objects
import "../js/historylib.js" as HistoryLib
import "../js/history/common.js" as HistoryCommon
/*!
\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() {
undoCount = 0
redoCount = 0
undoStack = []
redoStack = []
}
/*!
\qmlmethod var History::serialize()
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]
}
/*!
\qmlmethod void History::unserialize(var undoSt, var redoSt)
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 HistoryLib.Actions[undoSt[i][0]](...undoSt[i][1]))
for(let i = 0; i < redoSt.length; i++)
redoStack.push(new HistoryLib.Actions[redoSt[i][0]](...redoSt[i][1]))
undoCount = undoSt.length;
redoCount = redoSt.length;
objectLists.update()
}
/*!
\qmlmethod void History::addToHistory(var action)
Adds an instance of historylib.Action to history.
*/
function addToHistory(action) {
if(action instanceof 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
}
}
/*!
\qmlmethod void History::undo()
Undoes the historylib.Action at the top of the undo stack and pushes it to the top of the redo stack.
*/
function undo() {
if(undoStack.length > 0) {
var action = undoStack.pop()
action.undo()
objectLists.update()
redoStack.push(action)
undoCount--;
redoCount++;
saved = false
}
}
/*!
\qmlmethod void History::redo()
Redoes the historylib.Action at the top of the redo stack and pushes it to the top of the undo stack.
*/
function redo() {
if(redoStack.length > 0) {
var action = redoStack.pop()
action.redo()
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--;
} else {
running = false;
}
}
}
Timer {
id: redoTimer
interval: 5; running: false; repeat: true
property int toRedoCount: 0
onTriggered: {
if(toRedoCount > 0) {
historyObj.redo()
toRedoCount--;
} else {
running = false;
}
}
}
Component.onCompleted: {
HistoryLib.history = historyObj
HistoryCommon.themeTextColor = sysPalette.windowText
}
}

View file

@ -1,5 +0,0 @@
module eu.ad5001.LogarithmPlotter.History
History 1.0 History.qml
HistoryBrowser 1.0 HistoryBrowser.qml
HistoryItem 1.0 HistoryItem.qml

View file

@ -1,466 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.12
import "js/objects.js" as Objects
import "js/utils.js" as Utils
import "js/mathlib.js" as MathLib
/*!
\qmltype LogGraphCanvas
\inqmlmodule eu.ad5001.LogarithmPlotter
\brief Canvas used to display the diagram.
Provides a customized canvas with several helper methods to be used by objects.
\sa LogarithmPlotter, PickLocationOverlay
*/
Canvas {
id: canvas
anchors.top: separator.bottom
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 int LogGraphCanvas::maxgradx
Max power of the logarithmic scaled on the x axis in logarithmic mode.
*/
property int maxgradx: 20
/*!
\qmlproperty var LogGraphCanvas::yaxisstepExpr
Expression for the y axis step (used to create labels).
*/
property var yaxisstepExpr: (new MathLib.Expression(`x*(${yaxisstep})`))
/*!
\qmlproperty double LogGraphCanvas::yaxisstep1
Value of the for the y axis step.
*/
property double yaxisstep1: yaxisstepExpr.execute(1)
/*!
\qmlproperty int LogGraphCanvas::drawMaxY
Minimum value of y that should be drawn onto the canvas.
*/
property int drawMaxY: Math.ceil(Math.max(Math.abs(ymax), Math.abs(px2y(canvasSize.height)))/yaxisstep1)
/*!
\qmlproperty var LogGraphCanvas::xaxisstepExpr
Expression for the x axis step (used to create labels).
*/
property var xaxisstepExpr: (new MathLib.Expression(`x*(${xaxisstep})`))
/*!
\qmlproperty double LogGraphCanvas::xaxisstep1
Value of the for the x axis step.
*/
property double xaxisstep1: xaxisstepExpr.execute(1)
/*!
\qmlproperty int LogGraphCanvas::drawMaxX
Maximum value of x that should be drawn onto the canvas.
*/
property int drawMaxX: Math.ceil(Math.max(Math.abs(xmin), Math.abs(px2x(canvasSize.width)))/xaxisstep1)
property var imageLoaders: {}
property var ctx
Component.onCompleted: imageLoaders = {}
onPaint: function(rect) {
//console.log('Redrawing')
if(rect.width == canvas.width) { // Redraw full canvas
ctx = getContext("2d");
reset(ctx)
drawGrille(ctx)
drawAxises(ctx)
drawLabels(ctx)
ctx.lineWidth = linewidth
for(var objType in Objects.currentObjects) {
for(var obj of Objects.currentObjects[objType]){
ctx.strokeStyle = obj.color
ctx.fillStyle = obj.color
if(obj.visible) obj.draw(canvas, ctx)
}
}
ctx.lineWidth = 1
}
}
onImageLoaded: {
Object.keys(imageLoaders).forEach((key) => {
if(isImageLoaded(key)) {
// Calling callback
imageLoaders[key][0](canvas, ctx, imageLoaders[key][1])
delete imageLoaders[key]
}
})
}
/*!
\qmlmethod void LogGraphCanvas::reset(var ctx)
Resets the canvas to a blank one with default setting using 2D \c ctx.
*/
function reset(ctx){
// Reset
ctx.fillStyle = "#FFFFFF"
ctx.strokeStyle = "#000000"
ctx.font = `${canvas.textsize-2}px sans-serif`
ctx.fillRect(0,0,width,height)
}
// Drawing the log based graph
/*!
\qmlmethod void LogGraphCanvas::drawGrille(var ctx)
Draws the grid using 2D \c ctx.
*/
function drawGrille(ctx) {
ctx.strokeStyle = "#C0C0C0"
if(logscalex) {
for(var xpow = -maxgradx; xpow <= maxgradx; xpow++) {
for(var xmulti = 1; xmulti < 10; xmulti++) {
drawXLine(ctx, Math.pow(10, xpow)*xmulti)
}
}
} else {
for(var x = 0; x < drawMaxX; x+=1) {
drawXLine(ctx, x*xaxisstep1)
drawXLine(ctx, -x*xaxisstep1)
}
}
for(var y = 0; y < drawMaxY; y+=1) {
drawYLine(ctx, y*yaxisstep1)
drawYLine(ctx, -y*yaxisstep1)
}
}
/*!
\qmlmethod void LogGraphCanvas::drawAxises(var ctx)
Draws the graph axises using 2D \c ctx.
*/
function drawAxises(ctx) {
ctx.strokeStyle = "#000000"
var axisypos = logscalex ? 1 : 0
drawXLine(ctx, axisypos)
drawYLine(ctx, 0)
var axisypx = x2px(axisypos) // X coordinate of Y axis
var axisxpx = y2px(0) // Y coordinate of X axis
// Drawing arrows
drawLine(ctx, axisypx, 0, axisypx-10, 10)
drawLine(ctx, axisypx, 0, axisypx+10, 10)
drawLine(ctx, canvasSize.width, axisxpx, canvasSize.width-10, axisxpx-10)
drawLine(ctx, canvasSize.width, axisxpx, canvasSize.width-10, axisxpx+10)
}
/*!
\qmlmethod void LogGraphCanvas::drawLabels(var ctx)
Draws all labels (graduation & axises labels) using 2D \c ctx.
*/
function drawLabels(ctx) {
var axisypx = x2px(logscalex ? 1 : 0) // X coordinate of Y axis
var axisxpx = y2px(0) // Y coordinate of X axis
// Labels
ctx.fillStyle = "#000000"
ctx.font = `${canvas.textsize+2}px sans-serif`
ctx.fillText(ylabel, axisypx+10, 24)
var textSize = ctx.measureText(xlabel).width
ctx.fillText(xlabel, canvasSize.width-14-textSize, axisxpx-5)
// Axis graduation labels
ctx.font = `${canvas.textsize-2}px sans-serif`
var txtMinus = ctx.measureText('-').width
if(showxgrad) {
if(logscalex) {
for(var xpow = -maxgradx; xpow <= maxgradx; xpow+=1) {
var textSize = ctx.measureText("10"+Utils.textsup(xpow)).width
if(xpow != 0)
drawVisibleText(ctx, "10"+Utils.textsup(xpow), x2px(Math.pow(10,xpow))-textSize/2, axisxpx+16+(6*(y==0)))
}
} else {
for(var x = 1; x < drawMaxX; x += 1) {
var drawX = x*xaxisstep1
var txtX = xaxisstepExpr.simplify(x)
var textSize = measureText(ctx, txtX, 6).height
drawVisibleText(ctx, txtX, x2px(drawX)-4, axisxpx+textsize/2+textSize)
drawVisibleText(ctx, '-'+txtX, x2px(-drawX)-4, axisxpx+textsize/2+textSize)
}
}
}
if(showygrad) {
for(var y = 0; y < drawMaxY; y += 1) {
var drawY = y*yaxisstep1
var txtY = yaxisstepExpr.simplify(y)
var textSize = ctx.measureText(txtY).width
drawVisibleText(ctx, txtY, axisypx-6-textSize, y2px(drawY)+4+(10*(y==0)))
if(y != 0)
drawVisibleText(ctx, '-'+txtY, axisypx-6-textSize-txtMinus, y2px(-drawY)+4)
}
}
ctx.fillStyle = "#FFFFFF"
}
/*!
\qmlmethod void LogGraphCanvas::drawXLine(var ctx, double x)
Draws an horizontal line at \c x plot coordinate using 2D \c ctx.
*/
function drawXLine(ctx, x) {
if(visible(x, ymax)) {
drawLine(ctx, x2px(x), 0, x2px(x), canvasSize.height)
}
}
/*!
\qmlmethod void LogGraphCanvas::drawXLine(var ctx, double x)
Draws an vertical line at \c y plot coordinate using 2D \c ctx.
*/
function drawYLine(ctx, y) {
if(visible(xmin, y)) {
drawLine(ctx, 0, y2px(y), canvasSize.width, y2px(y))
}
}
/*!
\qmlmethod void LogGraphCanvas::drawVisibleText(var ctx, string text, double x, double y)
Writes multline \c text onto the canvas using 2D \c ctx.
\note The \c x and \c y properties here are relative to the canvas, not the plot.
*/
function drawVisibleText(ctx, text, x, y) {
if(x > 0 && x < canvasSize.width && y > 0 && y < canvasSize.height) {
text.toString().split("\n").forEach(function(txt, i){
ctx.fillText(txt, x, y+(canvas.textsize*i))
})
}
}
/*!
\qmlmethod void LogGraphCanvas::drawVisibleImage(var ctx, var image, double x, double y)
Draws an \c image onto the canvas using 2D \c ctx.
\note The \c x, \c y \c width and \c height properties here are relative to the canvas, not the plot.
*/
function drawVisibleImage(ctx, image, x, y, width, height) {
console.log("Drawing image", isImageLoaded(image), isImageError(image))
markDirty(Qt.rect(x, y, width, height));
ctx.drawImage(image, x, y, width, height)
/*if(true || (x > 0 && x < canvasSize.width && y > 0 && y < canvasSize.height)) {
}*/
}
/*!
\qmlmethod var LogGraphCanvas::measureText(var ctx, string text)
Measures the wicth and height of a multiline \c text that would be drawn onto the canvas using 2D \c ctx.
Return format: dictionary {"width": width, "height": height}
*/
function measureText(ctx, text) {
var theight = 0
var twidth = 0
text.split("\n").forEach(function(txt, i){
theight += canvas.textsize
if(ctx.measureText(txt).width > twidth) twidth = ctx.measureText(txt).width
})
return {'width': twidth, 'height': theight}
}
/*!
\qmlmethod double LogGraphCanvas::x2px(double x)
Converts an \c x coordinate to it's relative position on the canvas.
It supports both logarithmic and non logarithmic scale depending on the currently selected mode.
*/
function x2px(x) {
if(logscalex) {
var logxmin = Math.log(xmin)
return (Math.log(x)-logxmin)*xzoom
} else return (x - xmin)*xzoom
}
/*!
\qmlmethod double LogGraphCanvas::y2px(double y)
Converts an \c y coordinate to it's relative position on the canvas.
The y axis not supporting logarithmic scale, it only support linear convertion.
*/
function y2px(y) {
return (ymax-y)*yzoom
}
/*!
\qmlmethod double LogGraphCanvas::px2x(double px)
Converts an x \c px position on the canvas to it's corresponding coordinate on the plot.
It supports both logarithmic and non logarithmic scale depending on the currently selected mode.
*/
function px2x(px) {
if(logscalex) {
return Math.exp(px/xzoom+Math.log(xmin))
} else return (px/xzoom+xmin)
}
/*!
\qmlmethod double LogGraphCanvas::px2x(double px)
Converts an x \c px position on the canvas to it's corresponding coordinate on the plot.
It supports both logarithmic and non logarithmic scale depending on the currently selected mode.
*/
function px2y(px) {
return -(px/yzoom-ymax)
}
/*!
\qmlmethod bool LogGraphCanvas::visible(double x, double y)
Checks whether a plot point (\c x, \c y) is visible or not on the canvas.
*/
function visible(x, y) {
return (x2px(x) >= 0 && x2px(x) <= canvasSize.width) && (y2px(y) >= 0 && y2px(y) <= canvasSize.height)
}
/*!
\qmlmethod bool LogGraphCanvas::drawLine(var ctx, double x1, double y1, double x2, double y2)
Draws a line from plot point (\c x1, \c y1) to plot point (\c x2, \¢ y2) using 2D \c ctx.
*/
function drawLine(ctx, x1, y1, x2, y2) {
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
/*!
\qmlmethod bool LogGraphCanvas::drawDashedLine2(var ctx, double x1, double y1, double x2, double y2)
Draws a dashed line from plot point (\c x1, \c y1) to plot point (\c x2, \¢ y2) using 2D \c ctx.
*/
function drawDashedLine2(ctx, x1, y1, x2, y2, dashPxSize = 5) {
ctx.setLineDash([dashPxSize, dashPxSize]);
drawLine(ctx, x1, y1, x2, y2)
ctx.setLineDash([]);
}
/*!
\qmlmethod bool LogGraphCanvas::drawDashedLine(var ctx, double x1, double y1, double x2, double y2)
Draws a dashed line from plot point (\c x1, \c y1) to plot point (\c x2, \¢ y2) using 2D \c ctx.
(Legacy slower method)
*/
function drawDashedLine(ctx, x1, y1, x2, y2, dashPxSize = 10) {
var distance = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
var progPerc = dashPxSize/distance
ctx.beginPath();
ctx.moveTo(x1, y1);
for(var i = 0; i < 1; i += progPerc) {
ctx.lineTo(x1-(x1-x2)*i, y1-(y1-y2)*i)
ctx.moveTo(x1-(x1-x2)*(i+progPerc/2), y1-(y1-y2)*(i+progPerc/2))
}
ctx.stroke();
}
/*!
\qmlmethod var LogGraphCanvas::renderLatexImage(string ltxText, color)
Renders latex markup \c ltxText to an image and loads it. Returns a dictionary with three values: source, width and height.
*/
function renderLatexImage(ltxText, color, callback) {
let [ltxSrc, ltxWidth, ltxHeight] = Latex.render(ltxText, textsize, color).split(",")
let imgData = {
"source": ltxSrc,
"width": parseFloat(ltxWidth),
"height": parseFloat(ltxHeight)
};
if(!isImageLoaded(ltxSrc) && !isImageLoading(ltxSrc)){
// Wait until the image is loaded to callback.
loadImage(ltxSrc)
imageLoaders[ltxSrc] = [callback, imgData]
} else {
// Callback directly
callback(canvas, ctx, imgData)
}
}
}

View file

@ -1,309 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Dialogs 1.3 as D
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import "../js/objects.js" as Objects
import "../js/objs/common.js" as ObjectsCommons
import "../js/historylib.js" as HistoryLib
import "../js/utils.js" as Utils
import "../js/mathlib.js" as MathLib
/*!
\qmltype EditorDialog
\inqmlmodule eu.ad5001.LogarithmPlotter.ObjectLists
\brief Dialog used to edit properties of objects.
This class contains the dialog that allows to edit all properties of objects.
\todo In the future, this class should be optimized so that each property doesn't instanciate one instance of each setting type.
\sa LogarithmPlotter, ObjectLists
*/
D.Dialog {
id: objEditor
/*!
\qmlproperty string EditorDialog::objType
Type of object being edited by the dialog.
*/
property string objType: 'Point'
/*!
\qmlproperty int EditorDialog::objIndex
Index of the objects amongst the ones of it's type.
*/
property int objIndex: 0
/*!
\qmlproperty var EditorDialog::obj
Instance of the object being edited.
*/
property var obj: Objects.currentObjects[objType][objIndex]
title: "LogarithmPlotter"
width: 350
height: 400
Label {
id: dlgTitle
anchors.left: parent.left
anchors.top: parent.top
verticalAlignment: TextInput.AlignVCenter
text: qsTr("Edit properties of %1 %2").arg(Objects.types[objEditor.objType].displayType()).arg(objEditor.obj.name)
font.pixelSize: 20
color: sysPalette.windowText
}
Column {
id: dlgProperties
anchors.top: dlgTitle.bottom
width: objEditor.width - 20
spacing: 10
Setting.TextSetting {
id: nameProperty
height: 30
label: qsTr("Name")
icon: "common/label.svg"
min: 1
width: dlgProperties.width
value: objEditor.obj.name
onChanged: function(newValue) {
var newName = Utils.parseName(newValue)
if(newName != '' && objEditor.obj.name != newName) {
if(Objects.getObjectByName(newName) != null) {
newName = ObjectsCommons.getNewName(newName)
}
history.addToHistory(new HistoryLib.NameChanged(
objEditor.obj.name, objEditor.objType, newName
))
Objects.currentObjects[objEditor.objType][objEditor.objIndex].name = newName
objEditor.obj = Objects.currentObjects[objEditor.objType][objEditor.objIndex]
objectListList.update()
}
}
}
Setting.ComboBoxSetting {
id: labelContentProperty
height: 30
width: dlgProperties.width
label: qsTr("Label content")
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) {
objEditor.obj.labelContent = idModel[newIndex]
objectListList.update()
}
}
}
// Dynamic properties
Repeater {
id: dlgCustomProperties
Item {
height: customPropComment.height + customPropText.height + customPropCheckBox.height + customPropCombo.height + customPropListDict.height
width: dlgProperties.width
property string label: qsTranslate('prop',modelData[0])
property string icon: Utils.camelCase2readable(modelData[0])
// Item for comments
Label {
id: customPropComment
width: parent.width
height: visible ? implicitHeight : 0
visible: modelData[0].startsWith('comment')
// Translated text with object name.
property string trText: visible ? qsTranslate('comment', modelData[1]).toString() : ''
text: (visible && trText.includes("%1") ? trText.arg(objEditor.obj.name) : trText).toString()
//color: sysPalette.windowText
wrapMode: Text.WordWrap
}
// Setting for text & number settings as well as domains & expressions
Setting.TextSetting {
id: customPropText
height: visible ? 30 : 0
width: parent.width
label: parent.label
icon: `settings/custom/${parent.icon}.svg`
isDouble: modelData[1] == 'number'
visible: paramTypeIn(modelData[1], ['Expression', 'Domain', 'string', 'number'])
defValue: visible ? {
'Expression': () => Utils.simplifyExpression(objEditor.obj[modelData[0]].toEditableString()),
'Domain': () => objEditor.obj[modelData[0]].toString(),
'string': () => objEditor.obj[modelData[0]],
'number': () => objEditor.obj[modelData[0]]
}[modelData[1]]() : ""
onChanged: function(newValue) {
var newValue = {
'Expression': () => new MathLib.Expression(newValue),
'Domain': () => MathLib.parseDomain(newValue),
'string': () => newValue,
'number': () => parseFloat(newValue)
}[modelData[1]]()
// Ensuring old and new values are different to prevent useless adding to history.
if(objEditor.obj[modelData[0]] != newValue) {
history.addToHistory(new HistoryLib.EditedProperty(
objEditor.obj.name, objEditor.objType, modelData[0],
objEditor.obj[modelData[0]], newValue
))
objEditor.obj[modelData[0]] = newValue
Objects.currentObjects[objEditor.objType][objEditor.objIndex].update()
objectListList.update()
}
}
}
// Setting for boolean
CheckBox {
id: customPropCheckBox
visible: modelData[1] == 'boolean'
height: visible ? 20 : 0
width: parent.width
text: parent.label
//icon: visible ? `settings/custom/${parent.icon}.svg` : ''
checked: visible ? objEditor.obj[modelData[0]] : false
onClicked: {
history.addToHistory(new HistoryLib.EditedProperty(
objEditor.obj.name, objEditor.objType, modelData[0],
objEditor.obj[modelData[0]], this.checked
))
objEditor.obj[modelData[0]] = this.checked
Objects.currentObjects[objEditor.objType][objEditor.objIndex].update()
objectListList.update()
}
}
// Setting when selecting data from an enum, or an object of a certain type.
Setting.ComboBoxSetting {
id: customPropCombo
width: dlgProperties.width
height: visible ? 30 : 0
label: parent.label
icon: visible ? `settings/custom/${parent.icon}.svg` : ''
// True to select an object of type, false for enums.
property bool selectObjMode: paramTypeIn(modelData[1], ['ObjectType'])
property bool isRealObject: !selectObjMode || (modelData[1].objType != "ExecutableObject" && modelData[1].objType != "DrawableObject")
// Base, untranslated version of the model.
property var baseModel: visible ?
(selectObjMode ?
Objects.getObjectsName(modelData[1].objType).concat(
isRealObject ? [qsTr("+ Create new %1").arg(Objects.types[modelData[1].objType].displayType())] :
[]) :
modelData[1].values)
: []
// Translated verison of the model.
model: selectObjMode ? baseModel : modelData[1].translatedValues
visible: paramTypeIn(modelData[1], ['ObjectType', 'Enum'])
currentIndex: baseModel.indexOf(selectObjMode ? objEditor.obj[modelData[0]].name : objEditor.obj[modelData[0]])
onActivated: function(newIndex) {
if(selectObjMode) {
// This is only done when what we're selecting are Objects.
// Setting object property.
var selectedObj = Objects.getObjectByName(baseModel[newIndex], modelData[1].objType)
if(newIndex != 0) {
// Make sure we don't set the object to null.
if(selectedObj == null) {
// Creating new object.
selectedObj = Objects.createNewRegisteredObject(modelData[1].objType)
history.addToHistory(new HistoryLib.CreateNewObject(selectedObj.name, modelData[1].objType, selectedObj.export()))
baseModel = Objects.getObjectsName(modelData[1].objType).concat(
isRealObject ? [qsTr("+ Create new %1").arg(Objects.types[modelData[1].objType].displayType())] :
[])
currentIndex = baseModel.indexOf(selectedObj.name)
}
selectedObj.requiredBy.push(Objects.currentObjects[objEditor.objType][objEditor.objIndex])
//Objects.currentObjects[objEditor.objType][objEditor.objIndex].requiredBy = objEditor.obj[modelData[0]].filter((obj) => objEditor.obj.name != obj.name)
}
objEditor.obj.requiredBy = objEditor.obj.requiredBy.filter((obj) => objEditor.obj.name != obj.name)
history.addToHistory(new HistoryLib.EditedProperty(
objEditor.obj.name, objEditor.objType, modelData[0],
objEditor.obj[modelData[0]], selectedObj
))
objEditor.obj[modelData[0]] = selectedObj
} else if(baseModel[newIndex] != objEditor.obj[modelData[0]]) {
// Ensuring new property is different to not add useless history entries.
history.addToHistory(new HistoryLib.EditedProperty(
objEditor.obj.name, objEditor.objType, modelData[0],
objEditor.obj[modelData[0]], baseModel[newIndex]
))
objEditor.obj[modelData[0]] = baseModel[newIndex]
}
// Refreshing
Objects.currentObjects[objEditor.objType][objEditor.objIndex].update()
objectListList.update()
}
}
// Setting to edit lists or dictionaries (e.g sequences & repartition function values)
Setting.ListSetting {
id: customPropListDict
width: parent.width
height: visible ? implicitHeight : 0
visible: paramTypeIn(modelData[1], ['List', 'Dict'])
label: parent.label
//icon: `settings/custom/${parent.icon}.svg`
dictionaryMode: paramTypeIn(modelData[1], ['Dict'])
keyType: dictionaryMode ? modelData[1].keyType : 'string'
valueType: visible ? modelData[1].valueType : 'string'
preKeyLabel: visible ? (dictionaryMode ? modelData[1].preKeyLabel : modelData[1].label).replace(/\{name\}/g, objEditor.obj.name) : ''
postKeyLabel: visible ? (dictionaryMode ? modelData[1].postKeyLabel : '').replace(/\{name\}/g, objEditor.obj.name) : ''
keyRegexp: dictionaryMode ? modelData[1].keyFormat : /^.+$/
valueRegexp: visible ? modelData[1].format : /^.+$/
forbidAdding: visible ? modelData[1].forbidAdding : false
onChanged: {
var exported = exportModel()
history.addToHistory(new HistoryLib.EditedProperty(
objEditor.obj.name, objEditor.objType, modelData[0],
objEditor.obj[modelData[0]], exported
))
//Objects.currentObjects[objEditor.objType][objEditor.objIndex][modelData[0]] = exported
objEditor.obj[modelData[0]] = exported
//Objects.currentObjects[objEditor.objType][objEditor.objIndex].update()
objEditor.obj.update()
objectListList.update()
}
Component.onCompleted: {
if(visible) importModel(objEditor.obj[modelData[0]])
}
}
}
}
}
/*!
\qmlmethod void EditorDialog::show()
Shows the editor after the object to be edited is set.
*/
function show() {
dlgCustomProperties.model = [] // Reset
let objProps = Objects.types[objEditor.objType].properties()
dlgCustomProperties.model = Object.keys(objProps).map(prop => [prop, objProps[prop]]) // Converted to 2-dimentional array.
objEditor.open()
}
}

View file

@ -1,272 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.12
import QtQuick.Dialogs 1.3 as D
import QtQuick.Controls 2.12
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import "../js/objects.js" as Objects
import "../js/historylib.js" as HistoryLib
/*!
\qmltype ObjectLists
\inqmlmodule eu.ad5001.LogarithmPlotter
\brief Tab of the drawer that allows the user to manage the objects.
This item allows the user to syntheticly see all objects, while giving the user the ability
to show, hide, delete, change the location and color, as well as opening the editor dialog
for each object.
\sa LogarithmPlotter, ObjectCreationGrid, ObjectLists
*/
ScrollView {
id: objectListList
signal changed()
property var listViews: {'':''} // Needs to be initialized or will be undefined -_-
ScrollBar.horizontal.visible: false
ScrollBar.vertical.visible: true
ListView {
id: objectsListView
model: Object.keys(Objects.types)
width: implicitWidth //objectListList.width - (implicitHeight > objectListList.parent.height ? 20 : 0)
implicitHeight: contentItem.childrenRect.height + footer.height + 10
delegate: ListView {
id: objTypeList
property string objType: objectsListView.model[index]
property var editingRows: []
model: Objects.currentObjects[objType]
width: objectsListView.width
implicitHeight: contentItem.childrenRect.height
visible: model != undefined && model.length > 0
interactive: false
Component.onCompleted: objectListList.listViews[objType] = objTypeList // Listing in order to be refreshed
header: Row {
width: typeHeaderText.width + typeVisibilityCheckBox.visible
height: visible ? 20 : 0
visible: objTypeList.visible
CheckBox {
id: typeVisibilityCheckBox
checked: Objects.currentObjects[objType] != undefined ? Objects.currentObjects[objType].every(obj => obj.visible) : true
onClicked: {
for(var obj of Objects.currentObjects[objType]) obj.visible = this.checked
for(var obj of objTypeList.editingRows) obj.objVisible = this.checked
objectListList.changed()
}
ToolTip.visible: hovered
ToolTip.text: checked ? qsTr("Hide all %1").arg(Objects.types[objType].displayTypeMultiple()) : qsTr("Show all %1").arg(Objects.types[objType].displayTypeMultiple())
}
Label {
id: typeHeaderText
verticalAlignment: TextInput.AlignVCenter
text: qsTranslate("control", "%1: ").arg(Objects.types[objType].displayTypeMultiple())
font.pixelSize: 20
}
}
delegate: Item {
id: controlRow
property var obj: Objects.currentObjects[objType][index]
property alias objVisible: objVisibilityCheckBox.checked
height: 40
width: objTypeList.width
Component.onCompleted: objTypeList.editingRows.push(controlRow)
CheckBox {
id: objVisibilityCheckBox
checked: Objects.currentObjects[objType][index].visible
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 5
onClicked: {
history.addToHistory(new HistoryLib.EditedVisibility(
Objects.currentObjects[objType][index].name, objType, this.checked
))
Objects.currentObjects[objType][index].visible = this.checked
objectListList.changed()
controlRow.obj = Objects.currentObjects[objType][index]
}
ToolTip.visible: hovered
ToolTip.text: checked ?
qsTr("Hide %1 %2").arg(Objects.types[objType].displayType()).arg(obj.name) :
qsTr("Show %1 %2").arg(Objects.types[objType].displayType()).arg(obj.name)
}
Label {
id: objDescription
anchors.left: objVisibilityCheckBox.right
anchors.right: deleteButton.left
height: parent.height
verticalAlignment: TextInput.AlignVCenter
text: obj.getReadableString()
font.pixelSize: 14
MouseArea {
anchors.fill: parent
onClicked: {
objEditor.obj = Objects.currentObjects[objType][index]
objEditor.objType = objType
objEditor.objIndex = index
//objEditor.editingRow = controlRow
objEditor.show()
}
}
}
Button {
id: pointerButton
width: parent.height - 10
height: width
anchors.right: deleteButton.left
anchors.rightMargin: 5
anchors.topMargin: 5
Setting.Icon {
id: icon
width: 18
height: 18
anchors.centerIn: parent
color: sysPalette.windowText
source: '../icons/common/position.svg'
}
property bool hasXProp: Objects.types[objType].properties().hasOwnProperty('x')
property bool hasYProp: Objects.types[objType].properties().hasOwnProperty('y')
visible: hasXProp || hasYProp
ToolTip.visible: hovered
ToolTip.text: qsTr("Set %1 %2 position").arg(Objects.types[objType].displayType()).arg(obj.name)
onClicked: {
positionPicker.objType = objType
positionPicker.objName = obj.name
positionPicker.pickX = hasXProp
positionPicker.pickY = hasYProp
positionPicker.propertyX = 'x'
positionPicker.propertyY = 'y'
positionPicker.visible = true
}
}
Button {
id: deleteButton
width: parent.height - 10
height: width
anchors.right: colorPickRect.left
anchors.rightMargin: 5
anchors.topMargin: 5
icon.name: 'delete'
icon.source: '../icons/common/delete.svg'
icon.color: sysPalette.buttonText
ToolTip.visible: hovered
ToolTip.text: qsTr("Delete %1 %2").arg(Objects.types[objType].displayType()).arg(obj.name)
onClicked: {
history.addToHistory(new HistoryLib.DeleteObject(
obj.name, objType, obj.export()
))
Objects.currentObjects[objType][index].delete()
Objects.currentObjects[objType].splice(index, 1)
objectListList.update()
}
}
Rectangle {
id: colorPickRect
anchors.right: parent.right
anchors.rightMargin: 5
anchors.topMargin: 5
color: obj.color
width: parent.height - 10
height: width
radius: Math.min(width, height)
border.width: 2
border.color: sysPalette.windowText
MouseArea {
anchors.fill: parent
onClicked: pickColor.open()
}
}
D.ColorDialog {
id: pickColor
color: obj.color
title: qsTr("Pick new color for %1 %2").arg(Objects.types[objType].displayType()).arg(obj.name)
onAccepted: {
history.addToHistory(new HistoryLib.ColorChanged(
obj.name, objType, obj.color, color.toString()
))
obj.color = color.toString()
controlRow.obj = Objects.currentObjects[objType][index]
objectListList.update()
}
}
}
}
// Create items
footer: ObjectCreationGrid {
id: createRow
width: objectsListView.width
objectEditor: objEditor
objectLists: objectListList
}
}
// Object editor
EditorDialog {
id: objEditor
}
/*!
\qmlmethod void ObjectLists::update()
Updates the view of the ObjectLists.
*/
function update() {
objectListList.changed()
for(var objType in objectListList.listViews) {
objectListList.listViews[objType].model = Objects.currentObjects[objType]
}
}
/*!
\qmlmethod void ObjectLists::paramTypeIn(var parameter, var types)
Checks if the type of the provided \c parameter is in \c types.
\note The type can be normal string types ('boolean', 'string', 'number'...) or object types (Enum, Dictionay, Object types...). If the latter, only the type of object type should be provided in \c types. E.g: if you want to check if the parameter is an enum, add "Enum" to types.
*/
function paramTypeIn(parameter, types = []) {
if(types.includes(parameter.toString())) return true
if(typeof parameter == 'object' && 'type' in parameter)
return types.includes(parameter.type)
return false
}
}

View file

@ -1,217 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.12
import QtQuick.Controls 2.12
import "js/objects.js" as Objects
import "js/mathlib.js" as MathLib
import "js/historylib.js" as HistoryLib
/*!
\qmltype PickLocationOverlay
\inqmlmodule eu.ad5001.LogarithmPlotter
\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
on a specific object. It allows the user to pick a new location on the canvas to place the object at.
This overlay allows to set the precision of the pick as well as whether the pick should be on the plot grid.
\sa LogarithmPlotter, LogGraphCanvas
*/
Item {
id: pickerRoot
visible: false
/*!
\qmlproperty var PickLocationOverlay::canvas
logGraphCanvas instance.
*/
property var canvas
/*!
\qmlproperty string PickLocationOverlay::objType
Type of object whose position the user is picking.
*/
property string objType: 'Point'
/*!
\qmlproperty string PickLocationOverlay::objType
Name of the object whose position the user is picking.
*/
property string objName: 'A'
/*!
\qmlproperty bool PickLocationOverlay::pickX
true if the user should be picking a position on the x axis.
*/
property bool pickX: true
/*!
\qmlproperty bool PickLocationOverlay::pickY
true if the user should be picking a position on the y axis.
*/
property bool pickY: true
/*!
\qmlproperty string PickLocationOverlay::propertyX
Name of the object's property whose x value is being changed.
*/
property string propertyX: 'x'
/*!
\qmlproperty string PickLocationOverlay::propertyY
Name of the object's property whose y value is being changed.
*/
property string propertyY: 'y'
/*!
\qmlproperty int PickLocationOverlay::precision
Precision of the picked value (post-dot precision).
*/
property alias precision: precisionSlider.value
Rectangle {
color: sysPalette.window
opacity: 0.35
anchors.fill: parent
}
MouseArea {
id: picker
anchors.fill: parent
hoverEnabled: parent.visible
cursorShape: Qt.CrossCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if(mouse.button == Qt.LeftButton) { // Validate
if(parent.pickX) {
let newValue = picked.mouseX.toString()
newValue = {
'Expression': () => new MathLib.Expression(newValue),
'number': () => parseFloat(newValue)
}[Objects.types[objType].properties()[propertyX]]()
let obj = Objects.getObjectByName(objName, objType)
history.addToHistory(new HistoryLib.EditedProperty(
objName, objType, propertyX, obj[propertyX], newValue
))
obj[propertyX] = newValue
obj.update()
objectLists.update()
}
if(parent.pickY) {
let newValue = picked.mouseY.toString()
newValue = {
'Expression': () => new MathLib.Expression(newValue),
'number': () => parseFloat(newValue)
}[Objects.types[objType].properties()[propertyY]]()
let obj = Objects.getObjectByName(objName, objType)
history.addToHistory(new HistoryLib.EditedProperty(
objName, objType, propertyY, obj[propertyY], newValue
))
obj[propertyY] = newValue
obj.update()
objectLists.update()
}
}
pickerRoot.visible = false;
}
}
Row {
height: precisionSlider.height
Text {
text: " "+ qsTr("Pointer precision:") + " "
color: 'black'
anchors.verticalCenter: parent.verticalCenter
}
Slider {
id: precisionSlider
from: 0
value: 2
to: 10
stepSize: 1
ToolTip {
parent: precisionSlider.handle
visible: precisionSlider.pressed
text: precisionSlider.value.toFixed(0)
}
}
CheckBox {
id: snapToGridCheckbox
text: qsTr("Snap to grid")
checked: false
}
}
Rectangle {
id: xCursor
width: 1
height: parent.height
color: 'black'
anchors.top: parent.top
anchors.left: parent.left
anchors.leftMargin: canvas.x2px(picked.mouseX)
visible: parent.pickX
}
Rectangle {
id: yCursor
width: parent.width
height: 1
color: 'black'
anchors.top: parent.top
anchors.left: parent.left
anchors.topMargin: canvas.y2px(picked.mouseY)
visible: parent.pickY
}
Text {
id: picked
x: picker.mouseX - width - 5
y: picker.mouseY - height - 5
property double axisX: canvas.xaxisstep1
property double mouseX: {
let xpos = canvas.px2x(picker.mouseX)
if(snapToGridCheckbox.checked) {
if(canvas.logscalex) {
// Calculate the logged power
let pow = Math.pow(10, Math.floor(Math.log10(xpos)))
return pow*Math.round(xpos/pow)
} else {
return canvas.xaxisstep1*Math.round(xpos/canvas.xaxisstep1)
}
} else {
return xpos.toFixed(parent.precision)
}
}
property double mouseY: {
let ypos = canvas.px2y(picker.mouseY)
if(snapToGridCheckbox.checked) {
return canvas.yaxisstep1*Math.round(ypos/canvas.yaxisstep1)
} else {
return ypos.toFixed(parent.precision)
}
}
color: 'black'
text: {
if(parent.pickX && parent.pickY)
return `(${mouseX}, ${mouseY})`
if(parent.pickX)
return `X = ${mouseX}`
if(parent.pickY)
return `Y = ${mouseY}`
}
}
}

View file

@ -1,124 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.12
import QtQuick.Dialogs 1.3 as D
import QtQuick.Controls 2.12
/*!
\qmltype About
\inqmlmodule eu.ad5001.LogarithmPlotter.Popup
\brief About popup of LogarithmPlotter.
\sa LogarithmPlotter
*/
D.Dialog {
id: about
title: qsTr("About LogarithmPlotter")
width: 400
height: 600
Image {
id: logo
source: "../icons/logarithmplotter.svg"
sourceSize.width: 64
sourceSize.height: 64
width: 64
height: 64
anchors.horizontalCenter: parent.horizontalCenter
anchors.rightMargin: width/2
anchors.top: parent.top
anchors.topMargin: 10
}
Label {
id: appName
anchors.top: logo.bottom
anchors.left: parent.left
anchors.topMargin: 10
horizontalAlignment: Text.AlignHCenter
width: parent.width
wrapMode: Text.WordWrap
font.pixelSize: 25
text: qsTr("LogarithmPlotter v%1").arg(Helper.getVersion())
}
Label {
id: description
anchors.top: appName.bottom
anchors.left: parent.left
anchors.topMargin: 10
horizontalAlignment: Text.AlignHCenter
width: parent.width
wrapMode: Text.WordWrap
font.pixelSize: 18
text: qsTr("2D plotter software to make BODE plots, sequences and repartition functions.")
}
Label {
id: debugInfos
anchors.top: description.bottom
anchors.left: parent.left
anchors.topMargin: 10
horizontalAlignment: Text.AlignHCenter
width: parent.width
wrapMode: Text.WordWrap
font.pixelSize: 14
text: Helper.getDebugInfos()
}
Label {
id: copyrightInfos
anchors.top: debugInfos.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 10
width: Math.min(410, parent.width)
wrapMode: Text.WordWrap
textFormat: Text.RichText
font.pixelSize: 13
text: "Copyright © 2022 Ad5001 &lt;mail@ad5001.eu&gt;<br>
<br>
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.<br>
<br>
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.<br>
<br>
You should have received a copy of the GNU General Public License along with this program. If not, see <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>."
onLinkActivated: Qt.openUrlExternally(link)
}
Row {
anchors.top: copyrightInfos.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 10
spacing: 5
Button {
id: openIssueButton
text: qsTr('Report a bug')
icon.name: 'tools-report-bug'
onClicked: Qt.openUrlExternally('https://git.ad5001.eu/Ad5001/LogarithmPlotter')
}
Button {
id: officialWebsiteButton
text: qsTr('Official website')
icon.name: 'web-browser'
onClicked: Qt.openUrlExternally('https://apps.ad5001.eu/logarithmplotter/')
}
}
}

View file

@ -1,153 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.12
import QtQuick.Controls 2.12
/*!
\qmltype GreetScreen
\inqmlmodule eu.ad5001.LogarithmPlotter.Popup
\brief Overlay displayed when LogarithmPlotter is launched for the first time or when it was just updated.
It contains several settings as well as an easy access to the changelog
\sa LogarithmPlotter, Settings, AppMenuBar, Changelog
*/
Popup {
id: greetingPopup
x: (parent.width-width)/2
y: Math.max(20, (parent.height-height)/2)
width: Math.max(welcome.width+70, checkForUpdatesSetting.width, resetRedoStackSetting.width)+20
height: Math.min(parent.height-40, 500)
modal: true
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
Item {
id: welcome
height: logo.height
width: logo.width + 10 + welcomeText.width
anchors.top: parent.top
anchors.topMargin: (parent.width-width)/2
anchors.horizontalCenter: parent.horizontalCenter
Image {
id: logo
source: "../icons/logarithmplotter.svg"
sourceSize.width: 48
sourceSize.height: 48
width: 48
height: 48
}
Label {
id: welcomeText
anchors.verticalCenter: parent.verticalCenter
anchors.left: logo.right
anchors.leftMargin: 10
//width: parent.width
wrapMode: Text.WordWrap
font.pixelSize: 32
text: qsTr("Welcome to LogarithmPlotter")
}
}
Label {
id: versionText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: welcome.bottom
anchors.topMargin: 10
//width: parent.width
wrapMode: Text.WordWrap
width: implicitWidth
font.pixelSize: 18
font.italic: true
text: qsTr("Version %1").arg(Helper.getVersion())
}
Label {
id: helpText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: versionText.bottom
anchors.topMargin: 40
//width: parent.width
wrapMode: Text.WordWrap
font.pixelSize: 14
width: parent.width - 50
text: qsTr("Take a few seconds to configure LogarithmPlotter.\nThese settings can be changed at any time from the \"Settings\" menu.")
}
CheckBox {
id: checkForUpdatesSetting
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: helpText.bottom
anchors.topMargin: 10
checked: Helper.getSettingBool("check_for_updates")
text: qsTr('Check for updates on startup (requires online connectivity)')
onClicked: {
Helper.setSettingBool("check_for_updates", checked)
checkForUpdatesMenuSetting.checked = checked
}
}
CheckBox {
id: resetRedoStackSetting
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: checkForUpdatesSetting.bottom
checked: Helper.getSettingBool("reset_redo_stack")
text: qsTr('Reset redo stack when a new action is added to history')
onClicked: {
Helper.setSettingBool("reset_redo_stack", checked)
resetRedoStackMenuSetting.checked = checked
}
}
Row {
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
spacing: 10
anchors.horizontalCenter: parent.horizontalCenter
Button {
id: userManualBtn
text: qsTr("User manual")
font.pixelSize: 18
onClicked: Qt.openUrlExternally("https://git.ad5001.eu/Ad5001/LogarithmPlotter/wiki/_Sidebar")
}
Button {
id: changelogBtn
text: qsTr("Changelog")
font.pixelSize: 18
onClicked: changelog.open()
}
Button {
id: doneBtn
text: qsTr("Done")
font.pixelSize: 18
onClicked: greetingPopup.close()
}
}
Component.onCompleted: if(Helper.getSetting("last_install_greet") != Helper.getVersion()) {
greetingPopup.open()
}
onClosed: Helper.setSetting("last_install_greet", Helper.getVersion())
}

View file

@ -1,110 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
sodipodi:docname="Function.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2021-09-07)">
<defs
id="defs833" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="15.268708"
inkscape:cy="12.238724"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="true"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid1403" />
</sodipodi:namedview>
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
<dc:date>2021</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Ad5001</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>(C) Ad5001 2021 - Licensed under CC4.0-BY-NC-SA</dc:title>
</cc:Agent>
</dc:rights>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-nc-nd/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-nc-nd/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:prohibits
rdf:resource="http://creativecommons.org/ns#CommercialUse" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<path
id="rect1415"
style="fill:#000000;fill-rule:evenodd"
d="M 2,9 C 2,5 6,5 6,5 H 7 V 7 H 6 C 6,7 4,7 4,9 v 2 h 2 v 2 H 4 v 5 H 2 V 13 H 0 v -2 h 2 z"
sodipodi:nodetypes="ccccccccccccccccc" />
<path
id="rect839"
style="fill:#000000;fill-rule:evenodd;stroke-width:2"
d="m 12,3 v 2 c 0,0 -2,0 -2,7 0,7 2,7 2,7 v 2 C 8,21 8,12 8,12 8,12 8,3 12,3 Z"
sodipodi:nodetypes="ccccccc" />
<path
id="rect857"
style="fill:#000000;fill-rule:evenodd;stroke-width:2"
d="m 12,10 h 2 l 6,8 h -2 z"
sodipodi:nodetypes="ccccc" />
<path
id="rect857-7"
style="fill:#000000;fill-rule:evenodd;stroke-width:2"
d="m 12,18 h 2 l 6,-8 h -2 z"
sodipodi:nodetypes="ccccc" />
<path
id="rect839-3"
style="fill:#000000;fill-rule:evenodd;stroke-width:2"
d="m 20,3 v 2 c 0,0 2,0 2,7 0,7 -2,7 -2,7 v 2 c 4,0 4,-9 4,-9 0,0 0,-9 -4,-9 z"
sodipodi:nodetypes="ccccccc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
sodipodi:docname="Gain Bode.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2021-09-07)">
<defs
id="defs1469" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="15.839192"
inkscape:cx="15.763196"
inkscape:cy="7.8365971"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="true"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid2039" />
<inkscape:grid
type="xygrid"
id="grid2058" />
</sodipodi:namedview>
<metadata
id="metadata1472">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:14.257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0"
id="rect835"
width="14"
height="2"
x="0"
y="17" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:17.3333px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="-0.12666447"
y="12.134649"
id="text839"><tspan
sodipodi:role="line"
id="tspan837"
x="-0.12666447"
y="12.134649"
style="font-size:17.3333px">ω</tspan></text>
<circle
style="fill:#000000;fill-rule:evenodd;stroke-width:2"
id="path837"
cx="13"
cy="18"
r="4" />
<path
id="rect837"
style="fill:#000000;fill-rule:evenodd;stroke-width:2.10035"
transform="rotate(30)"
d="m 20.686533,-6.169873 2.232051,-0.1339746 -0.06218,13.8923049 -2.23205,0.1339746 z"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -1,88 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
sodipodi:docname="Phase Bode.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2021-09-07)">
<defs
id="defs10" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.4"
inkscape:cx="15.347905"
inkscape:cy="8.3727678"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="true"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid19" />
</sodipodi:namedview>
<metadata
id="metadata13">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#000000;stroke-width:1.1547"
id="rect26"
width="8"
height="2"
x="5"
y="18" />
<path
id="rect26-3"
style="fill:#000000;stroke-width:1.22474"
d="m 15,2 v 14 h 2 V 4 h 7 V 2 Z"
sodipodi:nodetypes="ccccccc" />
<circle
style="fill:#000000;stroke-width:2.09999"
id="path45"
cx="16"
cy="19"
r="4" />
<text
xml:space="preserve"
style="font-size:18px;line-height:1.25;font-family:sans-serif;text-align:center;letter-spacing:0px;text-anchor:middle;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
x="6.4359932"
y="11.702"
id="text49"><tspan
sodipodi:role="line"
id="tspan47"
x="6.4359932"
y="11.702"
style="font-size:18px;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none">φ</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path style="opacity:1;vector-effect:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0" d="M9.98 18.12a3.5 3.5 0 0 1-3.064 3.855 3.5 3.5 0 0 1-3.887-3.022 3.5 3.5 0 0 1 2.982-3.919 3.5 3.5 0 0 1 3.95 2.94"/><text xml:space="preserve" style="font-style:normal;font-weight:400;font-size:17.3373px;line-height:1.25;font-family:sans-serif;letter-spacing:0;word-spacing:0;fill-opacity:1;stroke:none;stroke-width:1.00023" x="12.067" y="13.923" transform="scale(.99447 1.00556)"><tspan x="12.067" y="13.923" style="font-size:17.3373px;stroke-width:1.00023">A</tspan></text></svg>

Before

Width:  |  Height:  |  Size: 772 B

View file

@ -1,103 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
sodipodi:docname="Sequence.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2021-09-07)">
<defs
id="defs10" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.4"
inkscape:cx="-1.4929284"
inkscape:cy="9.7261905"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid19" />
</sodipodi:namedview>
<metadata
id="metadata13">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<text
xml:space="preserve"
style="font-size:17.3333px;line-height:1.25;font-family:sans-serif;text-align:center;letter-spacing:0px;text-anchor:middle"
x="7.483983"
y="16.134649"
id="text908"><tspan
sodipodi:role="line"
id="tspan906"
x="7.483983"
y="16.134649"
style="font-size:17.3333px">u</tspan></text>
<text
xml:space="preserve"
style="font-size:17px;line-height:1.25;font-family:sans-serif;text-align:center;letter-spacing:0px;text-anchor:middle;stroke-width:1.00003"
x="16.365566"
y="18.663307"
id="text912"
transform="scale(1.0000324,0.9999676)"><tspan
sodipodi:role="line"
id="tspan910"
x="16.365566"
y="18.663307"
style="font-size:17px;stroke-width:1.00003">n</tspan></text>
<g
aria-label="("
id="text852"
style="font-style:normal;font-weight:normal;font-size:12px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.4396;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0022756,0,0,1.2616817,-0.26079098,-9.0560687)">
<path
d="M 2.712,9.86 C 1.536,11.528 0.48,12.956 0.48,15.8 c 0,2.844 1.056,4.272 2.232,5.94 L 3.408,21.26 C 2.328,19.664 1.632,18.368 1.632,15.8 c 0,-2.58 0.696,-3.864 1.776,-5.46 z"
style="font-size:12px;stroke:#000000;stroke-width:0.4396;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path854" />
</g>
<g
aria-label="("
id="text852-3"
style="font-style:normal;font-weight:normal;font-size:12px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.4396;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(-1.0030304,0,0,1.2658306,24.414952,-9.1000412)">
<path
d="M 2.712,9.86 C 1.536,11.528 0.48,12.956 0.48,15.8 c 0,2.844 1.056,4.272 2.232,5.94 L 3.408,21.26 C 2.328,19.664 1.632,18.368 1.632,15.8 c 0,-2.58 0.696,-3.864 1.776,-5.46 z"
style="font-size:12px;stroke:#000000;stroke-width:0.4396;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path854-6" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.9 KiB

View file

@ -1,96 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
sodipodi:docname="Somme gains Bode.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2021-09-07)">
<defs
id="defs1469" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="63.356768"
inkscape:cx="15.947723"
inkscape:cy="5.6917309"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="true"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid2039" />
<inkscape:grid
type="xygrid"
id="grid2058" />
</sodipodi:namedview>
<metadata
id="metadata1472">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<path
id="rect838"
style="fill:#000000;fill-rule:evenodd;stroke-width:2"
d="M 2,2 H 8 V 3 H 4 L 7,6 4,9 h 4 v 1 H 2 V 9 L 5,6 2,3 Z"
sodipodi:nodetypes="ccccccccccccc" />
<rect
style="opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:14.257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0"
id="rect835"
width="14"
height="2"
x="0"
y="17" />
<circle
style="fill:#000000;fill-rule:evenodd;stroke-width:2"
id="path837"
cx="13"
cy="18"
r="4" />
<path
id="rect837"
style="fill:#000000;fill-rule:evenodd;stroke-width:2.10035"
transform="rotate(30)"
d="m 20.686533,-6.169873 2.232051,-0.1339746 -0.06218,13.8923049 -2.23205,0.1339746 z"
sodipodi:nodetypes="ccccc" />
<g
aria-label="G"
id="text846"
style="font-style:normal;font-weight:normal;font-size:12px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none">
<path
d="m 13,2 c 0,0 -3,0 -3,3 0,3 0,5 3,5 2,0 3,0 3,-2 V 6 h -3 v 1 h 2 v 1 c 0,1 -1,1 -2,1 -1,0 -2,0 -2,-4 0,-1 1,-2 2,-2 2,0 2,1 2,1 h 1 c 0,0 0,-2 -3,-2 z"
style="font-size:12px"
id="path848"
sodipodi:nodetypes="sssccccccsssccs" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -1,93 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
sodipodi:docname="Somme gains Bode.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2021-09-07)">
<defs
id="defs1469" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.4"
inkscape:cx="22.985246"
inkscape:cy="9.8906279"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="true"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid2039" />
<inkscape:grid
type="xygrid"
id="grid2058" />
</sodipodi:namedview>
<metadata
id="metadata1472">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<path
id="path1414"
style="opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0"
d="m 19.979376,19.120606 a 3.5,3.5 0 0 1 -3.06333,3.854578 3.5,3.5 0 0 1 -3.886652,-3.022533 3.5,3.5 0 0 1 2.9814,-3.918293 3.5,3.5 0 0 1 3.9495,2.939936" />
<rect
style="opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:16.166;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0"
id="rect835"
width="18"
height="2"
x="0"
y="18.5" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:16px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="-0.5703125"
y="11.875"
id="text839"><tspan
sodipodi:role="line"
id="tspan837"
x="-0.5703125"
y="11.875"
style="font-size:16px">ΣG</tspan></text>
<rect
style="opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:19.0663;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0"
id="rect835-3"
width="25.038315"
height="2"
x="-10.17229"
y="23.748709"
ry="0"
transform="rotate(-60)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
sodipodi:docname="Somme phases Bode.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2021-09-07)">
<defs
id="defs10" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.4"
inkscape:cx="15.347905"
inkscape:cy="8.3727678"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="true">
<inkscape:grid
type="xygrid"
id="grid19" />
</sodipodi:namedview>
<metadata
id="metadata13">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#000000;stroke-width:1.41421"
id="rect26"
width="12"
height="2"
x="9"
y="18" />
<rect
style="fill:#000000;stroke-width:0.912867"
id="rect26-3"
width="5"
height="2"
x="19"
y="2" />
<rect
style="fill:#000000;stroke-width:1.5"
id="rect43"
width="2"
height="16"
x="19"
y="4" />
<circle
style="fill:#000000;stroke-width:2.09999"
id="path45"
cx="20"
cy="19"
r="3.5" />
<text
xml:space="preserve"
style="font-size:16px;line-height:1.25;font-family:sans-serif;text-align:center;letter-spacing:0px;text-anchor:middle"
x="8.7617188"
y="11.664062"
id="text49"><tspan
sodipodi:role="line"
id="tspan47"
x="8.7617188"
y="11.664062"
style="font-size:16px">Σφ</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
sodipodi:docname="Text.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2021-09-07)">
<defs
id="defs1469" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.4"
inkscape:cx="13.763421"
inkscape:cy="16.975675"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="true"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid2039" />
<inkscape:grid
type="xygrid"
id="grid2058" />
</sodipodi:namedview>
<metadata
id="metadata1472">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<g
aria-label="X"
transform="matrix(0.99446808,0,0,1.0055627,2,0.50000001)"
id="text14"
style="font-style:normal;font-weight:normal;font-size:17.3373px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.00023" />
<path
id="rect12"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.670999;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4,3 h 8 V 5 H 9 v 14 h 3 v 2 H 4 V 19 H 7 V 5 H 4 Z"
sodipodi:nodetypes="ccccccccccccc" />
<path
id="rect837"
style="fill:#000000;fill-rule:evenodd;stroke-width:2"
d="m 16,5 h 2 v 3 h 2 v 2 h -2 v 5 c 0,2 2,2 2,2 v 2 c 0,0 -4,0 -4,-4 V 10 H 14 V 8 h 2 z"
sodipodi:nodetypes="ccccccccccccccc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -1,85 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
sodipodi:docname="X Cursor.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2021-09-07)">
<defs
id="defs1469" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.4"
inkscape:cx="19.545462"
inkscape:cy="13.163586"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="true"
inkscape:window-width="1829"
inkscape:window-height="916"
inkscape:window-x="19"
inkscape:window-y="31"
inkscape:window-maximized="0">
<inkscape:grid
type="xygrid"
id="grid2039" />
<inkscape:grid
type="xygrid"
id="grid2058" />
</sodipodi:namedview>
<metadata
id="metadata1472">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<g
aria-label="X"
transform="matrix(0.99446808,0,0,1.0055627,-2.2765848e-8,0.50000001)"
id="text14"
style="font-style:normal;font-weight:normal;font-size:17.3373px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.00023" />
<rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.774803;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect12"
width="2"
height="24"
x="17"
y="0"
ry="2.14841e-13" />
<path
id="rect835"
style="fill:#000000;fill-rule:evenodd;stroke-width:2"
d="m 5,2 h 2 l 8,14 h -2 z"
sodipodi:nodetypes="ccccc" />
<path
id="rect835-6"
style="fill:#000000;fill-rule:evenodd;stroke-width:2"
d="M 15,2 H 13 L 5,16 h 2 z"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -1 +0,0 @@
../../common/position.svg

View file

@ -1 +0,0 @@
../../common/position.svg

View file

@ -1 +0,0 @@
../../common/position.svg

File diff suppressed because it is too large Load diff

View file

@ -1,58 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
var themeTextColor;
class Action {
// Type of the action done.
type(){return 'Unknown'}
// Icon associated with the item
// TargetName is the name of the object that's targeted by the event.
constructor(targetName = "", targetType = "Point") {
this.targetName = targetName
this.targetType = targetType
}
undo() {}
redo() {}
export() {
return [this.targetName, this.targetType]
}
// String used in the toolkit
getReadableString() {
return 'Unknown action'
}
// Returns an HTML tag containing the icon of a type
getIconRichText(type) {
return `<img source="../icons/objects/${type}.svg" style="color: ${themeTextColor};" width=18 height=18></img>`
}
// String used in the preview
getHTMLString() {
return this.getReadableString()
}
}

View file

@ -1,121 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "../objects.js" as Objects
.import "../mathlib.js" as MathLib
.import "../objs/common.js" as Common
.import "common.js" as C
class EditedProperty extends C.Action {
// Action used everytime an object's property has been changed
type(){return 'EditedProperty'}
icon(){return 'modify'}
color(darkVer=false){
return darkVer ? 'darkslateblue' : 'cyan';
}
constructor(targetName = "", targetType = "Point", targetProperty = "visible", previousValue = false, newValue = true, valueIsExpressionNeedingImport = false) {
super(targetName, targetType)
this.targetProperty = targetProperty
this.targetPropertyReadable = qsTranslate("prop", this.targetProperty)
this.previousValue = previousValue
this.newValue = newValue
this.propertyType = Objects.types[targetType].properties()[targetProperty]
if(valueIsExpressionNeedingImport) {
if(this.propertyType == "Expression") {
this.previousValue = new MathLib.Expression(this.previousValue);
this.newValue = new MathLib.Expression(this.newValue);
} else if(this.propertyType == "Domain") {
this.previousValue = MathLib.parseDomain(this.previousValue);
this.newValue = MathLib.parseDomain(this.newValue);
} else {
// Objects
this.previousValue = Objects.getObjectByName(this.previousValue);
this.newValue = Objects.getObjectByName(this.newValue);
}
}
this.setReadableValues()
}
undo() {
Objects.getObjectByName(this.targetName, this.targetType)[this.targetProperty] = this.previousValue
}
redo() {
Objects.getObjectByName(this.targetName, this.targetType)[this.targetProperty] = this.newValue
}
export() {
if(this.previousValue instanceof MathLib.Expression) {
return [this.targetName, this.targetType, this.targetProperty, this.previousValue.toEditableString(), this.newValue.toEditableString(), true]
} else if(this.previousValue instanceof Common.DrawableObject) {
return [this.targetName, this.targetType, this.targetProperty, this.previousValue.name, this.newValue.name, true]
} else {
return [this.targetName, this.targetType, this.targetProperty, this.previousValue, this.newValue, false]
}
}
setReadableValues() {
this.prev = "";
this.next = "";
if(this.propertyType instanceof Object) {
switch(this.propertyType.type) {
case "Enum":
this.prev = this.propertyType.translatedValues[this.propertyType.values.indexOf(this.previousValue)]
this.next = this.propertyType.translatedValues[this.propertyType.values.indexOf(this.newValue)]
break;
case "ObjectType":
this.prev = this.previousValue == null ? "null" : this.previousValue.name
this.next = this.newValue == null ? "null" : this.newValue.name
break;
case "List":
this.prev = this.previousValue.join(",")
this.next = this.newValue.name.join(",")
break;
case "Dict":
this.prev = JSON.stringify(this.previousValue).replace("'", "\\'").replace('"', "'")
this.next = JSON.stringify(this.newValue).replace("'", "\\'").replace('"', "'")
break;
}
} else {
this.prev = this.previousValue == null ? "null" : this.previousValue.toString()
this.next = this.newValue == null ? "null" : this.newValue.toString()
}
}
getReadableString() {
return qsTr('%1 of %2 %3 changed from "%4" to "%5".')
.arg(this.targetPropertyReadable)
.arg(Objects.types[this.targetType].displayType())
.arg(this.targetName).arg(this.prev).arg(this.next)
}
getHTMLString() {
return qsTr('%1 of %2 changed from %3 to %4.')
.arg(this.targetPropertyReadable)
.arg('<b style="font-size: 15px;">&nbsp;' + this.targetName + '&nbsp;</b>')
.arg('<tt style="background: rgba(128,128,128,0.1);">&nbsp;'+this.prev+'&nbsp;</tt>')
.arg('<tt style="background: rgba(128,128,128,0.1);">&nbsp;'+this.next+'</tt>')
// .arg('<b style="font-size: 15px;">' + Objects.types[this.targetType].displayType())
}
}

View file

@ -1,50 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "../expr-eval.js" as ExprEval
.import "../utils.js" as Utils
.import "latex.js" as Latex
var evalVariables = { // Variables not provided by expr-eval.js, needs to be provided manualy
"pi": Math.PI,
"π": Math.PI,
"inf": Infinity,
"Infinity": Infinity,
"∞": Infinity,
"e": Math.E,
"E": Math.E
}
var currentVars = {}
const parser = new ExprEval.Parser()
parser.functions.integral = function(a, b, f, variable) {
// https://en.wikipedia.org/wiki/Simpson%27s_rule
f = parser.parse(f).toJSFunction(variable, currentVars)
return (b-a)/6*(f(a)+4*f((a+b)/2)+f(b))
}
const DERIVATION_PRECISION = 0.1
parser.functions.derivative = function(f, variable, x) {
f = parser.parse(f).toJSFunction(variable, currentVars)
return (f(x+DERIVATION_PRECISION/2)-f(x-DERIVATION_PRECISION/2))/DERIVATION_PRECISION
}

View file

@ -1,77 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "common.js" as C
.import "latex.js" as Latex
.import "../utils.js" as Utils
/**
* Represents any kind of x-based or non variable based expression.
*/
class Expression {
constructor(expr) {
this.expr = expr
this.calc = C.parser.parse(expr).simplify()
this.cached = this.isConstant()
this.cachedValue = this.cached ? this.calc.evaluate(C.evalVariables) : null
this.latexMarkup = Latex.expressionToLatex(this.calc.tokens)
}
isConstant() {
return !this.expr.includes("x") && !this.expr.includes("n")
}
execute(x = 1) {
if(this.cached) return this.cachedValue
C.currentVars = Object.assign({'x': x}, C.evalVariables)
return this.calc.evaluate(C.currentVars)
}
simplify(x) {
var expr = this.calc.substitute('x', x).simplify()
if(expr.evaluate(C.evalVariables) == 0) return '0'
var str = Utils.makeExpressionReadable(expr.toString());
if(str != undefined && str.match(/^\d*\.\d+$/)) {
if(str.split('.')[1].split('0').length > 7) {
// Likely rounding error
str = parseFloat(str.substring(0, str.length-1)).toString();
}
}
return str
}
duplicate() {
return new Expression(this.toEditableString())
}
toEditableString() {
return this.calc.toString()
}
toString(forceSign=false) {
var str = Utils.makeExpressionReadable(this.calc.toString())
if(str[0] != '-' && forceSign) str = '+' + str
return str
}
}
function executeExpression(expr){
return (new Expression(expr.toString())).execute()
}

View file

@ -1,246 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "../expr-eval.js" as ExprEval
/**
* Puts element within parenthesis.
*
* @param {string} elem - element to put within parenthesis.
* @returns {string}
*/
function par(elem) {
return '(' + elem + ')'
}
/**
* Checks if the element contains at least one of the elements of
* the string array contents , and returns the parenthesis version if so.
*
* @param {string} elem - element to put within parenthesis.
* @param {Array} contents - Array of elements to put within parenthesis.
* @returns {string}
*/
function parif(elem, contents) {
return contents.some(x => elem.toString().includes(x)) ? par(elem) : elem
}
/**
* Creates a latex expression for a function.
*
* @param {string} f - Function to convert
* @param {Array} args - Arguments of the function
* @returns {string}
*/
function functionToLatex(f, args) {
switch(f) {
case "derivative":
return '\\frac{d' + args[0].substr(1, args[0].length-2).replace(new RegExp(by, 'g'), 'x') + '}{dx}';
break;
case "integral":
return '\\int\\limits^{' + args[0] + '}_{' + args[1] + '}' + args[2].substr(1, args[2].length-2) + ' d' + args[3];
break;
case "sqrt":
return '\\sqrt\\left(' + args.join(', ') + '\\right)';
break;
case "abs":
return '\\left|' + args.join(', ') + '\\right|';
break;
case "floor":
return '\\left\\lfloor' + args.join(', ') + '\\right\\rfloor';
break;
case "ceil":
return '\\left\\lceil' + args.join(', ') + '\\right\\rceil';
break;
default:
return '\\mathrm{' + f + '}\\left(' + args.join(', ') + '\\right)';
break;
}
}
/**
* Creates a latex variable from a variable.
*
* @param {string} vari - variable to convert
* @returns {string}
*/
function variableToLatex(vari) {
unicodechars = ["α","β","γ","δ","ε","ζ","η",
"π","θ","κ","λ","μ","ξ","ρ",
"ς","σ","τ","φ","χ","ψ","ω",
"Γ","Δ","Θ","Λ","Ξ","Π","Σ",
"Φ","Ψ","Ω","ₐ","ₑ","ₒ","ₓ",
"ₕ","ₖ","ₗ","ₘ","ₙ","ₚ","ₛ",
"ₜ","¹","²","³","⁴","⁵","⁶",
"⁷","⁸","⁹","⁰","₁","₂","₃",
"₄","₅","₆","₇","₈","₉","₀"]
equivalchars = ["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}"]
for(int i = 0; i < unicodechars.length; i++) {
if(vari.includes(unicodechars[i]))
vari = vari.replaceAll(unicodechars[i], equivalchars[i])
}
return vari;
}
/**
* Converts expr-eval tokens to a latex string.
*
* @param {Array} tokens - expr-eval tokens list
* @returns {string}
*/
function expressionToLatex(tokens) {
var nstack = [];
var n1, n2, n3;
var f, args, argCount;
for (var i = 0; i < tokens.length; i++) {
var item = tokens[i];
var type = item.type;
switch(type) {
case ExprEval.INUMBER:
if (typeof item.value === 'number' && item.value < 0) {
nstack.push(par(item.value));
} else if (Array.isArray(item.value)) {
nstack.push('[' + item.value.map(ExprEval.escapeValue).join(', ') + ']');
} else {
nstack.push(ExprEval.escapeValue(item.value));
}
break;
case ExprEval.IOP2:
n2 = nstack.pop();
n1 = nstack.pop();
f = item.value;
switch(f) {
case '-':
case '+':
nstack.push(n1 + this.ope + n2);
break;
case '||':
case 'or':
case '&&':
case 'and':
case '==':
case '!=':
nstack.push(par(n1) + this.ope + par(n2));
break;
case '*':
nstack.push(parif(n1,['+','-']) + " \\times " + parif(n2,['+','-']));
break;
case '/':
nstack.push("\\frac{" + n1 + "}{" + n2 + "}");
break;
case '^':
nstack.push(parif(n1,['+','-','*','/','!']) + "^{" + n2 + "}");
break;
case '%':
nstack.push(parif(n1,['+','-','*','/','!','^']) + " \\mathrm{mod} " + parif(n2,['+','-','*','/','!','^']));
break;
case '[':
nstack.push(n1 + '[' + n2 + ']');
break;
default:
throw new EvalError("Unknown operator " + ope + ".");
}
break;
case ExprEval.IOP3: // Thirdiary operator
n3 = nstack.pop();
n2 = nstack.pop();
n1 = nstack.pop();
f = item.value;
if (f === '?') {
nstack.push('(' + n1 + ' ? ' + n2 + ' : ' + n3 + ')');
} else {
throw new EvalError('Unknown operator ' + ope + '.');
}
break;
case ExprEval.IVAR:
case ExprEval.IVARNAME:
nstack.push(variableToLatex(item.value));
break;
case ExprEval.IOP1: // Unary operator
n1 = nstack.pop();
f = item.value;
switch(f) {
case '-':
case '+':
nstack.push(par(f + n1));
break;
case '!':
nstack.push(parif(n1,['+','-','*','/','^']) + '!');
break;
default:
nstack.push(f + parif(n1,['+','-','*','/','^']));
break;
}
break;
case ExprEval.IFUNCALL:
argCount = item.value;
args = [];
while (argCount-- > 0) {
args.unshift(nstack.pop());
}
f = nstack.pop();
// Handling various functions
nstack.push(functionToLatex(f, args))
case ExprEval.IFUNDEF:
nstack.push(par(n1 + '(' + args.join(', ') + ') = ' + n2));
break;
case ExprEval.IMEMBER:
n1 = nstack.pop();
nstack.push(n1 + '.' + item.value);
break;
case ExprEval.IARRAY:
argCount = item.value;
args = [];
while (argCount-- > 0) {
args.unshift(nstack.pop());
}
nstack.push('[' + args.join(', ') + ']');
break;
case ExprEval.IEXPR:
nstack.push('(' + expressionToLatex(item.value) + ')');
break;
case ExprEval.IENDSTATEMENT:
break;
default:
throw new EvalError('invalid Expression');
break;
}
}
if (nstack.length > 1) {
if (toJS) {
nstack = [ nstack.join(',') ];
} else {
nstack = [ nstack.join(';') ];
}
}
console.log(nstack[0]);
return String(nstack[0]);
}

View file

@ -1,78 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "common.js" as C
.import "expression.js" as Expr
.import "../utils.js" as Utils
/**
* Represents mathematical object for sequences.
*/
class Sequence extends Expr.Expression {
constructor(name, baseValues = {}, valuePlus = 1, expr = "") {
// u[n+valuePlus] = expr
super(expr)
this.name = name
this.baseValues = baseValues
this.calcValues = Object.assign({}, baseValues)
for(var n in this.calcValues)
if(['string', 'number'].includes(typeof this.calcValues[n]))
this.calcValues[n] = parser.parse(this.calcValues[n].toString()).simplify().evaluate(C.evalVariables)
this.valuePlus = parseInt(valuePlus)
}
isConstant() {
return this.expr.indexOf("n") == -1
}
execute(n = 1) {
if(n in this.calcValues)
return this.calcValues[n]
this.cache(n)
return this.calcValues[n]
}
simplify(n = 1) {
if(n in this.calcValues)
return Utils.makeExpressionReadable(this.calcValues[n].toString())
this.cache(n)
return Utils.makeExpressionReadable(this.calcValues[n].toString())
}
cache(n = 1) {
var str = Utils.simplifyExpression(this.calc.substitute('n', n-this.valuePlus).toString())
var expr = parser.parse(str).simplify()
var l = {'n': n-this.valuePlus} // Just in case, add n (for custom functions)
l[this.name] = this.calcValues
currentVars = Object.assign(l, C.evalVariables)
this.calcValues[n] = expr.evaluate(currentVars)
}
toString(forceSign=false) {
var str = Utils.makeExpressionReadable(this.calc.toString())
if(str[0] != '-' && forceSign) str = '+' + str
var subtxt = this.valuePlus == 0 ? 'ₙ' : Utils.textsub('n+' + this.valuePlus)
var ret = `${this.name}${subtxt} = ${str}${this.baseValues.length == 0 ? '' : "\n"}`
ret += Object.keys(this.baseValues).map(
n => `${this.name}${Utils.textsub(n)} = ${this.baseValues[n]}`
).join('; ')
return ret
}
}

View file

@ -1,76 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "utils.js" as Utils
.import "mathlib.js" as MathLib
.import "parameters.js" as P
var types = {}
var currentObjects = {}
function getObjectByName(objName, objType = null) {
var objectTypes = Object.keys(currentObjects)
if(typeof objType == 'string' && objType != "") {
if(objType == "ExecutableObject") {
objectTypes = getExecutableTypes()
} else if(currentObjects[objType] != undefined) {
objectTypes = [objType]
}
}
if(Array.isArray(objType)) objectTypes = objType
var retObj = null
if(objName != "" && objName != null) {
objectTypes.forEach(function(objType){
if(currentObjects[objType] == undefined) return null
currentObjects[objType].forEach(function(obj){
if(obj.name == objName) retObj = obj
})
})
}
return retObj
}
function getObjectsName(objType) {
if(objType == "ExecutableObject") {
var types = getExecutableTypes()
var elementNames = ['']
types.forEach(function(elemType){
elementNames = elementNames.concat(currentObjects[elemType].map(obj => obj.name))
})
return elementNames
}
if(currentObjects[objType] == undefined) return []
return currentObjects[objType].map(obj => obj.name)
}
function getExecutableTypes() {
return Object.keys(currentObjects).filter(objType => types[objType].executable())
}
function createNewRegisteredObject(objType, args=[]) {
if(Object.keys(types).indexOf(objType) == -1) return null // Object type does not exist.
var newobj = new types[objType](...args)
if(Object.keys(currentObjects).indexOf(objType) == -1) {
currentObjects[objType] = []
}
currentObjects[objType].push(newobj)
return newobj
}

View file

@ -1,147 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "../utils.js" as Utils
.import "../objects.js" as Objects
// This file contains the default data to be imported from all other objects
function getNewName(allowedLetters) {
// Allows to get a new name, based on the allowed letters,
// as well as adding a sub number when needs be.
var newid = 0
var ret
do {
var letter = allowedLetters[newid % allowedLetters.length]
var num = Math.floor((newid - (newid % allowedLetters.length)) / allowedLetters.length)
ret = letter + (num > 0 ? Utils.textsub(num-1) : '')
newid += 1
} while(Objects.getObjectByName(ret) != null)
return ret
}
class DrawableObject {
// Class to extend for every type of object that
// can be drawn on the canvas.
// Base name of the object. Needs to be constant over time.
static type(){return 'Unknown'}
// (Potentially translated) name of the object to be shown to the user.
static displayType(){return 'Unknown'}
// Label used for the list on the ObjectsList sidebar.
static displayTypeMultiple(){return 'Unknowns'}
// Whether this object can be created by the user
// or are instantiated by other objects.
static createable() {return true}
// Properties are set with key as property name and
// value as it's type name (e.g 'Expression', 'string'...),
// an Enum for enumerations, an ObjectType for DrawableObjects
// with a specific type, a List instance for lists, a
// Dictionary instance for dictionaries...
// Used for property modifier in the sidebar.
static properties() {return {}}
// Whether the object can be executed (instance of ExecutableObject)
static executable() {return false}
constructor(name, visible = true, color = null, labelContent = 'name + value') {
if(color == null) color = Utils.getRandomColor()
this.type = 'Unknown'
this.name = name
this.visible = visible
this.color = color
this.labelContent = labelContent // "null", "name", "name + value"
this.requiredBy = []
}
export() {
// Should return what will be inputed as arguments when a file is loaded (serializable form)
return [this.name, this.visible, this.color.toString(), this.labelContent]
}
getReadableString() {
return `${this.name} = Unknown`
}
toLatexString() {
return this.getReadableString()
}
getLabel() {
switch(this.labelContent) {
case 'name':
return this.name
case 'name + value':
return this.toLatexString()
case 'null':
return ''
}
}
update() {
for(var req of this.requiredBy) {
req.update()
}
}
delete() {
for(var toRemove of this.requiredBy) {
toRemove.delete()
Objects.currentObjects[toRemove.type] = Objects.currentObjects[toRemove.type].filter(obj => obj.name != toRemove.name)
}
}
draw(canvas, ctx) {}
toString() {
return this.name;
}
}
class ExecutableObject extends DrawableObject {
// Class to be extended for every class upon which we
// calculate an y for a x with the execute function.
// If a value cannot be found during execute, it should
// return null. However, theses values should
// return false when passed to canExecute.
execute(x = 1) {return 0}
canExecute(x = 1) {return true}
// Simplify returns the simplified string of the expression.
simplify(x = 1) {return '0'}
// Whether the object can be executed (instance of ExecutableObject)
static executable() {return true}
}
function registerObject(obj) {
// Registers an object to be used in LogarithmPlotter.
// This function is called from autoload.js
if(obj.prototype instanceof DrawableObject) {
Objects.types[obj.type()] = obj
} else {
console.error("Could not register object " + (obj.type()) + ", as it isn't a DrawableObject.")
}
}

View file

@ -1,197 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "common.js" as Common
.import "../utils.js" as Utils
.import "../mathlib.js" as MathLib
.import "../parameters.js" as P
class Function extends Common.ExecutableObject {
static type(){return 'Function'}
static displayType(){return qsTr('Function')}
static displayTypeMultiple(){return qsTr('Functions')}
/*static properties() {return {
'expression': 'Expression',
'definitionDomain': 'Domain',
'destinationDomain': 'Domain',
'comment1': 'Ex: R+* (ℝ⁺*), N (), Z-* (ℤ⁻*), ]0;1[, {3;4;5}',
'labelPosition': P.Enum.Position,
'displayMode': new P.Enum('application', 'function'),
'labelX': 'number',
'comment2': 'The following parameters are used when the definition domain is a non-continuous set. (Ex: , , sets like {0;3}...)',
'drawPoints': 'boolean',
'drawDashedLines': 'boolean'
}}*/
static properties() {return {
[QT_TRANSLATE_NOOP('prop','expression')]: 'Expression',
[QT_TRANSLATE_NOOP('prop','definitionDomain')]: 'Domain',
[QT_TRANSLATE_NOOP('prop','destinationDomain')]: 'Domain',
'comment1': QT_TRANSLATE_NOOP(
'comment',
'Ex: R+* (ℝ⁺*), N (), Z-* (ℤ⁻*), ]0;1[, {3;4;5}'
),
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
[QT_TRANSLATE_NOOP('prop','displayMode')]: P.Enum.FunctionDisplayType,
[QT_TRANSLATE_NOOP('prop','labelX')]: 'number',
'comment2': QT_TRANSLATE_NOOP(
'comment',
'The following parameters are used when the definition domain is a non-continuous set. (Ex: , , sets like {0;3}...)'
),
[QT_TRANSLATE_NOOP('prop','drawPoints')]: 'boolean',
[QT_TRANSLATE_NOOP('prop','drawDashedLines')]: 'boolean'
}}
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
expression = 'x', definitionDomain = 'RPE', destinationDomain = 'R',
displayMode = 'application', labelPosition = 'above', labelX = 1,
drawPoints = true, drawDashedLines = true) {
if(name == null) name = Common.getNewName('fghjqlmnopqrstuvwabcde')
super(name, visible, color, labelContent)
this.type = 'Function'
if(typeof expression == 'number' || typeof expression == 'string') expression = new MathLib.Expression(expression.toString())
this.expression = expression
if(typeof definitionDomain == 'string') definitionDomain = MathLib.parseDomain(definitionDomain)
this.definitionDomain = definitionDomain
if(typeof destinationDomain == 'string') destinationDomain = MathLib.parseDomain(destinationDomain)
this.destinationDomain = destinationDomain
this.displayMode = displayMode
this.labelPosition = labelPosition
this.labelX = labelX
this.drawPoints = drawPoints
this.drawDashedLines = drawDashedLines
}
getReadableString() {
if(this.displayMode == 'application') {
return `${this.name}: ${this.definitionDomain}${this.destinationDomain}\n ${' '.repeat(this.name.length)}x ⟼ ${this.expression.toString()}`
} else {
return `${this.name}(x) = ${this.expression.toString()}\nD${Utils.textsub(this.name)} = ${this.definitionDomain}`
}
}
export() {
return [this.name, this.visible, this.color.toString(), this.labelContent,
this.expression.toEditableString(), this.definitionDomain.toString(), this.destinationDomain.toString(),
this.displayMode, this.labelPosition, this.labelX, this.drawPoints, this.drawDashedLines]
}
execute(x = 1) {
if(this.definitionDomain.includes(x))
return this.expression.execute(x)
return null
}
canExecute(x = 1) {
return this.definitionDomain.includes(x)
}
simplify(x = 1) {
if(this.definitionDomain.includes(x))
return this.expression.simplify(x)
return ''
}
draw(canvas, ctx) {
Function.drawFunction(canvas, ctx, this.expression, this.definitionDomain, this.destinationDomain, this.drawPoints, this.drawDashedLines)
// Label
var text = this.getLabel()
ctx.font = `${canvas.textsize}px sans-serif`
var textSize = canvas.measureText(ctx, text)
var posX = canvas.x2px(this.labelX)
var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) {
case 'above':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
break;
case 'below':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+textSize.height)
break;
case 'left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height/2)
break;
case 'right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height/2)
break;
case 'above-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
break;
case 'above-right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height)
break;
case 'below-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY+textSize.height)
break;
case 'below-right':
canvas.drawVisibleText(ctx, text, posX, posY+textSize.height)
break;
}
}
static drawFunction(canvas, ctx, expr, definitionDomain, destinationDomain, drawPoints = true, drawDash = true) {
// Reusable in other objects.
// Drawing small traits every 2px
var pxprecision = 0.2
var previousX = canvas.px2x(0)
var previousY;
if(definitionDomain instanceof MathLib.SpecialDomain && definitionDomain.moveSupported) {
// Point based functions.
previousX = definitionDomain.next(previousX)
if(previousX === null) previousX = definitionDomain.next(canvas.px2x(0))
previousY = expr.execute(previousX)
if(!drawPoints && !drawDash) return
while(previousX !== null && canvas.x2px(previousX) < canvas.canvasSize.width) {
// Reconverted for canvas to fix for logarithmic scales.
var currentX = definitionDomain.next(canvas.px2x(canvas.x2px(previousX)+pxprecision));
var currentY = expr.execute(currentX)
if(currentX === null) break;
if((definitionDomain.includes(currentX) || definitionDomain.includes(previousX)) &&
(destinationDomain.includes(currentY) || destinationDomain.includes(previousY))) {
if(drawDash)
canvas.drawDashedLine(ctx, canvas.x2px(previousX), canvas.y2px(previousY), canvas.x2px(currentX), canvas.y2px(currentY))
if(drawPoints) {
ctx.fillRect(canvas.x2px(previousX)-5, canvas.y2px(previousY)-1, 10, 2)
ctx.fillRect(canvas.x2px(previousX)-1, canvas.y2px(previousY)-5, 2, 10)
}
}
previousX = currentX
previousY = currentY
}
if(drawPoints) {
// Drawing the last cross
ctx.fillRect(canvas.x2px(previousX)-5, canvas.y2px(previousY)-1, 10, 2)
ctx.fillRect(canvas.x2px(previousX)-1, canvas.y2px(previousY)-5, 2, 10)
}
} else {
previousY = expr.execute(previousX)
for(var px = pxprecision; px < canvas.canvasSize.width; px += pxprecision) {
var currentX = canvas.px2x(px)
var currentY = expr.execute(currentX)
if((definitionDomain.includes(currentX) || definitionDomain.includes(previousX)) &&
(destinationDomain.includes(currentY) || destinationDomain.includes(previousY)) &&
Math.abs(previousY-currentY)<100) {
canvas.drawLine(ctx, canvas.x2px(previousX), canvas.y2px(previousY), canvas.x2px(currentX), canvas.y2px(currentY))
}
previousX = currentX
previousY = currentY
}
}
}
}

View file

@ -1,176 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "common.js" as Common
.import "function.js" as F
.import "../objects.js" as Objects
.import "../utils.js" as Utils
.import "../mathlib.js" as MathLib
.import "../historylib.js" as HistoryLib
.import "../parameters.js" as P
class GainBode extends Common.ExecutableObject {
static type(){return 'Gain Bode'}
static displayType(){return qsTr('Bode Magnitude')}
static displayTypeMultiple(){return qsTr('Bode Magnitudes')}
/*static properties() {return {
'om_0': new P.ObjectType('Point'),
'pass': new P.Enum('high', 'low'),
'gain': 'Expression',
'labelPosition': new P.Enum('above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
'labelX': 'number',
'omGraduation': 'boolean'
}}*/
static properties() {return {
[QT_TRANSLATE_NOOP('prop','om_0')]: new P.ObjectType('Point'),
[QT_TRANSLATE_NOOP('prop','pass')]: P.Enum.BodePass,
[QT_TRANSLATE_NOOP('prop','gain')]: 'Expression',
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
[QT_TRANSLATE_NOOP('prop','labelX')]: 'number',
[QT_TRANSLATE_NOOP('prop','omGraduation')]: 'boolean'
}}
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
om_0 = '', pass = 'high', gain = '20', labelPosition = 'above', labelX = 1, omGraduation = false) {
if(name == null) name = Common.getNewName('G')
if(name == 'G') name = 'G₀' // G is reserved for sum of BODE magnitudes (Somme gains Bode).
super(name, visible, color, labelContent)
this.type = 'Gain Bode'
if(typeof om_0 == "string") {
// Point name or create one
om_0 = Objects.getObjectByName(om_0, 'Point')
if(om_0 == null) {
// Create new point
om_0 = Objects.createNewRegisteredObject('Point')
om_0.name = Common.getNewName('ω')
om_0.labelContent = 'name'
om_0.color = this.color
HistoryLib.history.addToHistory(new HistoryLib.CreateNewObject(om_0.name, 'Point', om_0.export()))
labelPosition = 'below'
}
om_0.requiredBy.push(this)
}
this.om_0 = om_0
this.pass = pass
if(typeof gain == 'number' || typeof gain == 'string') gain = new MathLib.Expression(gain.toString())
this.gain = gain
this.labelPosition = labelPosition
this.labelX = labelX
this.omGraduation = omGraduation
}
getReadableString() {
let pass = this.pass == "low" ? qsTr("low-pass") : qsTr("high-pass");
return `${this.name}: ${pass}; ${this.om_0.name} = ${this.om_0.x}\n ${' '.repeat(this.name.length)}${this.gain.toString(true)} dB/dec`
}
export() {
return [this.name, this.visible, this.color.toString(), this.labelContent,
this.om_0.name, this.pass.toString(), this.gain.toEditableString(), this.labelPosition, this.labelX, this.omGraduation]
}
execute(x=1) {
if(typeof x == 'string') x = MathLib.executeExpression(x)
if((this.pass == 'high' && x < this.om_0.x) || (this.pass == 'low' && x > this.om_0.x)) {
var dbfn = new MathLib.Expression(`${this.gain.execute()}*(ln(x)-ln(${this.om_0.x}))/ln(10)+${this.om_0.y}`)
return dbfn.execute(x)
} else {
return this.om_0.y.execute()
}
}
simplify(x = 1) {
var xval = x
if(typeof x == 'string') xval = MathLib.executeExpression(x)
if((this.pass == 'high' && xval < this.om_0.x) || (this.pass == 'low' && xval > this.om_0.x)) {
var dbfn = new MathLib.Expression(`${this.gain.execute()}*(ln(x)-ln(${this.om_0.x}))/ln(10)+${this.om_0.y}`)
return dbfn.simplify(x)
} else {
return this.om_0.y.toString()
}
}
canExecute(x = 1) {
return true
}
draw(canvas, ctx) {
var base = [canvas.x2px(this.om_0.x), canvas.y2px(this.om_0.y)]
var dbfn = new MathLib.Expression(`${this.gain.execute()}*(ln(x)-ln(${this.om_0.x}))/ln(10)+${this.om_0.y}`)
var inDrawDom = new MathLib.EmptySet()
if(this.pass == 'high') {
// High pass, linear line from begining, then constant to the end.
canvas.drawLine(ctx, base[0], base[1], canvas.canvasSize.width, base[1])
inDrawDom = MathLib.parseDomain(`]-inf;${this.om_0.x}[`)
} else {
// Low pass, constant from the beginning, linear line to the end.
canvas.drawLine(ctx, base[0], base[1], 0, base[1])
inDrawDom = MathLib.parseDomain(`]${this.om_0.x};+inf[`)
}
F.Function.drawFunction(canvas, ctx, dbfn, inDrawDom, MathLib.Domain.R)
// Dashed line representing break in function
var xpos = canvas.x2px(this.om_0.x.execute())
var dashPxSize = 10
for(var i = 0; i < canvas.canvasSize.height && this.omGraduation; i += dashPxSize*2)
canvas.drawLine(ctx, xpos, i, xpos, i+dashPxSize)
// Label
var text = this.getLabel()
ctx.font = `${canvas.textsize}px sans-serif`
var textSize = canvas.measureText(ctx, text)
var posX = canvas.x2px(this.labelX)
var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) {
case 'above':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
break;
case 'below':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+textSize.height)
break;
case 'left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height/2)
break;
case 'right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height/2)
break;
case 'above-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
break;
case 'above-right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height)
break;
case 'below-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY+textSize.height)
break;
case 'below-right':
canvas.drawVisibleText(ctx, text, posX, posY+textSize.height)
break;
}
}
update() {
super.update()
if(Objects.currentObjects['Somme gains Bode'] != undefined && Objects.currentObjects['Somme gains Bode'].length > 0) {
Objects.currentObjects['Somme gains Bode'][0].recalculateCache()
} else {
Objects.createNewRegisteredObject('Somme gains Bode')
}
}
}

View file

@ -1,164 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "common.js" as Common
.import "../objects.js" as Objects
.import "../mathlib.js" as MathLib
.import "../historylib.js" as HistoryLib
.import "../parameters.js" as P
class PhaseBode extends Common.ExecutableObject {
static type(){return 'Phase Bode'}
static displayType(){return qsTr('Bode Phase')}
static displayTypeMultiple(){return qsTr('Bode Phases')}
/*static properties() {return {
'om_0': new P.ObjectType('Point'),
'phase': 'Expression',
'unit': new P.Enum('°', 'deg', 'rad'),
'labelPosition': new P.Enum('above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
'labelX': 'number'
}}*/
static properties() {return {
[QT_TRANSLATE_NOOP('prop','om_0')]: new P.ObjectType('Point'),
[QT_TRANSLATE_NOOP('prop','phase')]: 'Expression',
[QT_TRANSLATE_NOOP('prop','unit')]: new P.Enum('°', 'deg', 'rad'),
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
[QT_TRANSLATE_NOOP('prop','labelX')]: 'number'
}}
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
om_0 = '', phase = 90, unit = '°', labelPosition = 'above', labelX = 1) {
if(name == null) name = Common.getNewName('φ')
if(name == 'φ') name = 'φ₀' // φ is reserved for sum of BODE phases (Somme phases Bode).
super(name, visible, color, labelContent)
this.type = 'Phase Bode'
if(typeof phase == 'number' || typeof phase == 'string') phase = new MathLib.Expression(phase.toString())
this.phase = phase
if(typeof om_0 == "string") {
// Point name or create one
om_0 = Objects.getObjectByName(om_0, 'Point')
if(om_0 == null) {
// Create new point
om_0 = Objects.createNewRegisteredObject('Point')
om_0.name = Common.getNewName('ω')
om_0.color = this.color
om_0.labelContent = 'name'
om_0.labelPosition = this.phase.execute() >= 0 ? 'bottom' : 'top'
HistoryLib.history.addToHistory(new HistoryLib.CreateNewObject(om_0.name, 'Point', om_0.export()))
labelPosition = 'below'
}
om_0.requiredBy.push(this)
}
this.om_0 = om_0
this.unit = unit
this.labelPosition = labelPosition
this.labelX = labelX
}
export() {
return [this.name, this.visible, this.color.toString(), this.labelContent,
this.om_0.name, this.phase.toEditableString(), this.unit, this.labelPosition, this.labelX]
}
getReadableString() {
return `${this.name}: ${this.phase.toString(true)}${this.unit} at ${this.om_0.name} = ${this.om_0.x}`
}
execute(x=1) {
if(typeof x == 'string') x = MathLib.executeExpression(x)
if(x < this.om_0.x) {
return this.om_0.y.execute()
} else {
return this.om_0.y.execute() + this.phase.execute()
}
}
simplify(x = 1) {
var xval = x
if(typeof x == 'string') xval = MathLib.executeExpression(x)
if(xval < this.om_0.x) {
return this.om_0.y.toString()
} else {
var newExp = this.om_0.y.toEditableString() + ' + ' + this.phase.toEditableString()
return (new MathLib.Expression(newExp)).toString()
}
}
canExecute(x = 1) {
return true
}
draw(canvas, ctx) {
var baseX = canvas.x2px(this.om_0.x.execute())
var omy = this.om_0.y.execute()
var augmt = this.phase.execute()
var baseY = canvas.y2px(omy)
var augmtY = canvas.y2px(omy+augmt)
// Before change line.
canvas.drawLine(ctx, 0, baseY, Math.min(baseX, canvas.canvasSize.height), baseY)
// Transition line.
canvas.drawLine(ctx, baseX, baseY, baseX, augmtY)
// After change line
canvas.drawLine(ctx, Math.max(0, baseX), augmtY, canvas.canvasSize.width, augmtY)
// Label
var text = this.getLabel()
ctx.font = `${canvas.textsize}px sans-serif`
var textSize = canvas.measureText(ctx, text)
var posX = canvas.x2px(this.labelX)
var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) {
case 'above':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
break;
case 'below':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+textSize.height)
break;
case 'left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height/2)
break;
case 'right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height/2)
break;
case 'above-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
break;
case 'above-right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height)
break;
case 'below-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY+textSize.height)
break;
case 'below-right':
canvas.drawVisibleText(ctx, text, posX, posY+textSize.height)
break;
}
}
update() {
if(Objects.currentObjects['Somme phases Bode'] != undefined && Objects.currentObjects['Somme phases Bode'].length > 0) {
Objects.currentObjects['Somme phases Bode'][0].recalculateCache()
} else {
Objects.createNewRegisteredObject('Somme phases Bode')
}
}
}

View file

@ -1,126 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "common.js" as Common
.import "../mathlib.js" as MathLib
.import "../parameters.js" as P
class Point extends Common.DrawableObject {
static type(){return 'Point'}
static displayType(){return qsTr('Point')}
static displayTypeMultiple(){return qsTr('Points')}
/*static properties() {return {
'x': 'Expression',
'y': 'Expression',
'labelPosition': new P.Enum('above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
'pointStyle': new P.Enum('●', '✕', ''),
}}*/
static properties() {return {
[QT_TRANSLATE_NOOP('prop','x')]: 'Expression',
[QT_TRANSLATE_NOOP('prop','y')]: 'Expression',
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
[QT_TRANSLATE_NOOP('prop','pointStyle')]: new P.Enum('●', '✕', '')
}}
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
x = 1, y = 0, labelPosition = 'above', pointStyle = '●') {
if(name == null) name = Common.getNewName('ABCDEFJKLMNOPQRSTUVW')
super(name, visible, color, labelContent)
this.type = 'Point'
if(typeof x == 'number' || typeof x == 'string') x = new MathLib.Expression(x.toString())
this.x = x
if(typeof y == 'number' || typeof y == 'string') y = new MathLib.Expression(y.toString())
this.y = y
this.labelPosition = labelPosition
this.pointStyle = pointStyle
}
getReadableString() {
return `${this.name} = (${this.x}, ${this.y})`
}
toLatexString() {
return `${this.name} = \\left(${this.x.latexMarkup}, ${this.y.latexMarkup}\\right)`
}
export() {
return [this.name, this.visible, this.color.toString(), this.labelContent, this.x.toEditableString(), this.y.toEditableString(), this.labelPosition, this.pointStyle]
}
draw(canvas, ctx) {
var [canvasX, canvasY] = [canvas.x2px(this.x.execute()), canvas.y2px(this.y.execute())]
var pointSize = 8+(ctx.lineWidth*2)
switch(this.pointStyle) {
case '●':
ctx.beginPath();
ctx.ellipse(canvasX-pointSize/2, canvasY-pointSize/2, pointSize, pointSize)
ctx.fill();
break;
case '✕':
canvas.drawLine(ctx, canvasX-pointSize/2, canvasY-pointSize/2, canvasX+pointSize/2, canvasY+pointSize/2)
canvas.drawLine(ctx, canvasX-pointSize/2, canvasY+pointSize/2, canvasX+pointSize/2, canvasY-pointSize/2)
break;
case '':
ctx.fillRect(canvasX-pointSize/2, canvasY-1, pointSize, 2)
ctx.fillRect(canvasX-1, canvasY-pointSize/2, 2, pointSize)
break;
}
let drawLabel = function(canvas, ctx, ltxImg) {
//console.log(JSON.stringify(ltxImg), canvas.isImageLoaded(ltxImg.source), this, this.labelPosition)
switch(this.labelPosition) {
case 'top':
case 'above':
canvas.drawVisibleImage(ctx, ltxImg.source, canvasX-ltxImg.width/2, canvasY-(ltxImg.height+4), ltxImg.width, ltxImg.height)
break;
case 'bottom':
case 'below':
canvas.drawVisibleImage(ctx, ltxImg.source, canvasX-ltxImg.width/2, canvasY+4, ltxImg.width, ltxImg.height)
break;
case 'left':
canvas.drawVisibleImage(ctx, ltxImg.source, canvasX-(ltxImg.width+4), canvasY+4, ltxImg.width, ltxImg.height)
break;
case 'right':
canvas.drawVisibleImage(ctx, ltxImg.source, canvasX+4, canvasY+4, ltxImg.width, ltxImg.height)
break;
case 'top-left':
case 'above-left':
canvas.drawVisibleImage(ctx, ltxImg.source, canvasX-(ltxImg.width+4), canvasY-(ltxImg.height+4), ltxImg.width, ltxImg.height)
break;
case 'top-right':
case 'above-right':
canvas.drawVisibleImage(ctx, ltxImg.source, canvasX+4, canvasY-(ltxImg.height+4), ltxImg.width, ltxImg.height)
break;
case 'bottom-left':
case 'below-left':
canvas.drawVisibleImage(ctx, ltxImg.source, canvasX-(ltxImg.width+4), canvasY+4, ltxImg.width, ltxImg.height)
break;
case 'bottom-right':
case 'below-right':
canvas.drawVisibleImage(ctx, ltxImg.source, canvasX+4, canvasY+4, ltxImg.width, ltxImg.height)
break;
}
}
canvas.renderLatexImage(this.getLabel(), this.color, drawLabel.bind(this))
//canvas.drawVisibleImage(ctx, ltxImg.source, canvasX, canvasY)
}
}

View file

@ -1,181 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "common.js" as Common
.import "../parameters.js" as P
class RepartitionFunction extends Common.ExecutableObject {
static type(){return 'Repartition'}
static displayType(){return qsTr('Repartition')}
static displayTypeMultiple(){return qsTr('Repartition functions')}
/*static properties() {return {
'beginIncluded': 'boolean',
'drawLineEnds': 'boolean',
'comment1': 'Note: Specify the properties for each potential result.',
'probabilities': new P.Dictionary('string', 'float', /^-?[\d.,]+$/, /^-?[\d\.,]+$/, 'P({name} = ', ') = '),
'labelPosition': new P.Enum('above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
'labelX': 'number'
}}*/
static properties() {return {
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
[QT_TRANSLATE_NOOP('prop','labelX')]: 'number',
'comment1': QT_TRANSLATE_NOOP(
'comment',
'Note: Specify the probability for each value.'
),
[QT_TRANSLATE_NOOP('prop','probabilities')]: new P.Dictionary('string', 'float', /^-?[\d.,]+$/, /^-?[\d\.,]+$/, 'P({name} = ', ') = '),
}}
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
beginIncluded = true, drawLineEnds = true, probabilities = {'0': '0'}, labelPosition = 'above', labelX = 1) {
if(name == null) name = Common.getNewName('XYZUVW')
super(name, visible, color, labelContent)
this.beginIncluded = beginIncluded
this.drawLineEnds = drawLineEnds
this.probabilities = probabilities
this.labelPosition = labelPosition
this.labelX = labelX
this.update()
}
export() {
return [this.name, this.visible, this.color.toString(), this.labelContent,
this.beginIncluded, this.drawLineEnds, this.probabilities, this.labelPosition, this.labelX]
}
getReadableString() {
var keys = Object.keys(this.probabilities).sort((a,b) => a-b);
return `F_${this.name}(x) = P(${this.name} ≤ x)\n` + keys.map(idx => `P(${this.name}=${idx})=${this.probabilities[idx]}`).join("; ")
}
execute(x = 1) {
var ret = 0;
Object.keys(this.probabilities).sort((a,b) => a-b).forEach(idx => {
if(x >= idx) ret += parseFloat(this.probabilities[idx].replace(/,/g, '.'))
})
return ret
}
canExecute(x = 1) {return true}
// Simplify returns the simplified string of the expression.
simplify(x = 1) {
return this.execute(x)
}
getLabel() {
switch(this.labelContent) {
case 'name':
return `P(${this.name} ≤ x)`
case 'name + value':
return this.getReadableString()
case 'null':
return ''
}
}
draw(canvas, ctx) {
var currentY = 0;
var keys = Object.keys(this.probabilities).map(idx => parseInt(idx)).sort((a,b) => a-b)
if(canvas.visible(keys[0],this.probabilities[keys[0]].replace(/,/g, '.'))) {
canvas.drawLine(ctx,
0,
canvas.y2px(0),
canvas.x2px(keys[0]),
canvas.y2px(0)
)
if(canvas.visible(keys[0],0)) {
ctx.beginPath();
ctx.arc(canvas.x2px(keys[0])+4,canvas.y2px(0), 4, Math.PI / 2, 3 * Math.PI / 2);
ctx.stroke();
}
}
for(var i = 0; i < keys.length-1; i++) {
var idx = keys[i];
currentY += parseFloat(this.probabilities[idx].replace(/,/g, '.'));
if(canvas.visible(idx,currentY) || canvas.visible(keys[i+1],currentY)) {
canvas.drawLine(ctx,
Math.max(0,canvas.x2px(idx)),
canvas.y2px(currentY),
Math.min(canvas.canvasSize.width,canvas.x2px(keys[i+1])),
canvas.y2px(currentY)
)
if(canvas.visible(idx,currentY)) {
ctx.beginPath();
ctx.arc(canvas.x2px(idx),canvas.y2px(currentY), 4, 0, 2 * Math.PI);
ctx.fill();
}
if(canvas.visible(keys[i+1],currentY)) {
ctx.beginPath();
ctx.arc(canvas.x2px(keys[i+1])+4,canvas.y2px(currentY), 4, Math.PI / 2, 3 * Math.PI / 2);
ctx.stroke();
}
}
}
if(canvas.visible(keys[keys.length-1],currentY+parseFloat(this.probabilities[keys[keys.length-1]]))) {
canvas.drawLine(ctx,
Math.max(0,canvas.x2px(keys[keys.length-1])),
canvas.y2px(currentY+parseFloat(this.probabilities[keys[keys.length-1]].replace(/,/g, '.'))),
canvas.canvasSize.width,
canvas.y2px(currentY+parseFloat(this.probabilities[keys[keys.length-1]].replace(/,/g, '.')))
)
ctx.beginPath();
ctx.arc(
canvas.x2px(keys[keys.length-1]),
canvas.y2px(currentY+parseFloat(this.probabilities[keys[keys.length-1]].replace(/,/g, '.'))),
4, 0, 2 * Math.PI);
ctx.fill();
}
// Label
var text = this.getLabel()
ctx.font = `${canvas.textsize}px sans-serif`
var textSize = canvas.measureText(ctx, text)
var posX = canvas.x2px(this.labelX)
var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) {
case 'above':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
break;
case 'below':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+textSize.height)
break;
case 'left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height/2)
break;
case 'right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height/2)
break;
case 'above-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
break;
case 'above-right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height)
break;
case 'below-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY+textSize.height)
break;
case 'below-right':
canvas.drawVisibleText(ctx, text, posX, posY+textSize.height)
break;
}
}
}

View file

@ -1,147 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "common.js" as Common
.import "function.js" as F
.import "../mathlib.js" as MathLib
.import "../parameters.js" as P
class Sequence extends Common.ExecutableObject {
static type(){return 'Sequence'}
static displayType(){return qsTr('Sequence')}
static displayTypeMultiple(){return qsTr('Sequences')}
static properties() {return {
[QT_TRANSLATE_NOOP('prop','drawPoints')]: 'boolean',
[QT_TRANSLATE_NOOP('prop','drawDashedLines')]: 'boolean',
[QT_TRANSLATE_NOOP('prop','defaultExpression')]: new P.Dictionary('string', 'int', /^.+$/, /^\d+$/, '{name}[n+', '] = ', true),
'comment1': QT_TRANSLATE_NOOP(
'comment',
'Note: Use %1[n] to refer to %1ₙ, %1[n+1] for %1ₙ₊₁...'
),
[QT_TRANSLATE_NOOP('prop','baseValues')]: new P.Dictionary('string', 'int', /^.+$/, /^\d+$/, '{name}[', '] = '),
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
[QT_TRANSLATE_NOOP('prop','labelX')]: 'number',
}}
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
drawPoints = true, drawDashedLines = true, defaultExp = {1: "n"},
baseValues = {0: 0}, labelPosition = 'above', labelX = 1) {
if(name == null) name = Common.getNewName('uvwPSUVWabcde')
super(name, visible, color, labelContent)
this.drawPoints = drawPoints
this.drawDashedLines = drawDashedLines
this.defaultExpression = defaultExp
this.baseValues = baseValues
this.labelPosition = labelPosition
this.labelX = labelX
this.update()
}
export() {
return [this.name, this.visible, this.color.toString(), this.labelContent,
this.drawPoints, this.drawDashedLines, this.defaultExpression, this.baseValues, this.labelPosition, this.labelX]
}
update() {
super.update()
if(
this.sequence == null || this.baseValues != this.sequence.baseValues ||
this.sequence.name != this.name ||
this.sequence.expr != Object.values(this.defaultExpression)[0] ||
this.sequence.valuePlus != Object.keys(this.defaultExpression)[0]
)
this.sequence = new MathLib.Sequence(
this.name, this.baseValues,
Object.keys(this.defaultExpression)[0],
Object.values(this.defaultExpression)[0]
)
}
getReadableString() {
return this.sequence.toString()
}
execute(x = 1) {
if(x % 1 == 0)
return this.sequence.execute(x)
return null
}
canExecute(x = 1) {return x%1 == 0}
// Simplify returns the simplified string of the expression.
simplify(x = 1) {
if(x % 1 == 0)
return this.sequence.simplify(x)
return null
}
getLabel() {
switch(this.labelContent) {
case 'name':
return `(${this.name}ₙ)`
case 'name + value':
return this.getReadableString()
case 'null':
return ''
}
}
draw(canvas, ctx) {
F.Function.drawFunction(canvas, ctx, this.sequence, canvas.logscalex ? MathLib.Domain.NE : MathLib.Domain.N, MathLib.Domain.R, this.drawPoints, this.drawDashedLines)
// Label
var text = this.getLabel()
ctx.font = `${canvas.textsize}px sans-serif`
var textSize = canvas.measureText(ctx, text)
var posX = canvas.x2px(this.labelX)
var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) {
case 'above':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
break;
case 'below':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+textSize.height)
break;
case 'left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height/2)
break;
case 'right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height/2)
break;
case 'above-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
break;
case 'above-right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height)
break;
case 'below-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY+textSize.height)
break;
case 'below-right':
canvas.drawVisibleText(ctx, text, posX, posY+textSize.height)
break;
}
}
}

View file

@ -1,174 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "common.js" as Common
.import "function.js" as F
.import "../objects.js" as Objects
.import "../mathlib.js" as MathLib
.import "../parameters.js" as P
class SommeGainsBode extends Common.DrawableObject {
static type(){return 'Somme gains Bode'}
static displayType(){return qsTr('Bode Magnitudes Sum')}
static displayTypeMultiple(){return qsTr('Bode Magnitudes Sum')}
static createable() {return false}
/*static properties() {return {
'labelPosition': new P.Enum('above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
'labelX': 'number'
}}*/
static properties() {return {
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
[QT_TRANSLATE_NOOP('prop','labelX')]: 'number',
}}
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
labelPosition = 'above', labelX = 1) {
if(name == null) name = 'G'
super(name, visible, color, labelContent)
this.labelPosition = labelPosition
this.labelX = labelX
this.recalculateCache()
}
export() {
return [this.name, this.visible, this.color.toString(), this.labelContent, this.labelPosition, this.labelX]
}
getReadableString() {
return `${this.name} = ${Objects.getObjectsName('Gain Bode').join(' + ')}`
}
execute(x = 0) {
for(var [dbfn, inDrawDom] of this.cachedParts) {
if(inDrawDom.includes(x)) {
return dbfn.execute(x)
}
}
return null
}
canExecute(x = 1) {
return true // Should always be true
}
simplify(x = 1) {
for(var [dbfn, inDrawDom] of this.cachedParts) {
if(inDrawDom.includes(x)) {
return dbfn.simplify(x)
}
}
return ''
}
recalculateCache() {
this.cachedParts = []
// Calculating this is fairly resource expansive so it's cached.
if(Objects.currentObjects['Gain Bode'] != undefined) {
console.log('Recalculating cache gain')
// Minimum to draw (can be expended if needed, just not infinite or it'll cause issues.
var drawMin = 0.001
var baseY = 0
var om0xGains = {1000000000: 0} // To draw the last part
var om0xPass = {1000000000: 'high'} // To draw the last part
Objects.currentObjects['Gain Bode'].forEach(function(gainObj) { // Sorting by their om_0 position.
var om0x = gainObj.om_0.x.execute()
if(om0xGains[om0x] == undefined) {
om0xGains[om0x] = gainObj.gain.execute()
om0xPass[om0x] = gainObj.pass == 'high'
} else {
om0xGains[om0x+0.001] = gainObj.gain.execute()
om0xPass[om0x+0.001] = gainObj.pass == 'high'
}
baseY += gainObj.execute(drawMin)
})
// Sorting the om_0x
var om0xList = Object.keys(om0xGains).map(x => parseFloat(x)) // THEY WERE CONVERTED TO STRINGS...
om0xList.sort((a,b) => a - b)
// Adding the total gains.
var gainsBeforeP = []
var gainsAfterP = []
var gainTotal = 0
for(var om0x of om0xList){
if(om0xPass[om0x]) { // High-pass
gainsBeforeP.push(om0xGains[om0x])
gainsAfterP.push(0)
gainTotal += om0xGains[om0x] // Gain at first
} else {
gainsBeforeP.push(0)
gainsAfterP.push(om0xGains[om0x])
}
}
// Calculating parts
var previousPallier = drawMin
for(var pallier = 0; pallier < om0xList.length; pallier++) {
var dbfn = new MathLib.Expression(`${gainTotal}*(ln(x)-ln(${previousPallier}))/ln(10)+${baseY}`)
var inDrawDom = MathLib.parseDomain(`]${previousPallier};${om0xList[pallier]}]`)
this.cachedParts.push([dbfn, inDrawDom])
previousPallier = om0xList[pallier]
baseY = dbfn.execute(om0xList[pallier])
gainTotal += gainsAfterP[pallier] - gainsBeforeP[pallier]
}
}
}
draw(canvas, ctx) {
if(this.cachedParts.length > 0) {
for(var [dbfn, inDrawDom] of this.cachedParts) {
F.Function.drawFunction(canvas, ctx, dbfn, inDrawDom, MathLib.Domain.R)
if(inDrawDom.includes(this.labelX)) {
// Label
var text = this.getLabel()
ctx.font = `${canvas.textsize}px sans-serif`
var textSize = canvas.measureText(ctx, text)
var posX = canvas.x2px(this.labelX)
var posY = canvas.y2px(dbfn.execute(this.labelX))
switch(this.labelPosition) {
case 'above':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
break;
case 'below':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+textSize.height)
break;
case 'left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height/2)
break;
case 'right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height/2)
break;
case 'above-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
break;
case 'above-right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height)
break;
case 'below-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY+textSize.height)
break;
case 'below-right':
canvas.drawVisibleText(ctx, text, posX, posY+textSize.height)
break;
}
}
}
}
}
}

View file

@ -1,158 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "common.js" as Common
.import "../objects.js" as Objects
.import "../mathlib.js" as MathLib
.import "../parameters.js" as P
class SommePhasesBode extends Common.ExecutableObject {
static type(){return 'Somme phases Bode'}
static displayType(){return qsTr('Bode Phases Sum')}
static displayTypeMultiple(){return qsTr('Bode Phases Sum')}
static createable() {return false}
/*static properties() {return {
'labelPosition': new P.Enum('above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
'labelX': 'number'
}}*/
static properties() {return {
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
[QT_TRANSLATE_NOOP('prop','labelX')]: 'number',
}}
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
labelPosition = 'above', labelX = 1) {
if(name == null) name = 'φ'
super(name, visible, color, labelContent)
this.labelPosition = labelPosition
this.labelX = labelX
this.recalculateCache()
}
export() {
return [this.name, this.visible, this.color.toString(), this.labelContent, this.labelPosition, this.labelX]
}
getReadableString() {
return `${this.name} = ${Objects.getObjectsName('Phase Bode').join(' + ')}`
}
execute(x=1) {
if(typeof x == 'string') x = MathLib.executeExpression(x)
for(var i = 0; i < this.om0xList.length-1; i++) {
if(x >= this.om0xList[i] && x < this.om0xList[i+1]) return this.phasesList[i]
}
}
simplify(x = 1) {
var xval = x
if(typeof x == 'string') xval = MathLib.executeExpression(x)
for(var i = 0; i < this.om0xList.length-1; i++) {
if(xval >= this.om0xList[i] && xval < this.om0xList[i+1]) {
return (new MathLib.Expression(this.phasesExprList[i])).simplify()
}
}
return '0'
}
canExecute(x = 1) {
return true
}
recalculateCache() {
// Minimum to draw (can be expended if needed, just not infinite or it'll cause issues.
var drawMin = 0.001
var drawMax = 100000
this.om0xList = [drawMin, drawMax]
this.phasesList = [0]
this.phasesExprList = ['0']
var phasesDict = {}
var phasesExprDict = {}
phasesDict[drawMax] = 0
if(Objects.currentObjects['Phase Bode'] != undefined) {
console.log('Recalculating cache phase')
for(var obj of Objects.currentObjects['Phase Bode']) {
this.om0xList.push(obj.om_0.x.execute())
if(phasesDict[obj.om_0.x.execute()] == undefined) {
phasesDict[obj.om_0.x.execute()] = obj.phase.execute()
phasesExprDict[obj.om_0.x.execute()] = obj.phase.toEditableString()
} else {
phasesDict[obj.om_0.x.execute()] += obj.phase.execute()
phasesExprDict[obj.om_0.x.execute()] += '+' + obj.phase.toEditableString()
}
this.phasesList[0] += obj.om_0.y.execute()
this.phasesExprList[0] += '+' + obj.om_0.y.toEditableString()
}
this.om0xList.sort((a,b) => a - b)
var totalAdded = this.phasesList[0]
for(var i = 1; i < this.om0xList.length; i++) {
this.phasesList[i] = this.phasesList[i-1] + phasesDict[this.om0xList[i]]
this.phasesExprList[i] = this.phasesExprList[i-1] + '+' + phasesDict[this.om0xList[i]]
}
}
}
draw(canvas, ctx) {
for(var i = 0; i < this.om0xList.length-1; i++) {
var om0xBegin = canvas.x2px(this.om0xList[i])
var om0xEnd = canvas.x2px(this.om0xList[i+1])
var baseY = canvas.y2px(this.phasesList[i])
var nextY = canvas.y2px(this.phasesList[i+1])
canvas.drawLine(ctx, om0xBegin, baseY, om0xEnd, baseY)
canvas.drawLine(ctx, om0xEnd, baseY, om0xEnd, nextY)
}
// Label
var text = this.getLabel()
ctx.font = `${canvas.textsize}px sans-serif`
var textSize = canvas.measureText(ctx, text)
var posX = canvas.x2px(this.labelX)
var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) {
case 'above':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
break;
case 'below':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+textSize.height)
break;
case 'left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height/2)
break;
case 'right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height/2)
break;
case 'above-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
break;
case 'above-right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height)
break;
case 'below-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY+textSize.height)
break;
case 'below-right':
canvas.drawVisibleText(ctx, text, posX, posY+textSize.height)
break;
}
}
}

View file

@ -1,100 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "common.js" as Common
.import "../mathlib.js" as MathLib
.import "../parameters.js" as P
class Text extends Common.DrawableObject {
static type(){return 'Text'}
static displayType(){return qsTr('Text')}
static displayTypeMultiple(){return qsTr('Texts')}
/*static properties() {return {
'x': 'Expression',
'y': 'Expression',
'labelPosition': new P.Enum('center', 'above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
'text': 'string',
}}*/
static properties() {return {
[QT_TRANSLATE_NOOP('prop','x')]: 'Expression',
[QT_TRANSLATE_NOOP('prop','y')]: 'Expression',
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Positioning,
[QT_TRANSLATE_NOOP('prop','text')]: 'string'
}}
constructor(name = null, visible = true, color = null, labelContent = 'null',
x = 1, y = 0, labelPosition = 'center', text = 'New text') {
if(name == null) name = Common.getNewName('t')
super(name, visible, color, labelContent)
this.type = 'Point'
if(typeof x == 'number' || typeof x == 'string') x = new MathLib.Expression(x.toString())
this.x = x
if(typeof y == 'number' || typeof y == 'string') y = new MathLib.Expression(y.toString())
this.y = y
this.labelPosition = labelPosition
this.text = text
}
getReadableString() {
return `${this.name} = "${this.text}"`
}
export() {
return [this.name, this.visible, this.color.toString(), this.labelContent, this.x.toEditableString(), this.y.toEditableString(), this.labelPosition, this.text]
}
draw(canvas, ctx) {
var [canvasX, canvasY] = [canvas.x2px(this.x.execute()), canvas.y2px(this.y.execute())]
ctx.font = `${canvas.textsize}px sans-serif`
var textSize = ctx.measureText(this.text).width
switch(this.labelPosition) {
case 'center':
canvas.drawVisibleText(ctx, this.text, canvasX-textSize/2, canvasY+4)
break;
case 'top':
canvas.drawVisibleText(ctx, this.text, canvasX-textSize/2, canvasY-16)
break;
case 'bottom':
canvas.drawVisibleText(ctx, this.text, canvasX-textSize/2, canvasY+16)
break;
case 'left':
canvas.drawVisibleText(ctx, this.text, canvasX-textSize-5, canvasY+4)
break;
case 'right':
canvas.drawVisibleText(ctx, this.text, canvasX+5, canvasY+4)
break;
case 'top-left':
canvas.drawVisibleText(ctx, this.text, canvasX-textSize-5, canvasY-16)
break;
case 'top-right':
canvas.drawVisibleText(ctx, this.text, canvasX+5, canvasY-16)
break;
case 'bottom-left':
canvas.drawVisibleText(ctx, this.text, canvasX-textSize-5, canvasY+16)
break;
case 'bottom-right':
canvas.drawVisibleText(ctx, this.text, canvasX+5, canvasY+16)
break;
}
}
}

View file

@ -1,190 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "common.js" as Common
.import "../objects.js" as Objects
.import "../mathlib.js" as MathLib
.import "../parameters.js" as P
class XCursor extends Common.DrawableObject {
static type(){return 'X Cursor'}
static displayType(){return qsTr('X Cursor')}
static displayTypeMultiple(){return qsTr('X Cursors')}
/*static properties() {
return {
'x': 'Expression',
'targetElement': new P.ObjectType('ExecutableObject'),
'labelPosition': new P.Enum('left', 'right'),
'approximate': 'boolean',
'rounding': 'number',
'displayStyle': new P.Enum(
'— — — — — — —',
'⸺⸺⸺⸺⸺⸺',
'• • • • • • • • • •'
),
'targetValuePosition' : new P.Enum('Next to target', 'With label', 'Hidden')
}
}*/
static properties() {return {
[QT_TRANSLATE_NOOP('prop','x')]: 'Expression',
[QT_TRANSLATE_NOOP('prop','targetElement')]: new P.ObjectType('ExecutableObject'),
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
[QT_TRANSLATE_NOOP('prop','approximate')]: 'boolean',
[QT_TRANSLATE_NOOP('prop','rounding')]: 'number',
[QT_TRANSLATE_NOOP('prop','displayStyle')]: new P.Enum(
'— — — — — — —',
'⸺⸺⸺⸺⸺⸺',
'• • • • • • • • • •'
),
[QT_TRANSLATE_NOOP('prop','targetValuePosition')]: P.Enum.XCursorValuePosition,
}}
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
x = 1, targetElement = null, labelPosition = 'left', approximate = true,
rounding = 3, displayStyle = '— — — — — — —', targetValuePosition = 'Next to target') {
if(name == null) name = Common.getNewName('X')
super(name, visible, color, labelContent)
this.type = 'X Cursor'
this.approximate = approximate
this.rounding = rounding
if(typeof x == 'number' || typeof x == 'string') x = new MathLib.Expression(x.toString())
this.x = x
this.targetElement = targetElement
if(typeof targetElement == "string") {
this.targetElement = Objects.getObjectByName(targetElement, elementTypes)
}
this.labelPosition = labelPosition
this.displayStyle = displayStyle
this.targetValuePosition = targetValuePosition
}
export() {
return [this.name, this.visible, this.color.toString(), this.labelContent,
this.x.toEditableString(), this.targetElement == null ? null : this.targetElement.name, this.labelPosition,
this.approximate, this.rounding, this.displayStyle, this.targetValuePosition]
}
getReadableString() {
if(this.targetElement == null) return `${this.name} = ${this.x.toString()}`
return `${this.name} = ${this.x.toString()}\n${this.getTargetValueLabel()}`
}
getTargetValueLabel() {
var t = this.targetElement
var approx = ''
if(this.approximate) {
approx = t.execute(this.x.execute())
approx = approx.toPrecision(this.rounding + Math.round(approx).toString().length)
}
return `${t.name}(${this.name}) = ${t.simplify(this.x.toEditableString())}` +
(this.approximate ? ' ≈ ' + approx : '')
}
getLabel() {
switch(this.labelContent) {
case 'name':
return this.name
break;
case 'name + value':
switch(this.targetValuePosition) {
case 'Next to target':
case 'Hidden':
return `${this.name} = ${this.x.toString()}`
break;
case 'With label':
return this.getReadableString()
break;
}
case 'null':
return ''
}
}
draw(canvas, ctx) {
var xpos = canvas.x2px(this.x.execute())
switch(this.displayStyle) {
case '— — — — — — —':
var dashPxSize = 10
for(var i = 0; i < canvas.canvasSize.height; i += dashPxSize*2)
canvas.drawLine(ctx, xpos, i, xpos, i+dashPxSize)
break;
case '⸺⸺⸺⸺⸺⸺':
canvas.drawXLine(ctx, this.x.execute())
break;
case '• • • • • • • • • •':
var pointDistancePx = 10
var pointSize = 2
ctx.beginPath();
for(var i = 0; i < canvas.canvasSize.height; i += pointDistancePx)
ctx.ellipse(xpos-pointSize/2, i-pointSize/2, pointSize, pointSize)
ctx.fill();
break;
}
// Label
var text = this.getLabel()
ctx.font = `${canvas.textsize}px sans-serif`
var textSize = canvas.measureText(ctx, text)
switch(this.labelPosition) {
case 'left':
case 'above-left':
case 'below-left':
case 'below':
case 'above':
canvas.drawVisibleText(ctx, text, xpos-textSize.width-5, textSize.height+5)
break;
case 'right':
case 'above-right':
case 'below-right':
canvas.drawVisibleText(ctx, text, xpos+5, textSize.height+5)
break;
}
if(this.targetValuePosition == 'Next to target' && this.targetElement != null) {
var text = this.getTargetValueLabel()
var textSize = canvas.measureText(ctx, text)
var ypox = canvas.y2px(this.targetElement.execute(this.x.execute()))
switch(this.labelPosition) {
case 'left':
case 'below':
case 'above':
canvas.drawVisibleText(ctx, text, xpos-textSize.width-5, ypox+textSize.height)
break;
case 'above-left':
canvas.drawVisibleText(ctx, text, xpos-textSize.width-5, ypox+textSize.height+12)
break;
case 'below-left':
canvas.drawVisibleText(ctx, text, xpos-textSize.width-5, ypox+textSize.height-12)
break;
case 'right':
canvas.drawVisibleText(ctx, text, xpos+5, ypox+textSize.height)
break;
case 'above-right':
canvas.drawVisibleText(ctx, text, xpos+5, ypox+textSize.height+12)
break;
case 'below-right':
canvas.drawVisibleText(ctx, text, xpos+5, ypox+textSize.height-12)
break;
}
}
}
}

View file

@ -1,101 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
class Enum {
constructor(...values) {
this.type = 'Enum'
this.values = values
this.translatedValues = values.map(x => qsTr(x))
}
}
class ObjectType {
constructor(objType) {
this.type = 'ObjectType'
this.objType = objType
}
}
class List {
constructor(type, format = /^.+$/, label = '', forbidAdding = false) {
// type can be string, int and double.
this.type = 'List'
this.valueType = type
this.format = format
this.label = label
this.forbidAdding = forbidAdding
}
}
class Dictionary {
constructor(type, keyType = 'string', format = /^.+$/, keyFormat = /^.+$/, preKeyLabel = '', postKeyLabel = ': ', forbidAdding = false) {
// type & keyType can be string, int and double.
this.type = 'Dict'
this.valueType = type
this.keyType = keyType
this.format = format
this.keyFormat = keyFormat
this.preKeyLabel = preKeyLabel
this.postKeyLabel = postKeyLabel
this.forbidAdding = forbidAdding
}
}
// Common parameters for Enums
Enum.Position = new Enum(
QT_TR_NOOP('above'),
QT_TR_NOOP('below'),
QT_TR_NOOP('left'),
QT_TR_NOOP('right'),
QT_TR_NOOP('above-left'),
QT_TR_NOOP('above-right'),
QT_TR_NOOP('below-left'),
QT_TR_NOOP('below-right')
)
Enum.Positioning = new Enum(
QT_TR_NOOP('center'),
QT_TR_NOOP('top'),
QT_TR_NOOP('bottom'),
QT_TR_NOOP('left'),
QT_TR_NOOP('right'),
QT_TR_NOOP('top-left'),
QT_TR_NOOP('top-right'),
QT_TR_NOOP('bottom-left'),
QT_TR_NOOP('bottom-right')
)
Enum.FunctionDisplayType = new Enum(
QT_TR_NOOP('application'),
QT_TR_NOOP('function')
)
Enum.BodePass = new Enum(
QT_TR_NOOP('high'),
QT_TR_NOOP('low')
)
Enum.XCursorValuePosition = new Enum(
QT_TR_NOOP('Next to target'),
QT_TR_NOOP('With label'),
QT_TR_NOOP('Hidden')
)

View file

@ -1,663 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "reference.js" as Reference
const DERIVATION_PRECISION = 0.01
const OPERATION_PRIORITY = {
"+": 10, "-": 10,
"*": 20, "/": 20
}
enum ASEType {
UNKNOWN,
VARIABLE,
NUMBER,
STRING,
FUNCTION,
CONSTANT,
OPERATION,
NEGATION // Example: -x.
}
class AbstractSyntaxElement {
type = ASEType.UNKNOWN;
execute(variables) {
return null;
}
simplify() {
return this;
}
derivate(variable) {
return this;
}
integrate(variable) {
return this;
}
toEditableString() {
return "";
}
toLatex() {
return "";
}
isConstant() {
return true;
}
}
class Variable extends AbstractSyntaxElement {
type = ASEType.VARIABLE;
constructor(variableName) {
this.varName = variableName;
}
execute(variables) {
if(variables.includes(this.varName)) {
return variables[this.varName];
} else {
throw new EvalError("Unknown variable " + this.varName + ".");
}
}
derivate(variable) {
if(variable == this.varName)
return new NumberElement(1);
return this;
}
integrate(variable) {
if(variable == this.varName)
// <var>^2/2
return new Operation(new Operation(this, '^', new NumberElement(2)), '/', new NumberElement(2));
return this;
}
toEditableString() {
return this.varName;
}
toLatex() {
return this.varName;
}
isConstant() {
return false;
}
}
class ArrayVariable extends Variable {
constructor(arrayName, astIndex) {
super(arrayName + "[" + astIndex.toEditableString() + "]")
this.arrayName = arrayName;
this.astIndex = astIndex;
}
execute(variables) {
if(variables.includes(this.arrayName)) {
let index = this.astIndex.execute(variables)
if(index % 1 != 0 || index < 0) { // Float index.
throw new EvalError("Non-integer array index " + index + " used as array index for " + this.varName + ".");
} else if(variables[this.arrayName].length <= index) {
throw new EvalError("Out-of-range index " + index + " used as array index for " + this.varName + ".");
} else {
return variables[this.arrayName][index];
}
} else {
throw new EvalError("Unknown variable " + this.varName + ".");
}
toLatex() {
return this.varName;
}
}
simplify() {
return new ArrayVariable(this.arrayName, this.astIndex.simplify());
}
toLatex() {
return this.arrayName + '\\left[' + this.astIndex.toLatex() + '\\right]';
}
isConstant() {
return false;
}
}
class Constant extends Variable {
type = ASEType.CONSTANT;
constructor(constant) {
super(constant)
}
execute(variables) {
if(Reference.CONSTANTS_LIST.includes(this.varName)) {
return Reference.CONSTANTS[this.varName];
} else {
throw new EvalError("Unknown constant " + this.varName + ".");
}
}
derivate(variable) {
if(variable == this.varName)
return new NumberElement(0);
return this;
}
integrate(variable) {
return new Operation(new Variable(variable), '^', this);
}
toEditableString() {
return this.varName;
}
toLatex() {
return this.varName;
}
isConstant() {
return true;
}
}
class NumberElement extends AbstractSyntaxElement {
type = ASEType.NUMBER;
constructor(number) {
this.value = parseFloat(number);
}
derivate(variable) {
return new NumberElement(0);
}
integrate(variable) {
return new Variable(variable);
}
toEditableString() {
return this.value.toString();
}
toLatex() {
return this.value.toString();
}
isConstant() {
return true;
}
}
class StringElement extends AbstractSyntaxElement {
type = ASEType.STRING;
constructor(str) {
this.str = str;
}
execute(variables) {
return this.str
}
derivate(variable) {
return this;
}
integrate(variable) {
return this;
}
toEditableString() {
return '"' + this.str + '"';
}
toLatex() {
return this.str;
}
isConstant() {
return true;
}
}
class FunctionElement extends AbstractSyntaxElement {
type = ASEType.FUNCTION;
constructor(functionName, astArguments) {
this.function = functionName;
this.args = astArguments;
}
execute(variables) {
if(this.function == "derivate") {
return executeDerivative(variables)
} else if(this.function == "integrate") {
return executeIntegral(variables)
} else if(Reference.FUNCTIONS_LIST.includes(this.function)) {
let args = this.args.map(arg => arg.execute(variables));
return Reference.FUNCTIONS[this.function](...args);
} else {
throw new EvalError("Unknown function " + this.function + ".");
}
}
executeDerivative(variables) {
// Calculate derivation.
if(this.args.length == 2)
if(this.args[1] instanceof Variable) {
let d = this.args[1].varName; // derivative variable name.
if(Object.keys(variables).includes(d)) {
let plus = this.args[0].execute(Object.assign({}, variables, {d: variables[d]+DERIVATION_PRECISION/2}));
let min = this.args[0].execute(Object.assign({}, variables, {d: variables[d]-DERIVATION_PRECISION/2}));
return (plus-min)/DERIVATION_PRECISION
} else
throw new EvalError("Undefined variable " + d + ".");
} else
throw new EvalError(`Argument 1 of function derivate must be a variable.`)
else
throw new EvalError(`Function 'derivate' can only have 2 arguments. ${this.args.length} provided.`)
}
executeIntegral(variables) {
// Calculate integral.
// Using simons rule
// https://en.wikipedia.org/wiki/Simpson%27s_rule
let d, f, a, b;
if(this.args.length == 2)
// Integral(f,var) integral of f by var.
if(this.args[1] instanceof Variable)
if(Object.keys(variables).includes(d)) {
d = this.args[1].varName; // derivative variable name.
if(!Object.keys(variables).includes(d))
throw new EvalError("Undefined variable " + d + ".")
a = 0;
b = variables[d];
f = this.args[0].execute;
} else
else
throw new EvalError(`Argument 2 of function derivate must be a variable.`)
else if(this.args.length == 4)
// Integral(a,b,f,var) integral from a to b of f by var.
if(this.args[3] instanceof Variable)
if(Object.keys(variables).includes(d)) {
a = this.args[0].execute(variables);
b = this.args[1].execute(variables);
f = this.args[2].execute;
d = this.args[3].varName; // derivative variable name.
if(!Object.keys(variables).includes(d))
throw new EvalError("Undefined variable " + d + ".");
}
else
throw new EvalError(`Argument 4 of function derivate must be a variable.`)
else
throw new EvalError(`Function 'derivate' can only have 2 or 4 arguments. ${this.args.length} provided.`)
// (b-a)/6*(f(a)+4*f((a+b)/2)+f(b))
let f_a = f(Object.assign({}, variables, {d: a})), f_b = f(Object.assign({}, variables, {d: b}));
let f_m = f(Object.assign({}, variables, {d: (a+b)/2}))
return (b-a)/6*(f_a+4*f_m+f_b);
}
simplify() {
let args = this.args.map(arg => arg.simplify(variables));
let newFunc = new FunctionElement(this.function, args);
let result;
if(newFunc.isConstant() && (result = newFunc.execute({})) % 1 == 0) { // Simplification (e.g. cos(0), sin(π/2)...)
return new NumberElement(result);
} else {
return newFunc;
}
}
derivate(variable) {
//TODO: Use DERIVATIVES elements in reference.
return new FunctionElement("derivate", this, variable);
}
integrate(variable) {
//TODO: Use INTEGRALS elements in reference.
return new FunctionElement("integrate", this, variable);
}
toEditableString() {
return this.function + '(' + this.args.map(arg => arg.toEditableString()).join(', ') + ')';
}
toLatex() {
switch(this.function) {
case "sqrt":
return '\\sqrt{' + this.args.map(arg => arg.toLatex()).join(', ') + '}';
case "abs":
return '\\left|' + this.args.map(arg => arg.toLatex()).join(', ') + '\\right|';
case "floor":
return '\\left\\lfloor' + this.args.map(arg => arg.toLatex()).join(', ') + '\\right\\rfloor';
case "ceil":
return '\\left\\lceil' + this.args.map(arg => arg.toLatex()).join(', ') + '\\right\\rceil';
default:
return '\\mathrm{' + this.function + '}\\left(' + this.args.map(arg => arg.toLatex()).join(', ') + '\\right)';
}
}
isConstant() {
if(this.function == "derivate")
return this.args[0].isConstant();
else if(this.function == "integrate")
return this.args.length == 4 && this.args[0].isConstant() && this.args[1].isConstant() && this.args[2].isConstant();
else
return this.args.every(x => x.isConstant());
}
}
class Operation extends AbstractSyntaxElement {
type = ASEType.OPERATION;
constructor(leftHand, operation, rightHand) {
this.leftHand = leftHand;
this.ope = operation;
this.rightHand = rightHand;
}
evaluate(variables) {
switch(this.ope) {
case '+':
return this.leftHand.evaluate(variables) + this.rightHand.evaluate(variables);
case '-':
return this.leftHand.evaluate(variables) - this.rightHand.evaluate(variables);
case '*':
return this.leftHand.evaluate(variables) * this.rightHand.evaluate(variables);
case '/':
return this.leftHand.evaluate(variables) / this.rightHand.evaluate(variables);
case '%':
return this.leftHand.evaluate(variables) % this.rightHand.evaluate(variables);
case '^':
return Math.pow(this.leftHand.evaluate(variables), this.rightHand.evaluate(variables));
default:
throw new EvalError("Unknown operator " + ope + ".");
}
}
simplify() {
let leftHand = this.leftHand.simplify();
let rightHand = this.rightHand.simplify();
let newOpe = new Operation(leftHand, this.ope, rightHand);
if(leftHand.isConstant() && rightHand.isConstant() && Math.abs(newOpe.execute({})) < 1000000) {
// Do not simplify to too big numbers
switch(this.ope) {
case '+':
case '-':
case '*':
case '^':
case '%':
return new NumberElement(newOpe.execute({}));
case '/':
if(result % 1 == 0)
return new NumberElement(newOpe.execute({}));
else {
let simplified = simplifyFraction(leftHand.number, rightHand.number)
return new Operation(new NumberElement(simplified[0]), '/', new NumberElement(simplified[1]))
}
return this.leftHand.evaluate(variables) / this.rightHand.evaluate(variables);
return Math.pow(this.leftHand.evaluate(variables), this.rightHand.evaluate(variables));
default:
throw new EvalError("Unknown operator " + ope + ".");
}
} else {
// Simplifications of +- 0 or *1
switch(this.ope) {
case '+':
case '-':
if(leftHand.type == ASEType.NUMBER && leftHand.value == 0)
return rightHand;
else if(rightHand.type == ASEType.NUMBER && rightHand.value == 0) {
if(ope == '-') leftHand.value = -leftHand.value;
return leftHand;
} else
return newOpe
case '*':
if((leftHand.type == ASEType.NUMBER && leftHand.value == 0) || (rightHand.type == ASEType.NUMBER && rightHand.value == 0))
return new NumberElement(0);
else if(leftHand.type == ASEType.NUMBER && leftHand.value == 1)
return rightHand;
else if(rightHand.type == ASEType.NUMBER && rightHand.value == 1)
return leftHand;
else
return newOpe
case '^':
if(rightHand.type == ASEType.NUMBER && rightHand.value == 0)
return new NumberElement(1);
else if(rightHand.type == ASEType.NUMBER && rightHand.value == 1)
return new NumberElement(leftHand.value);
else
return newOpe;
case '/':
if(rightHand.type == ASEType.NUMBER && rightHand.value == 1)
return new NumberElement(leftHand.value);
else
return newOpe;
case '%':
return newOpe;
default:
throw new EvalError("Unknown operator " + ope + ".");
}
}
}
derivate(variable) {
switch(this.ope) {
case '-':
case '+':
return new Operation(this.leftHand.derivate(variable), this.ope, this.rightHand.derivate(variable));
case '*':
return new Operation(
new Operation(this.leftHand, '*', this.rightHand.derivate(variable)),
'+',
new Operation(this.leftHand.derivate(variable), '*', this.rightHand),
);
case '/':
return new Operation(
new Operation(
new Operation(this.leftHand, '*', this.rightHand.derivate(variable)),
'-',
new Operation(this.leftHand.derivate(variable), '*', this.rightHand),
),
'/',
new Operation(this.rightHand, '^', new NumberElement(2))
);
case '^':
case '%':
return new FunctionElement("derivate", this.toEditableString());
default:
throw new EvalError("Unknown operator " + ope + ".");
}
}
integrate(variable) {
switch(this.ope) {
case '-':
case '+':
return new Operation(this.leftHand.integrate(variable), this.ope, this.rightHand.integrate(variable));
case '*':
return new Operation(
new Operation(this.leftHand.derivate(variable), '*', this.rightHand),
'+',
new Operation(this.leftHand, '*', this.rightHand.derivate(variable))
);
case '/':
return new Operation(
new Operation(this.leftHand.derivate(variable), '*', this.rightHand),
'+',
new Operation(this.leftHand, '*', this.rightHand.derivate(variable))
);
case '^':
case '%':
return new FunctionElement("integrate", this.toEditableString());
default:
throw new EvalError("Unknown operator " + ope + ".");
}
}
toEditableString() {
let leftString = this.leftHand.toEditableString();
let rightString = this.rightHand.toEditableString();
if(this.leftHand.type == ASEType.OPERATION && OPERATION_PRIORITY[this.ope] > OPERATION_PRIORITY[this.leftHand.ope])
leftString = "(" + leftString + ")"
if(this.rightHand.type == ASEType.OPERATION && OPERATION_PRIORITY[this.ope] > OPERATION_PRIORITY[this.rightHand.ope])
rightString = "(" + rightString + ")"
return leftString + " " + this.ope + " " + rightString;
}
toLatex() {
switch(this.ope) {
case '-':
case '+':
return this.leftHand.toLatex() + this.ope + this.rightHand.toLatex();
case '*':
return this.leftHand.toLatex() + " \\times " + this.rightHand.toLatex();
case '%':
return this.leftHand.toLatex() + " \\mathrm{mod} " + this.rightHand.toLatex();
case '/':
return "\\frac{" + this.leftHand.toLatex() + "}{" + this.rightHand.toLatex() + "}"
case '^':
return this.leftHand.toLatex() + "^{" + this.rightHand.toLatex() + "}";
default:
throw new EvalError("Unknown operator " + ope + ".");
}
return this.leftHand.toLatex() + ope + this.rightHand.toLatex();
}
isConstant() {
return this.leftHand.isConstant() && this.rightHand.isConstant();
}
}
function simplifyFraction(num,den) {
// More than gcd because it allows decimals fractions.
let mult = 1;
if(num%1 != 0)
mult = Math.max(mult,Math.pow(10,num.toString().split('.')[1].length))
else if(den%1 != 0)
mult = Math.max(mult,Math.pow(10,den.toString().split('.')[1].length))
let a = Math.abs(num*mult);
let b = Math.abs(den*mult);
let gcd = 0
if (b > a) {let temp = a; a = b; b = temp;}
while (gcd == 0) {
if (b == 0) gcd = a;
a %= b;
if (a == 0) gcd = b;
b %= a;
}
return [num*mult/gcd, den*mult/gcd]
}
class Negation extends AbstractSyntaxElement {
type = ASEType.NEGATION;
constructor(variableName) {
this.varName = variableName;
}
execute(variables) {
if(variables.includes(this.varName)) {
return variables[this.varName];
} else {
throw new EvalError("Unknown variable " + this.varName + ".");
}
}
derivate(variable) {
if(variable == this.varName)
return new NumberElement(1);
return this;
}
integrate(variable) {
if(variable == this.varName)
// <var>^2/2
return new Operation(new Operation(this, '^', new NumberElement(2)), '/', new NumberElement(2));
return this;
}
toEditableString() {
return this.varName;
}
toLatex() {
return this.varName;
}
isConstant() {
return false;
}
}
class Negation extends AbstractSyntaxElement {
type = ASEType.NEGATION;
constructor(expression) {
this.expression = expression;
}
execute(variables) {
if(variables.includes(this.arrayName)) {
let index = this.astIndex.execute(variables)
if(index % 1 != 0 || index < 0) { // Float index.
throw new EvalError("Non-integer array index " + index + " used as array index for " + this.varName + ".");
} else if(variables[this.arrayName].length <= index) {
throw new EvalError("Out-of-range index " + index + " used as array index for " + this.varName + ".");
} else {
return variables[this.arrayName][index];
}
} else {
throw new EvalError("Unknown variable " + this.varName + ".");
}
toLatex() {
return this.varName;
}
}
simplify() {
return new Negation(this.expression.simplify());
}
derivate(variable) {
return new Negation(this.expression.derivate(variable));
}
integrate(variable) {
return new Negation(this.expression.integrate(variable));
}
toLatex() {
return '-' + this.expression.toLatex();
}
isConstant() {
return this.expression.isConstant();
}
}

View file

@ -1,47 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
import "ast.js" as AST
import "tokenizer.js" as TK
class ExpressionBuilder {
constructor(tokenizer) {
this.tokenizer = tokenizer;
}
parseExpression(delimitors = '') {
// Parse a sequence of operations, and orders them based on OPERATION_PRIORITY.
let elements = []
let operators = []
let firstToken = this.tokenizer.peek();
if(firstToken.type == TK.TokenType.OPERATOR) // First operations.
if(firstToken.value == "-") {
// TODO: Set initial argument.
this.tokenizer.skip(TK.TokenType.OPERATOR)
} else
tokenizer.input.raise(`Invalid operator ${firstToken.value} at begining of statement.`)
else {
}
}
parseOperation()`
}

View file

@ -1,88 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
const CONSTANTS = {
"π": Math.PI,
"pi": Math.PI,
"inf": Infinity,
"infinity": Infinity,
"∞": Infinity,
"e": Infinity
};
const CONSTANTS_LIST = Object.keys(CONSTANTS);
const FUNCTIONS = {
"abs": Math.abs,
"acos": Math.acos,
"acosh": Math.acosh,
"asin": Math.asin,
"asinh": Math.asinh,
"atan": Math.atan,
"atan2": Math.atan2,
"atanh": Math.atanh,
"cbrt": Math.cbrt,
"ceil": Math.ceil,
"clz32": Math.clz32,
"cos": Math.cos,
"cosh": Math.cosh,
"exp": Math.exp,
"expm1": Math.expm1,
"floor": Math.floor,
"fround": Math.fround,
"hypot": Math.hypot,
"imul": Math.imul,
"log": Math.log,
"log10": Math.log10,
"log1p": Math.log1p,
"log2": Math.log2,
"max": Math.max,
"min": Math.min,
"pow": Math.log2,
"random": Math.random,
"round": Math.round,
"sign": Math.sign,
"sin": Math.sin,
"sinh": Math.sinh,
"sqrt": Math.sqrt,
"tan": Math.tan,
"tanh": Math.tanh,
"trunc": Math.trunc,
}
const FUNCTIONS_LIST = Object.keys(FUNCTIONS);
// TODO: Complete
const DERIVATIVES = {
"abs": "abs(<1>)/<1>",
"acos": "-derivate(<1>)/sqrt(1-(<1>)^2)",
"acosh": "derivate(<1>)/sqrt((<1>)^2-1)",
"asin": "derivate(<1>)/sqrt(1-(<1>)^2)",
"asinh": "derivate(<1>)/sqrt((<1>)^2+1)",
"atan": "derivate(<1>)/(1+(<1>)^2)",
"atan2": "",
}
const INTEGRALS = {
"abs": "integrate(<1>)*sign(<1>)",
"acos": "",
"acosh": "",
"asin": "",
"asinh": "",
"atan": "",
"atan2": "",
}

View file

@ -1,141 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
.import "reference.js" as Reference
const WHITESPACES = " \t\n\r"
const STRING_LIMITORS = '"\'`';
const OPERATORS = "+-*/^%";
const PUNCTUTATION = "()[]{},";
const NUMBER_CHARS = "0123456789."
const IDENTIFIER_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789_₀₁₂₃₄₅₆₇₈₉αβγδεζηθκλμξρςστφχψωₐₑₒₓₔₕₖₗₘₙₚₛₜ"
enum TokenType {
// Expression type
VARIABLE,
CONSTANT,
FUNCTION,
OPERATOR,
PUNCT,
NUMBER,
STRING
}
class Token {
constructor(type, value) {
this.type = type;
this.value = value;
}
}
class ExpressionTokenizer {
constructor(input) {
this.input = input;
this.currentToken = null;
}
skipWhitespaces() {
while(!this.input.atEnd() && WHITESPACES.includes(this.input.peek()))
this.input.next();
}
readString() {
let delimitation = this.input.peek();
if(STRING_LIMITORS.includes(delimitation)) {
this.input.skip(delimitation)
let included = "";
let justEscaped = false;
while(!this.input.atEnd() && (!STRING_LIMITORS.includes(this.input.peek()) || justEscaped)) {
justEscaped = this.input.peek() == "\\"
if(!justEscaped)
included += this.input.next();
}
this.input.skip(delimitation)
return new Token(TokenType.STRING, included);
} else {
this.input.raise("Unexpected " + delimitation + ". Expected string delimitator")
}
}
readNumber() {
let included = "";
let hasDot = false;
while(!this.input.atEnd() && NUMBER_CHARS.includes(this.input.peek())) {
if(this.input.peek() == ".") {
if(hasDot) this.input.raise("Unexpected '.'. Expected digit")
hasDot = true;
}
included += this.input.next();
}
}
readIdentifier() {
let identifier = "";
let hasDot = false;
while(!this.input.atEnd() && IDENTIFIER_CHARS.includes(this.input.peek())) {
identifier += this.input.next();
}
if(Reference.CONSTANTS_LIST.includes(identifier.toLowerCase())) {
return new Token(TokenType.CONSTANT, identifier.toLowerCase())
} else if(Reference.FUNCTIONS_LIST.includes(identifier.toLowerCase())) {
return new Token(TokenType.FUNCTION, identifier.toLowerCase())
} else {
return new Token(TokenType.VARIABLE, identifier)
}
}
readNextToken() {
this.skipWhitespaces()
if(input.atEnd()) return null;
let c = input.peek();
if(STRING_LIMITORS.includes(c)) return this.readString();
if(NUMBER_CHARS.includes(c)) return this.readNumber();
if(IDENTIFIER_CHARS.includes(c)) return this.readIdentifier();
if(Reference.CONSTANTS_LIST.includes(c)) return new Token(TokenType.CONSTANT, c);
if(OPERATORS.includes(c)) return new Token(TokenType.OPERATOR, c);
if(PUNCTUTATION.includes(c)) return new Token(TokenType.PUNCT, c);
this.input.throw("Unknown token character " + c)
}
peek() {
if(this.currentToken == null) this.currentToken = this.readNextToken();
return this.currentToken;
}
next() {
let tmp;
if(this.currentToken == null)
tmp = this.readNextToken();
else
tmp = this.currentToken;
this.currentToken = null;
return tmp;
}
atEnd() {
return this.peek() == null;
}
skip(type) {
Token next = Next();
if(next.type != type)
input.raise("Unexpected token " + next.type.oLowerCase() + ' "' + next.value + '". Expected ' + type.toLowerCase());
}
}

View file

@ -1,349 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
.pragma library
var 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": "ᶻ"
}
var 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
function textsup(text) {
var ret = ""
text = text.toString()
for (var i = 0; i < text.length; i++) {
if(Object.keys(powerpos).indexOf(text[i]) >= 0) {
ret += powerpos[text[i]]
} else {
ret += text[i]
}
}
return ret
}
// Put a text in sub position
function textsub(text) {
var ret = ""
text = text.toString()
for (var i = 0; i < text.length; i++) {
if(Object.keys(indicepos).indexOf(text[i]) >= 0) {
ret += indicepos[text[i]]
} else {
ret += text[i]
}
}
return ret
}
function simplifyExpression(str) {
var replacements = [
// Operations not done by parser.
[// Decomposition way 2
/(^.?|[+-] |\()([-.\d\w]+) ([*/]) \((([-.\d\w] [*/] )?[-\d\w.]+) ([+\-]) (([-.\d\w] [*/] )?[\d\w.+]+)\)(.?$| [+-]|\))/g,
"$1$2 $3 $4 $6 $2 $3 $7$9"
],
[ // Decomposition way 2
/(^.?|[+-] |\()\((([-.\d\w] [*/] )?[-\d\w.]+) ([+\-]) (([-.\d\w] [*/] )?[\d\w.+]+)\) ([*/]) ([-.\d\w]+)(.?$| [+-]|\))/g,
"$1$2 $7 $8 $4 $5 $7 $8$9"
],
[ // Factorisation of π elements.
/(([-\d\w.]+ [*/] )*)(pi|π)(( [/*] [-\d\w.]+)*) ([+-]) (([-\d\w.]+ [*/] )*)(pi|π)(( [/*] [-\d\w.]+)*)?/g,
function(match, m1, n1, pi1, m2, ope2, n2, opeM, m3, n3, pi2, m4, ope4, n4) {
// g1, g2, g3 , g4, g5, g6, g7, g8, g9, g10, g11,g12 , g13
// We don't care about mx & pix, ope2 & ope4 are either / or * for n2 & n4.
// 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)
//var [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)
var [ope2, ope4] = [ope2, ope4].map(ope => ope == '/' ? '/' : '*')
var coeff1 = n1*n2
var coeff2 = n3*n4
var 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}`}
],
[ // Removing parenthesis when content is only multiplied.
/(^.?|[*\/] |\()\(([^)(+-]+)\)(.?$| [*\/+-]|\))/g,
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}`}
],
[// Simplification additions/substractions.
/(^.?|[^*\/] |\()([-.\d]+) (\+|\-) (\([^)(]+\)|[^)(]+) (\+|\-) ([-.\d]+)(.?$| [^*\/]|\))/g,
function(match, b4, n1, op1, middle, op2, n2, after) {
var total
if(op2 == '+') {
total = parseFloat(n1) + parseFloat(n2)
} else {
total = parseFloat(n1) - parseFloat(n2)
}
return `${b4}${total} ${op1} ${middle}${after}`
}
],
[// Simplification multiplications/divisions.
/([-.\d]+) (\*|\/) (\([^)(]+\)|[^)(+-]+) (\*|\/) ([-.\d]+)/g,
function(match, n1, op1, middle, op2, n2) {
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 == '*') {
return `${parseFloat(n1) * parseFloat(n2)} ${op1} ${middle}`
} else {
return `${parseFloat(n1) / parseFloat(n2)} ${op1} ${middle}`
}
}
}
],
[// Starting & ending parenthesis if not needed.
/^\s*\((.*)\)\s*$/g,
function(match, middle) {
var str = middle
// Replace all groups
while(/\([^)(]+\)/g.test(str))
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('(')) {
return middle
} else {
return `(${middle})`
}
}
],
// Simple simplifications
[/(\s|^|\()0(\.0+)? \* (\([^)(]+\))/g, '$10'],
[/(\s|^|\()0(\.0+)? \* ([^)(+-]+)/g, '$10'],
[/(\([^)(]\)) \* 0(\.0+)?(\s|$|\))/g, '0$3'],
[/([^)(+-]) \* 0(\.0+)?(\s|$|\))/g, '0$3'],
[/(\s|^|\()1(\.0+)? (\*|\/) /g, '$1'],
[/(\s|^|\()0(\.0+)? (\+|\-) /g, '$1'],
[/ (\*|\/) 1(\.0+)?(\s|$|\))/g, '$3'],
[/ (\+|\-) 0(\.0+)?(\s|$|\))/g, '$3'],
[/(^| |\() /g, '$1'],
[/ ($|\))/g, '$1'],
]
// Replacements
var found
do {
found = false
for(var replacement of replacements)
while(replacement[0].test(str)) {
found = true
str = str.replace(replacement[0], replacement[1])
}
} while(found)
return str
}
function makeExpressionReadable(str) {
var replacements = [
// variables
[/pi/g, 'π'],
[/Infinity/g, '∞'],
[/inf/g, '∞'],
// Other
[/ \* /g, '×'],
[/ \^ /g, '^'],
[/\^\(([^\^]+)\)/g, function(match, p1) { return textsup(p1) }],
[/\^([^ "]+)/g, function(match, p1) { return textsup(p1) }],
[/_\(([^_]+)\)/g, function(match, p1) { return textsub(p1) }],
[/_([^ "]+)/g, function(match, p1) { return textsub(p1) }],
[/\[([^\[\]]+)\]/g, function(match, p1) { return textsub(p1) }],
[/(\d|\))×/g, '$1'],
//[/×(\d|\()/g, '$1'],
[/\(([^)(+.\/-]+)\)/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}`
} else {
return `${textsup(b)}${textsub(a)} ${body} d${by}`
}
}],
[/derivative\(?("|')(.+)("|'), ?("|')(.+)("|'), ?(.+)\)?/g, function(match, p1, body, p2, p3, by, p4, x) {
return `d(${body.replace(new RegExp(by, 'g'), 'x')})/dx`
}]
]
str = simplifyExpression(str)
// Replacements
for(var replacement of replacements)
while(replacement[0].test(str))
str = str.replace(replacement[0], replacement[1])
return str
}
function parseName(str, removeUnallowed = true) {
var 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(var replacement of replacements)
str = str.replace(replacement[0], replacement[1])
return str
}
String.prototype.toLatinUppercase = function() {
return this.replace(/[a-z]/g, function(match){return match.toUpperCase()})
}
function camelCase2readable(label) {
var parsed = parseName(label, false)
return parsed.charAt(0).toLatinUppercase() + parsed.slice(1).replace(/([A-Z])/g," $1")
}
function getRandomColor() {
var clrs = '0123456789ABCDEF';
var color = '#';
for(var i = 0; i < 6; i++) {
color += clrs[Math.floor(Math.random() * (16-5*(i%2==0)))];
}
return color;
}

View file

@ -1,4 +0,0 @@
module eu.ad5001.LogarithmPlotter
Settings 1.0 Settings.qml
Alert 1.0 Alert.qml

View file

@ -1,161 +0,0 @@
"""
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
"""
from PySide2.QtWidgets import QMessageBox, QApplication
from PySide2.QtCore import QRunnable, QThreadPool, QThread, QObject, Signal, Slot, QCoreApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtGui import QImage
from PySide2 import __version__ as PySide2_version
from os import chdir, path
from json import loads
from sys import version as sys_version
from urllib.request import urlopen
from urllib.error import HTTPError, URLError
from LogarithmPlotter import __VERSION__
from LogarithmPlotter.util import config
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/")
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.gotChangelog.emit(msg_text)
class Helper(QObject):
changelogFetched = Signal(str)
gotChangelog = Signal(str)
def __init__(self, cwd: str, tmpfile: str):
QObject.__init__(self)
self.cwd = cwd
self.tmpfile = tmpfile
self.gotChangelog.connect(self.fetched)
def fetched(self, changelog: str):
self.changelogFetched.emit(changelog)
@Slot(str, str)
def write(self, filename, filedata):
chdir(self.cwd)
if path.exists(path.dirname(path.realpath(filename))):
if filename.split(".")[-1] == "lpf":
# Add header to file
filedata = "LPFv1" + filedata
f = open(path.realpath(filename), 'w', -1, 'utf8')
f.write(filedata)
f.close()
chdir(path.dirname(path.realpath(__file__)))
@Slot(str, result=str)
def load(self, filename):
chdir(self.cwd)
data = '{}'
if path.exists(path.realpath(filename)):
f = open(path.realpath(filename), 'r', -1, 'utf8')
data = f.read()
f.close()
try:
if data[:5] == "LPFv1":
# V1 version of the file
data = data[5:]
elif data[0] == "{" and "type" in loads(data) and loads(data)["type"] == "logplotv1":
pass
elif data[:3] == "LPF":
# More recent version of LogarithmPlotter file, but incompatible with the current format
raise Exception(QCoreApplication.translate("This file was created by a more recent version of LogarithmPlotter and cannot be backloaded in LogarithmPlotter v{}.\nPlease update LogarithmPlotter to open this file.".format(__VERSION__)))
else:
raise Exception("Invalid LogarithmPlotter file.")
except Exception as e: # If file can't be loaded
QMessageBox.warning(None, 'LogarithmPlotter', QCoreApplication.translate('main','Could not open file "{}":\n{}').format(filename, e), QMessageBox.Ok) # Cannot parse file
else:
QMessageBox.warning(None, 'LogarithmPlotter', QCoreApplication.translate('main','Could not open file: "{}"\nFile does not exist.').format(filename), QMessageBox.Ok) # Cannot parse file
try:
chdir(path.dirname(path.realpath(__file__)))
except NotADirectoryError as e:
# Triggered on bundled versions of MacOS when it shouldn't. Prevents opening files.
# See more at https://git.ad5001.eu/Ad5001/LogarithmPlotter/issues/1
pass
return data
@Slot(result=str)
def gettmpfile(self):
return self.tmpfile
@Slot()
def copyImageToClipboard(self):
clipboard = QApplication.clipboard()
clipboard.setImage(QImage(self.tmpfile))
@Slot(result=str)
def getVersion(self):
return __VERSION__
@Slot(str, result=str)
def getSetting(self, namespace):
return config.getSetting(namespace)
@Slot(str, result=bool)
def getSettingBool(self, namespace):
return config.getSetting(namespace)
@Slot(str, str)
def setSetting(self, namespace, value):
return config.setSetting(namespace, value)
@Slot(str, bool)
def setSettingBool(self, namespace, value):
return config.setSetting(namespace, value)
@Slot(str)
def setLanguage(self, new_lang):
config.setSetting("language", new_lang)
@Slot(result=str)
def getDebugInfos(self):
"""
Returns the version info about Qt, PySide2 & Python
"""
return QCoreApplication.translate('main',"Built with PySide2 (Qt) v{} and python v{}").format(PySide2_version, sys_version.split("\n")[0])
@Slot()
def fetchChangelog(self):
changelog_cache_path = path.join(path.dirname(path.realpath(__file__)), "CHANGELOG.md")
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()
else:
# Fetch it from the internet.
runnable = ChangelogFetcher(self)
QThreadPool.globalInstance().start(runnable)

View file

@ -1,57 +0,0 @@
"""
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
"""
from PySide2.QtCore import QObject, Slot
from PySide2.QtGui import QImage, QColor
from PySide2.QtWidgets import QApplication
from os import path
from sympy import preview
from tempfile import TemporaryDirectory
class Latex(QObject):
def __init__(self, tempdir: str, palette):
QObject.__init__(self)
self.tempdir = tempdir
self.palette = palette
fg = self.palette.windowText().color().convertTo(QColor.Rgb)
@Slot(str, float, QColor, result=str)
def render(self, latexstring, font_size, color = True):
exprpath = path.join(self.tempdir.name, f'{hash(latexstring)}_{font_size}_{color.rgb()}.png')
print("Rendering", latexstring, exprpath)
if not path.exists(exprpath):
fg = color.convertTo(QColor.Rgb)
fg = f'rgb {fg.redF()} {fg.greenF()} {fg.blueF()}'
preview('$$' + latexstring + '$$', viewer='file', filename=exprpath, dvioptions=[
"-T", "tight",
"-z", "0",
"--truecolor",
f"-D {font_size * 72.27 / 10}", # See https://linux.die.net/man/1/dvipng#-D for convertion
"-bg", "Transparent",
"-fg", fg],
euler=True)
img = QImage(exprpath);
# 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'{exprpath},{img.width()},{img.height()}'
@Slot(str)
def copyLatexImageToClipboard(self, latexstring):
global tempfile
clipboard = QApplication.clipboard()
clipboard.setImage(self.render(latexstring))

103
README.md
View file

@ -1,4 +1,5 @@
# ![icon](https://git.ad5001.eu/Ad5001/LogarithmPlotter/raw/branch/master/logplotter.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/)
[![On flathub](https://img.shields.io/flathub/v/eu.ad5001.LogarithmPlotter?label=on%20flathub&logo=Flathub&logoColor=white&color=4A86CF)](https://flathub.org/apps/details/eu.ad5001.LogarithmPlotter)
@ -7,56 +8,79 @@
2D plotter software to make Bode plots, sequences and distribution functions.
## Screenshots
![Magnitude example](https://apps.ad5001.eu/img/full/logarithmplotter.png)
![Phase example](https://apps.ad5001.eu/img/en/logarithmplotter/phase.png)
![Object settings](https://apps.ad5001.eu/img/en/logarithmplotter/object-settings.webp)
You can find more screenshots on the [app website](https://apps.ad5001.eu/logarithmplotter/).
You can find more screenshots on the [app's website](https://apps.ad5001.eu/logarithmplotter/).
## Run
## Build & Run
You can simply run LogarithmPlotter using `python3 run.py`.
First, you'll need to install all the required dependencies:
In order to test translations, you can use the `--lang=<lang code>` command line option to force the detected locale of LogarithmPlotter.
- [Python 3](https://python.org) with [poetry](https://python-poetry.org/), setup a virtual environment, go to the `runtime-pyside6` directory, and call
`poetry install`.
- [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
`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`.
In order to test translations, you can use the `--lang=<lang code>` commandline option to force the locale.
## Install
### Generate installers:
All scripts noted here can be found in the `scripts` directory.
You can generate installers from LogarithmPlotter after installing all the dependencies:
For all builds, you need [Python 3](https://python.org) with [PySide2](https://pypi.org/project/PySide2/) installable with `pip install PySide2`.
- Windows installer:
- You need `pyinstaller`. You can install it using `pip install pyinstaller`.
- Run the `build-windows.bat` script (or `build-wine.sh` if you're cross-compiling with wine on Linux) to build an exe for LogarithmPlotter.
- You also need [NSIS](https://nsis.sourceforge.io/Main_Page) (Linux users can install the [nsis](https://pkgs.org/download/nsis) package).
- Run the `package-windows.bat` script (or `package-wine.sh`if you're cross-compiling on Linux). You will find a logarithmplotter-setup.exe installer in the dist/accountfree/ folder.
- MacOS Archive creator installer:
- You need `pyinstaller`. You can install it using `pip install pyinstaller`.
- Run the `build-macosx.sh` script to build an .app for LogarithmPlotter which can be found in the dist directory.
- Run the `package-macosx.sh` script. You will find a LogarithmPlotter-v0.1-dev-setup.dmg installer in the dist/ folder.
You can generate installers for LogarithmPlotter after installing all the dependencies.
- Windows installer (crosscompiling from Linux):
- Run `build-wine.sh` (requires wine) to build an exe for LogarithmPlotter in build/runtime-pyside6/dist.
- You also need [NSIS](https://nsis.sourceforge.io/Main_Page) (the [nsis](https://pkgs.org/download/nsis) package is available on linux).
- Run the `package-wine.sh` script. You will find a logarithmplotter-setup.exe installer in the build/runtime-pyside6/dist/logarithmplotter/ folder.
- MacOS Archive creator installer:
- Run the `build-macosx.sh` script to build an .app for LogarithmPlotter which can be found in the build/runtime-pyside6/dist directory.
- Run the `package-macosx.sh` script. You will find a LogarithmPlotter-v&lt;version&gt;-setup.dmg installer in the
build/runtime-pyside6/build/pysdist/ folder.
- Linux packages:
- To build a DEB, you need DPKG and stdeb. You can install the later by using `pip install stdeb`.
- To build and install the flatpak, you need [flatpak-builder](https://docs.flatpak.org/en/latest/flatpak-builder.html) installed.
- To build the snap, you need [snapcraft](https://snapcraft.io) installed.
- Run `package-linux.sh`.
### Linux
Run `bash linux/install_local.sh`
- Run `package-deb.sh`. It will create an DSC and a DEB in build/runtime-pyside6/deb_dist/
- Run `scripts/build.sh` followed by `snapcraft`. It .snap file in the root directory.
- See [the flatpak repo](https://github.com/Ad5001/eu.ad5001.LogarithmPlotter) for instrutions on how to build the flatpak.
## Contribute
There are several ways to contribute to LogarithmPlotter.
- You can help to translate [the project on Hosted Weblate](https://hosted.weblate.org/engage/logarithmplotter/):
[![Translation status](https://hosted.weblate.org/widgets/logarithmplotter/-/logarithmplotter/multi-auto.svg)](https://hosted.weblate.org/engage/logarithmplotter/)
There are several ways you can contribute to LogarithmPlotter.
- You can help the development of LogarithmPlotter. In order to get started, take a look at the [wiki](https://git.ad5001.eu/Ad5001/LogarithmPlotter/wiki/_pages).
- You can help to translate [the project on Hosted Weblate](https://hosted.weblate.org/engage/logarithmplotter/):
[![Translation status](https://hosted.weblate.org/widgets/logarithmplotter/-/logarithmplotter/multi-auto.svg)](https://hosted.weblate.org/engage/logarithmplotter/)
- You can help the development of LogarithmPlotter. In order to get started, take a look at
the [wiki](https://git.ad5001.eu/Ad5001/LogarithmPlotter/wiki/_pages).
## Tests
To run LogarithmPlotter's tests, follow these steps:
- Python
- Install python3 and [poetry](https://python-poetry.org/)
- 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
LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
Copyright (C) 2022 Ad5001 <mail@ad5001.eu>
LogarithmPlotter - 2D plotter software to make Bode plots, sequences and repartition functions.
Copyright (C) 2021-2024 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
@ -71,6 +95,19 @@ There are several ways to contribute to LogarithmPlotter.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
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:
- 🇳🇴 Norwegian translation by [Allan Nordhøy](https://github.com/comradekingu)
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)
- 🇪🇸 Spanish translation by gallegonovato and [IngrownMink4](https://github.com/IngrownMink4)
### Libraries used
LogarithmPlotter includes [expr-eval](https://github.com/silentmatt/expr-eval) a port
of [ndef.parser](https://web.archive.org/web/20111023001618/http://www.undefined.ch/mparser/index.html) by Raphael Graf
&lt;r@undefined.ch&gt;, ported to javascript by Matthew Crumley
&lt;email@matthewcrumley.com&gt; (http://silentmatt.com/), and then to QMLJS by Ad5001.
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).

1897
assets/i18n/lp_de.ts Normal file

File diff suppressed because it is too large Load diff

1897
assets/i18n/lp_en.ts Normal file

File diff suppressed because it is too large Load diff

1889
assets/i18n/lp_es.ts Normal file

File diff suppressed because it is too large Load diff

1900
assets/i18n/lp_fr.ts Normal file

File diff suppressed because it is too large Load diff

1897
assets/i18n/lp_hu.ts Normal file

File diff suppressed because it is too large Load diff

1800
assets/i18n/lp_nb_NO.ts Normal file

File diff suppressed because it is too large Load diff

1563
assets/i18n/lp_template.ts Normal file

File diff suppressed because it is too large Load diff

2
assets/i18n/release.sh Executable file
View file

@ -0,0 +1,2 @@
#!/bin/bash
pyside6-lrelease *.ts

65
assets/i18n/update.sh Executable file
View file

@ -0,0 +1,65 @@
#!/bin/bash
#
# This file automatically renames .mjs files to js, and (tries) to fix most common ECMAScript
# specificities so that lupdate doesn't cry out in pain.
# See also: https://bugreports.qt.io/browse/QTBUG-123819
#
escape() {
str="$1"
str="${str//\//\\/}" # Escape slashes
str="${str//\*/\\*}" # Escape asterixes
echo "$str"
}
replace() {
file="$1"
from="$(escape "$2")"
to="$(escape "$3")"
sed -i "s/${from}/${to}/g" "$file"
}
rm ../qml/eu/ad5001/LogarithmPlotter/js/index.mjs # Remove index which should not be scanned
files=$(find ../../common/src -name '*.mjs')
for file in $files; do
echo "Moving '$file' to '${file%.*}.js'..."
mv "$file" "${file%.*}.js"
# Replacements to make it valid js
replace "${file%.*}.js" "^import" "/*import"
replace "${file%.*}.js" "^export *" "/*export *"
replace "${file%.*}.js" '.mjs"$' '.mjs"*/'
replace "${file%.*}.js" "^export default" "/*export default*/"
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 "----------------------------"
echo "| Updating translations... |"
echo "----------------------------"
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..."
for file in $files; do
replace "$lp" "${file%.*}.js" "$file"
done
done
for file in $files; do
echo "Moving '${file%.*}.js' to '$file'..."
mv "${file%.*}.js" "$file"
# Resetting changes
replace "$file" "/*await */" "await"
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" "// #" " #"
replace "$file" "/*this.#*/" "this.#"
done

View file

Before

Width:  |  Height:  |  Size: 198 B

After

Width:  |  Height:  |  Size: 198 B

View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

View file

Before

Width:  |  Height:  |  Size: 289 B

After

Width:  |  Height:  |  Size: 289 B

View file

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

Before

Width:  |  Height:  |  Size: 620 B

After

Width:  |  Height:  |  Size: 620 B

View file

Before

Width:  |  Height:  |  Size: 261 B

After

Width:  |  Height:  |  Size: 261 B

View file

@ -0,0 +1 @@
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd"><path d="M14 0v10l2-1.518 2 1.518v-10h4v24h-17c-1.657 0-3-1.343-3-3v-18c0-1.657 1.343-3 3-3h9zm6 20h-14.505c-1.375 0-1.375 2 0 2h14.505v-2z"/></svg>

After

Width:  |  Height:  |  Size: 251 B

View file

@ -0,0 +1 @@
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd"><path d="M12 0l-2.138 2.63-3.068-1.441-.787 3.297-3.389.032.722 3.312-3.039 1.5 2.088 2.671-2.088 2.67 3.039 1.499-.722 3.312 3.389.033.787 3.296 3.068-1.441 2.138 2.63 2.139-2.63 3.068 1.441.786-3.296 3.39-.033-.722-3.312 3.038-1.499-2.087-2.67 2.087-2.671-3.038-1.5.722-3.312-3.39-.032-.786-3.297-3.068 1.441-2.139-2.63zm0 15.5c.69 0 1.25.56 1.25 1.25s-.56 1.25-1.25 1.25-1.25-.56-1.25-1.25.56-1.25 1.25-1.25zm1-1.038v-7.462h-2v7.462h2z"/></svg>

After

Width:  |  Height:  |  Size: 550 B

View file

Before

Width:  |  Height:  |  Size: 273 B

After

Width:  |  Height:  |  Size: 273 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M24 13.616v-3.232l-2.869-1.02c-.198-.687-.472-1.342-.811-1.955l1.308-2.751-2.285-2.285-2.751 1.307c-.613-.339-1.269-.613-1.955-.811l-1.021-2.869h-3.232l-1.021 2.869c-.686.198-1.342.471-1.955.811l-2.751-1.308-2.285 2.285 1.308 2.752c-.339.613-.614 1.268-.811 1.955l-2.869 1.02v3.232l2.869 1.02c.197.687.472 1.342.811 1.955l-1.308 2.751 2.285 2.286 2.751-1.308c.613.339 1.269.613 1.955.811l1.021 2.869h3.232l1.021-2.869c.687-.198 1.342-.472 1.955-.811l2.751 1.308 2.285-2.286-1.308-2.751c.339-.613.613-1.268.811-1.955l2.869-1.02zm-12 2.384c-2.209 0-4-1.791-4-4s1.791-4 4-4 4 1.791 4 4-1.791 4-4 4z"/></svg>

After

Width:  |  Height:  |  Size: 696 B

View file

Before

Width:  |  Height:  |  Size: 270 B

After

Width:  |  Height:  |  Size: 270 B

View file

Before

Width:  |  Height:  |  Size: 370 B

After

Width:  |  Height:  |  Size: 370 B

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1 @@
../common/close.svg

View file

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Some files were not shown because too many files have changed in this diff Show more