diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml index 81dbd57..59c7973 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/AppMenuBar.qml @@ -33,7 +33,6 @@ import "js/historylib.mjs" as HistoryLib \sa LogarithmPlotter */ MenuBar { - property var settingsMenu: settingsSubMenu Menu { title: qsTr("&File") diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml index 973142f..fd9a737 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogGraphCanvas.qml @@ -168,4 +168,45 @@ Canvas { } }) } + + /*! + \qmlmethod double LogGraphCanvas::x2px(double x) + Converts an \c x coordinate to it's relative position on the canvas. + It supports both logarithmic and non logarithmic scale depending on the currently selected mode. + */ + function x2px(x) { + if(logscalex) { + var logxmin = Math.log(xmin) + return (Math.log(x)-logxmin)*xzoom + } else return (x - xmin)*xzoom + } + + /*! + \qmlmethod double LogGraphCanvas::y2px(double y) + Converts an \c y coordinate to it's relative position on the canvas. + The y axis not supporting logarithmic scale, it only support linear convertion. + */ + function y2px(y) { + return (ymax-y)*yzoom + } + + /*! + \qmlmethod double LogGraphCanvas::px2x(double px) + Converts an x \c px position on the canvas to it's corresponding coordinate on the plot. + It supports both logarithmic and non logarithmic scale depending on the currently selected mode. + */ + function px2x(px) { + if(logscalex) { + return Math.exp(px/xzoom+Math.log(xmin)) + } else return (px/xzoom+xmin) + } + + /*! + \qmlmethod double LogGraphCanvas::px2x(double px) + Converts an x \c px position on the canvas to it's corresponding coordinate on the plot. + It supports both logarithmic and non logarithmic scale depending on the currently selected mode. + */ + function px2y(px) { + return -(px/yzoom-ymax) + } } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml index a6f57d6..0fd529c 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml @@ -90,7 +90,7 @@ Repeater { root.changed() } } - } + } } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Preferences.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Preferences.qml index 6f5ac7e..aece6aa 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Preferences.qml +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Popup/Preferences.qml @@ -20,7 +20,8 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting -import "../js/setting/common.mjs" as S +import "../js/preferences/common.mjs" as S +import "../js/utils.mjs" as Utils /*! \qmltype Preferences @@ -60,11 +61,75 @@ Popup { label: setting.displayName icon: `settings/${setting.icon}.svg` currentIndex: setting.value() - model: setting.values() + 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 @@ -90,7 +155,7 @@ Popup { clip: true Repeater { - model: Object.keys(Modules.Settings.categories) + model: Object.keys(Modules.Preferences.categories) Button { // width: 150 @@ -98,8 +163,8 @@ Popup { text: qsTranslate('settingCategory', modelData) onClicked: { - settingList.model = Modules.Settings.categories[modelData] - settingCategoryName.text = text + settingView.model = Modules.Preferences.categories[modelData] + settingView.name = text } } } @@ -133,50 +198,55 @@ Popup { width: 1 } - ScrollView { + ListView { id: settingView clip: true width: 500 - height: parent.height + spacing: 10 + model: Modules.Preferences.categories.general + anchors { + top: parent.top + bottom: parent.bottom + } + ScrollBar.vertical: ScrollBar { } + property string name: qsTranslate('settingCategory', 'general') + - Column { - spacing: 10 - clip: true - width: settingView.width - - Text { - id: settingCategoryName - font.pixelSize: 32 - color: sysPalette.windowText - text: qsTranslate('settingCategory', 'general') - - Rectangle { - id: bottomSeparator - anchors.top: parent.bottom - opacity: 0.3 - color: sysPalette.windowText - width: settingView.width - height: 1 - } - } + header: Text { + id: settingCategoryName + font.pixelSize: 32 + height: 48 + color: sysPalette.windowText + text: settingView.name - Repeater { - id: settingList - model: Modules.Settings.categories.general - - delegate: Component { - Loader { - width: settingView.width - property var setting: modelData - sourceComponent: { - if(setting instanceof S.BoolSetting) - return boolSettingComponent - else if(setting instanceof S.EnumIntSetting) - return enumIntSettingComponent - else - console.log('Unknown setting type!', modelData.constructor) - } - } + 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) } } } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ComboBoxSetting.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ComboBoxSetting.qml index d701661..d29ab7c 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ComboBoxSetting.qml +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ComboBoxSetting.qml @@ -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) diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml index ad7e67c..d121781 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml @@ -80,6 +80,17 @@ Item { 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 @@ -177,8 +188,9 @@ 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: visible ? qsTranslate("control", "%1: ").arg(control.label) : "" @@ -380,7 +392,7 @@ Item { id: objectPropertiesList category: qsTr("Object Properties") - visbilityCondition: doesObjectExist + visbilityCondition: control.allowGraphObjects && doesObjectExist itemStartIndex: 0 itemSelected: parent.itemSelected property bool isEnteringProperty: ( @@ -457,7 +469,7 @@ Item { id: executableObjectsList category: qsTr("Executable Objects") - visbilityCondition: parent.currentToken.identifier && !parent.previousToken.dot + 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) @@ -472,7 +484,7 @@ Item { id: objectsList category: qsTr("Objects") - visbilityCondition: parent.currentToken.identifier && !parent.previousToken.dot + 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) diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/Icon.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/Icon.qml index f845eb9..aeffe53 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/Icon.qml +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/Icon.qml @@ -17,7 +17,7 @@ */ import QtQuick import QtQuick.Window -import Qt5Compat.GraphicalEffects +import QtQuick.Controls.impl /*! \qmltype Icon @@ -41,20 +41,16 @@ Item { \qmlproperty string Icon::source Path of the icon image source. */ - property alias sourceSize: img.sourceSize.width + property alias sourceSize: img.sourceS - Image { + ColorImage { id: img height: parent.height width: parent.width - visible: false - sourceSize.width: width*Screen.devicePixelRatio - sourceSize.height: width*Screen.devicePixelRatio - } - - ColorOverlay { - anchors.fill: img - source: img + // visible: false + property int sourceS: width*Screen.devicePixelRatio + sourceSize.width: sourceS + sourceSize.height: sourceS color: parent.color } } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml index d1c4c9d..c795037 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml @@ -100,14 +100,14 @@ 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: visible ? qsTranslate("control", "%1: ").arg(control.label) : "" visible: control.label != "" } - TextField { id: input @@ -128,8 +128,10 @@ Item { 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() diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml index cf09695..067c70d 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml @@ -44,83 +44,83 @@ 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: 18 + 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. @@ -159,7 +159,7 @@ ScrollView { height: 30 isDouble: true label: qsTr("X Zoom") - min: 1 + min: 0.1 icon: "settings/xzoom.svg" width: settings.settingWidth value: settings.xzoom.toFixed(2) @@ -173,6 +173,7 @@ ScrollView { id: zoomY height: 30 isDouble: true + min: 0.1 label: qsTr("Y Zoom") icon: "settings/yzoom.svg" width: settings.settingWidth @@ -226,10 +227,10 @@ ScrollView { label: qsTr("Max X") icon: "settings/xmax.svg" width: settings.settingWidth - value: Modules.Canvas.px2x(canvas.width).toFixed(2) + defValue: canvas.px2x(canvas.width).toFixed(2) onChanged: function(xvaluemax) { if(xvaluemax > settings.xmin) { - settings.xzoom = settings.xzoom * canvas.width/(Modules.Canvas.x2px(xvaluemax)) // Adjusting zoom to fit. = (end)/(px of current point) + 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.") @@ -245,10 +246,10 @@ ScrollView { label: qsTr("Min Y") icon: "settings/ymin.svg" width: settings.settingWidth - defValue: Modules.Canvas.px2y(canvas.height).toFixed(2) + defValue: canvas.px2y(canvas.height).toFixed(2) onChanged: function(yvaluemin) { if(yvaluemin < settings.ymax) { - settings.yzoom = settings.yzoom * canvas.height/(Modules.Canvas.y2px(yvaluemin)) // Adjusting zoom to fit. = (end)/(px of current point) + 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.") diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/icons/common/Text.svg b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/icons/common/text.svg similarity index 100% rename from LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/icons/common/Text.svg rename to LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/icons/common/text.svg diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/icons/settings/label.svg b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/icons/settings/label.svg new file mode 120000 index 0000000..280f9ad --- /dev/null +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/icons/settings/label.svg @@ -0,0 +1 @@ +../common/label.svg \ No newline at end of file diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/icons/settings/text.svg b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/icons/settings/text.svg new file mode 120000 index 0000000..a705389 --- /dev/null +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/icons/settings/text.svg @@ -0,0 +1 @@ +../common/text.svg \ No newline at end of file diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/autoload.js b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/autoload.js index 211aa9e..5763db0 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/autoload.js +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/autoload.js @@ -7,4 +7,4 @@ .import "history/common.mjs" as HistoryCommon .import "canvas.mjs" as CanvasAPI .import "io.mjs" as IOAPI -.import "settings.mjs" as SettingsAPI \ No newline at end of file +.import "preferences.mjs" as PreferencesAPI \ No newline at end of file diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/canvas.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/canvas.mjs index 9649634..cdd0777 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/canvas.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/canvas.mjs @@ -377,10 +377,7 @@ class CanvasAPI extends Module { * @returns {number} */ x2px(x) { - if(this.logscalex) { - let logxmin = Math.log(this.xmin) - return (Math.log(x)-logxmin)*this.xzoom - } else return (x - this.xmin)*this.xzoom + return this._canvas.x2px(x) } /** @@ -390,7 +387,7 @@ class CanvasAPI extends Module { * @returns {number} */ y2px(y) { - return (this.ymax-y)*this.yzoom + return this._canvas.y2px(y) } /** @@ -400,9 +397,7 @@ class CanvasAPI extends Module { * @returns {number} */ px2x(px) { - if(this.logscalex) { - return Math.exp(px/this.xzoom+Math.log(this.xmin)) - } else return (px/this.xzoom+this.xmin) + return this._canvas.px2x(px) } /** @@ -412,7 +407,7 @@ class CanvasAPI extends Module { * @returns {number} */ px2y(px) { - return -(px/this.yzoom-this.ymax) + return this._canvas.px2y(px) } /** diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/settings.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences.mjs similarity index 74% rename from LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/settings.mjs rename to LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences.mjs index 8fff543..0407ee1 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/settings.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences.mjs @@ -16,12 +16,13 @@ * along with this program. If not, see . */ import {Module} from "modules.mjs" -import General from "setting/general.mjs" -import Editor from "setting/expression.mjs" +import General from "preferences/general.mjs" +import Editor from "preferences/expression.mjs" +import DefaultGraph from "preferences/default.mjs" -class SettingsAPI extends Module { +class PreferencesAPI extends Module { constructor() { - super('Settings', [ + super('Preferences', [ Modules.Canvas, Modules.Latex ]) @@ -29,11 +30,11 @@ class SettingsAPI extends Module { this.categories = { [QT_TRANSLATE_NOOP('settingCategory', 'general')]: General, [QT_TRANSLATE_NOOP('settingCategory', 'editor')]: Editor, - [QT_TRANSLATE_NOOP('settingCategory', 'default')]: [], + [QT_TRANSLATE_NOOP('settingCategory', 'default')]: DefaultGraph, } } } /** @type {CanvasAPI} */ -Modules.Settings = Modules.Settings || new SettingsAPI() -export const API = Modules.Settings \ No newline at end of file +Modules.Preferences = Modules.Preferences || new PreferencesAPI() +export const API = Modules.Preferences \ No newline at end of file diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/common.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/common.mjs new file mode 100644 index 0000000..48cd1de --- /dev/null +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/common.mjs @@ -0,0 +1,137 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import {Expression} from "../mathlib.mjs" + +class Setting { + constructor(type, name, nameInConfig, icon) { + this.type = type + this.name = name + this.displayName = qsTr(name) + this.nameInConfig = nameInConfig + this.icon = icon + } + + /** + * Returns the value of the setting. + * @returns {string|boolean|number} + */ + value() { + throw new TypeError(`value of ${this.constructor} not implemented.`) + } + + /** + * Sets the value of the setting + * @param {string|boolean|number|Expression} value + */ + set(value) { + throw new TypeError(`value of ${this.constructor} not implemented.`) + } + + toString() { + return `Setting<${this.type} ${this.name}>` + } +} + +export class BoolSetting extends Setting { + constructor(name, nameInConfig, icon) { + super('bool', name, nameInConfig, icon) + } + + value() { + return Helper.getSettingBool(this.nameInConfig) + } + + set(value) { + Helper.setSettingBool(this.nameInConfig, value) + } +} + +export class NumberSetting extends Setting { + constructor(name, nameInConfig, icon, min = -Infinity, max = +Infinity) { + super('number', name, nameInConfig, icon) + this.min = typeof min == 'number' ? () => min : min + this.max = typeof max == 'number' ? () => max : max + } + + value() { + return Helper.getSettingInt(this.nameInConfig) + } + + set(value) { + Helper.setSettingInt(this.nameInConfig, value) + } +} + +export class EnumIntSetting extends Setting { + constructor(name, nameInConfig, icon, values = []) { + super('enum', name, nameInConfig, icon) + this.values = values + } + + value() { + return Helper.getSettingInt(this.nameInConfig) + } + + set(value) { + Helper.setSettingInt(this.nameInConfig, value) + } +} + +export class ExpressionSetting extends Setting { + constructor(name, nameInConfig, icon, variables = []) { + super('expression', name, nameInConfig, icon) + this.variables = variables + } + + value() { + return Helper.getSetting(this.nameInConfig) + } + + /** + * + * @param {Expression} value + */ + set(value) { + let vars = value.calc.variables() + if(vars.length === this.variables.length && vars.every(x => this.variables.includes(x))) + Helper.setSetting(this.nameInConfig, value) + else { + let undefinedVars = vars.filter(x => !this.variables.includes(x)) + let allowed = '' + if(this.variables.length > 0) + allowed = `Allowed variables: ${this.variables.join(', ')}.` + throw new TypeError(`Cannot use variable(s) ${undefinedVars.join(', or ')} to define ${this.displayName}. ${allowed}`) + } + } +} + +export class StringSetting extends Setting { + constructor(name, nameInConfig, icon, defaultValues = []) { + super('string', name, nameInConfig, icon) + this.defaultValues = defaultValues + } + + value() { + return Helper.getSetting(this.nameInConfig) + } + + set(value) { + Helper.setSetting(this.nameInConfig, value) + } +} \ No newline at end of file diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/default.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/default.mjs new file mode 100644 index 0000000..1546729 --- /dev/null +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/default.mjs @@ -0,0 +1,120 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import {BoolSetting, ExpressionSetting, NumberSetting, StringSetting} from "common.mjs" + + +const XZOOM = new NumberSetting( + QT_TR_NOOP("X Zoom"), + "default_graph.xzoom", + "xzoom", + 0.1 +) + +const YZOOM = new NumberSetting( + QT_TR_NOOP("Y Zoom"), + "default_graph.xzoom", + "yzoom", + 0.1 +) + +const XMIN = new NumberSetting( + QT_TR_NOOP("Min X"), + "default_graph.xmin", + "xmin", + () => Helper.getSettingBool("default_graph.logscalex") ? 1e-100 : -Infinity +) + +const YMAX = new NumberSetting( + QT_TR_NOOP("Max Y"), + "default_graph.ymax", + "ymax" +) + +const XAXISSTEP = new ExpressionSetting( + QT_TR_NOOP("X Axis Step"), + "default_graph.xaxisstep", + "xaxisstep", +) + +const YAXISSTEP = new ExpressionSetting( + QT_TR_NOOP("Y Axis Step"), + "default_graph.yaxisstep", + "yaxisstep", +) + +const LINE_WIDTH = new NumberSetting( + QT_TR_NOOP("Line width"), + "default_graph.linewidth", + "linewidth", + 1 +) + +const TEXT_SIZE = new NumberSetting( + QT_TR_NOOP("Text size (px)"), + "default_graph.textsize", + "textsize" +) + +const X_LABEL = new StringSetting( + QT_TR_NOOP('X Label'), + "default_graph.xlabel", + "xlabel", + ["", "x", "ω (rad/s)"] +) + +const Y_LABEL = new StringSetting( + QT_TR_NOOP('Y Label'), + "default_graph.ylabel", + "xlabel", + ["", "y", "G (dB)", "φ (°)", "φ (deg)", "φ (rad)"] +) + +const LOG_SCALE_X = new BoolSetting( + QT_TR_NOOP('X Log scale'), + "default_graph.logscalex", + "logscalex" +) + +const SHOW_X_GRAD = new BoolSetting( + QT_TR_NOOP('Show X graduation'), + "default_graph.showxgrad", + "showxgrad" +) + +const SHOW_Y_GRAD = new BoolSetting( + QT_TR_NOOP('Show Y graduation'), + "default_graph.showygrad", + "showygrad" +) + +export default [ + XZOOM, + YZOOM, + XMIN, + YMAX, + XAXISSTEP, + YAXISSTEP, + LINE_WIDTH, + TEXT_SIZE, + X_LABEL, + Y_LABEL, + LOG_SCALE_X, + SHOW_X_GRAD, + SHOW_Y_GRAD +] diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/expression.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/expression.mjs new file mode 100644 index 0000000..92990b8 --- /dev/null +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/expression.mjs @@ -0,0 +1,51 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import {BoolSetting, EnumIntSetting} from "common.mjs" + +const AUTOCLOSE_FORMULA = new BoolSetting( + QT_TR_NOOP("Automatically close parenthesises and brackets"), + 'expression_editor.autoclose', + 'text' +) + +const ENABLE_SYNTAX_HIGHLIGHTING = new BoolSetting( + QT_TR_NOOP("Enable syntax highlighting"), + 'expression_editor.colorize', + 'appearance' +) + +const ENABLE_AUTOCOMPLETE = new BoolSetting( + QT_TR_NOOP("Enable autocompletion"), + 'autocompletion.enabled', + 'label' +) + +const PICK_COLOR_SCHEME = new EnumIntSetting( + QT_TR_NOOP("Color Scheme"), + 'expression_editor.color_scheme', + 'color', + ["Breeze Light", "Breeze Dark", "Solarized", "Github Light", "Github Dark", "Nord", "Monokai"] +) + +export default [ + AUTOCLOSE_FORMULA, + ENABLE_AUTOCOMPLETE, + ENABLE_SYNTAX_HIGHLIGHTING, + PICK_COLOR_SCHEME +] \ No newline at end of file diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/setting/general.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/general.mjs similarity index 75% rename from LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/setting/general.mjs rename to LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/general.mjs index 2430b52..0954f67 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/setting/general.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/general.mjs @@ -18,17 +18,17 @@ import {BoolSetting} from "common.mjs" -class CheckForUpdates extends BoolSetting { - constructor() { - super(QT_TR_NOOP("Check for updates on startup"), 'check_for_updates', 'update') - } -} +const CHECK_FOR_UPDATES = new BoolSetting( + QT_TR_NOOP("Check for updates on startup"), + 'check_for_updates', + 'update' +) -class ResetRedoStack extends BoolSetting { - constructor() { - super(qsTr("Reset redo stack automaticly"), 'reset_redo_stack', 'timeline') - } -} +const RESET_REDO_STACK = new BoolSetting( + QT_TR_NOOP("Reset redo stack automaticly"), + 'reset_redo_stack', + 'timeline' +) class EnableLatex extends BoolSetting { constructor() { @@ -43,7 +43,7 @@ class EnableLatex extends BoolSetting { } export default [ - new CheckForUpdates(), - new ResetRedoStack(), + CHECK_FOR_UPDATES, + RESET_REDO_STACK, new EnableLatex() ] \ No newline at end of file diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/setting/common.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/setting/common.mjs deleted file mode 100644 index 2e395c6..0000000 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/setting/common.mjs +++ /dev/null @@ -1,67 +0,0 @@ -/** - * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -class Setting { - constructor(name, nameInConfig, icon) { - this.name = name - this.displayName = qsTr(name) - this.nameInConfig = nameInConfig - this.icon = icon - } - - /** - * Returns the value of the setting. - * @returns {string|boolean|number} - */ - value() { - throw new TypeError(`value of ${this.constructor} not implemented.`) - } - - /** - * Sets the value of the setting - * @param {string|boolean|number} value - */ - set(value) { - throw new TypeError(`value of ${this.constructor} not implemented.`) - } -} - -export class BoolSetting extends Setting { - value() { - return Helper.getSettingBool(this.nameInConfig) - } - - set(value) { - Helper.setSettingBool(this.nameInConfig, value) - } -} - -export class IntSetting extends Setting { - value() { - return Helper.getSettingInt(this.nameInConfig) - } - - set(value) { - Helper.setSettingInt(this.nameInConfig, value) - } -} - -export class EnumIntSetting extends IntSetting { - values() { - throw new TypeError(`enumerations of ${this.constructor} not implemented.`) - } -} \ No newline at end of file diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/setting/expression.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/setting/expression.mjs deleted file mode 100644 index 0fab509..0000000 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/setting/expression.mjs +++ /dev/null @@ -1,54 +0,0 @@ -/** - * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2021-2024 Ad5001 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import {BoolSetting, EnumIntSetting} from "common.mjs" - -class AutocloseFormula extends BoolSetting { - constructor() { - super(qsTr("Automatically close parenthesises and brackets"), 'expression_editor.autoclose', 'Text') - } -} - -class EnableSyntaxHighlighting extends BoolSetting { - constructor() { - super(qsTr("Enable syntax highlighting"), 'expression_editor.colorize', 'appearance') - } -} - -class EnableAutocomplete extends BoolSetting { - constructor() { - super(qsTr("Enable autocompletion"), 'autocompletion.enabled', 'label') - } -} - -class PickColorScheme extends EnumIntSetting { - constructor() { - super(qsTr("Color Scheme"), 'expression_editor.color_scheme', 'color') - } - - values() { - return ["Breeze Light", "Breeze Dark", "Solarized", "Github Light", "Github Dark", "Nord", "Monokai"] - } -} - -export default [ - new AutocloseFormula(), - new EnableAutocomplete(), - new EnableSyntaxHighlighting(), - new PickColorScheme() -] \ No newline at end of file diff --git a/LogarithmPlotter/util/config.py b/LogarithmPlotter/util/config.py index bdd11b7..5c2c653 100644 --- a/LogarithmPlotter/util/config.py +++ b/LogarithmPlotter/util/config.py @@ -34,6 +34,21 @@ DEFAULT_SETTINGS = { }, "autocompletion": { "enabled": True + }, + "default_graph": { + "xzoom": 100, + "yzoom": 10, + "xmin": 5/10, + "ymax": 25, + "xaxisstep": "4", + "yaxisstep": "4", + "xlabel": "", + "ylabel": "", + "linewidth": 1, + "textsize": 18, + "logscalex": True, + "showxgrad": True, + "showygrad": True } } diff --git a/LogarithmPlotter/util/helper.py b/LogarithmPlotter/util/helper.py index e6e9dfb..47e7395 100644 --- a/LogarithmPlotter/util/helper.py +++ b/LogarithmPlotter/util/helper.py @@ -129,8 +129,9 @@ class Helper(QObject): def getSetting(self, namespace): return config.getSetting(namespace) - @Slot(str, result=int) + @Slot(str, result=float) def getSettingInt(self, namespace): + print('Getting', namespace, config.getSetting(namespace)) return config.getSetting(namespace) @Slot(str, result=bool) @@ -145,7 +146,7 @@ class Helper(QObject): def setSettingBool(self, namespace, value): return config.setSetting(namespace, value) - @Slot(str, int) + @Slot(str, float) def setSettingInt(self, namespace, value): return config.setSetting(namespace, value)