diff --git a/common/src/events.mjs b/common/src/events.mjs index bed4dea..4e95db6 100644 --- a/common/src/events.mjs +++ b/common/src/events.mjs @@ -53,7 +53,7 @@ export class BaseEventEmitter { * @param {string} eventType - Name of the event to listen to. Throws an error if this object does not emit this kind of event. * @param {function(BaseEvent)} eventListener - The function to be called back when the event is emitted. */ - addEventListener(eventType, eventListener) { + on(eventType, eventListener) { if(!this.constructor.emits.includes(eventType)) { const className = this.constructor.name const eventTypes = this.constructor.emits.join(", ") @@ -70,14 +70,13 @@ export class BaseEventEmitter { * @param {function(BaseEvent)} eventListener - The function previously registered as a listener. * @returns {boolean} True if the listener was removed, false if it was not found. */ - removeEventListener(eventType, eventListener) { + off(eventType, eventListener) { if(!this.constructor.emits.includes(eventType)) { const className = this.constructor.name const eventTypes = this.constructor.emits.join(", ") throw new Error(`Cannot listen to unknown event ${eventType} in class ${className}. ${className} only emits: ${eventTypes}`) } return this.#listeners[eventType].delete(eventListener) - } /** diff --git a/common/src/module/io.mjs b/common/src/module/io.mjs index 183ae01..0b4c6fa 100644 --- a/common/src/module/io.mjs +++ b/common/src/module/io.mjs @@ -62,7 +62,7 @@ class IOAPI extends Module { // Add extension if necessary if(["lpf"].indexOf(filename.split(".")[filename.split(".").length - 1]) === -1) filename += ".lpf" - this.saveFilename = filename + Settings.set("saveFilename", filename, false) let objs = {} for(let objType in Objects.currentObjects) { objs[objType] = [] diff --git a/common/src/module/settings.mjs b/common/src/module/settings.mjs index 4d79ce2..44a6593 100644 --- a/common/src/module/settings.mjs +++ b/common/src/module/settings.mjs @@ -48,6 +48,8 @@ class ChangedEvent extends BaseEvent { class SettingsAPI extends Module { static emits = ["changed"] + #nonConfigurable = ["saveFilename"] + #properties = new Map([ ["saveFilename", ""], ["xzoom", 100], @@ -75,16 +77,18 @@ class SettingsAPI extends Module { super.initialize({ helper }) // Initialize default values. for(const key of this.#properties.keys()) { - switch(typeof this.#properties.get(key)) { - case "boolean": - this.set(key, helper.getSettingBool("default_graph."+key), false) - break - case "number": - this.set(key, helper.getSettingInt("default_graph."+key), false) - break - case "string": - this.set(key, helper.getSetting("default_graph."+key), false) - break + if(!this.#nonConfigurable.includes(key)) { + switch(typeof this.#properties.get(key)) { + case "boolean": + this.set(key, helper.getSettingBool("default_graph."+key), false) + break + case "number": + this.set(key, helper.getSettingInt("default_graph."+key), false) + break + case "string": + this.set(key, helper.getSetting("default_graph."+key), false) + break + } } } } @@ -101,8 +105,9 @@ class SettingsAPI extends Module { throw new Error(`Property ${property} is not a setting.`) } const oldValue = this.#properties.get(property) - console.debug("Setting", property, "from", oldValue, "to", value, `(${typeof value}, ${byUser})`) const propType = typeof oldValue + if(byUser) + console.debug("Setting", property, "from", oldValue, "to", value, `(${typeof value}, ${byUser})`) if(propType !== typeof value) throw new Error(`Value of ${property} must be a ${propType} (${typeof value} provided).`) this.#properties.set(property, value) diff --git a/common/src/preferences/default.mjs b/common/src/preferences/default.mjs index 0fa9531..20d62e3 100644 --- a/common/src/preferences/default.mjs +++ b/common/src/preferences/default.mjs @@ -28,7 +28,7 @@ const XZOOM = new NumberSetting( const YZOOM = new NumberSetting( qsTranslate("Settings", "Y Zoom"), - "default_graph.xzoom", + "default_graph.yzoom", "yzoom", 0.1 ) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml index d6b2c3f..51abb46 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/LogarithmPlotter.qml @@ -42,7 +42,7 @@ ApplicationWindow { width: 1000 height: 500 color: sysPalette.window - title: "LogarithmPlotter " + (settings.saveFilename != "" ? " - " + settings.saveFilename.split('/').pop() : "") + (history.saved ? "" : "*") + title: "LogarithmPlotter" SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active } SystemPalette { id: sysPaletteIn; colorGroup: SystemPalette.Disabled } @@ -250,5 +250,12 @@ ApplicationWindow { Component.onCompleted: { Modules.IO.initialize({ root, settings, alert }) Modules.Latex.initialize({ latex: Latex, helper: Helper }) + Modules.Settings.on("changed", (evt) => { + if(evt.property === "saveFilename") { + const fileName = evt.newValue.split('/').pop().split('\\').pop() + if(fileName !== "") + title = `${fileName}` + } + }) } } diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml index 2fb45d4..680c310 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/PickLocationOverlay.qml @@ -285,7 +285,7 @@ Item { const axisX = Modules.Canvas.axesSteps.x.value const xpos = Modules.Canvas.px2x(picker.mouseX) if(snapToGridCheckbox.checked) { - if(canvas.logscalex) { + if(Modules.Settings.logscalex) { // Calculate the logged power let pow = Math.pow(10, Math.floor(Math.log10(xpos))) return pow*Math.round(xpos/pow) diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml index b0a054a..3689dc1 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/TextSetting.qml @@ -37,7 +37,7 @@ Item { Emitted when the value of the text has been changed. The corresponding handler is \c onChanged. */ - signal changed(string newValue) + signal changed(var newValue) /*! \qmlproperty bool TextSetting::isInt diff --git a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml index 534556f..b440d07 100644 --- a/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml +++ b/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Settings.qml @@ -121,11 +121,6 @@ ScrollView { \sa Settings */ property bool showygrad: Helper.getSettingBool('default_graph.showygrad') - /*! - \qmlproperty bool Settings::saveFilename - Path of the currently opened file. Empty if no file is opened. - */ - property string saveFilename: "" Column { spacing: 10 @@ -136,15 +131,18 @@ ScrollView { id: fdiag onAccepted: { var filePath = fdiag.currentFile.toString().substr(7) - settings.saveFilename = filePath + Modules.Settings.set("saveFilename", filePath) if(exportMode) { Modules.IO.saveDiagram(filePath) } else { Modules.IO.loadDiagram(filePath) - if(xAxisLabel.find(settings.xlabel) == -1) xAxisLabel.model.append({text: settings.xlabel}) - xAxisLabel.editText = settings.xlabel - if(yAxisLabel.find(settings.ylabel) == -1) yAxisLabel.model.append({text: settings.ylabel}) - yAxisLabel.editText = settings.ylabel + // Adding labels. + if(xAxisLabel.find(Modules.Settings.xlabel) === -1) + xAxisLabel.model.append({text: Modules.Settings.xlabel}) + xAxisLabel.editText = Modules.Settings.xlabel + if(yAxisLabel.find(Modules.Settings.ylabel) === -1) + yAxisLabel.model.append({text: Modules.Settings.ylabel}) + yAxisLabel.editText = Modules.Settings.ylabel } } } @@ -158,11 +156,16 @@ ScrollView { min: 0.1 icon: "settings/xzoom.svg" width: settings.settingWidth - value: settings.xzoom.toFixed(2) + onChanged: function(newValue) { - settings.xzoom = newValue + Modules.Settings.set("xzoom", newValue, true) settings.changed() } + + function update(newValue) { + value = Modules.Settings.xzoom.toFixed(2) + maxX.update() + } } Setting.TextSetting { @@ -173,11 +176,16 @@ ScrollView { label: qsTr("Y Zoom") icon: "settings/yzoom.svg" width: settings.settingWidth - value: settings.yzoom.toFixed(2) + onChanged: function(newValue) { - settings.yzoom = newValue + Modules.Settings.set("yzoom", newValue, true) settings.changed() } + + function update(newValue) { + value = Modules.Settings.yzoom.toFixed(2) + minY.update() + } } // Positioning the graph @@ -189,14 +197,18 @@ ScrollView { label: qsTr("Min X") icon: "settings/xmin.svg" width: settings.settingWidth - defValue: settings.xmin + onChanged: function(newValue) { - if(parseFloat(maxX.value) > newValue) { - settings.xmin = newValue - settings.changed() - } else { - alert.show("Minimum x value must be inferior to maximum.") - } + Modules.Settings.set("xmin", newValue, true) + settings.changed() + } + + function update(newValue) { + let newVal = Modules.Settings.xmin + if(newVal > 1e-5) + newVal = newVal.toDecimalPrecision(8) + value = newVal + maxX.update() } } @@ -208,11 +220,16 @@ ScrollView { label: qsTr("Max Y") icon: "settings/ymax.svg" width: settings.settingWidth - defValue: settings.ymax + onChanged: function(newValue) { - settings.ymax = newValue + Modules.Settings.set("ymax", newValue, true) settings.changed() } + + function update() { + value = Modules.Settings.ymax + minY.update() + } } Setting.TextSetting { @@ -223,15 +240,24 @@ ScrollView { label: qsTr("Max X") icon: "settings/xmax.svg" width: settings.settingWidth - defValue: Modules.Canvas.px2x(canvas.width).toFixed(2) + onChanged: function(xvaluemax) { - if(xvaluemax > settings.xmin) { - settings.xzoom = settings.xzoom * canvas.width/(Modules.Canvas.x2px(xvaluemax)) // Adjusting zoom to fit. = (end)/(px of current point) + if(xvaluemax > Modules.Settings.xmin) { + const newXZoom = Modules.Settings.xzoom * canvas.width/(Modules.Canvas.x2px(xvaluemax)) // Adjusting zoom to fit. = (end)/(px of current point) + Modules.Settings.set("xzoom", newXZoom, true) + zoomX.update() settings.changed() } else { alert.show("Maximum x value must be superior to minimum.") } } + + function update() { + let newVal = Modules.Canvas.px2x(canvas.width) + if(newVal > 1e-5) + newVal = newVal.toDecimalPrecision(8) + value = newVal + } } Setting.TextSetting { @@ -242,15 +268,21 @@ ScrollView { label: qsTr("Min Y") icon: "settings/ymin.svg" width: settings.settingWidth - defValue: Modules.Canvas.px2y(canvas.height).toFixed(2) + onChanged: function(yvaluemin) { if(yvaluemin < settings.ymax) { - settings.yzoom = settings.yzoom * canvas.height/(Modules.Canvas.y2px(yvaluemin)) // Adjusting zoom to fit. = (end)/(px of current point) + const newYZoom = Modules.Settings.yzoom * canvas.height/(Modules.Canvas.y2px(yvaluemin)) // Adjusting zoom to fit. = (end)/(px of current point) + Modules.Settings.set("yzoom", newYZoom, true) + zoomY.update() settings.changed() } else { alert.show("Minimum y value must be inferior to maximum.") } } + + function update() { + value = Modules.Canvas.px2y(canvas.height).toDecimalPrecision(8) + } } Setting.TextSetting { @@ -260,12 +292,16 @@ ScrollView { label: qsTr("X Axis Step") icon: "settings/xaxisstep.svg" width: settings.settingWidth - defValue: settings.xaxisstep - visible: !settings.logscalex + onChanged: function(newValue) { - settings.xaxisstep = newValue + Modules.Settings.set("xaxisstep", newValue, true) settings.changed() } + + function update() { + value = Modules.Settings.xaxisstep + visible = !Modules.Settings.logscalex + } } Setting.TextSetting { @@ -275,11 +311,13 @@ ScrollView { label: qsTr("Y Axis Step") icon: "settings/yaxisstep.svg" width: settings.settingWidth - defValue: settings.yaxisstep + onChanged: function(newValue) { - settings.yaxisstep = newValue + Modules.Settings.set("yaxisstep", newValue, true) settings.changed() } + + function update() { value = Modules.Settings.yaxisstep } } Setting.TextSetting { @@ -290,11 +328,13 @@ ScrollView { min: 1 icon: "settings/linewidth.svg" width: settings.settingWidth - defValue: settings.linewidth + onChanged: function(newValue) { - settings.linewidth = newValue + Modules.Settings.set("linewidth", newValue, true) settings.changed() } + + function update() { value = Modules.Settings.linewidth } } Setting.TextSetting { @@ -305,11 +345,13 @@ ScrollView { min: 1 icon: "settings/textsize.svg" width: settings.settingWidth - defValue: settings.textsize + onChanged: function(newValue) { - settings.textsize = newValue + Modules.Settings.set("textsize", newValue, true) settings.changed() } + + function update() { value = Modules.Settings.textsize } } Setting.ComboBoxSetting { @@ -318,24 +360,31 @@ ScrollView { width: settings.settingWidth label: qsTr('X Label') icon: "settings/xlabel.svg" + editable: true model: ListModel { ListElement { text: "" } ListElement { text: "x" } ListElement { text: "ω (rad/s)" } } - currentIndex: find(settings.xlabel) - editable: true + onAccepted: function(){ editText = JS.Utils.parseName(editText, false) - if (find(editText) === -1) model.append({text: editText}) - settings.xlabel = editText + if(find(editText) === -1) model.append({text: editText}) + currentIndex = find(editText) + Modules.Settings.set("xlabel", editText, true) settings.changed() } + onActivated: function(selectedId) { - settings.xlabel = model.get(selectedId).text + Modules.Settings.set("xlabel", model.get(selectedId).text, true) settings.changed() } - Component.onCompleted: editText = settings.xlabel + + function update() { + editText = Modules.Settings.xlabel + if(find(editText) === -1) model.append({text: editText}) + currentIndex = find(editText) + } } Setting.ComboBoxSetting { @@ -344,6 +393,7 @@ ScrollView { width: settings.settingWidth label: qsTr('Y Label') icon: "settings/ylabel.svg" + editable: true model: ListModel { ListElement { text: "" } ListElement { text: "y" } @@ -352,39 +402,52 @@ ScrollView { ListElement { text: "φ (deg)" } ListElement { text: "φ (rad)" } } - currentIndex: find(settings.ylabel) - editable: true + onAccepted: function(){ editText = JS.Utils.parseName(editText, false) - if (find(editText) === -1) model.append({text: editText, yaxisstep: root.yaxisstep}) - settings.ylabel = editText + if(find(editText) === -1) model.append({text: editText}) + currentIndex = find(editText) + Modules.Settings.set("ylabel", editText, true) settings.changed() } + onActivated: function(selectedId) { - settings.ylabel = model.get(selectedId).text + Modules.Settings.set("ylabel", model.get(selectedId).text, true) settings.changed() } - Component.onCompleted: editText = settings.ylabel + + function update() { + editText = Modules.Settings.ylabel + if(find(editText) === -1) model.append({text: editText}) + currentIndex = find(editText) + } } CheckBox { id: logScaleX - checked: settings.logscalex text: qsTr('X Log scale') onClicked: { - settings.logscalex = checked + Modules.Settings.set("logscalex", checked, true) + if(Modules.Settings.xmin <= 0) // Reset xmin to prevent crash. + Modules.Settings.set("xmin", .5) settings.changed() } + + function update() { + checked = Modules.Settings.logscalex + xAxisStep.update() + } } CheckBox { id: showXGrad - checked: settings.showxgrad text: qsTr('Show X graduation') onClicked: { - settings.showxgrad = checked + Modules.Settings.set("showxgrad", checked, true) settings.changed() } + + function update() { checked = Modules.Settings.showxgrad } } CheckBox { @@ -392,9 +455,10 @@ ScrollView { checked: settings.showygrad text: qsTr('Show Y graduation') onClicked: { - settings.showygrad = checked + Modules.Settings.set("showygrad", checked, true) settings.changed() } + function update() { checked = Modules.Settings.showygrad } } Button { @@ -440,10 +504,10 @@ ScrollView { Saves the current canvas in the opened file. If no file is currently opened, prompts to pick a save location. */ function save() { - if(settings.saveFilename == "") { + if(Modules.Settings.saveFilename == "") { saveAs() } else { - Modules.IO.saveDiagram(settings.saveFilename) + Modules.IO.saveDiagram(Modules.Settings.saveFilename) } } @@ -464,4 +528,30 @@ ScrollView { fdiag.exportMode = false fdiag.open() } + + /** + * Initializing the settings + */ + Component.onCompleted: function() { + const matchedElements = new Map([ + ["xzoom", zoomX], + ["yzoom", zoomY], + ["xmin", minX], + ["ymax", maxY], + ["xaxisstep", xAxisStep], + ["yaxisstep", yAxisStep], + ["xlabel", xAxisLabel], + ["ylabel", yAxisLabel], + ["linewidth", lineWidth], + ["textsize", textSize], + ["logscalex", logScaleX], + ["showxgrad", showXGrad], + ["showygrad", showYGrad] + ]) + Modules.Settings.on("changed", (evt) => { + if(matchedElements.has(evt.property)) + matchedElements.get(evt.property).update() + }) + Modules.Settings.initialize({ helper: Helper }) + } }