Compare commits

...

295 commits

Author SHA1 Message Date
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
Ad5001 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
Ad5001 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
Ad5001 997a1645a0
Removing Settings submenu.
All checks were successful
continuous-integration/drone/push Build is passing
2024-04-02 22:50:43 +02:00
Ad5001 fefb0f92b0
New, rewamped Greet Screen. 2024-04-02 22:49:56 +02:00
Ad5001 665906ecb3
New preferences panel. 2024-04-02 22:11:54 +02:00
Ad5001 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
Ad5001 5f8c756dc7
Enforcing type safety at import. 2024-04-01 23:48:57 +02:00
Ad5001 8e75f13e9a
Removing vanished translations.
All checks were successful
continuous-integration/drone/push Build is passing
2024-03-29 17:56:09 +01:00
Ad5001 82e8413e56
Creating IO JS module.
All checks were successful
continuous-integration/drone/push Build is passing
2024-03-29 17:53:10 +01:00
Ad5001 73cba85592
Creating Canvas JS Module.
All checks were successful
continuous-integration/drone/push Build is passing
2024-03-29 01:55:13 +01:00
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 80f1077b35
Updating snapcraft
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-11 23:28:42 +01:00
Ad5001 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
Ad5001 f9b0bb99ce
Updating appstream
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2024-01-11 20:15:25 +01:00
Ad5001 557592708f
Fixing building for debian 2024-01-11 19:56:25 +01:00
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 2d6389bfd5
Updating images for CI 2024-01-11 01:49:29 +01:00
Ad5001 d0851b819f
Updating windows installer
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-11 01:15:43 +01:00
Ad5001 cff994d9d7
Fixing macos building
Some checks failed
continuous-integration/drone/push Build is failing
2024-01-11 00:59:01 +01:00
Ad5001 fde2526c54
Updating copyrights
Some checks failed
continuous-integration/drone/push Build is failing
2024-01-11 00:11:09 +01:00
Ad5001 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
Ad5001 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
Ad5001 874046960f
Changing linux descriptions
Some checks failed
continuous-integration/drone/push Build is failing
2024-01-10 23:32:47 +01:00
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 22106f97b5
Adding new strings
Some checks failed
continuous-integration/drone/push Build is failing
2023-10-10 02:13:17 +02:00
Ad5001 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
Ad5001 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
Ad5001 d991deee7b
Reworking the derivative function, removed assignement in parser.
The new derivative now supports executable elements.
2023-10-10 00:53:35 +02:00
Ad5001 ed4d30573c
Adding usage for functions. 2023-10-10 00:05:19 +02:00
Ad5001 3f1d089a78
Minor modifications, adding usage to derivative. 2023-10-09 23:28:29 +02:00
Ad5001 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
Ad5001 062fde6b16
Updating build script for newest pyinstaller version. 2023-10-09 22:26:50 +02:00
Ad5001 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
Ad5001 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
Ad5001 cf754a7a34
Better handling of constants in simplified expressions. 2023-10-09 18:37:28 +02:00
Ad5001 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
Ad5001 7542d63121
Adding new characters to insert chars popup. 2023-10-09 17:20:32 +02:00
Ad5001 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
Ad5001 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
Ad5001 9879e7fbc9
Fixing changelog 2023-10-08 18:34:09 +02:00
Ad5001 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
Ad5001 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
Ad5001 9f2b08b938
Fixing "Unknown variable ∞." message.
It occured when using a domain with the infinity symbol.
2023-10-08 16:31:01 +02:00
Ad5001 3039aade29
Fixing some issues with infinity in domains. 2023-10-08 16:24:16 +02:00
Ad5001 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
Ad5001 0b5aa36c23
Adding view position changer overlay. 2023-10-07 19:11:19 +02:00
Ad5001 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
Ad5001 e67619771b
Fixing macOS building script. 2023-05-27 11:09:13 +02:00
Ad5001 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
Ad5001 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
Ad5001 273d5539ec
Forgot to update the debian changelog. 2023-05-27 10:11:19 +02:00
Ad5001 5e7dbb8fa6
Adding changelog 2023-05-27 10:07:40 +02:00
Ad5001 1e30bee220
Updating snapcraft building
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-26 20:11:41 +02:00
Ad5001 ebf07dccfa
Disabling interactive thanks dialog.
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-26 18:05:05 +02:00
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 16effe064c
Disabling generation of HDPI latex pngs, as they aren't used in PySide6. 2023-05-24 11:49:45 +02:00
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 35ce1c4824
Adding error handling for function argument errors. 2023-05-24 07:03:12 +02:00
Ad5001 75e70903f1
Fixing coloration in dark theme of autocomplete categories. 2023-05-24 06:47:34 +02:00
Ad5001 016a21ecb4
Adding new translations
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-24 04:18:55 +02:00
Ad5001 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
Ad5001 d1843b455a
Fixing issue with sums & latex variables. 2023-05-24 03:58:13 +02:00
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 fce2a5ba0d
Adding version freeze for changelog
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-23 12:51:47 +02:00
Ad5001 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
Ad5001 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
Ad5001 20c1ed005e
Removing warning
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-22 09:49:20 +02:00
Ad5001 d8534d1e0d
Adding bottom borders to dialogs 2023-05-22 09:31:43 +02:00
Ad5001 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
Ad5001 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
Ad5001 0ac690d0c1
Fixing cursor from expression editor.
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-22 07:22:33 +02:00
Ad5001 37150b5823
Fixing CI image
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-22 06:18:03 +02:00
Ad5001 0539f988e2
Adding new strings
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2023-05-22 06:17:08 +02:00
Ad5001 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
Ad5001 9f20a80228
Merge branch 'qt6' 2023-05-22 05:57:03 +02:00
Ad5001 5ef8cac1c0
Adding color schemes for expressions 2023-05-22 05:56:34 +02:00
Ad5001 7ec80e6682
Custom color schemes! 2023-05-22 05:17:12 +02:00
Ad5001 43d78e17e5
Improving LaTeX rendering DPI. 2023-05-22 04:21:53 +02:00
Ad5001 93308f2bfa
Forgot adding setting icon 2023-05-22 03:41:50 +02:00
Ad5001 508f316bc5
Better pick location settings overlay 2023-05-22 03:41:20 +02:00
Ad5001 424eef6e17
Fixing opening file in settings, updating CI images to PySide6. 2023-05-22 01:50:22 +02:00
Ad5001 f40c242877
Bumping copyright 2023-05-22 00:19:58 +02:00
Ad5001 aecc02c606
Updating to Qt6 2023-05-22 00:15:09 +02:00
Ad5001 78ffc8c645
Changing RegExpValidator to RegularExpressionValidator. 2023-05-21 22:32:49 +02:00
Ad5001 98f26d4919
Removing unclosed tag.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-28 22:02:52 +02:00
Ad5001 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
Ad5001 ba98fc3611
Fixing appstream data.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-28 19:26:00 +02:00
Ad5001 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
Ad5001 fe13351e99
Removing flatpak submodule.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-28 17:38:41 +02:00
Ad5001 225ae67834
Releasing v0.3.0!
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-28 16:41:20 +02:00
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 b0b77834a8
Fixing inability to open and load files due to greet screen fixes. 2022-10-22 14:17:52 +02:00
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 3cd4ad6a20
Object properties for autocompletion!
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-20 16:23:12 +02:00
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 15b87fc15d
Variables & objects (+ their type) in autocompletion. 2022-10-20 01:14:09 +02:00
Ad5001 77ae54fa18
More autocompletion! 2022-10-20 00:37:02 +02:00
Ad5001 5da8dcefe5
First crack at autocompletion. 2022-10-19 23:44:04 +02:00
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 ddb5156396
Fixing mistranslated string.
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-19 02:49:43 +02:00
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 32db56304b
Expression editor!
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-18 23:24:58 +02:00
Ad5001 64d1419452
Fixing bugs in recursive object deletion and dependency. 2022-10-18 22:40:49 +02:00
Ad5001 fcf5ef9539
Fixing a few bugs related to dependency and text. 2022-10-18 22:17:10 +02:00
Ad5001 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
Ad5001 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
Ad5001 29e62fee6e
Trying to fix deb build
Some checks failed
continuous-integration/drone/push Build is failing
2022-10-18 17:49:49 +02:00
Ad5001 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
Ad5001 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
Ad5001 9facc2389c
Attempting to fix blurry icons and Latex renders in the objects tab. 2022-10-18 02:00:56 +02:00
Ad5001 15fd660e0c
Adding support for latex images in the objects tab. 2022-10-18 01:47:49 +02:00
Ad5001 dfdd576296
Componentizing the object's row. 2022-10-18 01:12:24 +02:00
Ad5001 b8d312bb23
Fixing build²
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-18 00:49:15 +02:00
Ad5001 8c6784663e
Fixing build
Some checks failed
continuous-integration/drone/push Build is failing
2022-10-18 00:47:27 +02:00
Ad5001 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
Ad5001 1ba594c4f7
Fixing executing function in expression. 2022-10-17 22:54:02 +02:00
Ad5001 6b535dd8a2
Adding object properties usable in expressions 2022-10-17 22:30:59 +02:00
Ad5001 fad5325501
Better handling of Object names in a separate dictionary. 2022-10-17 20:25:29 +02:00
Ad5001 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
Ad5001 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
Ad5001 20f8d68f13
Starting v0.2.1
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-23 02:17:34 +02:00
Ad5001 a5ce17e7f3
Updating appstream images 2022-04-23 02:14:26 +02:00
Ad5001 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
Ad5001 cb733a556c
Releasing v0.2.0
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-22 17:05:15 +02:00
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 3a2fcb1be1
Adding new translations strings.
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-04-16 19:25:01 +02:00
Ad5001 836e6d8922
Merge branch 'latex-rendering' 2022-04-16 19:18:31 +02:00
Ad5001 eef42655e5
Trying to fix build
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-04-02 18:20:04 +02:00
Ad5001 1f581c46ec
Adding thanks to popup
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-02 18:17:09 +02:00
Ad5001 f77b1ce331
Fixing snapcraft
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-04-02 16:39:21 +02:00
Ad5001 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
Ad5001 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
Ad5001 27759362cb
Toggle for latex setting
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-03-07 20:28:50 +01:00
Ad5001 7120e3a781
Fixing timeout on build.
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-03-07 17:25:30 +01:00
Ad5001 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
Ad5001 2691ba687f
Changed a few serif text to sans serif. 2022-03-07 15:06:40 +01:00
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 6539ca8caa
Fixing linux tests
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-03-07 02:50:50 +01:00
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 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
Ad5001 8251504fbe
Latex markup for sequences and bode phases 2022-03-06 18:31:03 +01:00
Ad5001 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
Ad5001 de0220fecf
Implemented latex for distributions 2022-03-06 01:13:20 +01:00
Ad5001 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
Ad5001 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
Ad5001 ccf3de5783
Fixing typos
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-03-05 21:00:29 +01:00
Ad5001 b5600046e9
Fixing build to add sympy.
Some checks failed
continuous-integration/drone/push Build is failing
2022-03-05 20:58:38 +01:00
Ad5001 1142ca1c00
Starting latex rendering (canvas side).
Some checks failed
continuous-integration/drone/push Build is failing
2022-03-05 20:57:21 +01:00
Ad5001 23cd86a2e3
Starting latex rendering 2022-03-05 18:19:20 +01:00
Ad5001 1c0850a200
Updating description line, changing tempfile to tempdir.
All checks were successful
continuous-integration/drone/push Build is passing
2022-03-05 17:49:35 +01:00
Ad5001 8b01a8f0e8
Componented mathlib.
All checks were successful
continuous-integration/drone/push Build is passing
2022-03-05 17:35:58 +01:00
Ad5001 8f1bc652b4
Addign dependencies for latex.
All checks were successful
continuous-integration/drone/push Build is passing
2022-03-05 16:43:22 +01:00
Ad5001 44e39e5265
Bug fixes and slight file moving
All checks were successful
continuous-integration/drone/push Build is passing
- Gradients are no longer hidden when filtered out
- Fixing #1 - Opening files don't work on compiled versions of LogarithmPlotter on MacOS
- Moving python modules to "util" directory for more clarity
- Moving flatpak metainfo to eu.ad5001.LogarithmPlotter repository.
2022-03-05 16:19:47 +01:00
Ad5001 20c910f884
Starting v0.1.9
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-19 18:42:50 +01:00
Ad5001 86eb454e39
Correcting mistranslating in appstream file. 2022-02-19 18:41:15 +01:00
Ad5001 90abfe63f6
Fixing snapcraft bugs.
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-19 18:02:01 +01:00
Ad5001 d34701b980
Removing hyperlink from changelog for flatpak.
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-19 17:24:29 +01:00
Ad5001 c535d48039
Fixing bug and continuing v0.1.8
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-19 16:35:13 +01:00
Ad5001 5b0add3876
Preparing release for v0.1.8 2022-02-19 16:21:51 +01:00
Ad5001 fcd6b71cb6
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (179 of 179 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2022-02-18 20:33:43 +01:00
Ad5001 df6e3234ea
Translated using Weblate (Spanish)
Currently translated at 8.9% (16 of 179 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/
2022-02-18 20:33:42 +01:00
Ad5001 71ff9aa33b
Translated using Weblate (German)
Currently translated at 100.0% (179 of 179 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2022-02-18 20:33:42 +01:00
Ad5001 080c6cea54
Translated using Weblate (English)
Currently translated at 100.0% (179 of 179 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2022-02-18 20:33:42 +01:00
Ad5001 d7a3fe0f6d
Adding new translatable strings.
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-18 20:22:32 +01:00
Ad5001 867b9fed68
User manual links, adding official website in about.
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-18 16:24:29 +01:00
Ad5001 87104a3d71
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-18 01:32:06 +01:00
Ad5001 a4d8dd92c2
Adding manual generation. 2022-02-18 01:31:51 +01:00
Ad5001 ae62d3d26a
Fixing X Cursors' history and label position. 2022-02-15 18:59:14 +01:00
Ad5001 0c05a62982
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (176 of 176 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2022-02-10 17:55:48 +01:00
Ad5001 6cce189f0a
Translated using Weblate (English)
Currently translated at 100.0% (176 of 176 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2022-02-10 17:55:48 +01:00
Ad5001 9c26195f66
Fixing bug with slight cliping at the bottom of the sidebar. 2022-02-08 14:51:41 +01:00
Ad5001 f229dc014c
Fixing bug with TextInput allowing unallowed characters. 2022-02-08 14:33:08 +01:00
Ad5001 ca51f979b8
FINALLY fixed the bug related to ALT+ shortcuts 2022-02-07 14:19:02 +01:00
Ad5001 f4c6e82c6d
Trying to fix the issue that ALT+ menu shortcuts do not work.
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-07 13:34:23 +01:00
Ad5001 dd7e078525
Fixing flatpak issue with the KDE SDK that makes button have no width on startup. 2022-02-07 13:14:15 +01:00
Ad5001 033f065f92
Starting v0.1.8
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-03 15:48:32 +01:00
Ad5001 f4dfca4171
Shortening changelog 2022-02-03 15:25:42 +01:00
Ad5001 c4893c675c
Forgot to properly tag the other one.
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-03 13:13:56 +01:00
Ad5001 599f144c1c
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-03 13:00:46 +01:00
Ad5001 546317388e
Fixing appstream metadata. 2022-02-03 13:00:35 +01:00
Ad5001 fea238c706
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-03 12:56:39 +01:00
Ad5001 fec6a6b00a
Fixing setup for launchpad for good. 2022-02-03 12:56:18 +01:00
Ad5001 499feace1c
Release v0.1.7
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-03 00:26:23 +01:00
Ad5001 727231c954
Fixing clipping through the search bar in history.
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-02 23:03:46 +01:00
Ad5001 f11792c03a
Translated using Weblate (German)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (176 of 176 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2022-02-01 21:52:37 +01:00
Ad5001 09a7a9b704
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (176 of 176 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2022-02-01 21:46:17 +01:00
Ad5001 b080c3d683
Translated using Weblate (English)
Currently translated at 100.0% (176 of 176 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2022-02-01 21:46:17 +01:00
Ad5001 460e0ab178
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (175 of 175 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2022-02-01 20:40:13 +01:00
Ad5001 7b24a54ca2
Translating history filter placeholder text.
Some checks failed
continuous-integration/drone/push Build is failing
2022-02-01 20:39:55 +01:00
Ad5001 1b5d0725c8
Adding scrollbar to objects list 2022-02-01 17:33:36 +01:00
Ad5001 3f107f1ba4
Filtering on history!
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-01 09:59:31 +01:00
Ad5001 600027a707
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter 2022-02-01 09:42:13 +01:00
Ad5001 e23a8755e9
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (175 of 175 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2022-02-01 09:42:05 +01:00
Ad5001 32c6b3e342
Translated using Weblate (English)
Currently translated at 100.0% (175 of 175 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2022-02-01 09:42:05 +01:00
Ad5001 b51fe6ae84
Removing history items border for AESTHETICS. 2022-02-01 08:53:44 +01:00
Ad5001 719d56127d
Enhanced overall readability of history through usage
All checks were successful
continuous-integration/drone/push Build is passing
+ Using bold and 1 space padding for object names (for long actions)
+ Using color blocs for colors
+ Removed verbose object type from property edition (still accessible from tooltip)
+ Property edition values are now monospaced and have a slight shade as background
+ Using "rename" for name changing verbs.
2022-01-31 23:07:00 +01:00
Ad5001 2d12291075
Using some qt method instead of helper when possible 2022-01-31 21:39:51 +01:00
Ad5001 3119c3f9dc
A lot of history changes
+ History item labels are now RichText which allows for better representation of certain items.
+ History item labels are now multiline
+ History item labels now have a very small separator to distinguish them from each other.
+ Separating history actions into components
2022-01-31 20:17:24 +01:00
Ad5001 73877a0dd4
Merge branch 'master' of https://git.ad5001.eu/Ad5001/LogarithmPlotter
All checks were successful
continuous-integration/drone/push Build is passing
2022-01-31 17:15:46 +01:00
Ad5001 82d2ee84b7
Fixing black icons when using dark theme on KDE SDK 2022-01-31 17:15:33 +01:00
Ad5001 78343cf153
Removing horizontal scrollbar from history 2022-01-31 17:05:05 +01:00
Ad5001 2f8df68453
Translated using Weblate (French)
All checks were successful
continuous-integration/drone/push Build is passing
Currently translated at 100.0% (174 of 174 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/
2022-01-31 13:52:58 +01:00
Ad5001 a13784569a
Translated using Weblate (German)
Currently translated at 100.0% (174 of 174 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/
2022-01-31 13:52:58 +01:00
Ad5001 714129d86e
Translated using Weblate (English)
Currently translated at 100.0% (174 of 174 strings)

Translation: LogarithmPlotter/LogarithmPlotter
Translate-URL: https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/
2022-01-31 13:52:58 +01:00
Ad5001 7030af60f1
Fixing bug with pick new color dialog, trying to fix icons on dark theme, adding keyword to metadata. 2022-01-30 23:24:49 +01:00
Ad5001 77688fa715
Adding tooltips, fixing non translated "Create new object" object type
All checks were successful
continuous-integration/drone/push Build is passing
2022-01-30 13:20:34 +01:00
Ad5001 2d7c038b46
Trying to fix localized appstream description 2022-01-30 13:13:47 +01:00
Ad5001 9873263308
Updating translations
All checks were successful
continuous-integration/drone/push Build is passing
2022-01-30 03:19:05 +01:00
Ad5001 95f7e683c7
Redesigning history browser. 2022-01-30 03:16:47 +01:00
Ad5001 402061a4b1
Optimising a few svg 2022-01-30 01:39:53 +01:00
Ad5001 12fb88cab9
Fixing icon paths 2022-01-30 01:37:46 +01:00
Ad5001 7a8b35c83b
Moving icons 2022-01-30 01:33:52 +01:00
Ad5001 b852eed489
More composenting of history 2022-01-30 01:22:33 +01:00
Ad5001 22328c6227
Starting v0.1.7
All checks were successful
continuous-integration/drone/push Build is passing
2022-01-30 00:33:25 +01:00
Ad5001 b84f236277
Fixed launchpad issues
All checks were successful
continuous-integration/drone/push Build is passing
2022-01-29 20:14:21 +01:00
Ad5001 fe6c805bc7
Trying to fix launchpad building.
All checks were successful
continuous-integration/drone/push Build is passing
2022-01-29 19:15:41 +01:00
218 changed files with 17953 additions and 9650 deletions

3
.gitignore vendored
View file

@ -12,8 +12,11 @@ linux/flatpak/.flatpak-builder
**/**.jsc
**/**.pyc
**/**.qm
**/**.log
*.jsc
*.qmlc
*.log
**/*.dxvk-cache
.DS_Store
**/.DS_Store
**/__pycache__/

3
.gitmodules vendored
View file

@ -1,6 +1,3 @@
[submodule "LogarithmPlotter/qml/eu/ad5001/MixedMenu"]
path = 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,67 +1,313 @@
# 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**
* There is now a [user manual](https://git.ad5001.eu/Ad5001/LogarithmPlotter/wiki/_Sidebar) for LogarithmPlotter! Contributions apprecriated.
**Changes**
* A link to [LogarithmPlotter's official website](https://apps.ad5001.eu/logarithmplotter/) has been added in the about dialog.
* A link to the [user manual](https://git.ad5001.eu/Ad5001/LogarithmPlotter/wiki/_Sidebar) has been added both on the greeting screen and the `Help` menu.
**Added translations**
* User manual.
* Official website.
**Fixed bugs**
* The label position of X Cursors now display the label even when unexpected values are entered.
* X Cursors target object in history are now properly rendered when no object were selected
* Fixed slight clipping at the bottom of the border.
* TextInput no longer allow to input forbidden characters for numbers.
* ALT+ shortcuts on the menu bar now work. NOTE: May break some mobile configuration. [Qt bug report](https://bugreports.qt.io/browse/QTBUG-100539)
* (flatpak) Buttons on side menu to create object now have proper width on startup.
**Internal changes**
* There is now a script to generate offline versions of the manual based on their online version.
* Sidebar button width is now fixed.
* Artifacts have been added to appstream metadata.
## v0.1.7 (03 Feb 2022)
**New**
* The history browser has been completly redesigned, improving UX.
* The history browser now features a filter bar.
* All side panel tabs now have a visually identifiable scrollbar.
**Changes**
* Shorter rich text representations of history entries to improve readability.
* Usage of gradiants and icons to better identify history entries at a glance.
* History entries are now showing the whole label on several lines, instead of cutting it at the end.
* New history action for renaming.
* New history action for coloring. Note: color changing history entries created in previous versions of LogarithmPlotter will not be updated.
* Tooltips for object creation buttons have been added.
* Tooltips have been set to have a delay of 200ms to match most software's handling of them.
* Object creation buttons now have a unified style accross all platforms.
**Added translations**
* History action of renaming objects.
* History action of changing the color of objects.
* Filtering for history browser.
**Fixed bugs**
* Visibility history actions (shown and hidden) are now properly savedmaking loading them not automaticly changed to "Show".
* Name changes history actions are now properly saved.
* Non translated object type on the "+ Create new object" item selection combobox for Bode Magnitude and Phase.
* Proper handling for future LogarithmPlotter files.
* Shortcuts not being displayed in the menu bar are now properly shown.
* (flatpak) Black versions of the icons when using a black theme with the KDE SDK.
* (debian) Fixed launchpad building properly.
**Internal changes**
* Better organisation on icons.
* Historylib has been separated in several files.
* Trying to switch metainfo once more to try and fix another bug.
* Keywords added to metainfo.
## v0.1.6 (29 Jan 2022)
* New: A new changelog popup is available at startup and in the help menu.
* Added translation: Object properties names.
* Added translation: Object properties enum values.
* Added translation: Object comments.
* Added translation: Most elements using a ":".
* Fixed bug: X Cursor's targets can now be set to null.
* Fixed bug: History now imports domains and objects properly.
* Fixed bug: Proper handling for future LogarithmPlotter files.
* Fixed bug (debian): Fixing bug that created a /build directory and didn't put the icons in the right directories.
**New**
* A new changelog popup is available at startup and in the help menu.
**Added translations**
* Object properties names.
* Object properties enum values.
* Object comments.
* Most elements using a ":".
**Fixed bugs**
* X Cursor's targets can now be set to null.
* History now imports domains and objects properly.
* Proper handling for future LogarithmPlotter files.
* (debian) Fixing bug that created a /build directory and didn't put the icons in the right directories.
**Other**
* Other: Refractoring done on helper.
* Other: All QML elements are now properly commented.
* Other: Scripts have been moved to it's own directory.
* Other: Added changelog to metainfo for flathub.
-- Ad5001 <mail@ad5001.eu> Sat, 29 Jan 2022 20:00:00 +0100
## v0.1.5 (26 Jan 2022)
* New: LogarithmPlotter has now better handling of very high values in logarithmic scale.
* Added translation for flatpak metadata, including translated image.
* [URGENT PATCH] Fixed bug: File saving dialog was not working.
* [URGENT PATCH] Fixed bug: Debian packages does include any language file.
* Fixed bug: X Cursor pointing does not detect any object.
**New**
-- Ad5001 <mail@ad5001.eu> Wed, 26 Jan 2022 10:00:00 +0100
* LogarithmPlotter has now better handling of very high values in logarithmic scale.
**Added translations**
* Flatpak metadata, including translated image.
**Fixed bugs**
* (!) File saving dialog was not working.
* (!) Debian packages does include any language file.
* X Cursor pointing does not detect any object.
## v0.1.4 (24 Jan 2022)
* New feature: LogarithmPlotter detects unsaved changes.
* New feature: LogarithmPlotter is now translated! See https://hosted.weblate.org/engage/logarithmplotter/ to help.
**New**
* LogarithmPlotter detects unsaved changes.
* LogarithmPlotter is now translated!
* New translation: English by Ad5001: 100%
* New translation: French by Ad5001: 100%
* New translation: German by Ad5001: 100%
* New translation: Hungarian by Óvári (@ovari on github): 100%
* New translation: Norvegian by Allan Nordhøy (@comradekingu on github): 80%
**Fixed bugs**
* Fixed bug: No notification when closing LogarithmPlotter with unsaved changes.
* Fixed bug: π unavailable in symbols.
-- Ad5001 <mail@ad5001.eu> Mon, 24 Jan 2022 20:00:00 +0100
## v0.1.3 (18 Jan 2022)
* Fixed bug: Confined packages (snapcraft & flatpak) won't show error messages related to update checks.
* FIxed bug: Equations of the form (x + y) / z were not being simplified properly.
**Fixed bugs**
-- Ad5001 <mail@ad5001.eu> Wed, 18 Jan 2022 20:00:00 +0100
* Sandboxed packages (snapcraft and flatpak) won't show error messages related to update checks.
* Equations of the form (x + y) / z were not being simplified properly.
## v0.1.2 (30 Sep 2021)
* Fixed bug: Unable to move Bode diagrams elements when having deleted the sum element.
* Fixed bug: Names were not not being changed from previous object when editing a new one.
* Fixed bug: Bode Magnitude was not drawn far enough.
* Fixed bug: Bode Magnitude had undefined ending.
* Fixed other bugs from v0.1.1.
**Fixed bugs**
-- Ad5001 <mail@ad5001.eu> Mon, 30 Sep 2021 20:00:00 +0100
* Unable to move Bode diagrams elements when having deleted the sum element.
* Names were not not being changed from previous object when editing a new one.
* Bode Magnitude was not drawn far enough.
* Bode Magnitude had undefined ending.
* Other bugs patched in v0.1.1.
## v0.1 (26 Aug 2021)
* Initial release.
-- Ad5001 <mail@ad5001.eu> Mon, 06 Jun 2021 08:48:28 +0100

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>.

View file

@ -1,6 +1,6 @@
"""
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -17,7 +17,7 @@
"""
from shutil import which
__VERSION__ = "0.1.6"
__VERSION__ = "0.6.0"
is_release = False

View file

@ -1,6 +1,6 @@
"""
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

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 +1,2 @@
#!/bin/bash
lupdate -extensions js,qs,qml,py -recursive .. -ts lp_*.ts
lupdate -extensions mjs,js,qs,qml,py -recursive .. -ts lp_*.ts

View file

@ -1,6 +1,6 @@
"""
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -18,98 +18,113 @@
from time import time
start_time = time()
from PySide6.QtWidgets import QApplication
from PySide6.QtQml import QQmlApplicationEngine
from PySide6.QtCore import Qt, QTranslator, QLocale
from PySide6.QtGui import QIcon
from PySide2.QtWidgets import QApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCore import QTranslator, QLocale
from PySide2.QtGui import QIcon
from tempfile import mkstemp
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
from sys import path as sys_path
# Create the temporary file for saving copied screenshots
fd, tmpfile = mkstemp(suffix='.png')
start_time = time()
# 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 config, native, __VERSION__
from LogarithmPlotter.update import check_for_updates
from LogarithmPlotter.helper import Helper
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
from LogarithmPlotter.util.js import PyJSValue
config.init()
def get_linux_theme():
des = {
"KDE": "org.kde.desktop",
"gnome": "default",
"lxqt": "fusion",
"mate": "fusion",
"KDE": "Fusion",
"gnome": "Basic",
"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"
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]
if not 'QT_QUICK_CONTROLS_STYLE' in environ:
environ["QT_QUICK_CONTROLS_STYLE"] = {
"linux": get_linux_theme(),
"freebsd": get_linux_theme(),
"win32": "Universal" if os_release == "10" else "Fusion",
"cygwin": "Fusion",
"darwin": "macOS"
}[platform]
dep_time = time()
print("Loaded dependencies in " + str((dep_time - start_time)*1000) + "ms.")
print("Loaded dependencies in " + str((dep_time - start_time) * 1000) + "ms.")
icon_fallbacks = QIcon.fallbackSearchPaths();
icon_fallbacks.append(path.realpath(path.join(getcwd(), "qml", "eu", "ad5001", "LogarithmPlotter", "icons")))
icon_fallbacks.append(path.realpath(path.join(getcwd(), "qml", "eu", "ad5001", "LogarithmPlotter", "icons", "settings")))
icon_fallbacks.append(path.realpath(path.join(getcwd(), "qml", "eu", "ad5001", "LogarithmPlotter", "icons", "settings", "custom")))
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);
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
app = QApplication(argv)
app.setApplicationName("LogarithmPlotter")
app.setDesktopFileName("eu.ad5001.LogarithmPlotter.desktop")
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="]
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")))):
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)
engine.rootContext().setContextProperty("Helper", helper)
latex = Latex(tempdir)
js_globals = PyJSValue(engine.globalObject())
js_globals.Modules = engine.newObject()
js_globals.Helper = engine.newQObject(helper)
js_globals.Latex = engine.newQObject(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.
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")))
@ -119,23 +134,26 @@ def run():
# 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])
js_globals.Modules.IO.loadDiagram(argv[-1])
chdir(path.dirname(path.realpath(__file__)))
if platform == "darwin":
macOSFileOpenHandler.init_graphics(engine.rootObjects()[0])
macOSFileOpenHandler.init_io(js_globals.Modules.IO)
# Check for LaTeX installation if LaTeX support is enabled
if config.getSetting("enable_latex"):
latex.check_latex_install()
# Check for updates
if config.getSetting("check_for_updates"):
check_for_updates(__VERSION__, engine.rootObjects()[0])
exit_code = app.exec_()
close(fd)
remove(tmpfile)
exit_code = app.exec()
tempdir.cleanup()
config.save()
exit(exit_code)
if __name__ == "__main__":
run()

View file

@ -1,9 +1,64 @@
<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>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"><title
id="title836">LogarithmPlotter Icon v1.0</title><defs
id="defs833" /><metadata
id="metadata836"><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>LogarithmPlotter Icon v1.0</dc:title><cc:license
rdf:resource="http://creativecommons.org/licenses/by-nc-sa/4.0/" /><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 - All rights reserved</dc:title></cc:Agent></dc:rights></cc:Work><cc:License
rdf:about="http://creativecommons.org/licenses/by-nc-sa/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:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" /></cc:License></rdf:RDF></metadata><g
id="layer2"
transform="matrix(1,0,0,0.94444444,0,1.1666667)"
style="fill:#666666"><rect
style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1546"
width="18"
height="18"
x="3"
y="3"
ry="2.25" /></g><g
id="layer2-6"
transform="matrix(1,0,0,0.94444444,0,0.16666668)"
style="fill:#f9f9f9"><rect
style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1546-7"
width="18"
height="18"
x="3"
y="3"
ry="2.25" /></g><g
id="layer1"
style="stroke-width:2;stroke-dasharray:none"><rect
style="fill:#000000;fill-rule:evenodd;stroke-width:1.86898;stroke-dasharray:none;stroke-opacity:0"
id="rect1410"
width="14"
height="2"
x="5"
y="15.5" /><rect
style="fill:#000000;fill-rule:evenodd;stroke-width:2;stroke-dasharray:none;stroke-opacity:0"
id="rect1412"
width="2"
height="15"
x="9"
y="3.9768662" /><path
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1529"
d="M 18,4 C 18,10.017307 13.40948,15.5 5,15.5" /></g></svg>

Before

Width:  |  Height:  |  Size: 488 B

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -1,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,11 +16,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.12
import QtQuick.Dialogs 1.3
import QtQuick
import Qt.labs.platform as Native
//import QtQuick.Controls 2.15
import eu.ad5001.MixedMenu 1.1
import "js/objects.js" as Objects
import "js/historylib.js" as HistoryLib
import "js/historylib.mjs" as HistoryLib
/*!
\qmltype AppMenuBar
@ -88,30 +89,36 @@ MenuBar {
icon.color: enabled ? sysPalette.windowText : sysPaletteIn.windowText
enabled: history.redoCount > 0
}
MenuSeparator { }
Action {
text: qsTr("&Copy plot")
shortcut: StandardKey.Copy
onTriggered: root.copyDiagramToClipboard()
icon.name: 'edit-copy'
}
MenuSeparator { }
Action {
text: qsTr("&Preferences")
shortcut: StandardKey.Copy
onTriggered: preferences.open()
icon.name: 'settings'
}
}
Menu {
title: qsTr("&Create")
// Services repeater
Repeater {
model: Object.keys(Objects.types)
model: Object.keys(Modules.Objects.types)
MenuItem {
text: Objects.types[modelData].displayType()
visible: Objects.types[modelData].createable()
text: Modules.Objects.types[modelData].displayType()
visible: Modules.Objects.types[modelData].createable()
height: visible ? implicitHeight : 0
icon.name: modelData
icon.source: './icons/' + modelData + '.svg'
icon.source: './icons/objects/' + modelData + '.svg'
icon.color: sysPalette.buttonText
onTriggered: {
var newObj = Objects.createNewRegisteredObject(modelData)
var newObj = Modules.Objects.createNewRegisteredObject(modelData)
history.addToHistory(new HistoryLib.CreateNewObject(newObj.name, modelData, newObj.export()))
objectLists.update()
}
@ -119,38 +126,22 @@ MenuBar {
}
}
Menu {
title: qsTr("&Settings")
Action {
id: checkForUpdatesMenuSetting
text: qsTr("Check for updates on startup")
checkable: true
checked: Helper.getSettingBool("check_for_updates")
onTriggered: Helper.setSettingBool("check_for_updates", checked)
icon.name: 'update'
}
Action {
id: resetRedoStackMenuSetting
text: qsTr("Reset redo stack automaticly")
checkable: true
checked: Helper.getSettingBool("reset_redo_stack")
onTriggered: Helper.setSettingBool("reset_redo_stack", checked)
icon.name: 'timeline'
}
}
Menu {
title: qsTr("&Help")
Action {
text: qsTr("&Source code")
icon.name: 'software-sources'
onTriggered: Helper.openUrl("https://git.ad5001.eu/Ad5001/LogarithmPlotter/issues")
onTriggered: Qt.openUrlExternally("https://git.ad5001.eu/Ad5001/LogarithmPlotter")
}
Action {
text: qsTr("&Report a bug")
icon.name: 'tools-report-bug'
onTriggered: Helper.openUrl("https://git.ad5001.eu/Ad5001/LogarithmPlotter/issues")
onTriggered: Qt.openUrlExternally("https://git.ad5001.eu/Ad5001/LogarithmPlotter/issues")
}
Action {
text: qsTr("&User manual")
icon.name: 'documentation'
onTriggered: Qt.openUrlExternally("https://git.ad5001.eu/Ad5001/LogarithmPlotter/wiki/_Sidebar")
}
Action {
text: qsTr("&Changelog")
@ -160,9 +151,14 @@ MenuBar {
Action {
text: qsTr("&Help translating!")
icon.name: 'translator'
onTriggered: Helper.openUrl("https://hosted.weblate.org/engage/logarithmplotter/")
onTriggered: Qt.openUrlExternally("https://hosted.weblate.org/engage/logarithmplotter/")
}
MenuSeparator { }
Action {
text: qsTr("&Thanks")
icon.name: 'about'
onTriggered: thanksTo.open()
}
Action {
text: qsTr("&About")
shortcut: StandardKey.HelpContents
@ -171,16 +167,17 @@ MenuBar {
}
}
MessageDialog {
Native.MessageDialog {
id: saveUnsavedChangesDialog
title: qsTr("Save unsaved changes?")
icon: StandardIcon.Question
text: qsTr("This plot contains unsaved changes. By doing this, all unsaved data will be lost. Continue?")
standardButtons: StandardButton.Yes | StandardButton.No
onYes: Qt.quit()
buttons: Native.MessageDialog.Save | Native.MessageDialog.Discard | Native.MessageDialog.Cancel
onSaveClicked: settings.save()
onDiscardClicked: Qt.quit()
}
function showSaveUnsavedChangesDialog() {
saveUnsavedChangesDialog.visible = true
function openSaveUnsavedChangesDialog() {
saveUnsavedChangesDialog.open()
}
}

View file

@ -1,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,14 +16,14 @@
* 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 QtQuick
import QtQml
import QtQuick.Window
import "../js/historylib.mjs" as HistoryLib
/*!
\qmltype History
\inqmlmodule eu.ad5001.LogarithmPlotter
\inqmlmodule eu.ad5001.LogarithmPlotter.History
\brief QObject holding persistantly for undo & redo stacks.
\sa HistoryBrowser, historylib
@ -123,14 +123,16 @@ Item {
}
/*!
\qmlmethod void History::undo()
\qmlmethod void History::undo(bool updateObjectList = true)
Undoes the historylib.Action at the top of the undo stack and pushes it to the top of the redo stack.
By default, will update the graph and the object list. This behavior can be disabled by setting the \c updateObjectList to false.
*/
function undo() {
function undo(updateObjectList = true) {
if(undoStack.length > 0) {
var action = undoStack.pop()
action.undo()
objectLists.update()
if(updateObjectList)
objectLists.update()
redoStack.push(action)
undoCount--;
redoCount++;
@ -139,14 +141,16 @@ Item {
}
/*!
\qmlmethod void History::redo()
\qmlmethod void History::redo(bool updateObjectList = true)
Redoes the historylib.Action at the top of the redo stack and pushes it to the top of the undo stack.
By default, will update the graph and the object list. This behavior can be disabled by setting the \c updateObjectList to false.
*/
function redo() {
function redo(updateObjectList = true) {
if(redoStack.length > 0) {
var action = redoStack.pop()
action.redo()
objectLists.update()
if(updateObjectList)
objectLists.update()
undoStack.push(action)
undoCount++;
redoCount--;
@ -185,7 +189,7 @@ Item {
property int toUndoCount: 0
onTriggered: {
if(toUndoCount > 0) {
historyObj.undo()
historyObj.undo(toUndoCount % 4 == 1) // Only redraw once every 4 changes.
toUndoCount--;
} else {
running = false;
@ -199,7 +203,7 @@ Item {
property int toRedoCount: 0
onTriggered: {
if(toRedoCount > 0) {
historyObj.redo()
historyObj.redo(toRedoCount % 4 == 1) // Only redraw once every 4 changes.
toRedoCount--;
} else {
running = false;
@ -208,6 +212,8 @@ Item {
}
Component.onCompleted: {
HistoryLib.history = historyObj
Modules.History.history = historyObj
Modules.History.themeTextColor = sysPalette.windowText
Modules.History.imageDepth = Screen.devicePixelRatio
}
}

View file

@ -0,0 +1,168 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick.Controls
import QtQuick
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import "../js/utils.mjs" as Utils
/*!
\qmltype HistoryBrowser
\inqmlmodule eu.ad5001.LogarithmPlotter.History
\brief Tab of the drawer that allows to navigate through the undo and redo history.
Creates a scrollable view containing a list of history actions based on the redo stack, then a "Now" indicator
followed by the entirety of the saved undo stack. Each action can be click to restore a state of the graph at
some point of the history.
\sa LogarithmPlotter, Settings, ObjectLists
*/
Item {
id: historyBrowser
/*!
\qmlproperty int HistoryBrowser::actionWidth
Width of the actions.
*/
property int actionWidth: width-20
/*!
\qmlproperty int HistoryBrowser::darkTheme
true when the system is running with a dark theme, false otherwise.
*/
property bool darkTheme: isDarkTheme()
Setting.TextSetting {
id: filterInput
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
placeholderText: qsTr("Filter...")
category: "all"
}
ScrollView {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: filterInput.bottom
ScrollBar.horizontal.visible: false
clip: true
Flickable {
width: parent.width
height: parent.height
contentHeight: redoColumn.height + nowRect.height + undoColumn.height
contentWidth: parent.width
Column {
id: redoColumn
anchors.right: parent.right
anchors.top: parent.top
width: actionWidth
Repeater {
model: history.redoCount
HistoryItem {
id: redoButton
width: actionWidth
//height: actionHeight
isRedo: true
idx: index
darkTheme: historyBrowser.darkTheme
hidden: !(filterInput.value == "" || content.includes(filterInput.value))
}
}
}
Text {
anchors.left: parent.left
anchors.bottom: nowRect.top
text: qsTr("Redo >")
color: sysPaletteIn.windowText
transform: Rotation { origin.x: 30; origin.y: 30; angle: 270}
height: 70
width: 20
visible: history.redoCount > 0
}
Rectangle {
id: nowRect
anchors.right: parent.right
anchors.top: redoColumn.bottom
width: actionWidth
height: 40
color: sysPalette.highlight
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 5
text: qsTr("> Now")
color: sysPalette.windowText
}
}
Column {
id: undoColumn
anchors.right: parent.right
anchors.top: nowRect.bottom
width: actionWidth
Repeater {
model: history.undoCount
HistoryItem {
id: undoButton
width: actionWidth
//height: actionHeight
isRedo: false
idx: index
darkTheme: historyBrowser.darkTheme
hidden: !(filterInput.value == "" || content.includes(filterInput.value))
}
}
}
Text {
anchors.left: parent.left
anchors.top: undoColumn.top
text: qsTr("< Undo")
color: sysPaletteIn.windowText
transform: Rotation { origin.x: 30; origin.y: 30; angle: 270}
height: 60
width: 20
visible: history.undoCount > 0
}
}
}
/*!
\qmlmethod bool HistoryBrowser::isDarkTheme()
Checks whether the system is running with a light or dark theme.
*/
function isDarkTheme() {
let hex = sysPalette.windowText.toString()
// We only check the first parameter, as on all normal OSes, text color is grayscale.
return parseInt(hex.substr(1,2), 16) > 128
}
}

View file

@ -0,0 +1,147 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick.Controls
import QtQuick
import Qt5Compat.GraphicalEffects
import "../js/utils.mjs" as Utils
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
/*!
\qmltype HistoryItem
\inqmlmodule eu.ad5001.LogarithmPlotter.History
\brief Item representing an history action.
Creates a scrollable view containing a list of history actions based on the redo stack, then a "Now" indicator
followed by the entirety of the saved undo stack. Each action can be click to restore a state of the graph at
some point of the history.
\sa HistoryBrowser
*/
Button {
id: redoButton
flat: true
/*!
\qmlproperty bool HistoryItem::isRedo
true if the action is in the redo stack, false othewise.
*/
property bool isRedo
/*!
\qmlproperty int HistoryItem::idx
Index of the item within the HistoryBrowser list.
*/
property int idx
/*!
\qmlproperty bool HistoryItem::darkTheme
true when the system is running with a dark theme, false otherwise.
*/
property bool darkTheme
/*!
\qmlproperty bool HistoryItem::hidden
true when the item is filtered out, false otherwise.
*/
property bool hidden: false
/*!
\qmlproperty int HistoryItem::historyAction
Associated history action.
*/
readonly property var historyAction: isRedo ? history.redoStack[idx] : history.undoStack[history.undoCount-idx-1]
/*!
\qmlproperty int HistoryItem::actionHeight
Base height of the action.
*/
readonly property int actionHeight: 40
/*!
\qmlproperty color HistoryItem::clr
Color of the history action.
*/
readonly property color clr: historyAction.color(darkTheme)
/*!
\qmlproperty string HistoryItem::clr
Label description of the history item.
*/
readonly property string content: historyAction.getReadableString()
height: hidden ? 8 : Math.max(actionHeight, label.height + 15)
LinearGradient {
anchors.fill: parent
//opacity: hidden ? 0.6 : 1
start: Qt.point(0, 0)
end: Qt.point(parent.width, 0)
gradient: Gradient {
GradientStop { position: 0.1; color: "transparent" }
GradientStop { position: 1.5; color: clr }
}
}
Setting.Icon {
id: icon
anchors.left: parent.left
anchors.leftMargin: 6
anchors.verticalCenter: parent.verticalCenter
visible: !hidden
width: 18
height: 18
color: sysPalette.windowText
source: `../icons/history/${historyAction.icon()}.svg`
}
Label {
id: label
anchors.left: icon.right
anchors.right: parent.right
anchors.leftMargin: 6
anchors.rightMargin: 20
anchors.verticalCenter: parent.verticalCenter
visible: !hidden
font.pixelSize: 14
text: historyAction.getHTMLString().replace(/\$\{tag_color\}/g, clr)
textFormat: Text.RichText
clip: true
wrapMode: Text.WordWrap
}
Rectangle {
id: hiddenDot
anchors.centerIn: parent
visible: hidden
width: 5
height: 5
radius: 5
color: sysPalette.windowText
}
ToolTip.visible: hovered
ToolTip.delay: 200
ToolTip.text: content
onClicked: {
if(isRedo)
history.redoMultipleDefered(history.redoCount-idx)
else
history.undoMultipleDefered(+idx+1)
}
}

View file

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

View file

@ -1,146 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition 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.Controls 2.12
import QtQuick 2.12
import "js/utils.js" as Utils
/*!
\qmltype HistoryBrowser
\inqmlmodule eu.ad5001.LogarithmPlotter
\brief Tab of the drawer that allows to navigate through the undo and redo history.
Creates a scrollable view containing a list of history actions based on the redo stack, then a "Now" indicator
followed by the entirety of the saved undo stack. Each action can be click to restore a state of the graph at
some point of the history.
\sa LogarithmPlotter, Settings, ObjectLists
*/
ScrollView {
id: historyBrowser
/*!
\qmlproperty int HistoryBrowser::actionWidth
Width of the actions.
*/
property int actionWidth: width-20
/*!
\qmlproperty int HistoryBrowser::actionHeight
Height of the actions.
*/
property int actionHeight: 30
Flickable {
width: parent.width
height: parent.height
contentHeight: redoColumn.height + nowRect.height + undoColumn.height
contentWidth: parent.width
Column {
id: redoColumn
anchors.right: parent.right
anchors.top: parent.top
width: historyBrowser.actionWidth
Repeater {
model: history.redoCount
Button {
id: redoButton
width: historyBrowser.actionWidth
height: actionHeight
flat: true
text: history.redoStack[index].getReadableString()
ToolTip.visible: hovered
ToolTip.text: text
onClicked: {
history.redoMultipleDefered(history.redoCount-index)
}
}
}
}
Text {
anchors.left: parent.left
anchors.bottom: nowRect.top
text: qsTr("Redo >")
color: sysPaletteIn.windowText
transform: Rotation { origin.x: 30; origin.y: 30; angle: 270}
height: 70
width: 20
visible: history.redoCount > 0
}
Rectangle {
id: nowRect
anchors.right: parent.right
anchors.top: redoColumn.bottom
width: historyBrowser.actionWidth
height: actionHeight
color: sysPalette.highlight
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 5
text: qsTr("> Now")
color: sysPalette.windowText
}
}
Column {
id: undoColumn
anchors.right: parent.right
anchors.top: nowRect.bottom
width: historyBrowser.actionWidth
Repeater {
model: history.undoCount
Button {
id: undoButton
width: historyBrowser.actionWidth
height: actionHeight
flat: true
text: history.undoStack[history.undoCount-index-1].getReadableString()
ToolTip.visible: hovered
ToolTip.text: text
onClicked: {
history.undoMultipleDefered(index+1)
}
}
}
}
Text {
anchors.left: parent.left
anchors.top: undoColumn.top
text: qsTr("< Undo")
color: sysPaletteIn.windowText
transform: Rotation { origin.x: 30; origin.y: 30; angle: 270}
height: 60
width: 20
visible: history.undoCount > 0
}
}
}

View file

@ -1,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,10 +16,10 @@
* 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
import QtQuick
import Qt.labs.platform as Native
import "js/utils.mjs" as Utils
import "js/mathlib.mjs" as MathLib
/*!
\qmltype LogGraphCanvas
@ -127,209 +127,49 @@ Canvas {
property int maxgradx: 20
/*!
\qmlproperty var LogGraphCanvas::yaxisstepExpr
Expression for the y axis step (used to create labels).
\qmlproperty var LogGraphCanvas::imageLoaders
Dictionary of format {image: [callback.image data]} containing data for defered image loading.
*/
property var yaxisstepExpr: (new MathLib.Expression(`x*(${yaxisstep})`))
property var imageLoaders: {}
/*!
\qmlproperty double LogGraphCanvas::yaxisstep1
Value of the for the y axis step.
\qmlproperty var LogGraphCanvas::ctx
Cache for the 2D context so that it may be used asynchronously.
*/
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 ctx
Component.onCompleted: {
imageLoaders = {}
Modules.Canvas.initialize(canvas, drawingErrorDialog)
}
onPaint: {
Native.MessageDialog {
id: drawingErrorDialog
title: qsTranslate("expression", "LogarithmPlotter - Drawing error")
text: ""
function showDialog(objType, objName, error) {
text = qsTranslate("error", "Error while attempting to draw %1 %2:\n%3\n\nUndoing last change.").arg(objType).arg(objName).arg(error)
open()
}
}
onPaint: function(rect) {
//console.log('Redrawing')
var ctx = getContext("2d");
reset(ctx)
drawGrille(ctx)
drawAxises(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)
if(rect.width == canvas.width) { // Redraw full canvas
Modules.Canvas.redraw()
}
}
onImageLoaded: {
Object.keys(imageLoaders).forEach((key) => {
if(isImageLoaded(key)) {
// Calling callback
imageLoaders[key][0](canvas, ctx, imageLoaders[key][1])
delete imageLoaders[key]
}
}
ctx.lineWidth = 1
drawLabels(ctx)
}
/*!
\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 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.
@ -369,50 +209,4 @@ Canvas {
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();
}
}

View file

@ -1,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,15 +16,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQml 2.12
import QtQuick.Controls 2.12
import QtQml
import QtQuick.Controls
import eu.ad5001.MixedMenu 1.1
import QtQuick.Layouts 1.12
import QtQuick 2.12
// Auto loading all objects.
import "js/objs/autoload.js" as ALObjects
import QtQuick
import "js/objects.js" as Objects
// Auto loading all modules.
import "js/autoload.js" as ModulesAutoload
import eu.ad5001.LogarithmPlotter.History 1.0
import eu.ad5001.LogarithmPlotter.ObjectLists 1.0
import eu.ad5001.LogarithmPlotter.Popup 1.0 as Popup
@ -54,10 +55,14 @@ ApplicationWindow {
Popup.GreetScreen {}
Popup.Preferences {id: preferences}
Popup.Changelog {id: changelog}
Popup.About {id: about}
Popup.ThanksTo {id: thanksTo}
Popup.Alert {
id: alert
anchors.bottom: parent.bottom
@ -65,15 +70,16 @@ ApplicationWindow {
z: 3
}
Drawer {
Item {
id: sidebar
width: 300
height: parent.height
y: root.menuBar.height
//y: root.menuBar.height
readonly property bool inPortrait: root.width < root.height
modal: inPortrait
/*modal: true// inPortrait
interactive: inPortrait
position: inPortrait ? 0 : 1
*/
visible: !inPortrait
@ -108,7 +114,7 @@ ApplicationWindow {
anchors.topMargin: 5
anchors.leftMargin: 5
anchors.bottom: parent.bottom
anchors.bottomMargin: sidebarSelector.height
//anchors.bottomMargin: sidebarSelector.height
width: parent.width - 5
currentIndex: sidebarSelector.currentIndex
z: -1
@ -136,8 +142,8 @@ ApplicationWindow {
anchors.top: parent.top
anchors.left: sidebar.inPortrait ? parent.left : sidebar.right
height: parent.height
width: sidebar.inPortrait ? parent.width : parent.width - sidebar.position*sidebar.width
x: sidebar.position*sidebar.width
width: sidebar.inPortrait ? parent.width : parent.width - sidebar.width//*sidebar.position
x: sidebar.width//*sidebar.position
xmin: settings.xmin
ymax: settings.ymax
@ -155,7 +161,7 @@ ApplicationWindow {
property bool firstDrawDone: false
onPainted: if(!firstDrawDone) {
onPainted: if(!firstDrawDone) {
firstDrawDone = true;
console.info("First paint done in " + (new Date().getTime()-(StartTime*1000)) + "ms")
if(TestBuild == true) {
@ -164,6 +170,13 @@ ApplicationWindow {
}
}
ViewPositionChangeOverlay {
id: viewPositionChanger
anchors.fill: parent
canvas: parent
settingsInstance: settings
}
PickLocationOverlay {
id: positionPicker
anchors.fill: parent
@ -171,120 +184,6 @@ ApplicationWindow {
}
}
/*!
\qmlmethod void LogarithmPlotter::saveDiagram(string filename)
Saves the diagram to a certain \c filename.
*/
function saveDiagram(filename) {
if(['lpf'].indexOf(filename.split('.')[filename.split('.').length-1]) == -1)
filename += '.lpf'
settings.saveFilename = filename
var objs = {}
for(var objType in Objects.currentObjects){
objs[objType] = []
for(var obj of Objects.currentObjects[objType]) {
objs[objType].push(obj.export())
}
}
Helper.write(filename, JSON.stringify({
"xzoom": settings.xzoom,
"yzoom": settings.yzoom,
"xmin": settings.xmin,
"ymax": settings.ymax,
"xaxisstep": settings.xaxisstep,
"yaxisstep": settings.yaxisstep,
"xaxislabel": settings.xlabel,
"yaxislabel": settings.ylabel,
"logscalex": settings.logscalex,
"linewidth": settings.linewidth,
"showxgrad": settings.showxgrad,
"showygrad": settings.showygrad,
"textsize": settings.textsize,
"history": history.serialize(),
"width": root.width,
"height": root.height,
"objects": objs,
"type": "logplotv1"
}))
alert.show(qsTr("Saved plot to '%1'.").arg(filename.split("/").pop()))
history.saved = true
}
/*!
\qmlmethod void LogarithmPlotter::saveDiagram(string filename)
Loads the diagram from a certain \c filename.
*/
function loadDiagram(filename) {
let basename = filename.split("/").pop()
alert.show(qsTr("Loading file '%1'.").arg(basename))
let data = JSON.parse(Helper.load(filename))
let error = "";
if(Object.keys(data).includes("type") && data["type"] == "logplotv1") {
history.clear()
// Importing settings
settings.saveFilename = filename
settings.xzoom = data["xzoom"]
settings.yzoom = data["yzoom"]
settings.xmin = data["xmin"]
settings.ymax = data["ymax"]
settings.xaxisstep = data["xaxisstep"]
settings.yaxisstep = data["yaxisstep"]
settings.xlabel = data["xaxislabel"]
settings.ylabel = data["yaxislabel"]
settings.logscalex = data["logscalex"]
if("showxgrad" in data)
settings.showxgrad = data["showxgrad"]
if("showygrad" in data)
settings.textsize = data["showygrad"]
if("linewidth" in data)
settings.linewidth = data["linewidth"]
if("textsize" in data)
settings.textsize = data["textsize"]
root.height = data["height"]
root.width = data["width"]
// Importing objects
Objects.currentObjects = {}
for(var objType in data['objects']) {
if(Object.keys(Objects.types).indexOf(objType) > -1) {
Objects.currentObjects[objType] = []
for(var objData of data['objects'][objType]) {
var obj = new Objects.types[objType](...objData)
Objects.currentObjects[objType].push(obj)
}
} else {
error += qsTr("Unknown object type: %1.").arg(objType) + "\n";
}
}
// Importing history
if("history" in data)
history.unserialize(...data["history"])
// Refreshing sidebar
if(sidebarSelector.currentIndex == 0) {
// For some reason, if we load a file while the tab is on object,
// we get stuck in a Qt-side loop? Qt bug or side-effect here, I don't know.
sidebarSelector.currentIndex = 1
objectLists.update()
delayRefreshTimer.start()
} else {
objectLists.update()
}
} else {
error = qsTr("Invalid file provided.")
}
if(error != "") {
console.log(error)
alert.show(qsTr("Could not save file: ") + error)
// TODO: Error handling
return
}
drawCanvas.requestPaint()
alert.show(qsTr("Loaded file '%1'.").arg(basename))
history.saved = true
}
Timer {
id: delayRefreshTimer
repeat: false
@ -299,10 +198,26 @@ ApplicationWindow {
onTriggered: Qt.quit() // Quit after paint on test build
}
onClosing: {
onClosing: function(close) {
if(!history.saved) {
close.accepted = false
appMenu.showSaveUnsavedChangesDialog()
appMenu.openSaveUnsavedChangesDialog()
}
}
/*!
\qmlmethod void LogarithmPlotter::updateObjectsLists()
Updates the objects lists when loading a file.
*/
function updateObjectsLists() {
if(sidebarSelector.currentIndex === 0) {
// For some reason, if we load a file while the tab is on object,
// we get stuck in a Qt-side loop? Qt bug or side-effect here, I don't know.
sidebarSelector.currentIndex = 1
objectLists.update()
delayRefreshTimer.start()
} else {
objectLists.update()
}
}
@ -333,7 +248,7 @@ ApplicationWindow {
Action {
text: qsTr("&Update LogarithmPlotter")
icon.name: 'update'
onTriggered: Helper.openUrl("https://dev.apps.ad5001.eu/logarithmplotter")
onTriggered: Qt.openUrlExternally("https://apps.ad5001.eu/logarithmplotter/")
}
}

View file

@ -0,0 +1,336 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
import Qt.labs.platform as Native
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import "../../js/historylib.mjs" as HistoryLib
import "../../js/utils.mjs" as Utils
import "../../js/mathlib.mjs" as MathLib
/*!
\qmltype CustomPropertyList
\inqmlmodule eu.ad5001.LogarithmPlotter.ObjectLists.Editor
\brief Lists all custom properties editors inside a repeater and allow for edition.
This class repeats all of the custom properties and loads the appropriate editor for each kind of property.
\sa Dialog
*/
Repeater {
id: root
signal changed()
/*!
\qmlproperty var CustomPropertyList::obj
Object whose properties to list and edit.
*/
property var obj
/*!
\qmlproperty var CustomPropertyList::positionPicker
Reference to the global PositionPicker QML object.
*/
property var positionPicker
readonly property var textTypes: ['Domain', 'string', 'number']
readonly property var comboBoxTypes: ['ObjectType', 'Enum']
readonly property var listTypes: ['List', 'Dict']
// NOTE: All components have the declared properties 'propertyLabel', 'propertyIcon', propertyName' and 'propertyType' to access the object in question.
Component {
id: commentComponent
// Item for comments.
// NOTE: propertyType here is the content of the comment (yes, it's a bit backwards, but it's more clear on the properties side).
Label {
// Translated text with object name.
property string trText: qsTranslate('comment', propertyType).toString()
text: (trText.includes("%1") ? trText.arg(obj.name) : trText).toString()
//color: sysPalette.windowText
wrapMode: Text.WordWrap
}
}
Component {
id: expressionEditorComponent
// Setting for expressions
Setting.ExpressionEditor {
height: 30
label: propertyLabel
icon: `settings/custom/${propertyIcon}.svg`
defValue: Utils.simplifyExpression(obj[propertyName].toEditableString())
self: obj.name
variables: propertyType.variables
onChanged: function(newExpr) {
if(obj[propertyName].toString() != newExpr.toString()) {
history.addToHistory(new HistoryLib.EditedProperty(
obj.name, objType, propertyName,
obj[propertyName], newExpr
))
obj[propertyName] = newExpr
root.changed()
}
}
}
}
Component {
id: textEditorComponent
// Setting for text & number settings as well as domains
Setting.TextSetting {
height: 30
label: propertyLabel
icon: `settings/custom/${propertyIcon}.svg`
isDouble: propertyType == "number"
defValue: obj[propertyName] == null ? '' : obj[propertyName].toString()
category: {
return {
"Domain": "domain",
"string": "all",
"number": "all"
}[propertyType]
}
onChanged: function(newValue) {
try {
var newValueParsed = {
"Domain": () => MathLib.parseDomain(newValue),
"string": () => newValue,
"number": () => parseFloat(newValue)
}[propertyType]()
// Ensuring old and new values are different to prevent useless adding to history.
if(obj[propertyName] != newValueParsed) {
history.addToHistory(new HistoryLib.EditedProperty(
obj.name, objType, propertyName,
obj[propertyName], newValueParsed
))
obj[propertyName] = newValueParsed
root.changed()
}
} catch(e) {
// Error in expression or domain
console.trace()
parsingErrorDialog.showDialog(propertyName, newValue, e.message)
}
}
Native.MessageDialog {
id: parsingErrorDialog
title: qsTranslate("expression", "LogarithmPlotter - Parsing error")
text: ""
function showDialog(propName, propValue, error) {
text = qsTranslate("error", "Error while parsing expression for property %1:\n%2\n\nEvaluated expression: %3").arg(propName).arg(error).arg(propValue)
open()
}
}
}
}
Component {
id: checkboxComponent
// Setting for boolean
CheckBox {
height: 20
text: propertyLabel
//icon: `settings/custom/${propertyIcon}.svg`
checked: {
//if(obj[propertyName] == null) {
// return false
//}
return obj[propertyName]
}
onClicked: {
history.addToHistory(new HistoryLib.EditedProperty(
obj.name, objType, propertyName,
obj[propertyName], this.checked
))
obj[propertyName] = this.checked
root.changed()
}
}
}
Component {
id: comboBoxComponent
// Setting when selecting data from an enum, or an object of a certain type.
Setting.ComboBoxSetting {
height: 30
label: propertyLabel
icon: `settings/custom/${propertyIcon}.svg`
// True to select an object of type, false for enums.
property bool selectObjMode: paramTypeIn(propertyType, ['ObjectType'])
property bool isRealObject: !selectObjMode || (propertyType.objType != "ExecutableObject" && propertyType.objType != "DrawableObject")
// Base, untranslated version of the model.
property var baseModel: selectObjMode ?
Modules.Objects.getObjectsName(propertyType.objType).concat(
isRealObject ? [qsTr("+ Create new %1").arg(Modules.Objects.types[propertyType.objType].displayType())] : [])
: propertyType.values
// Translated version of the model.
model: selectObjMode ? baseModel : propertyType.translatedValues
currentIndex: baseModel.indexOf(selectObjMode ? obj[propertyName].name : obj[propertyName])
onActivated: function(newIndex) {
if(selectObjMode) {
// This is only done when what we're selecting are Objects.
// Setting object property.
var selectedObj = Modules.Objects.currentObjectsByName[baseModel[newIndex]]
if(newIndex != 0) {
// Make sure we don't set the object to null.
if(selectedObj == null) {
// Creating new object.
selectedObj = Modules.Objects.createNewRegisteredObject(propertyType.objType)
history.addToHistory(new HistoryLib.CreateNewObject(selectedObj.name, propertyType.objType, selectedObj.export()))
baseModel = Modules.Objects.getObjectsName(propertyType.objType).concat(
isRealObject ? [qsTr("+ Create new %1").arg(Modules.Objects.types[propertyType.objType].displayType())] :
[])
currentIndex = baseModel.indexOf(selectedObj.name)
}
selectedObj.requiredBy.push(Modules.Objects.currentObjects[objType][objIndex])
//Modules.Objects.currentObjects[objType][objIndex].requiredBy = obj[propertyName].filter((obj) => obj.name != obj.name)
}
obj.requiredBy = obj.requiredBy.filter((obj) => obj.name != obj.name)
history.addToHistory(new HistoryLib.EditedProperty(
obj.name, objType, propertyName,
obj[propertyName], selectedObj
))
obj[propertyName] = selectedObj
} else if(baseModel[newIndex] != obj[propertyName]) {
// Ensuring new property is different to not add useless history entries.
history.addToHistory(new HistoryLib.EditedProperty(
obj.name, objType, propertyName,
obj[propertyName], baseModel[newIndex]
))
obj[propertyName] = baseModel[newIndex]
}
// Refreshing
root.changed()
}
}
}
Component {
// Setting to edit lists or dictionaries (e.g sequences & repartition function values)
id: listDictEditorComponent
Setting.ListSetting {
label: propertyLabel
//icon: `settings/custom/${propertyIcon}.svg`
dictionaryMode: paramTypeIn(propertyType, ['Dict'])
keyType: dictionaryMode ? propertyType.keyType : 'string'
valueType: propertyType.valueType
preKeyLabel: (dictionaryMode ? propertyType.preKeyLabel : propertyType.label).replace(/\{name\}/g, obj.name).replace(/\{name_\}/g, obj.name.substring(obj.name.indexOf("_")+1))
postKeyLabel: (dictionaryMode ? propertyType.postKeyLabel : '').replace(/\{name\}/g, obj.name).replace(/\{name_\}/g, obj.name.substring(obj.name.indexOf("_")+1))
keyRegexp: dictionaryMode ? propertyType.keyFormat : /^.+$/
valueRegexp: propertyType.format
forbidAdding: propertyType.forbidAdding
onChanged: {
var exported = exportModel()
history.addToHistory(new HistoryLib.EditedProperty(
obj.name, objType, propertyName,
obj[propertyName], exported
))
//Modules.Objects.currentObjects[objType][objIndex][propertyName] = exported
obj[propertyName] = exported
root.changed()
}
Component.onCompleted: {
importModel(obj[propertyName])
}
}
}
delegate: Component {
Row {
width: dlgProperties.width
spacing: 5
Loader {
id: propertyEditor
width: dlgProperties.width - pointerButton.width
property string propertyName: modelData[0]
property var propertyType: modelData[1]
property string propertyLabel: qsTranslate('prop',propertyName)
property string propertyIcon: Utils.camelCase2readable(propertyName)
sourceComponent: {
if(propertyName.startsWith('comment'))
return commentComponent
else if(propertyType == 'boolean')
return checkboxComponent
else if(paramTypeIn(propertyType, ['Expression']))
return expressionEditorComponent
else if(paramTypeIn(propertyType, textTypes))
return textEditorComponent
else if(paramTypeIn(propertyType, comboBoxTypes))
return comboBoxComponent
else if(paramTypeIn(propertyType, listTypes))
return listDictEditorComponent
else
return {}
}
}
Button {
id: pointerButton
height: parent.height
width: visible ? height : 0
anchors.verticalCenter: parent.verticalCenter
property bool isXProp: ['labelX', 'x'].includes(propertyEditor.propertyName)
property bool isYProp: ['y'].includes(propertyEditor.propertyName)
visible: isXProp || isYProp
ToolTip.visible: hovered
ToolTip.text: qsTr("Pick on graph")
Setting.Icon {
id: icon
width: 18
height: 18
anchors.centerIn: parent
color: sysPalette.windowText
source: '../icons/common/position.svg'
}
onClicked: {
positionPicker.objType = objType
positionPicker.objName = obj.name
positionPicker.pickX = isXProp
positionPicker.pickY = isYProp
positionPicker.propertyX = propertyEditor.propertyName
positionPicker.propertyY = propertyEditor.propertyName
positionPicker.visible = true
objEditor.close()
}
}
}
}
}

View file

@ -0,0 +1,170 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
import QtQuick.Dialogs as D
import Qt.labs.platform as Native
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import eu.ad5001.LogarithmPlotter.Popup 1.0 as Popup
import "../../js/historylib.mjs" as HistoryLib
import "../../js/utils.mjs" as Utils
import "../../js/mathlib.mjs" as MathLib
/*!
\qmltype Dialog
\inqmlmodule eu.ad5001.LogarithmPlotter.ObjectLists.Editor
\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 Loader, ObjectLists
*/
Popup.BaseDialog {
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: Modules.Objects.currentObjects[objType][objIndex]
/*!
\qmlproperty var EditorDialog::posPicker
Reference to the global PositionPicker QML object.
*/
property var posPicker
title: "LogarithmPlotter"
width: 350
minimumHeight: Math.max(450,dlgProperties.height + margin*4 + 30)
maximumHeight: minimumHeight
Item {
anchors {
top: parent.top;
left: parent.left;
bottom: parent.bottom;
right: parent.right;
topMargin: margin;
leftMargin: margin;
bottomMargin: margin + 30;
rightMargin: margin;
}
Column {
id: dlgProperties
anchors.top: parent.top
width: objEditor.width - 20
spacing: 10
Label {
id: dlgTitle
verticalAlignment: TextInput.AlignVCenter
text: qsTr("Edit properties of %1 %2").arg(Modules.Objects.types[objEditor.objType].displayType()).arg(objEditor.obj.name)
font.pixelSize: 20
color: sysPalette.windowText
}
Native.MessageDialog {
id: invalidNameDialog
title: qsTr("LogarithmPlotter - Invalid object name")
text: ""
function showDialog(objectName) {
text = qsTr("An object with the name '%1' already exists.").arg(objectName)
open()
}
}
Setting.TextSetting {
id: nameProperty
height: 30
label: qsTr("Name")
icon: "common/label.svg"
category: "name"
width: dlgProperties.width
value: objEditor.obj.name
onChanged: function(newValue) {
let newName = Utils.parseName(newValue)
if(newName != '' && objEditor.obj.name != newName) {
if(newName in Modules.Objects.currentObjectsByName) {
invalidNameDialog.showDialog(newName)
} else {
history.addToHistory(new HistoryLib.NameChanged(
objEditor.obj.name, objEditor.objType, newName
))
Modules.Objects.renameObject(obj.name, newName)
objEditor.obj = Modules.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]
objEditor.obj.update()
objectListList.update()
}
}
}
// Dynamic properties
CustomPropertyList {
id: dlgCustomProperties
obj: objEditor.obj
positionPicker: posPicker
onChanged: {
obj.update()
objectListList.update()
}
}
}
}
/*!
\qmlmethod void EditorDialog::open()
Shows the editor after the object to be edited is set.
*/
function open() {
dlgCustomProperties.model = [] // Reset
let objProps = Modules.Objects.types[objEditor.objType].properties()
dlgCustomProperties.model = Object.keys(objProps).map(prop => [prop, objProps[prop]]) // Converted to 2-dimentional array.
objEditor.show()
}
}

View file

@ -0,0 +1,5 @@
module eu.ad5001.LogarithmPlotter.ObjectLists.Editor
Dialog 1.0 Dialog.qml
CustomPropertyList 1.0 CustomPropertyList.qml

View file

@ -1,306 +0,0 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition 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: "icons/settings/custom/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: "icons/settings/custom/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: `icons/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 ? `icons/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 ? `icons/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(modelData[1].objType)] : []) :
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(modelData[1].objType)] : [])
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: `icons/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,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,10 +16,11 @@
* 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/historylib.js" as HistoryLib
import QtQuick
import QtQuick.Controls
import "../js/historylib.mjs" as HistoryLib
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
/*!
\qmltype ObjectCreationGrid
@ -32,6 +33,21 @@ Column {
id: createRow
property var objectEditor
property var objectLists
property var posPicker
/*!
\qmlmethod int ObjectCreationGrid::openEditorDialog(var obj)
Opens the editor dialog for an object \c obj.
*/
function openEditorDialog(obj) {
// Open editor
objectEditor.obj = obj
objectEditor.objType = obj.type
objectEditor.objIndex = Modules.Objects.currentObjects[obj.type].indexOf(obj)
objectEditor.open()
// Disconnect potential link
posPicker.picked.disconnect(openEditorDialog)
}
Label {
id: createTitle
@ -44,29 +60,69 @@ Column {
width: parent.width
columns: 3
Repeater {
model: Object.keys(Objects.types)
model: Object.keys(Modules.Objects.types)
Button {
id: createBtn
text: Objects.types[modelData].displayType()
width: parent.width/3
visible: Objects.types[modelData].createable()
height: visible ? implicitHeight : 0
display: AbstractButton.TextUnderIcon
icon.name: modelData
icon.source: '../icons/' + modelData + '.svg'
icon.width: 24
icon.height: 24
icon.color: sysPalette.buttonText
width: 96
visible: Modules.Objects.types[modelData].createable()
height: visible ? width*0.8 : 0
// The KDE SDK is kinda buggy, so it respects neither specified color nor display propreties.
//display: AbstractButton.TextUnderIcon
Setting.Icon {
id: icon
width: 24
height: 24
anchors.left: parent.left
anchors.leftMargin: (parent.width-width)/2
anchors.top: parent.top
anchors.topMargin: (label.y-height)/2
color: sysPalette.windowText
source: '../icons/objects/'+modelData+'.svg'
}
Label {
id: label
anchors.bottom: parent.bottom
anchors.bottomMargin: 5
anchors.left: parent.left
anchors.leftMargin: 4
anchors.right: parent.right
anchors.rightMargin: 4
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 14
text: Modules.Objects.types[modelData].displayType()
wrapMode: Text.WordWrap
clip: true
}
ToolTip.visible: hovered
ToolTip.delay: 200
ToolTip.text: label.text
onClicked: {
var newObj = Objects.createNewRegisteredObject(modelData)
let newObj = Modules.Objects.createNewRegisteredObject(modelData)
history.addToHistory(new HistoryLib.CreateNewObject(newObj.name, modelData, newObj.export()))
objectLists.update()
objectEditor.obj = Objects.currentObjects[modelData][Objects.currentObjects[modelData].length - 1]
objectEditor.objType = modelData
objectEditor.objIndex = Objects.currentObjects[modelData].length - 1
objectEditor.show()
let hasXProp = newObj.constructor.properties().hasOwnProperty('x')
let hasYProp = newObj.constructor.properties().hasOwnProperty('y')
if(hasXProp || hasYProp) {
// Open picker
posPicker.objType = newObj.type
posPicker.objName = newObj.name
posPicker.pickX = hasXProp
posPicker.pickY = hasYProp
posPicker.propertyX = 'x'
posPicker.propertyY = 'y'
posPicker.visible = true
posPicker.picked.connect(openEditorDialog)
} else {
// Open editor
openEditorDialog(newObj)
}
}
}
}

View file

@ -1,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,219 +16,110 @@
* 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 "../js/objects.js" as Objects
import "../js/historylib.js" as HistoryLib
import QtQuick
// import QtQuick.Dialogs 1.3 as D
import QtQuick.Controls
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import eu.ad5001.LogarithmPlotter.ObjectLists.Editor 1.0 as Editor
/*!
\qmltype ObjectLists
\inqmlmodule eu.ad5001.LogarithmPlotter
\inqmlmodule eu.ad5001.LogarithmPlotter.ObjectLists
\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
This item allows the user to synthetically 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
*/
ListView {
ScrollView {
id: objectListList
signal changed()
property var listViews: {'':''} // Needs to be initialized or will be undefined -_-
model: Object.keys(Objects.types)
implicitHeight: contentItem.childrenRect.height + footer.height + 10
delegate: ListView {
id: objTypeList
property string objType: objectListList.model[index]
property var editingRows: []
model: Objects.currentObjects[objType]
width: objectListList.width
implicitHeight: contentItem.childrenRect.height
visible: model != undefined && model.length > 0
interactive: false
ScrollBar.horizontal.visible: false
ScrollBar.vertical.visible: true
ListView {
id: objectsListView
model: Object.keys(Modules.Objects.types)
//width: implicitWidth //objectListList.width - (implicitHeight > objectListList.parent.height ? 20 : 0)
implicitHeight: contentItem.childrenRect.height + footerItem.height + 10
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
delegate: ListView {
id: objTypeList
property string objType: objectsListView.model[index]
property var editingRows: []
model: Modules.Objects.currentObjects[objType]
width: objectsListView.width
implicitHeight: contentItem.childrenRect.height
visible: model != undefined && model.length > 0
interactive: false
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()
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: Modules.Objects.currentObjects[objType] != undefined ? Modules.Objects.currentObjects[objType].every(obj => obj.visible) : true
onClicked: {
for(var obj of Modules.Objects.currentObjects[objType]) obj.visible = this.checked
for(var obj of objTypeList.editingRows) obj.objVisible = this.checked
objectListList.changed()
}
ToolTip.visible: hovered
ToolTip.text: checked ?
qsTr("Hide all %1").arg(Modules.Objects.types[objType].displayTypeMultiple()) :
qsTr("Show all %1").arg(Modules.Objects.types[objType].displayTypeMultiple())
}
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(Modules.Objects.types[objType].displayTypeMultiple())
font.pixelSize: 20
}
}
Label {
id: typeHeaderText
verticalAlignment: TextInput.AlignVCenter
text: Objects.types[objType].displayTypeMultiple() + ":"
font.pixelSize: 20
delegate: ObjectRow {
id: controlRow
width: objTypeList.width
obj: Modules.Objects.currentObjects[objType][index]
posPicker: positionPicker
onChanged: {
obj = Modules.Objects.currentObjects[objType][index]
objectListList.update()
}
Component.onCompleted: objTypeList.editingRows.push(controlRow)
}
}
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
icon.name: 'position'
icon.source: '../icons/position.svg'
icon.color: sysPalette.buttonText
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/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())
onAccepted: {
history.addToHistory(new HistoryLib.EditedProperty(
obj.name, objType, "color",
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
posPicker: positionPicker
}
}
// Object editor
EditorDialog {
Editor.Dialog {
id: objEditor
}
// Create items
footer: ObjectCreationGrid {
id: createRow
width: parent.width
objectEditor: objEditor
objectLists: objectListList
posPicker: positionPicker
}
/*!
@ -238,7 +129,7 @@ ListView {
function update() {
objectListList.changed()
for(var objType in objectListList.listViews) {
objectListList.listViews[objType].model = Objects.currentObjects[objType]
objectListList.listViews[objType].model = Modules.Objects.currentObjects[objType]
}
}

View file

@ -0,0 +1,224 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Dialogs
import QtQuick.Controls
import QtQuick.Window
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import "../js/historylib.mjs" as HistoryLib
/*!
\qmltype ObjectRow
\inqmlmodule eu.ad5001.LogarithmPlotter.ObjectLists
\brief Row describing an object.
This item allows the user to see, control, and modify a graph object.
It includes the visibility checkbox, the description label (optionally latex if enabled),
the reposition and delete buttons, and the color picker.
\sa LogarithmPlotter, ObjectCreationGrid, ObjectLists
*/
Item {
id: objectRow
signal changed()
/*!
\qmlproperty var ObjectRow::obj
Object to show.
*/
property var obj
/*!
\qmlproperty var ObjectRow::posPicker
Reference to the global PositionPicker QML object.
*/
property var posPicker
/*!
\qmlproperty bool ObjectRow::objVisible
True if the object should be visible, false otherwise.
*/
property alias objVisible: objVisibilityCheckBox.checked
/*!
\qmlproperty bool ObjectRow::minHeight
Minimum height of the row.
*/
readonly property int minHeight: 40
height: objDescription.height
width: obj.typeList.width
CheckBox {
id: objVisibilityCheckBox
checked: obj.visible
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 5
onClicked: {
history.addToHistory(new HistoryLib.EditedVisibility(
obj.name, obj.type, this.checked
))
obj.visible = this.checked
changed()
}
ToolTip.visible: hovered
ToolTip.text: checked ?
qsTr("Hide %1 %2").arg(obj.constructor.displayType()).arg(obj.name) :
qsTr("Show %1 %2").arg(obj.constructor.displayType()).arg(obj.name)
}
Label {
id: objDescription
anchors.left: objVisibilityCheckBox.right
anchors.right: deleteButton.left
height: Modules.Latex.enabled ? Math.max(parent.minHeight, latexDescription.height+4) : parent.minHeight
verticalAlignment: TextInput.AlignVCenter
text: Modules.Latex.enabled ? "" : obj.getReadableString()
font.pixelSize: 14
Image {
id: latexDescription
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
visible: Modules.Latex.enabled
property double depth: Screen.devicePixelRatio
property var ltxInfo: visible ? Latex.render(obj.getLatexString(), depth*(parent.font.pixelSize+2), parent.color).split(",") : ["","0","0"]
source: visible ? ltxInfo[0] : ""
width: parseInt(ltxInfo[1])/depth
height: parseInt(ltxInfo[2])/depth
}
MouseArea {
anchors.fill: parent
onClicked: {
objEditor.obj = Modules.Objects.currentObjects[obj.type][index]
objEditor.objType = obj.type
objEditor.objIndex = index
//objEditor.editingRow = objectRow
objEditor.open()
}
}
}
Button {
id: pointerButton
width: parent.height - 10
height: width
anchors.right: deleteButton.left
anchors.rightMargin: 5
anchors.verticalCenter: parent.verticalCenter
Setting.Icon {
id: icon
width: 18
height: 18
anchors.centerIn: parent
color: sysPalette.windowText
source: '../icons/common/position.svg'
}
property bool hasXProp: obj.constructor.properties().hasOwnProperty('x')
property bool hasYProp: obj.constructor.properties().hasOwnProperty('y')
visible: hasXProp || hasYProp
ToolTip.visible: hovered
ToolTip.text: qsTr("Set %1 %2 position").arg(obj.constructor.displayType()).arg(obj.name)
onClicked: {
posPicker.objType = obj.type
posPicker.objName = obj.name
posPicker.pickX = hasXProp
posPicker.pickY = hasYProp
posPicker.propertyX = 'x'
posPicker.propertyY = 'y'
posPicker.visible = true
}
}
Button {
id: deleteButton
width: parent.minHeight - 10
height: width
anchors.right: colorPickRect.left
anchors.rightMargin: 5
anchors.verticalCenter: parent.verticalCenter
icon.name: 'delete'
icon.source: '../icons/common/delete.svg'
icon.color: sysPalette.buttonText
ToolTip.visible: hovered
ToolTip.text: qsTr("Delete %1 %2").arg(obj.constructor.displayType()).arg(obj.name)
onClicked: {
deleteRecursively(obj)
changed()
}
}
Rectangle {
id: colorPickRect
anchors.right: parent.right
anchors.rightMargin: 5
anchors.verticalCenter: parent.verticalCenter
color: obj.color
width: parent.minHeight - 10
height: width
radius: Math.min(width, height)
border.width: 2
border.color: sysPalette.windowText
MouseArea {
anchors.fill: parent
onClicked: pickColor.open()
}
}
ColorDialog {
id: pickColor
selectedColor: obj.color
title: qsTr("Pick new color for %1 %2").arg(obj.constructor.displayType()).arg(obj.name)
onAccepted: {
history.addToHistory(new HistoryLib.ColorChanged(
obj.name, obj.type, obj.color, selectedColor.toString()
))
obj.color = selectedColor.toString()
changed()
}
}
/*!
\qmlmethod void ObjectRow::deleteRecursively(var object)
Deletes an object and it's dependencies recursively.
*/
function deleteRecursively(object) {
for(let toRemove of object.requiredBy)
deleteRecursively(toRemove)
if(Modules.Objects.currentObjectsByName[object.name] != undefined) {
// Object still exists
// Temporary fix for objects require not being propertly updated.
object.requiredBy = []
history.addToHistory(new HistoryLib.DeleteObject(
object.name, object.type, object.export()
))
Modules.Objects.deleteObject(object.name)
}
}
}

View file

@ -2,5 +2,4 @@ module eu.ad5001.LogarithmPlotter.ObjectLists
ObjectLists 1.0 ObjectLists.qml
ObjectCreationGrid 1.0 ObjectCreationGrid.qml
EditorDialog 1.0 EditorDialog.qml
ObjectRow 1.0 ObjectRow.qml

View file

@ -1,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,11 +16,11 @@
* 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
import QtQuick
import QtQuick.Controls
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import "js/mathlib.mjs" as MathLib
import "js/historylib.mjs" as HistoryLib
/*!
\qmltype PickLocationOverlay
@ -36,6 +36,15 @@ import "js/historylib.js" as HistoryLib
Item {
id: pickerRoot
visible: false
clip: true
/*!
\qmlsignal PickLocationOverlay::picked(var obj)
Emitted when a location has been picked
The corresponding handler is \c onPicked.
*/
signal picked(var obj)
/*!
\qmlproperty var PickLocationOverlay::canvas
@ -54,12 +63,12 @@ Item {
property string objName: 'A'
/*!
\qmlproperty bool PickLocationOverlay::pickX
true if the user should be picking a position on the x axis.
true if the property in propertyX is pickable.
*/
property bool pickX: true
/*!
\qmlproperty bool PickLocationOverlay::pickY
true if the user should be picking a position on the y axis.
true if the property in propertyY is pickable.
*/
property bool pickY: true
/*!
@ -77,6 +86,16 @@ Item {
Precision of the picked value (post-dot precision).
*/
property alias precision: precisionSlider.value
/*!
\qmlproperty bool PickLocationOverlay::userPickX
true if the user can and wants to be picking a position on the x axis.
*/
readonly property bool userPickX: pickX && pickXCheckbox.checked
/*!
\qmlproperty bool PickLocationOverlay::userPickY
true if the user can and wants to be picking a position on the y axis.
*/
readonly property bool userPickY: pickY && pickYCheckbox.checked
Rectangle {
color: sysPalette.window
@ -90,66 +109,149 @@ Item {
hoverEnabled: parent.visible
cursorShape: Qt.CrossCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
onClicked: function(mouse) {
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
let newValueX = !parent.userPickX ? null : parseValue(picked.mouseX.toString(), objType, propertyX)
let newValueY = !parent.userPickY ? null : parseValue(picked.mouseY.toString(), objType, propertyY)
let obj = Modules.Objects.currentObjectsByName[objName]
// Set values
if(parent.userPickX && parent.userPickY) {
history.addToHistory(new HistoryLib.EditedPosition(
objName, objType, obj[propertyX], newValueX, obj[propertyY], newValueY
))
obj[propertyX] = newValue
obj[propertyX] = newValueX
obj[propertyY] = newValueY
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)
pickerRoot.picked(obj)
} else if(parent.userPickX) {
history.addToHistory(new HistoryLib.EditedProperty(
objName, objType, propertyY, obj[propertyY], newValue
objName, objType, propertyX, obj[propertyX], newValueX
))
obj[propertyY] = newValue
obj[propertyX] = newValueX
obj.update()
objectLists.update()
pickerRoot.picked(obj)
} else if(parent.userPickY) {
history.addToHistory(new HistoryLib.EditedProperty(
objName, objType, propertyY, obj[propertyY], newValueY
))
obj[propertyY] = newValueY
obj.update()
objectLists.update()
pickerRoot.picked(obj)
}
}
pickerRoot.visible = false;
}
}
Row {
height: precisionSlider.height
Text {
text: " "+ qsTr("Pointer precision:") + " "
color: 'black'
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
id: pickerSettings
radius: 15
color: sysPalette.window
width: pickerSettingsColumn.width + 30;
height: pickerSettingsColumn.height + 20
property bool folded: false;
x: -15 - ((width-55) * folded);
y: 10
z: 2
Slider {
id: precisionSlider
from: 0
value: 2
to: 10
stepSize: 1
ToolTip {
parent: precisionSlider.handle
visible: precisionSlider.pressed
text: precisionSlider.value.toFixed(0)
Row {
id: pickerSettingsColumn
anchors {
left: parent.left
top: parent.top
leftMargin: 20
topMargin: 10
}
spacing: 15
property int cellHeight: 15
Column {
spacing: 5
// width: 100
Text {
text: qsTr("Pointer precision:")
color: sysPalette.windowText
verticalAlignment: Text.AlignVCenter
height: pickerSettingsColumn.cellHeight
}
Text {
text: qsTr("Snap to grid:")
color: sysPalette.windowText
verticalAlignment: Text.AlignVCenter
height: pickerSettingsColumn.cellHeight
}
CheckBox {
id: pickXCheckbox
height: pickerSettingsColumn.cellHeight
text: qsTr("Pick X")
checked: pickX
visible: pickX
}
}
Column {
spacing: 5
Slider {
id: precisionSlider
from: 0
value: 2
to: 10
stepSize: 1
height: pickerSettingsColumn.cellHeight
ToolTip {
parent: precisionSlider.handle
visible: precisionSlider.pressed
text: precisionSlider.value.toFixed(0)
}
}
CheckBox {
id: snapToGridCheckbox
height: pickerSettingsColumn.cellHeight
// text: qsTr("Snap to grid")
checked: false
}
CheckBox {
id: pickYCheckbox
height: pickerSettingsColumn.cellHeight
text: qsTr("Pick Y")
checked: pickY
visible: pickY
}
}
Button {
width: 24
anchors.top: parent.top
anchors.bottom: parent.bottom
flat: true
onClicked: pickerSettings.folded = !pickerSettings.folded
ToolTip.visible: hovered
ToolTip.delay: 200
ToolTip.text: pickerSettings.folded ? qsTr("Open picker settings") : qsTr("Hide picker settings")
Setting.Icon {
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
width: 18
height: 18
color: sysPalette.windowText
source: `../icons/common/settings.svg`
}
}
}
CheckBox {
id: snapToGridCheckbox
text: qsTr("Snap to grid")
checked: false
}
}
@ -160,8 +262,8 @@ Item {
color: 'black'
anchors.top: parent.top
anchors.left: parent.left
anchors.leftMargin: canvas.x2px(picked.mouseX)
visible: parent.pickX
anchors.leftMargin: Modules.Canvas.x2px(picked.mouseX)
visible: parent.userPickX
}
Rectangle {
@ -171,47 +273,60 @@ Item {
color: 'black'
anchors.top: parent.top
anchors.left: parent.left
anchors.topMargin: canvas.y2px(picked.mouseY)
visible: parent.pickY
anchors.topMargin: Modules.Canvas.y2px(picked.mouseY)
visible: parent.userPickY
}
Text {
id: picked
x: picker.mouseX - width - 5
y: picker.mouseY - height - 5
property double axisX: canvas.xaxisstep1
color: 'black'
property double axisX: Modules.Canvas.axesStep.x.value
property double axisY: Modules.Canvas.axesStep.y.value
property double mouseX: {
let xpos = canvas.px2x(picker.mouseX)
let xpos = Modules.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)
return axisX*Math.round(xpos/axisX)
}
} else {
return xpos.toFixed(parent.precision)
}
}
property double mouseY: {
let ypos = canvas.px2y(picker.mouseY)
let ypos = Modules.Canvas.px2y(picker.mouseY)
if(snapToGridCheckbox.checked) {
return canvas.yaxisstep1*Math.round(ypos/canvas.yaxisstep1)
return axisY*Math.round(ypos/axisY)
} else {
return ypos.toFixed(parent.precision)
}
}
color: 'black'
text: {
if(parent.pickX && parent.pickY)
if(parent.userPickX && parent.userPickY)
return `(${mouseX}, ${mouseY})`
if(parent.pickX)
else if(parent.userPickX)
return `X = ${mouseX}`
if(parent.pickY)
else if(parent.userPickY)
return `Y = ${mouseY}`
else
return qsTr('(no pick selected)')
}
}
/*!
\qmlmethod void History::parseValue(string value, string objType, string propertyName)
Parses a given \c value as an expression or a number depending on the type of \c propertyName of all \c objType.
*/
function parseValue(value, objType, propertyName) {
if(Modules.Objects.types[objType].properties()[propertyName] == 'number')
return parseFloat(value)
else
return new MathLib.Expression(value)
}
}

View file

@ -1,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,9 +16,8 @@
* 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 QtQuick
import QtQuick.Controls
/*!
\qmltype About
@ -27,87 +26,112 @@ import QtQuick.Controls 2.12
\sa LogarithmPlotter
*/
D.Dialog {
BaseDialog {
id: about
title: qsTr("About LogarithmPlotter")
width: 400
height: 600
minimumHeight: 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>
Item {
anchors {
top: parent.top;
left: parent.left;
bottom: parent.bottom;
right: parent.right;
topMargin: margin;
leftMargin: margin;
bottomMargin: margin;
rightMargin: margin;
}
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 © 2021-2024 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: Helper.openUrl(link)
}
Button {
id: openIssueButton
anchors.top: copyrightInfos.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 10
text: qsTr('Report a bug')
icon.name: 'bug'
onClicked: Helper.openUrl('https://git.ad5001.eu/Ad5001/LogarithmPlotter')
onLinkActivated: Qt.openUrlExternally(link)
}
Row {
id: buttonsRow
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,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.12
import QtQuick
/*!
\qmltype Alert
\inqmlmodule eu.ad5001.LogarithmPlotter.Popup

View file

@ -0,0 +1,59 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
/*!
\qmltype BaseDialog
\inqmlmodule eu.ad5001.LogarithmPlotter.Popup
\brief Base dialog window in replacement of Dialog Popup from Qt 5.
\sa LogarithmPlotter
*/
Window {
id: base
color: sysPalette.window
visible: false;
flags: Qt.Dialog | Qt.Popup | Qt.MSWindowsFixedSizeDialogHint
modality: Qt.WindowModal
minimumWidth: width
maximumWidth: width
height: minimumHeight
property int margin: 10
Button {
id: closeButton
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.bottomMargin: margin
anchors.rightMargin: margin
text: qsTr('Close')
onClicked: close()
}
Shortcut {
sequence: "Esc"
onActivated: base.close()
}
function open() {
show()
}
}

View file

@ -1,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,8 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick
import QtQuick.Controls
/*!
\qmltype Changelog
@ -32,7 +32,7 @@ Popup {
id: changelogPopup
x: (parent.width-width)/2
y: Math.max(20, (parent.height-height)/2)
width: changelog.width+40
width: 800
height: Math.min(parent.height-40, 500)
modal: true
focus: true
@ -44,42 +44,62 @@ Popup {
*/
property bool changelogNeedsFetching: true
onAboutToShow: if(changelogNeedsFetching) Helper.fetchChangelog()
onAboutToShow: if(changelogNeedsFetching) {
Helper.fetchChangelog()
}
Connections {
target: Helper
function onChangelogFetched(chl) {
changelogNeedsFetching = false;
changelog.text = chl
changelogView.contentItem.implicitHeight = changelog.height
// console.log(changelog.height, changelogView.contentItem.implicitHeight)
}
}
ScrollView {
id: changelogView
anchors.top: parent.top
anchors.topMargin: 10
anchors.left: parent.left
anchors.leftMargin: 10
anchors.right: parent.right
anchors.rightMargin: 10
anchors.bottom: doneBtn.top
anchors.bottomMargin: 10
clip: true
Label {
id: changelog
color: sysPalette.windowText
width: 760
wrapMode: Text.WordWrap
textFormat: TextEdit.MarkdownText
text: qsTr("Fetching changelog...")
onLinkActivated: Helper.openUrl(link)
onLinkActivated: Qt.openUrlExternally(link)
}
}
Rectangle {
id: bottomSeparator
opacity: 0.3
color: sysPalette.windowText
width: parent.width * 2 / 3
height: 1
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: doneBtn.top
anchors.bottomMargin: 7
}
Button {
id: doneBtn
text: qsTr("Done")
text: qsTr("Close")
font.pixelSize: 18
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
anchors.bottomMargin: 7
anchors.horizontalCenter: parent.horizontalCenter
onClicked: changelogPopup.close()
}

View file

@ -1,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick.Dialogs 1.3 as D
import Qt.labs.platform
/*!
\qmltype FileDialog
@ -25,7 +25,7 @@ import QtQuick.Dialogs 1.3 as D
\sa LogarithmPlotter, Settings
*/
D.FileDialog {
FileDialog {
id: fileDialog
property bool exportMode: false
@ -33,6 +33,6 @@ D.FileDialog {
title: exportMode ? qsTr("Export Logarithm Plot file") : qsTr("Import Logarithm Plot file")
nameFilters: ["Logarithm Plot File (*.lpf)", "All files (*)"]
folder: shortcuts.documents
selectExisting: !exportMode
defaultSuffix: 'lpf'
fileMode: exportMode ? FileDialog.SaveFile : FileDialog.OpenFile
}

View file

@ -1,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,8 +16,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick
import QtQuick.Controls
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
/*!
\qmltype GreetScreen
@ -32,116 +33,123 @@ 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)
width: greetingLayout.width+20
height: Math.min(parent.height-40, 700)
modal: true
focus: true
clip: 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
}
Column {
id: greetingLayout
width: 600
spacing: 10
clip: true
topPadding: 35
Row {
id: welcome
height: logo.height
spacing: 10
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
wrapMode: Text.WordWrap
font.pixelSize: 32
text: qsTr("Welcome to LogarithmPlotter")
}
}
Label {
id: welcomeText
anchors.verticalCenter: parent.verticalCenter
anchors.left: logo.right
anchors.leftMargin: 10
//width: parent.width
id: versionText
anchors.horizontalCenter: parent.horizontalCenter
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
anchors.horizontalCenter: parent.horizontalCenter
Button {
id: changelogBtn
text: qsTr("Changelog")
width: implicitWidth
font.pixelSize: 18
onClicked: changelog.open()
}
Button {
id: doneBtn
text: qsTr("Done")
font.pixelSize: 18
onClicked: greetingPopup.close()
font.italic: true
text: qsTr("Version %1").arg(Helper.getVersion())
}
}
Grid {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: greetingLayout.bottom
anchors.topMargin: 50
columns: 2
spacing: 10
Repeater {
model: [{
name: qsTr("Changelog"),
icon: 'common/new.svg',
onClicked: () => changelog.open()
},{
name: qsTr("Preferences"),
icon: 'common/settings.svg',
onClicked: () => preferences.open()
},{
name: qsTr("User manual"),
icon: 'common/manual.svg',
onClicked: () => Qt.openUrlExternally("https://git.ad5001.eu/Ad5001/LogarithmPlotter/wiki/_Sidebar")
},{
name: qsTr("Close"),
icon: 'common/close.svg',
onClicked: () => greetingPopup.close()
}]
Button {
id: createBtn
width: 96
height: 96
onClicked: modelData.onClicked()
Timer {
running: Helper.getSetting("last_install_greet") != Helper.getVersion()
repeat: false
interval: 50
onTriggered: greetingPopup.open()
Setting.Icon {
id: icon
width: 24
height: 24
anchors {
left: parent.left
leftMargin: (parent.width-width)/2
top: parent.top
topMargin: (label.y-height)/2
}
color: sysPalette.windowText
source: '../icons/' + modelData.icon
}
Label {
id: label
anchors {
bottom: parent.bottom
bottomMargin: 5
left: parent.left
leftMargin: 4
right: parent.right
rightMargin: 4
}
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 14
text: modelData.name
wrapMode: Text.WordWrap
clip: true
}
}
}
}
Component.onCompleted: if(Helper.getSetting("last_install_greet") != Helper.getVersion()+1) {
greetingPopup.open()
}
onClosed: Helper.setSetting("last_install_greet", Helper.getVersion())

View file

@ -0,0 +1,106 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick.Controls
import QtQuick
/*!
\qmltype InsertCharacter
\inqmlmodule eu.ad5001.LogarithmPlotter.Setting
\brief Popup to insert special character.
\sa TextSetting, ExpressionEditor
*/
Popup {
id: insertPopup
signal selected(string character)
/*!
\qmlproperty string InsertCharacter::category
Type of special character to insert.
Possible values:
- expression
- domain
- name
- all
*/
property string category: 'all'
width: 280
height: Math.ceil(insertGrid.insertChars.length/insertGrid.columns)*(width/insertGrid.columns)+5
modal: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
Grid {
id: insertGrid
width: parent.width
columns: 7
property var insertCharsExpression: [
"∞","π","¹","²","³","⁴","⁵",
"⁶","⁷","⁸","⁹","⁰"
]
property var insertCharsDomain: [
"∅","","∩","","","","",
"⁺","⁻",...insertCharsExpression
]
property var insertCharsName: [
"α","β","γ","δ","ε","ζ","η",
"π","θ","κ","λ","μ","ξ","ρ",
"ς","σ","τ","φ","χ","ψ","ω",
"Γ","Δ","Θ","Λ","Ξ","Π","Σ",
"Φ","Ψ","Ω","ₐ","ₑ","ₒ","ₓ",
"ₕ","ₖ","ₗ","ₘ","ₙ","ₚ","ₛ",
"ₜ","₁","₂","₃","₄","₅","₆",
"₇","₈","₉","₀"
]
property var insertCharsAll: [
...insertCharsName, ...insertCharsDomain
]
property var insertChars: {
return {
"expression": insertCharsExpression,
"domain": insertCharsDomain,
"name": insertCharsName,
"all": insertCharsAll
}[insertPopup.category]
}
Repeater {
model: parent.insertChars.length
Button {
id: insertBtn
width: insertGrid.width/insertGrid.columns
height: width
text: insertGrid.insertChars[modelData]
flat: text == " "
font.pixelSize: 18
onClicked: {
selected(text)
}
}
}
}
}

View file

@ -0,0 +1,257 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import "../js/preferences/common.mjs" as S
import "../js/utils.mjs" as Utils
/*!
\qmltype Preferences
\inqmlmodule eu.ad5001.LogarithmPlotter.Popup
\brief Popup to change global application preferences.
\sa LogarithmPlotter, GreetScreen
*/
Popup {
id: preferencesPopup
x: (parent.width-width)/2
y: Math.max(20, (parent.height-height)/2)
width: settingPopupRow.width + 30
height: settingPopupRow.height + 20
modal: true
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
// Components for the preferences
Component {
id: boolSettingComponent
CheckBox {
height: 20
text: setting.displayName
checked: setting.value()
onClicked: setting.set(this.checked)
}
}
Component {
id: enumIntSettingComponent
// Setting when selecting data from an enum, or an object of a certain type.
Setting.ComboBoxSetting {
height: 30
label: setting.displayName
icon: `settings/${setting.icon}.svg`
currentIndex: setting.value()
model: setting.values
onActivated: function(newIndex) { setting.set(newIndex) }
}
}
Component {
id: stringSettingComponent
Setting.ComboBoxSetting {
height: 30
label: setting.displayName
icon: `settings/${setting.icon}.svg`
editable: true
currentIndex: find(setting.value())
model: setting.defaultValues
onAccepted: function() {
editText = Utils.parseName(editText, false)
if(find(editText) === -1) model.append(editText)
setting.set(editText)
}
onActivated: function(selectedId) {
setting.set(model[selectedId])
}
Component.onCompleted: editText = setting.value()
}
}
Component {
id: numberSettingComponent
Setting.TextSetting {
height: 30
isDouble: true
label: setting.displayName
min: setting.min()
icon: `settings/${setting.icon}.svg`
value: setting.value()
onChanged: function(newValue) {
if(newValue < setting.max())
setting.set(newValue)
else {
value = setting.max()
setting.set(setting.max())
}
}
}
}
Component {
id: expressionSettingComponent
Setting.ExpressionEditor {
height: 30
label: setting.displayName
icon: `settings/${setting.icon}.svg`
defValue: Utils.simplifyExpression(setting.value())
variables: setting.variables
allowGraphObjects: false
property string propertyName: setting.displayName
onChanged: function(newExpr) {
try {
setting.set(newExpr)
} catch(e) {
errorDialog.showDialog(propertyName, newExpr, e.message)
}
}
}
}
Row {
id: settingPopupRow
height: 300
width: categories.width + categorySeparator.width + settingView.width + 70
spacing: 15
anchors {
top: parent.top
bottom: parent.bottom
left: parent.left
right: parent.right
topMargin: 10
bottomMargin: 10
rightMargin: 15
leftMargin: 15
}
ColumnLayout {
id: categories
width: 150
height: parent.height
spacing: 0
clip: true
Repeater {
model: Object.keys(Modules.Preferences.categories)
Button {
// width: 150
Layout.fillWidth: true
text: qsTranslate('settingCategory', modelData)
onClicked: {
settingView.model = Modules.Preferences.categories[modelData]
settingView.name = text
}
}
}
Item {
Layout.fillHeight: true
Layout.fillWidth: true
Button {
id: closeButton
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
text: qsTr('Close')
onClicked: preferencesPopup.close()
}
}
}
Rectangle {
id: categorySeparator
anchors {
top: parent.top
topMargin: 5
}
opacity: 0.3
color: sysPalette.windowText
height: parent.height - 10
width: 1
}
ListView {
id: settingView
clip: true
width: 500
spacing: 10
model: Modules.Preferences.categories.general
anchors {
top: parent.top
bottom: parent.bottom
}
ScrollBar.vertical: ScrollBar { }
property string name: qsTranslate('settingCategory', 'general')
header: Text {
id: settingCategoryName
font.pixelSize: 32
height: 48
color: sysPalette.windowText
text: settingView.name
Rectangle {
id: bottomSeparator
anchors.bottom: parent.bottom
anchors.bottomMargin: 8
opacity: 0.3
color: sysPalette.windowText
width: settingView.width
height: 1
}
}
delegate: Component {
Loader {
width: settingView.width * 2 / 3
property var setting: modelData
sourceComponent: {
if(setting instanceof S.BoolSetting)
return boolSettingComponent
else if(setting instanceof S.EnumIntSetting)
return enumIntSettingComponent
else if(setting instanceof S.NumberSetting)
return numberSettingComponent
else if(setting instanceof S.ExpressionSetting)
return expressionSettingComponent
else if(setting instanceof S.StringSetting)
return stringSettingComponent
else
console.log('Unknown setting type!', modelData.constructor)
}
}
}
}
}
// Component.onCompleted: open()
}

View file

@ -0,0 +1,334 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Dialogs
import QtQuick.Controls
/*!
\qmltype ThanksTo
\inqmlmodule eu.ad5001.LogarithmPlotter.Popup
\brief Thanks to popup of LogarithmPlotter.
\sa LogarithmPlotter
*/
BaseDialog {
id: about
title: qsTr("Thanks and Contributions - LogarithmPlotter")
width: 450
minimumHeight: 710
Column {
anchors {
top: parent.top;
left: parent.left;
bottom: parent.bottom;
right: parent.right;
topMargin: margin;
leftMargin: margin;
bottomMargin: margin;
rightMargin: margin;
}
spacing: 10
ListView {
id: librariesListView
anchors.left: parent.left
width: parent.width
//height: parent.height
implicitHeight: contentItem.childrenRect.height
interactive: false
model: ListModel {
Component.onCompleted: {
append({
libName: 'expr-eval',
license: 'MIT',
licenseLink: 'https://raw.githubusercontent.com/silentmatt/expr-eval/master/LICENSE.txt',
linkName: qsTr('Source code'),
link: 'https://github.com/silentmatt/expr-eval',
authors: [{
authorLine: qsTr('Original library by Raphael Graf'),
email: 'r@undefined.ch',
website: 'https://web.archive.org/web/20111023001618/http://www.undefined.ch/mparser/index.html',
websiteName: qsTr('Source')
}, {
authorLine: qsTr('Ported to Javascript by Matthew Crumley'),
email: 'email@matthewcrumley.com',
website: 'https://silentmatt.com/',
websiteName: qsTr('Website')
}, {
authorLine: qsTr('Ported to QMLJS by Ad5001'),
email: 'mail@ad5001.eu',
website: 'https://ad5001.eu/',
websiteName: qsTr('Website')
}]
})
}
}
header: Label {
id: librariesUsedHeader
wrapMode: Text.WordWrap
font.pixelSize: 25
text: qsTr("Libraries included")
height: implicitHeight + 10
}
delegate: Column {
id: libClmn
width: librariesListView.width
spacing: 10
Item {
height: libraryHeader.height
width: parent.width
Label {
id: libraryHeader
anchors.left: parent.left
wrapMode: Text.WordWrap
font.pixelSize: 18
text: libName
}
Row {
anchors.right: parent.right
height: parent.height
spacing: 10
Button {
height: parent.height
text: license
icon.name: 'license'
onClicked: Qt.openUrlExternally(licenseLink)
}
Button {
height: parent.height
text: linkName
icon.name: 'web-browser'
onClicked: Qt.openUrlExternally(link)
}
}
}
ListView {
id: libAuthors
anchors.left: parent.left
anchors.leftMargin: 10
model: authors
width: parent.width - 10
implicitHeight: contentItem.childrenRect.height
interactive: false
delegate: Item {
id: libAuthor
width: librariesListView.width - 10
height: 50
Label {
id: libAuthorName
anchors.left: parent.left
anchors.right: buttons.left
anchors.verticalCenter: parent.verticalCenter
wrapMode: Text.WordWrap
font.pixelSize: 14
text: authorLine
}
Row {
id: buttons
anchors.right: parent.right
height: parent.height
spacing: 10
Button {
anchors.verticalCenter: parent.verticalCenter
text: websiteName
icon.name: 'web-browser'
height: parent.height - 10
onClicked: Qt.openUrlExternally(website)
}
Button {
anchors.verticalCenter: parent.verticalCenter
text: qsTr('Email')
icon.name: 'email'
height: parent.height - 10
onClicked: Qt.openUrlExternally('mailto:' + email)
}
}
}
}
Rectangle {
id: libSeparator
opacity: 0.3
color: sysPalette.windowText
width: parent.width
height: 1
}
}
}
ListView {
id: translationsListView
anchors.left: parent.left
width: parent.width
implicitHeight: contentItem.childrenRect.height
interactive: false
spacing: 3
model: ListModel {
Component.onCompleted: {
append({
tranName: '🇬🇧 ' + qsTr('English'),
link: 'https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/en/',
authors: [{
authorLine: 'Ad5001',
email: 'mail@ad5001.eu',
website: 'https://ad5001.eu',
websiteName: qsTr('Website')
}]
})
append({
tranName: '🇫🇷 ' + qsTr('French'),
link: 'https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/fr/',
authors: [{
authorLine: 'Ad5001',
website: 'https://ad5001.eu',
websiteName: qsTr('Website')
}]
})
append({
tranName: '🇩🇪 ' + qsTr('German'),
link: 'https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/de/',
authors: [{
authorLine: 'Ad5001',
website: 'https://ad5001.eu',
websiteName: qsTr('Website')
}]
})
append({
tranName: '🇭🇺 ' + qsTr('Hungarian'),
link: 'https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/hu/',
authors: [{
authorLine: 'Óvári',
website: 'https://github.com/ovari',
websiteName: qsTr('Github')
}]
})
append({
tranName: '🇳🇴 ' + qsTr('Norwegian'),
link: 'https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/no/',
authors: [{
authorLine: 'Allan Nordhøy',
website: 'https://github.com/comradekingu',
websiteName: qsTr('Github')
}]
})
}
}
header: Label {
id: translationsHeader
wrapMode: Text.WordWrap
font.pixelSize: 25
text: qsTr("Translations included")
height: implicitHeight + 10
}
delegate: Column {
id: tranClmn
width: translationsListView.width
Item {
width: parent.width
height: translationHeader.height + 10
Label {
id: translationHeader
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
wrapMode: Text.WordWrap
font.pixelSize: 18
text: tranName
}
Row {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
height: 30
spacing: 10
Button {
height: parent.height
text: qsTr('Improve')
icon.name: 'web-browser'
onClicked: Qt.openUrlExternally(link)
}
}
}
ListView {
id: tranAuthors
anchors.left: parent.left
anchors.leftMargin: 10
model: authors
width: parent.width - 10
implicitHeight: contentItem.childrenRect.height
interactive: false
delegate: Item {
id: tranAuthor
width: tranAuthors.width
height: 40
Label {
id: tranAuthorName
anchors.left: parent.left
anchors.right: buttons.left
anchors.verticalCenter: parent.verticalCenter
wrapMode: Text.WordWrap
font.pixelSize: 14
text: authorLine
}
Row {
id: buttons
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
height: 30
spacing: 10
Button {
text: websiteName
icon.name: 'web-browser'
height: parent.height
onClicked: Qt.openUrlExternally(website)
}
}
}
}
}
}
}
}

View file

@ -1,8 +1,11 @@
module eu.ad5001.LogarithmPlotter.Popup
BaseDialog 1.0 BaseDialog.qml
About 1.0 About.qml
Alert 1.0 Alert.qml
FileDialog 1.0 FileDialog.qml
GreetScreen 1.0 GreetScreen.qml
Changelog 1.0 Changelog.qml
ThanksTo 1.0 ThanksTo.qml
InsertCharacter 1.0 InsertCharacter.qml
Preferences 1.0 Preferences.qml

View file

@ -0,0 +1,125 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
/*!
\qmltype AutocompletionCategory
\inqmlmodule eu.ad5001.LogarithmPlotter.Setting
\brief ListView representing a category of autocompletion.
\sa ExpressionEditor
*/
ListView {
id: listFiltered
/*!
\qmlproperty int AutocompletionCategory::itemStartIndex
Start index of the first element in this list compared to the global autocompletion index.
*/
property int itemStartIndex: 0
/*!
\qmlproperty int AutocompletionCategory::itemSelected
The global autocompletion index.
*/
property int itemSelected: 0
/*!
\qmlproperty string AutocompletionCategory::category
Name of the category.
*/
property string category: ""
/*!
\qmlproperty var AutocompletionCategory::categoryItems
List of items in this category. To be filtered by the autocomplete to filters.
*/
property var categoryItems: []
/*!
\qmlproperty var AutocompletionCategory::autocompleteGenerator
Javascript function taking the name of the item to create an autocompletion item (dictionary with
a 'text', 'annotation' 'autocomplete', and 'cursorFinalOffset' keys.
*/
property var autocompleteGenerator: (item) => {return {'text': item, 'autocomplete': item, 'annotation': '', 'cursorFinalOffset': 0}}
/*!
\qmlproperty string AutocompletionCategory::baseText
Text to autocomplete.
*/
property string baseText: ""
/*!
\qmlproperty bool AutocompletionCategory::visbilityCondition
Condition to be met for the category to be visible.
*/
property bool visbilityCondition: true
width: parent.width
visible: model.length > 0
implicitHeight: contentItem.childrenRect.height
model: visbilityCondition ? categoryItems.filter((item) => item.includes(baseText)).map(autocompleteGenerator) : []
header: Column {
width: listFiltered.width
spacing: 2
topPadding: 5
bottomPadding: 5
Text {
leftPadding: 5
text: listFiltered.category
color: sysPalette.windowText
}
Rectangle {
height: 1
color: 'gray'
width: parent.width
}
}
delegate: Rectangle {
property bool selected: index + listFiltered.itemStartIndex == listFiltered.itemSelected
width: listFiltered.width
height: Math.max(autocompleteText.height, annotationText.height)
color: selected ? sysPalette.highlight : 'transparent'
Text {
id: autocompleteText
topPadding: 2
bottomPadding: 2
leftPadding: 15
text: listFiltered.model[index].text
color: parent.selected ? sysPalette.highlightedText : sysPalette.windowText
}
Text {
id: annotationText
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
topPadding: 2
bottomPadding: 2
rightPadding: 15
font.pixelSize: autocompleteText.font.pixelSize - 2
text: listFiltered.model[index].annotation
color: parent.selected ? sysPaletteIn.highlightedText : sysPaletteIn.windowText
}
}
}

View file

@ -1,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,8 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick
import QtQuick.Controls
/*!
\qmltype ComboBoxSetting
@ -103,7 +103,7 @@ Item {
id: iconLabel
anchors.top: parent.top
anchors.topMargin: icon == "" ? 0 : 3
source: control.visible ? "../" + control.icon : ""
source: control.visible ? "../icons/" + control.icon : ""
width: height
height: icon == "" && visible ? 0 : 24
color: sysPalette.windowText
@ -114,6 +114,7 @@ Item {
anchors.left: iconLabel.right
anchors.leftMargin: icon == "" ? 0 : 5
height: 30
width: Math.max(85, implicitWidth)
anchors.top: parent.top
verticalAlignment: TextInput.AlignVCenter
text: qsTranslate("control", "%1: ").arg(control.label)

View file

@ -0,0 +1,634 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick.Controls
import QtQuick
import Qt.labs.platform as Native
import eu.ad5001.LogarithmPlotter.Popup 1.0 as P
import "../js/mathlib.mjs" as MathLib
import "../js/utils.mjs" as Utils
import "../js/parsing/parsing.mjs" as Parsing
/*!
\qmltype ExpressionEditor
\inqmlmodule eu.ad5001.LogarithmPlotter.Setting
\brief Setting to edit strings and numbers.
\sa EditorDialog, AutocompletionCategory
*/
Item {
id: control
height: 30
/*!
\qmlsignal ExpressionEditor::changed(var newValue)
Emitted when the value of the expression has been changed.
The corresponding handler is \c onChanged.
*/
signal changed(var newValue)
/*!
\qmlproperty string ExpressionEditor::defValue
Default editable expression value of the editor.
*/
property string defValue
/*!
\qmlproperty string ExpressionEditor::value
Value of the editor.
*/
property alias value: editor.text
/*!
\qmlproperty string ExpressionEditor::self
Object or context of the expression to be edited.
Used to prevent circular dependency.
*/
property string self: ""
/*!
\qmlproperty var ExpressionEditor::variables
Accepted variables for the expression.
*/
property var variables: []
/*!
\qmlproperty string ExpressionEditor::placeholderText
Value of the editor.
*/
property alias placeholderText: editor.placeholderText
/*!
\qmlproperty string ExpressionEditor::label
Label of the editor.
*/
property string label
/*!
\qmlproperty string ExpressionEditor::icon
Icon path of the editor.
*/
property string icon: ""
/*!
\qmlproperty bool ExpressionEditor::allowGraphObjects
If true, allows graph objects to be used as part of the expression.
*/
property bool allowGraphObjects: true
/*!
\qmlproperty var ExpressionEditor::errorDialog
Allows to summon the error dialog when using additional external parsing.
*/
readonly property alias errorDialog: parsingErrorDialog
/*!
\qmlproperty string ExpressionEditor::openAndCloseMatches
Characters that when pressed, should be immediately followed up by their closing character.
TODO: Make it configurable.
*/
readonly property var openAndCloseMatches: {
"(": ")",
"[": "]",
"'": "'",
'"': '"'
}
/*!
\qmlproperty string ExpressionEditor::colorSchemes
Color schemes of the editor.
*/
readonly property var colorSchemes: [
{ // Breeze Light
'NORMAL': "#1F1C1B",
'VARIABLE': "#0057AE",
'CONSTANT': "#006E28",
'FUNCTION': "#644A9B",
'OPERATOR': "#CA60CA",
'STRING': "#BF0303",
'NUMBER': "#B08000"
},
{ // Breeze Dark
'NORMAL': "#CFCFC2",
'VARIABLE': "#2980B9",
'CONSTANT': "#27AE60",
'FUNCTION': "#8E44AD",
'OPERATOR': "#A44EA4",
'STRING': "#F44F4F",
'NUMBER': "#F67400"
},
{ // Solarized
'NORMAL': "#839496",
'VARIABLE': "#B58900",
'CONSTANT': "#859900",
'FUNCTION': "#268BD2",
'OPERATOR': "#859900",
'STRING': "#2AA198",
'NUMBER': "#2AA198"
},
{ // GitHub Light
'NORMAL': "#24292E",
'VARIABLE': "#D73A49",
'CONSTANT': "#6F42C1",
'FUNCTION': "#6F42C1",
'OPERATOR': "#24292E",
'STRING': "#032F62",
'NUMBER': "#005CC5"
},
{ // GitHub Dark
'NORMAL': "#E1E4E8",
'VARIABLE': "#F97583",
'CONSTANT': "#B392f0",
'FUNCTION': "#B392f0",
'OPERATOR': "#E1E4E8",
'STRING': "#9ECBFF",
'NUMBER': "#79B8FF"
},
{ // Nord
'NORMAL': "#D8DEE9",
'VARIABLE': "#81A1C1",
'CONSTANT': "#8FBCBB",
'FUNCTION': "#88C0D0",
'OPERATOR': "#81A1C1",
'STRING': "#A3BE8C",
'NUMBER': "#B48EAD"
},
{ // Monokai
'NORMAL': "#F8F8F2",
'VARIABLE': "#66D9EF",
'CONSTANT': "#F92672",
'FUNCTION': "#A6E22E",
'OPERATOR': "#F8F8F2",
'STRING': "#E6DB74",
'NUMBER': "#AE81FF"
}
]
Icon {
id: iconLabel
anchors.top: parent.top
anchors.topMargin: icon == "" ? 0 : 3
source: control.visible && icon != "" ? "../icons/" + control.icon : ""
width: height
height: icon == "" || !visible ? 0 : 24
color: sysPalette.windowText
}
Label {
id: labelItem
anchors.left: iconLabel.right
anchors.leftMargin: icon == "" ? 0 : 5
anchors.top: parent.top
height: parent.height
width: Math.max(85, implicitWidth)
verticalAlignment: TextInput.AlignVCenter
//color: sysPalette.windowText
text: visible ? qsTranslate("control", "%1: ").arg(control.label) : ""
visible: control.label != ""
}
Native.MessageDialog {
id: parsingErrorDialog
title: qsTranslate("expression", "LogarithmPlotter - Parsing error")
text: ""
function showDialog(propName, propValue, error) {
text = qsTranslate("expression", "Error while parsing expression for property %1:\n%2\n\nEvaluated expression: %3").arg(propName).arg(error).arg(propValue)
open()
}
}
TextField {
id: editor
anchors.top: parent.top
anchors.left: labelItem.right
anchors.leftMargin: 5
width: control.width - (labelItem.visible ? labelItem.width + 5 : 0) - iconLabel.width - 5
height: parent.height
verticalAlignment: TextInput.AlignVCenter
horizontalAlignment: control.label == "" ? TextInput.AlignLeft : TextInput.AlignHCenter
text: control.defValue
color: syntaxHighlightingEnabled ? sysPalette.window : sysPalette.windowText
focus: true
selectByMouse: true
property bool autocompleteEnabled: Helper.getSettingBool("autocompletion.enabled")
property bool syntaxHighlightingEnabled: Helper.getSettingBool("expression_editor.colorize")
property bool autoClosing: Helper.getSettingBool("expression_editor.autoclose")
property var tokens: autocompleteEnabled || syntaxHighlightingEnabled ? parent.tokens(text) : []
Keys.priority: Keys.BeforeItem // Required for knowing which key the user presses.
onEditingFinished: {
if(insertButton.focus || insertPopup.focus) return
let value = text
if(value != "" && value.toString() != defValue) {
let expr = parse(value)
if(expr != null) {
control.changed(expr)
defValue = expr.toEditableString()
}
}
}
onActiveFocusChanged: {
if(activeFocus && autocompleteEnabled)
autocompletePopup.open()
else
autocompletePopup.close()
}
cursorDelegate: Rectangle {
visible: editor.cursorVisible
color: sysPalette.windowText
width: editor.cursorRectangle.width
}
Keys.onUpPressed: function(event) {
if(autocompleteEnabled)
if(acPopupContent.itemSelected == 0)
acPopupContent.itemSelected = acPopupContent.itemCount-1
else
acPopupContent.itemSelected = acPopupContent.itemSelected-1
event.accepted = true
}
Keys.onDownPressed: function(event) {
if(autocompleteEnabled)
if(acPopupContent.itemSelected == Math.min(acPopupContent.itemCount-1))
acPopupContent.itemSelected = 0
else
acPopupContent.itemSelected = acPopupContent.itemSelected+1
event.accepted = true
}
Keys.onPressed: function(event) {
// Autocomplete popup events
if(autocompleteEnabled && (event.key == Qt.Key_Enter || event.key == Qt.Key_Return) && acPopupContent.itemCount > 0) {
acPopupContent.autocomplete()
event.accepted = true
} else
acPopupContent.itemSelected = 0
if(event.text in openAndCloseMatches && autoClosing) {
let start = selectionStart
insert(selectionStart, event.text)
insert(selectionEnd, openAndCloseMatches[event.text])
cursorPosition = start+1
event.accepted = true
}
}
Text {
id: colorizedEditor
anchors.fill: editor
verticalAlignment: TextInput.AlignVCenter
horizontalAlignment: control.label == "" ? TextInput.AlignLeft : TextInput.AlignHCenter
textFormat: Text.StyledText
text: parent.syntaxHighlightingEnabled ? colorize(parent.tokens) : ""
color: sysPalette.windowText
visible: parent.syntaxHighlightingEnabled
//font.pixelSize: parent.font.pixelSize
//opacity: editor.activeFocus ? 0 : 1
}
Popup {
id: autocompletePopup
x: 0
y: parent.height
closePolicy: Popup.NoAutoClose
width: editor.width
height: acPopupContent.height
padding: 0
Column {
id: acPopupContent
width: parent.width
readonly property var identifierTokenTypes: [
Parsing.TokenType.VARIABLE,
Parsing.TokenType.FUNCTION,
Parsing.TokenType.CONSTANT
]
property var currentToken: generateTokenInformation(getTokenAt(editor.tokens, editor.cursorPosition))
property var previousToken: generateTokenInformation(getPreviousToken(currentToken.token))
property var previousToken2: generateTokenInformation(getPreviousToken(previousToken.token))
property var previousToken3: generateTokenInformation(getPreviousToken(previousToken2.token))
visible: currentToken.exists
// Focus handling.
readonly property var lists: [objectPropertiesList, variablesList, constantsList, functionsList, executableObjectsList, objectsList]
readonly property int itemCount: objectPropertiesList.model.length + variablesList.model.length + constantsList.model.length + functionsList.model.length + executableObjectsList.model.length + objectsList.model.length
property int itemSelected: 0
/*!
\qmlmethod var ExpressionEditor::generateTokenInformation(var token)
Generates basic information about the given token (existence and type) used in autocompletion).
*/
function generateTokenInformation(token) {
let exists = token != null
return {
'token': token,
'exists': exists,
'value': exists ? token.value : null,
'type': exists ? token.type : null,
'startPosition': exists ? token.startPosition : 0,
'dot': exists ? (token.type == Parsing.TokenType.PUNCT && token.value == ".") : false,
'identifier': exists ? identifierTokenTypes.includes(token.type) : false
}
}
/*!
\qmlmethod void ExpressionEditor::autocompleteInfoAt(int idx)
Returns the autocompletion text information at a given position.
The information contains key 'text' (description text), 'autocomplete' (text to insert)
and 'cursorFinalOffset' (amount to add to the cursor's position after the end of the autocomplete)
*/
function autocompleteInfoAt(idx) {
if(idx >= itemCount) return ""
let startIndex = 0
for(let list of lists) {
if(idx < startIndex + list.model.length)
return list.model[idx-startIndex]
startIndex += list.model.length
}
}
/*!
\qmlmethod void ExpressionEditor::autocomplete()
Autocompletes with the current selected word.
*/
function autocomplete() {
let autotext = autocompleteInfoAt(itemSelected)
let startPos = currentToken.startPosition
console.log("Replacing", currentToken.value, "at", startPos, "with", autotext.autocomplete)
editor.remove(startPos, startPos+currentToken.value.length)
editor.insert(startPos, autotext.autocomplete)
editor.cursorPosition = startPos+autotext.autocomplete.length+autotext.cursorFinalOffset
}
/*!
\qmlmethod var ExpressionEditor::getPreviousToken(var token)
Returns the token before this one.
*/
function getPreviousToken(token) {
let newToken = getTokenAt(editor.tokens, token.startPosition)
if(newToken != null && newToken.type == Parsing.TokenType.WHITESPACE)
return getPreviousToken(newToken)
return newToken
}
AutocompletionCategory {
id: objectPropertiesList
category: qsTr("Object Properties")
visbilityCondition: control.allowGraphObjects && doesObjectExist
itemStartIndex: 0
itemSelected: parent.itemSelected
property bool isEnteringProperty: (
// Current token is dot.
(parent.currentToken.dot && parent.previousToken.identifier && !parent.previousToken2.dot) ||
// Current token is property identifier
(parent.currentToken.identifier && parent.previousToken.dot && parent.previousToken2.identifier && !parent.previousToken3.dot))
property string objectName: isEnteringProperty ?
(parent.currentToken.dot ? parent.previousToken.value : parent.previousToken2.value)
: ""
property bool doesObjectExist: isEnteringProperty && (objectName in Modules.Objects.currentObjectsByName)
property var objectProperties: doesObjectExist ?
Modules.Objects.currentObjectsByName[objectName].constructor.properties() :
{}
categoryItems: Object.keys(objectProperties)
autocompleteGenerator: (item) => {
let propType = objectProperties[item]
return {
'text': item, 'annotation': propType == null ? '' : propType.toString(),
'autocomplete': parent.currentToken.dot ? `.${item} ` : `${item} `,
'cursorFinalOffset': 0
}
}
baseText: parent.visible && !parent.currentToken.dot ? parent.currentToken.value : ""
}
AutocompletionCategory {
id: variablesList
category: qsTr("Variables")
visbilityCondition: parent.currentToken.identifier && !parent.previousToken.dot
itemStartIndex: objectPropertiesList.model.length
itemSelected: parent.itemSelected
categoryItems: control.variables
autocompleteGenerator: (item) => {return {
'text': item, 'annotation': '',
'autocomplete': item + " ", 'cursorFinalOffset': 0
}}
baseText: parent.visible ? parent.currentToken.value : ""
}
AutocompletionCategory {
id: constantsList
category: qsTr("Constants")
visbilityCondition: parent.currentToken.identifier && !parent.previousToken.dot
itemStartIndex: variablesList.itemStartIndex + variablesList.model.length
itemSelected: parent.itemSelected
categoryItems: Parsing.CONSTANTS_LIST
autocompleteGenerator: (item) => {return {
'text': item, 'annotation': Parsing.CONSTANTS[item],
'autocomplete': item + " ", 'cursorFinalOffset': 0
}}
baseText: parent.visible ? parent.currentToken.value : ""
}
AutocompletionCategory {
id: functionsList
category: qsTr("Functions")
visbilityCondition: parent.currentToken.identifier && !parent.previousToken.dot
itemStartIndex: constantsList.itemStartIndex + constantsList.model.length
itemSelected: parent.itemSelected
categoryItems: Parsing.FUNCTIONS_LIST
autocompleteGenerator: (item) => {return {
'text': item, 'annotation': Parsing.FUNCTIONS_USAGE[item].join(', '),
'autocomplete': item+'()', 'cursorFinalOffset': -1
}}
baseText: parent.visible ? parent.currentToken.value : ""
}
AutocompletionCategory {
id: executableObjectsList
category: qsTr("Executable Objects")
visbilityCondition: control.allowGraphObjects && parent.currentToken.identifier && !parent.previousToken.dot
itemStartIndex: functionsList.itemStartIndex + functionsList.model.length
itemSelected: parent.itemSelected
categoryItems: Modules.Objects.getObjectsName("ExecutableObject").filter(obj => obj != self)
autocompleteGenerator: (item) => {return {
'text': item, 'annotation': Modules.Objects.currentObjectsByName[item] == null ? '' : Objects.currentObjectsByName[item].constructor.displayType(),
'autocomplete': item+'()', 'cursorFinalOffset': -1
}}
baseText: parent.visible ? parent.currentToken.value : ""
}
AutocompletionCategory {
id: objectsList
category: qsTr("Objects")
visbilityCondition: control.allowGraphObjects && parent.currentToken.identifier && !parent.previousToken.dot
itemStartIndex: executableObjectsList.itemStartIndex + executableObjectsList.model.length
itemSelected: parent.itemSelected
categoryItems: Object.keys(Modules.Objects.currentObjectsByName).filter(obj => obj != self)
autocompleteGenerator: (item) => {return {
'text': item, 'annotation': `${Modules.Objects.currentObjectsByName[item].constructor.displayType()}`,
'autocomplete': item+'.', 'cursorFinalOffset': 0
}}
baseText: parent.visible ? parent.currentToken.value : ""
}
}
}
}
Button {
id: insertButton
text: "α"
anchors.right: parent.right
anchors.rightMargin: 5
anchors.verticalCenter: parent.verticalCenter
width: 20
height: width
onClicked: {
insertPopup.open()
insertPopup.focus = true
}
}
P.InsertCharacter {
id: insertPopup
x: Math.round((parent.width - width) / 2)
y: Math.round((parent.height - height) / 2)
category: "expression"
onSelected: function(c) {
editor.insert(editor.cursorPosition, c)
insertPopup.close()
focus = false
editor.focus = true
}
}
/*!
\qmlmethod var ExpressionEditor::parse(string newExpression)
Parses the \c newExpression as an expression, checks for errors, shows them if any.
Returns the parsed expression if possible, null otherwise..
*/
function parse(newExpression) {
let expr = null
try {
expr = new MathLib.Expression(value.toString())
// Check if the expression is valid, throws error otherwise.
if(!expr.allRequirementsFullfilled()) {
let undefVars = expr.undefinedVariables()
if(undefVars.length > 1)
throw new Error(qsTranslate('error', 'No object found with names %1.').arg(undefVars.join(', ')))
else
throw new Error(qsTranslate('error', 'No object found with name %1.').arg(undefVars.join(', ')))
}
if(expr.requiredObjects().includes(control.self))
throw new Error(qsTranslate('error', 'Object cannot be dependent on itself.'))
// Recursive dependencies
let dependentOnSelfObjects = expr.requiredObjects().filter(
(obj) => Modules.Objects.currentObjectsByName[obj].getDependenciesList()
.includes(Modules.Objects.currentObjectsByName[control.self])
)
if(dependentOnSelfObjects.length == 1)
throw new Error(qsTranslate('error', 'Circular dependency detected. Object %1 depends on %2.').arg(dependentOnSelfObjects[0].toString()).arg(control.self))
else if(dependentOnSelfObjects.length > 1)
throw new Error(qsTranslate('error', 'Circular dependency detected. Objects %1 depend on %2.').arg(dependentOnSelfObjects.map(obj => obj.toString()).join(', ')).arg(control.self))
//console.log(control.self, propertyName, expr.execute())
return expr
} catch(e) {
// Error in expression
parsingErrorDialog.showDialog(propertyName, newExpression, e.message)
return null
}
}
/*!
\qmlmethod var ExpressionEditor::tokens(string expressionText)
Generates a list of tokens from the given.
*/
function tokens(text) {
let tokenizer = new Parsing.Tokenizer(new Parsing.Input(text), true, false)
let tokenList = []
let token
while((token = tokenizer.next()) != null)
tokenList.push(token)
return tokenList
}
/*!
\qmlmethod var ExpressionEditor::getTokenAt(var tokens, int position)
Gets the token at the given position within the text.
Returns null if out of bounds.
*/
function getTokenAt(tokenList, position) {
let currentPosition = 0
for(let token of tokenList)
if(position <= (currentPosition + token.value.length))
return token
else
currentPosition += token.value.length
return null
}
/*!
\qmlmethod var ExpressionEditor::colorize(var tokenList)
Creates an HTML colorized string of the given tokens.
Returns the colorized and escaped expression if possible, null otherwise..
*/
function colorize(tokenList) {
let parsedText = ""
let scheme = colorSchemes[Helper.getSettingInt("expression_editor.color_scheme")]
for(let token of tokenList) {
switch(token.type) {
case Parsing.TokenType.VARIABLE:
parsedText += `<font color="${scheme.VARIABLE}">${token.value}</font>`
break;
case Parsing.TokenType.CONSTANT:
parsedText += `<font color="${scheme.CONSTANT}">${token.value}</font>`
break;
case Parsing.TokenType.FUNCTION:
parsedText += `<font color="${scheme.FUNCTION}">${Utils.escapeHTML(token.value)}</font>`
break;
case Parsing.TokenType.OPERATOR:
parsedText += `<font color="${scheme.OPERATOR}">${Utils.escapeHTML(token.value)}</font>`
break;
case Parsing.TokenType.NUMBER:
parsedText += `<font color="${scheme.NUMBER}">${Utils.escapeHTML(token.value)}</font>`
break;
case Parsing.TokenType.STRING:
parsedText += `<font color="${scheme.STRING}">${token.limitator}${Utils.escapeHTML(token.value)}${token.limitator}</font>`
break;
case Parsing.TokenType.WHITESPACE:
case Parsing.TokenType.PUNCT:
default:
parsedText += Utils.escapeHTML(token.value).replace(/ /g, '&nbsp;')
break;
}
}
return parsedText
}
}

View file

@ -1,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -15,8 +15,9 @@
* 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.7
import QtGraphicalEffects 1.0
import QtQuick
import QtQuick.Window
import QtQuick.Controls.impl
/*!
\qmltype Icon
@ -36,17 +37,20 @@ Item {
Path of the icon image source.
*/
property alias source: img.source
/*!
\qmlproperty string Icon::source
Path of the icon image source.
*/
property alias sourceSize: img.sourceS
Image {
ColorImage {
id: img
height: parent.height
width: parent.width
smooth: true
visible: false
}
ColorOverlay {
anchors.fill: img
source: img
// visible: false
property int sourceS: width*Screen.devicePixelRatio
sourceSize.width: sourceS
sourceSize.height: sourceS
color: parent.color
}
}

View file

@ -1,6 +1,24 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQml.Models 2.12
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
import QtQml.Models
/*!
\qmltype ListSetting
@ -86,7 +104,7 @@ Column {
id: iconLabel
anchors.top: parent.top
anchors.topMargin: icon == "" ? 0 : 3
source: control.visible ? "../" + control.icon : ""
source: control.visible ? "../icons/" + control.icon : ""
width: height
height: icon == "" || !visible ? 0 : 24
color: sysPalette.windowText
@ -122,8 +140,8 @@ Column {
visible: control.dictionaryMode
height: parent.height
width: visible ? 50 : 0
validator: RegExpValidator {
regExp: control.keyRegexp
validator: RegularExpressionValidator {
regularExpression: control.keyRegexp
}
verticalAlignment: TextInput.AlignVCenter
horizontalAlignment: TextInput.AlignHCenter
@ -162,8 +180,8 @@ Column {
id: valueInput
height: parent.height
width: parent.width - x - deleteButton.width - 5
validator: RegExpValidator {
regExp: control.valueRegexp
validator: RegularExpressionValidator {
regularExpression: control.valueRegexp
}
verticalAlignment: TextInput.AlignVCenter
horizontalAlignment: TextInput.AlignHCenter
@ -198,7 +216,7 @@ Column {
id: deleteButton
width: visible ? parent.height : 0
height: width
icon.source: './icons/delete.svg'
icon.source: './icons/common/delete.svg'
icon.name: 'delete'
visible: !control.forbidAdding

View file

@ -1,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,8 +16,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick.Controls 2.12
import QtQuick 2.12
import QtQuick.Controls
import QtQuick
import eu.ad5001.LogarithmPlotter.Popup 1.0 as Popup
/*!
\qmltype TextSetting
@ -48,6 +49,12 @@ Item {
If true, the input is being parsed an double before being emitting the \a changed signal.
*/
property bool isDouble: false
/*!
\qmlproperty bool TextSetting::category
Type of special character to insert from the popup.
\sa InsertCharacter::category
*/
property alias category: insertPopup.category
/*!
\qmlproperty double TextSetting::min
Minimum value for numbers that can be entered into the input.
@ -63,6 +70,11 @@ Item {
Value of the input.
*/
property alias value: input.text
/*!
\qmlproperty string TextSetting::placeholderText
Value of the input.
*/
property alias placeholderText: input.placeholderText
/*!
\qmlproperty string TextSetting::label
Label of the setting.
@ -78,7 +90,7 @@ Item {
id: iconLabel
anchors.top: parent.top
anchors.topMargin: icon == "" ? 0 : 3
source: control.visible ? "../" + control.icon : ""
source: control.visible && icon != "" ? "../icons/" + control.icon : ""
width: height
height: icon == "" || !visible ? 0 : 24
color: sysPalette.windowText
@ -88,31 +100,38 @@ Item {
id: labelItem
anchors.left: iconLabel.right
anchors.leftMargin: icon == "" ? 0 : 5
height: parent.height
anchors.top: parent.top
height: parent.height
width: Math.max(85, implicitWidth)
verticalAlignment: TextInput.AlignVCenter
//color: sysPalette.windowText
text: qsTranslate("control", "%1: ").arg(control.label)
text: visible ? qsTranslate("control", "%1: ").arg(control.label) : ""
visible: control.label != ""
}
TextField {
id: input
anchors.top: parent.top
anchors.left: labelItem.right
anchors.leftMargin: 5
width: control.width - labelItem.width - iconLabel.width - 10
width: control.width - (labelItem.visible ? labelItem.width + 5 : 0) - iconLabel.width - 5
height: parent.height
verticalAlignment: TextInput.AlignVCenter
horizontalAlignment: TextInput.AlignHCenter
horizontalAlignment: control.label == "" ? TextInput.AlignLeft : TextInput.AlignHCenter
color: sysPalette.windowText
validator: RegularExpressionValidator {
regularExpression: control.isInt ? /-?[0-9]+/ : control.isDouble ? /-?[0-9]+(\.[0-9]+)?/ : /.+/
}
focus: true
text: control.defValue
selectByMouse: true
onEditingFinished: {
onEditingFinished: function() {
if(insertButton.focus || insertPopup.focus) return
var value = text
if(control.isInt) value = Math.max(control.min,parseInt(value).toString()=="NaN"?control.min:parseInt(value))
if(control.isDouble) value = Math.max(control.min,parseFloat(value).toString()=="NaN"?control.min:parseFloat(value))
if(control.isInt)
value = isNaN(parseInt(value)) ? control.min : Math.max(control.min,parseInt(value))
if(control.isDouble)
value = isNaN(parseFloat(value)) ? control.min : Math.max(control.min,parseFloat(value))
if(value != "" && value.toString() != defValue) {
control.changed(value)
defValue = value.toString()
@ -121,6 +140,7 @@ Item {
}
Button {
id: insertButton
text: "α"
anchors.right: parent.right
anchors.rightMargin: 5
@ -128,54 +148,23 @@ Item {
width: 20
height: width
visible: !isInt && !isDouble
onClicked: insertPopup.open()
onClicked: {
insertPopup.open()
insertPopup.focus = true
}
}
Popup {
Popup.InsertCharacter {
id: insertPopup
x: Math.round((parent.width - width) / 2)
y: Math.round((parent.height - height) / 2)
width: 280
height: insertGrid.insertChars.length/insertGrid.columns*(width/insertGrid.columns)
modal: true
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
Grid {
id: insertGrid
width: parent.width
columns: 7
property var insertChars: [
"α","β","γ","δ","ε","ζ","η",
"π","θ","κ","λ","μ","ξ","ρ",
"ς","σ","τ","φ","χ","ψ","ω",
"Γ","Δ","Θ","Λ","Ξ","Π","Σ",
"Φ","Ψ","Ω","ₐ","ₑ","ₒ","ₓ",
"ₕ","ₖ","ₗ","ₘ","ₙ","ₚ","ₛ",
"ₜ","¹","²","³","⁴","⁵","⁶",
"⁷","⁸","⁹","⁰","₁","₂","₃",
"₄","₅","₆","₇","₈","₉","₀"
]
Repeater {
model: parent.insertChars.length
Button {
id: insertBtn
width: insertGrid.width/insertGrid.columns
height: width
text: insertGrid.insertChars[modelData]
flat: text == " "
font.pixelSize: 18
onClicked: {
input.insert(input.cursorPosition, insertGrid.insertChars[modelData])
insertPopup.close()
input.focus = true
}
}
}
onSelected: function(c) {
input.insert(input.cursorPosition, c)
insertPopup.close()
focus = false
input.focus = true
}
}
}

View file

@ -4,4 +4,5 @@ ComboBoxSetting 1.0 ComboBoxSetting.qml
Icon 1.0 Icon.qml
ListSetting 1.0 ListSetting.qml
TextSetting 1.0 TextSetting.qml
ExpressionEditor 1.0 ExpressionEditor.qml
AutocompletionCategory 1.0 AutocompletionCategory.qml

View file

@ -1,6 +1,6 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and repartition functions.
* Copyright (C) 2022 Ad5001
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,11 +16,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick.Controls 2.12
import QtQuick 2.12
import QtQuick
import QtQuick.Controls
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import eu.ad5001.LogarithmPlotter.Popup 1.0 as Popup
import "js/utils.js" as Utils
import "js/utils.mjs" as Utils
/*!
\qmltype Settings
@ -44,89 +44,93 @@ ScrollView {
Zoom on the x axis of the diagram, provided from settings.
\sa Settings
*/
property double xzoom: 100
property double xzoom: Helper.getSettingInt('default_graph.xzoom')
/*!
\qmlproperty double Settings::yzoom
Zoom on the y axis of the diagram, provided from settings.
\sa Settings
*/
property double yzoom: 10
property double yzoom: Helper.getSettingInt('default_graph.yzoom')
/*!
\qmlproperty double Settings::xmin
Minimum x of the diagram, provided from settings.
\sa Settings
*/
property double xmin: 5/10
property double xmin: Helper.getSettingInt('default_graph.xmin')
/*!
\qmlproperty double Settings::ymax
Maximum y of the diagram, provided from settings.
\sa Settings
*/
property double ymax: 25
property double ymax: Helper.getSettingInt('default_graph.ymax')
/*!
\qmlproperty string Settings::xaxisstep
Step of the x axis graduation, provided from settings.
\note: Only available in non-logarithmic mode.
\sa Settings
*/
property string xaxisstep: "4"
property string xaxisstep: Helper.getSetting('default_graph.xaxisstep')
/*!
\qmlproperty string Settings::yaxisstep
Step of the y axis graduation, provided from settings.
\sa Settings
*/
property string yaxisstep: "4"
property string yaxisstep: Helper.getSetting('default_graph.yaxisstep')
/*!
\qmlproperty string Settings::xlabel
Label used on the x axis, provided from settings.
\sa Settings
*/
property string xlabel: ""
property string xlabel: Helper.getSetting('default_graph.xlabel')
/*!
\qmlproperty string Settings::ylabel
Label used on the y axis, provided from settings.
\sa Settings
*/
property string ylabel: ""
property string ylabel: Helper.getSetting('default_graph.ylabel')
/*!
\qmlproperty double Settings::linewidth
Width of lines that will be drawn into the canvas, provided from settings.
\sa Settings
*/
property double linewidth: 1
property double linewidth: Helper.getSettingInt('default_graph.linewidth')
/*!
\qmlproperty double Settings::textsize
Font size of the text that will be drawn into the canvas, provided from settings.
\sa Settings
*/
property double textsize: 14
property double textsize: Helper.getSettingInt('default_graph.textsize')
/*!
\qmlproperty bool Settings::logscalex
true if the canvas should be in logarithmic mode, false otherwise.
Provided from settings.
\sa Settings
*/
property bool logscalex: true
property bool logscalex: Helper.getSettingBool('default_graph.logscalex')
/*!
\qmlproperty bool Settings::showxgrad
true if the x graduation should be shown, false otherwise.
Provided from settings.
\sa Settings
*/
property bool showxgrad: true
property bool showxgrad: Helper.getSettingBool('default_graph.showxgrad')
/*!
\qmlproperty bool Settings::showygrad
true if the y graduation should be shown, false otherwise.
Provided from settings.
\sa Settings
*/
property bool showygrad: true
property bool showygrad: Helper.getSettingBool('default_graph.showygrad')
/*!
\qmlproperty bool Settings::saveFilename
Path of the currently opened file. Empty if no file is opened.
*/
property string saveFilename: ""
Component.onCompleted: {
Modules.IO.initialize(root, settings, alert)
}
Column {
spacing: 10
width: parent.width
@ -135,12 +139,12 @@ ScrollView {
Popup.FileDialog {
id: fdiag
onAccepted: {
var filePath = fileUrl.toString().substr(7)
var filePath = fdiag.currentFile.toString().substr(7)
settings.saveFilename = filePath
if(exportMode) {
root.saveDiagram(filePath)
Modules.IO.saveDiagram(filePath)
} else {
root.loadDiagram(filePath)
Modules.IO.loadDiagram(filePath)
if(xAxisLabel.find(settings.xlabel) == -1) xAxisLabel.model.append({text: settings.xlabel})
xAxisLabel.editText = settings.xlabel
if(yAxisLabel.find(settings.ylabel) == -1) yAxisLabel.model.append({text: settings.ylabel})
@ -155,8 +159,8 @@ ScrollView {
height: 30
isDouble: true
label: qsTr("X Zoom")
min: 1
icon: "icons/settings/xzoom.svg"
min: 0.1
icon: "settings/xzoom.svg"
width: settings.settingWidth
value: settings.xzoom.toFixed(2)
onChanged: function(newValue) {
@ -169,8 +173,9 @@ ScrollView {
id: zoomY
height: 30
isDouble: true
min: 0.1
label: qsTr("Y Zoom")
icon: "icons/settings/yzoom.svg"
icon: "settings/yzoom.svg"
width: settings.settingWidth
value: settings.yzoom.toFixed(2)
onChanged: function(newValue) {
@ -186,7 +191,7 @@ ScrollView {
isDouble: true
min: -Infinity
label: qsTr("Min X")
icon: "icons/settings/xmin.svg"
icon: "settings/xmin.svg"
width: settings.settingWidth
defValue: settings.xmin
onChanged: function(newValue) {
@ -205,7 +210,7 @@ ScrollView {
isDouble: true
min: -Infinity
label: qsTr("Max Y")
icon: "icons/settings/ymax.svg"
icon: "settings/ymax.svg"
width: settings.settingWidth
defValue: settings.ymax
onChanged: function(newValue) {
@ -220,12 +225,12 @@ ScrollView {
isDouble: true
min: -Infinity
label: qsTr("Max X")
icon: "icons/settings/xmax.svg"
icon: "settings/xmax.svg"
width: settings.settingWidth
value: canvas.px2x(canvas.canvasSize.width).toFixed(2)
defValue: canvas.px2x(canvas.width).toFixed(2)
onChanged: function(xvaluemax) {
if(xvaluemax > settings.xmin) {
settings.xzoom = settings.xzoom * canvas.canvasSize.width/(canvas.x2px(xvaluemax)) // Adjusting zoom to fit. = (end)/(px of current point)
settings.xzoom = settings.xzoom * canvas.width/(canvas.x2px(xvaluemax)) // Adjusting zoom to fit. = (end)/(px of current point)
settings.changed()
} else {
alert.show("Maximum x value must be superior to minimum.")
@ -239,12 +244,12 @@ ScrollView {
isDouble: true
min: -Infinity
label: qsTr("Min Y")
icon: "icons/settings/ymin.svg"
icon: "settings/ymin.svg"
width: settings.settingWidth
defValue: canvas.px2y(canvas.canvasSize.height).toFixed(2)
defValue: canvas.px2y(canvas.height).toFixed(2)
onChanged: function(yvaluemin) {
if(yvaluemin < settings.ymax) {
settings.yzoom = settings.yzoom * canvas.canvasSize.height/(canvas.y2px(yvaluemin)) // Adjusting zoom to fit. = (end)/(px of current point)
settings.yzoom = settings.yzoom * canvas.height/(canvas.y2px(yvaluemin)) // Adjusting zoom to fit. = (end)/(px of current point)
settings.changed()
} else {
alert.show("Minimum y value must be inferior to maximum.")
@ -255,8 +260,9 @@ ScrollView {
Setting.TextSetting {
id: xAxisStep
height: 30
category: "expression"
label: qsTr("X Axis Step")
icon: "icons/settings/xaxisstep.svg"
icon: "settings/xaxisstep.svg"
width: settings.settingWidth
defValue: settings.xaxisstep
visible: !settings.logscalex
@ -269,8 +275,9 @@ ScrollView {
Setting.TextSetting {
id: yAxisStep
height: 30
category: "expression"
label: qsTr("Y Axis Step")
icon: "icons/settings/yaxisstep.svg"
icon: "settings/yaxisstep.svg"
width: settings.settingWidth
defValue: settings.yaxisstep
onChanged: function(newValue) {
@ -285,7 +292,7 @@ ScrollView {
isDouble: true
label: qsTr("Line width")
min: 1
icon: "icons/settings/linewidth.svg"
icon: "settings/linewidth.svg"
width: settings.settingWidth
defValue: settings.linewidth
onChanged: function(newValue) {
@ -300,7 +307,7 @@ ScrollView {
isDouble: true
label: qsTr("Text size (px)")
min: 1
icon: "icons/settings/textsize.svg"
icon: "settings/textsize.svg"
width: settings.settingWidth
defValue: settings.textsize
onChanged: function(newValue) {
@ -314,7 +321,7 @@ ScrollView {
height: 30
width: settings.settingWidth
label: qsTr('X Label')
icon: "icons/settings/xlabel.svg"
icon: "settings/xlabel.svg"
model: ListModel {
ListElement { text: "" }
ListElement { text: "x" }
@ -340,7 +347,7 @@ ScrollView {
height: 30
width: settings.settingWidth
label: qsTr('Y Label')
icon: "icons/settings/ylabel.svg"
icon: "settings/ylabel.svg"
model: ListModel {
ListElement { text: "" }
ListElement { text: "y" }
@ -440,7 +447,7 @@ ScrollView {
if(settings.saveFilename == "") {
saveAs()
} else {
root.saveDiagram(settings.saveFilename)
Modules.IO.saveDiagram(settings.saveFilename)
}
}

View file

@ -0,0 +1,153 @@
/**
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import "js/mathlib.mjs" as MathLib
import "js/historylib.mjs" as HistoryLib
/*!
\qmltype ViewPositionChangeOverlay
\inqmlmodule eu.ad5001.LogarithmPlotter
\brief Overlay used allow the user to drag the canvas' position and change the zoom level.
Provides an overlay over the canvas that detects mouse movements and changes the canvas view position
accordingly by providing new signals.
\sa LogarithmPlotter, LogGraphCanvas, Settings
*/
Item {
id: viewChangeRoot
visible: true
clip: true
/*!
\qmlsignal ViewPositionChangeOverlay::positionChanged(int deltaX, int deltaY)
Emmited when the user dragged the canvas and the view should be refreshed.
The corresponding handler is \c onPositionChanged.
*/
signal positionChanged(int deltaX, int deltaY)
/*!
\qmlsignal ViewPositionChangeOverlay::beginPositionChange()
Emmited when the user starts dragging the canvas.
The corresponding handler is \c onBeginPositionChange.
*/
signal beginPositionChange()
/*!
\qmlsignal ViewPositionChangeOverlay::endPositionChange(int deltaX, int deltaY)
Emmited when the user stops dragging the canvas.
The corresponding handler is \c onEndPositionChange.
*/
signal endPositionChange(int deltaX, int deltaY)
/*!
\qmlproperty var ViewPositionChangeOverlay::canvas
LogGraphCanvas instance.
*/
property var canvas
/*!
\qmlproperty var ViewPositionChangeOverlay::settingsInstance
Settings instance.
*/
property var settingsInstance
/*!
\qmlproperty int ViewPositionChangeOverlay::prevX
The x coordinate (on the mousearea) at the last change of the canvas position.
*/
property int prevX
/*!
\qmlproperty int ViewPositionChangeOverlay::prevY
The y coordinate (on the mousearea) at the last change of the canvas position.
*/
property int prevY
/*!
\qmlproperty double ViewPositionChangeOverlay::baseZoomMultiplier
How much should the zoom be mutliplied/scrolled by for one scroll step (120° on the mouse wheel).
*/
property double baseZoomMultiplier: 0.1
MouseArea {
id: dragArea
anchors.fill: parent
cursorShape: pressed ? Qt.ClosedHandCursor : Qt.OpenHandCursor
property int positionChangeTimer: 0
function updatePosition(deltaX, deltaY) {
settingsInstance.xmin = (Modules.Canvas.px2x(Modules.Canvas.x2px(settingsInstance.xmin)-deltaX))
settingsInstance.ymax += deltaY/canvas.yzoom
settingsInstance.ymax = settingsInstance.ymax.toFixed(4)
settingsInstance.changed()
parent.positionChanged(deltaX, deltaY)
}
onPressed: function(mouse) {
prevX = mouse.x
prevY = mouse.y
parent.beginPositionChange()
}
onPositionChanged: function(mouse) {
positionChangeTimer++
if(positionChangeTimer == 3) {
let deltaX = mouse.x - prevX
let deltaY = mouse.y - prevY
updatePosition(deltaX, deltaY)
prevX = mouse.x
prevY = mouse.y
positionChangeTimer = 0
}
}
onReleased: function(mouse) {
let deltaX = mouse.x - prevX
let deltaY = mouse.y - prevY
updatePosition(deltaX, deltaY)
parent.endPositionChange(deltaX, deltaY)
}
onWheel: function(wheel) {
// Scrolling
let scrollSteps = Math.round(wheel.angleDelta.y / 120)
let zoomMultiplier = Math.pow(1+baseZoomMultiplier, Math.abs(scrollSteps))
// Avoid floating-point rounding errors by removing the zoom *after*
let xZoomDelta = (settingsInstance.xzoom*zoomMultiplier - settingsInstance.xzoom)
let yZoomDelta = (settingsInstance.yzoom*zoomMultiplier - settingsInstance.yzoom)
if(scrollSteps < 0) { // Negative scroll
xZoomDelta *= -1
yZoomDelta *= -1
}
let newXZoom = (settingsInstance.xzoom+xZoomDelta).toFixed(0)
let newYZoom = (settingsInstance.yzoom+yZoomDelta).toFixed(0)
if(newXZoom == settingsInstance.xzoom) // No change, allow more precision.
newXZoom = (settingsInstance.xzoom+xZoomDelta).toFixed(4)
if(newYZoom == settingsInstance.yzoom) // No change, allow more precision.
newYZoom = (settingsInstance.yzoom+yZoomDelta).toFixed(4)
settingsInstance.xzoom = newXZoom
settingsInstance.yzoom = newYZoom
settingsInstance.changed()
}
}
}

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,78 +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="Point.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="23.448337"
inkscape:cy="9.9487426"
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="48"
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">
<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 9.979376,18.120606 a 3.5,3.5 0 0 1 -3.06333,3.854578 3.5,3.5 0 0 1 -3.8866522,-3.022533 3.5,3.5 0 0 1 2.9814002,-3.918293 3.5,3.5 0 0 1 3.9495,2.939936" />
<text
xml:space="preserve"
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"
x="12.066752"
y="13.922545"
id="text14"
transform="scale(0.99446808,1.0055627)"><tspan
sodipodi:role="line"
id="tspan12"
x="12.066752"
y="13.922545"
style="font-size:17.3373px;stroke-width:1.00023">A</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

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

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path style="fill:#000;fill-rule:evenodd;stroke-width:2.26779" d="M4 16 17 3l1 2-2 2c4 3 4 7 4 8v1h-1c0-1 0-5-4-8l-8 8h15v2H2Z"/></svg>

After

Width:  |  Height:  |  Size: 198 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M4 21.832c4.587.38 2.944-4.493 7.188-4.538l1.838 1.534c.458 5.538-6.315 6.773-9.026 3.004zm14.065-7.115c1.427-2.239 5.847-9.749 5.847-9.749.352-.623-.43-1.273-.976-.813 0 0-6.572 5.714-8.511 7.525-1.532 1.432-1.539 2.086-2.035 4.447l1.68 1.4c2.227-.915 2.868-1.039 3.995-2.81zM6.066 18.593c.666-1.134 1.748-2.977 4.447-3.262.434-2.087.607-3.3 2.547-5.112 1.373-1.282 4.938-4.409 7.021-6.229-1-2.208-4.141-4.023-8.178-3.99C5.279.055-.053 5.465 0 12.092a11.956 11.956 0 0 0 2.82 7.635c1.618.429 2.376.348 3.246-1.134zm6.952-15.835a2.006 2.006 0 0 1 2.016 1.983 2.005 2.005 0 0 1-1.986 2.016 1.997 1.997 0 0 1-2.014-1.984 1.994 1.994 0 0 1 1.984-2.015zM7.021 4.759a1.993 1.993 0 0 1 2.012 1.983 1.998 1.998 0 1 1-3.996.028 1.994 1.994 0 0 1 1.984-2.011zm-2.003 5.998a2 2 0 1 1 .03 4 1.995 1.995 0 0 1-2.011-1.985 1.998 1.998 0 0 1 1.981-2.015zm10.031 8.532c.021 2.239-.882 3.718-1.682 4.587l-.046.044c5.255-.591 9.062-4.304 6.266-7.889-1.373 2.047-2.534 2.442-4.538 3.258z" style="fill:#000"/></svg>

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path style="fill:#000;fill-rule:evenodd;stroke-width:2" d="m9 3 3-3 3 3h-2v6l5-5-1-1h4v4l-1-1-5 5h6V9l3 3-3 3v-2h-6l5 5 1-1v4h-4l1-1-5-5v6h2l-3 3-3-3h2v-6l-5 5 1 1H3v-4l1 1 5-5H3v2l-3-3 3-3v2h6L4 6 3 7V3h4L6 4l5 5V3Z"/></svg>

After

Width:  |  Height:  |  Size: 289 B

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
version="1.1"
id="svg6"
sodipodi:docname="remove.svg"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs10" />
<sodipodi:namedview
id="namedview8"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="true"
inkscape:zoom="34.458333"
inkscape:cx="12"
inkscape:cy="10.505441"
inkscape:window-width="1920"
inkscape:window-height="1007"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg6">
<inkscape:grid
type="xygrid"
id="grid822" />
</sodipodi:namedview>
<path
id="rect2"
style="fill-rule:evenodd;stroke-width:3.16228"
transform="rotate(135)"
d="M -1.4142136,-26.870058 H 1.4142136 V -7.0710678 H -1.4142136 Z"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#000000;fill-rule:evenodd;stroke-width:3.16228"
d="M 20,6 6,20 4,18 18,4 Z"
id="path4"
sodipodi:nodetypes="ccccc" />
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path style="fill:#000;stroke:none;stroke-width:1.55662" d="M5 8h1v14H5z"/><path style="fill:#000;stroke:none;stroke-width:2.73862" transform="scale(1 -1)" d="M2-7h20v1H2z"/><path style="fill:#000;stroke:none;stroke-width:.474342" d="M8 3h1v2H8z"/><path style="fill:#000;stroke:none;stroke-width:1.34164" d="M8 2h8v1H8z"/><path style="fill:#000;stroke:none;stroke-width:.500005" d="M15 3h1v2h-1z"/><path style="fill:#000;stroke:none;stroke-width:1.55662" d="M18 8h1v14h-1z"/><path style="fill:#000;stroke:none;stroke-width:.981983" d="M6 21h12v1H6z"/></svg>

After

Width:  |  Height:  |  Size: 620 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path style="fill:#000;fill-rule:evenodd;stroke-width:3.05505" d="M7 5h16v2H9l-5 5 5 5h12V7h2v12H7l-6-6v-2z"/><circle style="fill:#000;fill-rule:evenodd;stroke-width:2" cx="16" cy="12" r="3"/></svg>

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

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path style="fill:#000;fill-rule:evenodd;stroke-width:2" d="M12 2S6 2 6 8c0 4 6 13.936 6 13.936S18 12 18 8c0-6-6-6-6-6zm-.05 3A3 3 0 0 1 12 5a3 3 0 0 1 3 3 3 3 0 0 1-3 3 3 3 0 0 1-3-3 3 3 0 0 1 2.95-3z"/></svg>

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

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path style="fill:#000;fill-rule:evenodd;stroke-width:2.05798" d="M11 3h2v8h3c0-3-3-3-3-3V6s5 0 5 5h3v2h-3c0 5-5 5-5 5v-2s3 0 3-3h-3v8h-2v-8H8c0 3 3 3 3 3v2s-5 0-5-5H3v-2h3c0-5 5-5 5-5v2s-3 0-3 3h3z"/></svg>

After

Width:  |  Height:  |  Size: 270 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path style="fill:#000;fill-opacity:1;stroke:none;stroke-width:.670999;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M4 3h8v2H9v14h3v2H4v-2h3V5H4Z"/><path style="fill:#000;fill-rule:evenodd;stroke-width:2" d="M16 5h2v3h2v2h-2v5c0 2 2 2 2 2v2s-4 0-4-4v-5h-2V8h2z"/></svg>

After

Width:  |  Height:  |  Size: 370 B

View file

@ -1,104 +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="delete.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="34.185532"
inkscape:cy="11.508793"
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:none;stroke-width:1.55662"
id="rect26"
width="1"
height="14"
x="5"
y="8" />
<rect
style="fill:#000000;stroke:none;stroke-width:2.73862"
id="rect869"
width="20"
height="1"
x="2"
y="-7"
transform="scale(1,-1)" />
<rect
style="fill:#000000;stroke:none;stroke-width:0.474342"
id="rect871"
width="1"
height="2"
x="8"
y="3" />
<rect
style="fill:#000000;stroke:none;stroke-width:1.34164"
id="rect873"
width="8"
height="1"
x="8"
y="2" />
<rect
style="fill:#000000;stroke:none;stroke-width:0.500005"
id="rect875"
width="1"
height="2"
x="15"
y="3" />
<rect
style="fill:#000000;stroke:none;stroke-width:1.55662"
id="rect26-3"
width="1"
height="14"
x="18"
y="8" />
<rect
style="fill:#000000;stroke:none;stroke-width:0.981983"
id="rect894"
width="12"
height="1"
x="6"
y="21" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View file

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

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
version="1.1"
id="svg6"
sodipodi:docname="add.svg"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs10" />
<sodipodi:namedview
id="namedview8"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="34.458333"
inkscape:cx="12"
inkscape:cy="12.01451"
inkscape:window-width="1920"
inkscape:window-height="1007"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:3.67423"
width="3"
height="18"
x="10.5"
y="3"
ry="0"
id="rect2" />
<path
style="fill:#000000;fill-rule:evenodd;stroke-width:3.67423"
d="m 3,10.5 h 18 v 3 H 3 Z"
id="path4" />
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

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

View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
version="1.1"
id="svg6"
sodipodi:docname="modify.svg"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs10" />
<sodipodi:namedview
id="namedview8"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="true"
inkscape:zoom="34.458333"
inkscape:cx="11.767836"
inkscape:cy="11.085853"
inkscape:window-width="1920"
inkscape:window-height="1007"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg6">
<inkscape:grid
type="xygrid"
id="grid827" />
</sodipodi:namedview>
<path
id="rect2"
style="fill-rule:evenodd;stroke-width:3.16228"
d="m 8,1 h 8 V 9 L 13,6 3,16 1,14 11,4 Z"
sodipodi:nodetypes="cccccccc" />
<path
id="rect2-3"
style="fill-rule:evenodd;stroke-width:3.16228"
d="M 16,23 H 8 v -8 l 3,3 10,-10 2,2 -10,10 z"
sodipodi:nodetypes="cccccccc" />
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

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

View file

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

View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
version="1.1"
id="svg4"
sodipodi:docname="visibility.svg"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview6"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="true"
inkscape:zoom="34.458333"
inkscape:cx="12"
inkscape:cy="12.01451"
inkscape:window-width="1920"
inkscape:window-height="1007"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4">
<inkscape:grid
type="xygrid"
id="grid896" />
</sodipodi:namedview>
<path
d="m 12.015,7 c 4.751,0 8.063,3.012 9.504,4.636 C 20.118,13.473 16.806,17 12.015,17 7.595,17 4.085,13.464 2.537,11.593 4.03,9.946 7.354,7 12.015,7 Z m 0,-2 C 4.446,5 0,11.551 0,11.551 0,11.551 4.835,19 12.015,19 19.748,19 24,11.551 24,11.551 24,11.551 19.709,5 12.015,5 Z"
fill="#000000"
id="path2"
sodipodi:nodetypes="scscsscscs" />
<path
id="path894"
style="fill:#000000;fill-rule:evenodd;stroke-width:3"
d="M 12 8.5 A 3.5 3.5 0 0 0 8.5 12 A 3.5 3.5 0 0 0 12 15.5 A 3.5 3.5 0 0 0 15.5 12 A 3.5 3.5 0 0 0 12 8.5 z M 11 9.5 A 1.5 1.5 0 0 1 12.5 11 A 1.5 1.5 0 0 1 11 12.5 A 1.5 1.5 0 0 1 9.5 11 A 1.5 1.5 0 0 1 11 9.5 z " />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs833" />
<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:date>2021-2023</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Ad5001</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>(C) Ad5001 2021-2023 - 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
id="layer1">
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:17.3333px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none"
x="0.012050295"
y="17.985596"
id="text1"><tspan
id="tspan1"
x="0.012050295"
y="17.985596"
style="font-size:17.3333px">f</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:17.3333px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none"
x="10.913334"
y="18.134649"
id="text1-3"><tspan
id="tspan1-6"
x="10.913334"
y="18.134649"
style="font-size:17.3333px">x</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:17.3333px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none"
x="6.3066678"
y="17.646639"
id="text2"><tspan
id="tspan2"
x="6.3066678"
y="17.646639"
style="font-size:17.3333px">(</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:17.3333px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none"
x="18.306667"
y="17.646639"
id="text2-7"><tspan
id="tspan2-5"
x="18.306667"
y="17.646639"
style="font-size:17.3333px">)</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs1469" />
<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:date>2021-2023</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Ad5001</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>(C) Ad5001 2021-2023 - Licensed under CC4.0-BY-NC-SA</dc:title>
</cc:Agent>
</dc:rights>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-nc-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-nc-sa/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:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
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:17px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="-0.105"
y="11.959"
id="text839"><tspan
id="tspan837"
x="-0.105"
y="11.959"
style="font-size:17px">ω</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" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs10" />
<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:date>2021-2023</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Ad5001</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>(C) Ad5001 2021-2023 - Licensed under CC4.0-BY-NC-SA</dc:title>
</cc:Agent>
</dc:rights>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-nc-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-nc-sa/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:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
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" />
<circle
style="fill:#000000;stroke-width:2.09999"
id="path45"
cx="16"
cy="19"
r="4" />
<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:0;stroke-miterlimit:4;stroke-dasharray:none"
x="6.1339936"
y="11.163"
id="text49"><tspan
id="tspan47"
x="6.1339936"
y="11.163"
style="font-size:17px;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none">φ</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
version="1.1"
id="svg1"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs1" />
<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"
id="path1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:400;font-size:17px;line-height:1.25;font-family:sans-serif;letter-spacing:0;word-spacing:0;fill-opacity:1;stroke:none;stroke-width:1.00023"
x="11.964725"
y="13.701941"
transform="scale(0.99447036,1.0055604)"
id="text1"><tspan
x="11.964725"
y="13.701941"
style="font-size:17px;stroke-width:1.00023"
id="tspan1">A</tspan></text>
<metadata
id="metadata1">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:date>2021-2023</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Ad5001</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>(C) Ad5001 2021-2023 - Licensed under CC4.0-BY-NC-SA</dc:title>
</cc:Agent>
</dc:rights>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-nc-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-nc-sa/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:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs10" />
<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:date>2021-2023</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Ad5001</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>(C) Ad5001 2021-2023 - Licensed under CC4.0-BY-NC-SA</dc:title>
</cc:Agent>
</dc:rights>
</cc:Work>
</rdf:RDF>
</metadata>
<g
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;-inkscape-font-specification:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
x="7.483983"
y="16.134649"
id="text908"><tspan
id="tspan906"
x="7.483983"
y="16.134649"
style="font-size:17.3333px;-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal">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;-inkscape-font-specification:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
x="16.365566"
y="18.663307"
id="text912"
transform="scale(1.0000324,0.9999676)"><tspan
id="tspan910"
x="16.365566"
y="18.663307"
style="font-size:17px;stroke-width:1.00003;-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal">n</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:17.3333px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal"
x="-0.69333196"
y="17.646639"
id="text2"><tspan
id="tspan2"
x="-0.69333196"
y="17.646639"
style="font-size:17.3333px;-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal">(</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:17.3333px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal"
x="18.806667"
y="17.646639"
id="text2-7"><tspan
id="tspan2-5"
x="18.806667"
y="17.646639"
style="font-size:17.3333px;-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal">)</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
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.3 (0e150ed6c4, 2023-07-21)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<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.772321"
inkscape:cy="8.4598214"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="true"
inkscape:window-width="1920"
inkscape:window-height="1010"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1">
<inkscape:grid
type="xygrid"
id="grid2039"
originx="0"
originy="0"
spacingy="1"
spacingx="1"
units="px"
visible="true" />
<inkscape:grid
type="xygrid"
id="grid2058"
originx="0"
originy="0"
spacingy="1"
spacingx="1"
units="px"
visible="true" />
</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:date>2021-2023</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Ad5001</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>(C) Ad5001 2021-2023 - Licensed under CC4.0-BY-NC-SA</dc:title>
</cc:Agent>
</dc:rights>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-nc-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-nc-sa/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:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</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" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:17px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none"
x="13.844"
y="17.387978"
id="text1"><tspan
sodipodi:role="line"
id="tspan1"
x="13.844"
y="17.387978"
style="font-size:17px">t</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24.0px"
height="24.0px"
viewBox="0 0 24.0 24.0"
version="1.1"
id="SVGRoot"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs1469" />
<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:date>2021-2023</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Ad5001</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>(C) Ad5001 2021-2023 - Licensed under CC4.0-BY-NC-SA</dc:title>
</cc:Agent>
</dc:rights>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-nc-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-nc-sa/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:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
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="5"
y="0"
ry="2.14841e-13" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:17px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none"
x="10.915"
y="13.713"
id="text1"><tspan
id="tspan1"
x="10.915"
y="13.713"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17px;font-family:sans-serif;-inkscape-font-specification:sans-serif">X</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -1 +0,0 @@
./settings/custom/position.svg

View file

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

View file

@ -1 +1 @@
appearance.svg
../../common/appearance.svg

View file

@ -1 +1 @@
appearance.svg
../../common/appearance.svg

View file

@ -1 +1 @@
arrow.svg
../../common/arrow.svg

View file

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

View file

@ -1 +1 @@
angle.svg
../../common/angle.svg

View file

@ -1 +1 @@
appearance.svg
../../common/appearance.svg

View file

@ -1 +1 @@
target.svg
../../common/target.svg

View file

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

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