From d65f343b6002248898e620d880e1e8d019ed9c0b Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Tue, 18 Oct 2022 16:43:39 +0200 Subject: [PATCH] Reworking the Editor dialog to be much faster and cleaner. 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. --- .../ObjectLists/Editor/CustomPropertyList.qml | 256 ++++++++++++++ .../ObjectLists/Editor/Dialog.qml | 145 ++++++++ .../ObjectLists/Editor/qmldir | 5 + .../ObjectLists/EditorDialog.qml | 319 ------------------ .../ObjectLists/ObjectLists.qml | 5 +- .../ObjectLists/ObjectRow.qml | 21 +- .../Setting/LatexExpression.qml | 28 -- 7 files changed, 427 insertions(+), 352 deletions(-) create mode 100644 LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml create mode 100644 LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml create mode 100644 LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/qmldir delete mode 100644 LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/EditorDialog.qml delete mode 100644 LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/LatexExpression.qml diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml new file mode 100644 index 0000000..20f3885 --- /dev/null +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/CustomPropertyList.qml @@ -0,0 +1,256 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2022 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +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 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: dlgCustomProperties + + signal changed() + + /*! + \qmlproperty var CustomPropertyList::obj + Object whose properties to list and edit. + */ + property var obj + + readonly property var textTypes: ['Expression', '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: textEditorComponent + + // Setting for text & number settings as well as domains & expressions + Setting.TextSetting { + height: 30 + label: propertyLabel + icon: `settings/custom/${propertyIcon}.svg` + isDouble: propertyType == 'number' + defValue: { + switch(propertyType) { + case 'Expression': + return Utils.simplifyExpression(obj[propertyName].toEditableString()) + break + case 'string': + return obj[propertyName] + break + case 'Domain': + case 'number': + default: + return obj[propertyName].toString() + } + } + onChanged: function(newValue) { + var newValue = { + 'Expression': () => new MathLib.Expression(newValue), + '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] != newValue) { + history.addToHistory(new HistoryLib.EditedProperty( + obj.name, objType, propertyName, + obj[propertyName], newValue + )) + obj[propertyName] = newValue + Objects.currentObjects[objType][objIndex].update() + objectListList.update() + } + } + } + } + + Component { + id: checkboxComponent + + // Setting for boolean + CheckBox { + height: 20 + text: propertyLabel + //icon: `settings/custom/${propertyIcon}.svg` + + checked: obj[propertyName] + onClicked: { + history.addToHistory(new HistoryLib.EditedProperty( + obj.name, objType, propertyName, + obj[propertyName], this.checked + )) + obj[propertyName] = this.checked + Objects.currentObjects[objType][objIndex].update() + objectListList.update() + } + } + } + + 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 ? + Objects.getObjectsName(propertyType.objType).concat( + isRealObject ? [qsTr("+ Create new %1").arg(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 = Objects.currentObjectsByName[baseModel[newIndex]] + if(newIndex != 0) { + // Make sure we don't set the object to null. + if(selectedObj == null) { + // Creating new object. + selectedObj = Objects.createNewRegisteredObject(propertyType.objType) + history.addToHistory(new HistoryLib.CreateNewObject(selectedObj.name, propertyType.objType, selectedObj.export())) + baseModel = Objects.getObjectsName(propertyType.objType).concat( + isRealObject ? [qsTr("+ Create new %1").arg(Objects.types[propertyType.objType].displayType())] : + []) + currentIndex = baseModel.indexOf(selectedObj.name) + } + selectedObj.requiredBy.push(Objects.currentObjects[objType][objIndex]) + //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 + Objects.currentObjects[objType][objIndex].update() + objectListList.update() + } + } + } + + 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) + postKeyLabel: (dictionaryMode ? propertyType.postKeyLabel : '').replace(/\{name\}/g, obj.name) + 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 + )) + //Objects.currentObjects[objType][objIndex][propertyName] = exported + obj[propertyName] = exported + //Objects.currentObjects[objType][objIndex].update() + obj.update() + objectListList.update() + } + + Component.onCompleted: { + importModel(obj[propertyName]) + } + } + } + + delegate: Component { + Loader { + //height: customPropComment.height + customPropText.height + customPropCheckBox.height + customPropCombo.height + customPropListDict.height + width: dlgProperties.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, textTypes)) + return textEditorComponent + else if(paramTypeIn(propertyType, comboBoxTypes)) + return comboBoxComponent + else if(paramTypeIn(propertyType, listTypes)) + return listDictEditorComponent + else + return {} + } + } + } +} diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml new file mode 100644 index 0000000..bc6cdd7 --- /dev/null +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/Dialog.qml @@ -0,0 +1,145 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2022 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +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 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 +*/ +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 + + D.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" + width: dlgProperties.width + value: objEditor.obj.name + onChanged: function(newValue) { + let newName = Utils.parseName(newValue) + if(newName != '' && objEditor.obj.name != newName) { + if(newName in Objects.currentObjectsByName) { + invalidNameDialog.showDialog(newName) + } else { + history.addToHistory(new HistoryLib.NameChanged( + objEditor.obj.name, objEditor.objType, newName + )) + Objects.renameObject(obj.name, newName) + objEditor.obj = Objects.currentObjects[objEditor.objType][objEditor.objIndex] + objectListList.update() + } + } + } + } + + Setting.ComboBoxSetting { + id: labelContentProperty + height: 30 + width: dlgProperties.width + label: qsTr("Label content") + model: [qsTr("null"), qsTr("name"), qsTr("name + value")] + property var idModel: ["null", "name", "name + value"] + icon: "common/label.svg" + currentIndex: idModel.indexOf(objEditor.obj.labelContent) + onActivated: function(newIndex) { + if(idModel[newIndex] != objEditor.obj.labelContent) { + objEditor.obj.labelContent = idModel[newIndex] + objectListList.update() + } + } + } + + // Dynamic properties + CustomPropertyList { + id: dlgCustomProperties + obj: objEditor.obj + } + } + + /*! + \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() + } +} diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/qmldir b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/qmldir new file mode 100644 index 0000000..feb9724 --- /dev/null +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/Editor/qmldir @@ -0,0 +1,5 @@ +module eu.ad5001.LogarithmPlotter.ObjectLists.Editor + +Dialog 1.0 Dialog.qml +CustomPropertyList 1.0 CustomPropertyList.qml + diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/EditorDialog.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/EditorDialog.qml deleted file mode 100644 index 9cf4a12..0000000 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/EditorDialog.qml +++ /dev/null @@ -1,319 +0,0 @@ -/** - * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2022 Ad5001 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -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 - - D.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" - width: dlgProperties.width - value: objEditor.obj.name - onChanged: function(newValue) { - let newName = Utils.parseName(newValue) - if(newName != '' && objEditor.obj.name != newName) { - if(newName in Objects.currentObjectsByName) { - invalidNameDialog.showDialog(newName) - } else { - history.addToHistory(new HistoryLib.NameChanged( - objEditor.obj.name, objEditor.objType, newName - )) - Objects.renameObject(obj.name, newName) - objEditor.obj = Objects.currentObjects[objEditor.objType][objEditor.objIndex] - objectListList.update() - } - } - } - } - - Setting.ComboBoxSetting { - id: labelContentProperty - height: 30 - width: dlgProperties.width - label: qsTr("Label content") - model: [qsTr("null"), qsTr("name"), qsTr("name + value")] - property var idModel: ["null", "name", "name + value"] - icon: "common/label.svg" - currentIndex: idModel.indexOf(objEditor.obj.labelContent) - onActivated: function(newIndex) { - if(idModel[newIndex] != objEditor.obj.labelContent) { - objEditor.obj.labelContent = idModel[newIndex] - objectListList.update() - } - } - } - - // Dynamic properties - Repeater { - id: dlgCustomProperties - - Item { - height: customPropComment.height + customPropText.height + customPropCheckBox.height + customPropCombo.height + customPropListDict.height - width: dlgProperties.width - property string label: qsTranslate('prop',modelData[0]) - property string icon: Utils.camelCase2readable(modelData[0]) - - // Item for comments - Label { - id: customPropComment - width: parent.width - height: visible ? implicitHeight : 0 - visible: modelData[0].startsWith('comment') - // Translated text with object name. - property string trText: visible ? qsTranslate('comment', modelData[1]).toString() : '' - text: (visible && trText.includes("%1") ? trText.arg(objEditor.obj.name) : trText).toString() - //color: sysPalette.windowText - wrapMode: Text.WordWrap - } - - // Setting for text & number settings as well as domains & expressions - Setting.TextSetting { - id: customPropText - height: visible ? 30 : 0 - width: parent.width - label: parent.label - icon: `settings/custom/${parent.icon}.svg` - isDouble: modelData[1] == 'number' - visible: paramTypeIn(modelData[1], ['Expression', 'Domain', 'string', 'number']) - defValue: visible ? { - 'Expression': () => Utils.simplifyExpression(objEditor.obj[modelData[0]].toEditableString()), - 'Domain': () => objEditor.obj[modelData[0]].toString(), - 'string': () => objEditor.obj[modelData[0]], - 'number': () => objEditor.obj[modelData[0]] - }[modelData[1]]() : "" - onChanged: function(newValue) { - var newValue = { - 'Expression': () => new MathLib.Expression(newValue), - 'Domain': () => MathLib.parseDomain(newValue), - 'string': () => newValue, - 'number': () => parseFloat(newValue) - }[modelData[1]]() - // Ensuring old and new values are different to prevent useless adding to history. - if(objEditor.obj[modelData[0]] != newValue) { - history.addToHistory(new HistoryLib.EditedProperty( - objEditor.obj.name, objEditor.objType, modelData[0], - objEditor.obj[modelData[0]], newValue - )) - objEditor.obj[modelData[0]] = newValue - Objects.currentObjects[objEditor.objType][objEditor.objIndex].update() - objectListList.update() - } - } - } - - // Setting for boolean - CheckBox { - id: customPropCheckBox - visible: modelData[1] == 'boolean' - height: visible ? 20 : 0 - width: parent.width - text: parent.label - //icon: visible ? `settings/custom/${parent.icon}.svg` : '' - - checked: visible ? objEditor.obj[modelData[0]] : false - onClicked: { - history.addToHistory(new HistoryLib.EditedProperty( - objEditor.obj.name, objEditor.objType, modelData[0], - objEditor.obj[modelData[0]], this.checked - )) - objEditor.obj[modelData[0]] = this.checked - Objects.currentObjects[objEditor.objType][objEditor.objIndex].update() - objectListList.update() - } - } - - // Setting when selecting data from an enum, or an object of a certain type. - Setting.ComboBoxSetting { - id: customPropCombo - width: dlgProperties.width - height: visible ? 30 : 0 - label: parent.label - icon: visible ? `settings/custom/${parent.icon}.svg` : '' - // True to select an object of type, false for enums. - property bool selectObjMode: paramTypeIn(modelData[1], ['ObjectType']) - property bool isRealObject: !selectObjMode || (modelData[1].objType != "ExecutableObject" && modelData[1].objType != "DrawableObject") - - // Base, untranslated version of the model. - property var baseModel: visible ? - (selectObjMode ? - Objects.getObjectsName(modelData[1].objType).concat( - isRealObject ? [qsTr("+ Create new %1").arg(Objects.types[modelData[1].objType].displayType())] : - []) : - modelData[1].values) - : [] - // Translated version 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.currentObjectsByName[baseModel[newIndex]] - if(newIndex != 0) { - // Make sure we don't set the object to null. - if(selectedObj == null) { - // Creating new object. - selectedObj = Objects.createNewRegisteredObject(modelData[1].objType) - history.addToHistory(new HistoryLib.CreateNewObject(selectedObj.name, modelData[1].objType, selectedObj.export())) - baseModel = Objects.getObjectsName(modelData[1].objType).concat( - isRealObject ? [qsTr("+ Create new %1").arg(Objects.types[modelData[1].objType].displayType())] : - []) - currentIndex = baseModel.indexOf(selectedObj.name) - } - selectedObj.requiredBy.push(Objects.currentObjects[objEditor.objType][objEditor.objIndex]) - //Objects.currentObjects[objEditor.objType][objEditor.objIndex].requiredBy = objEditor.obj[modelData[0]].filter((obj) => objEditor.obj.name != obj.name) - } - objEditor.obj.requiredBy = objEditor.obj.requiredBy.filter((obj) => objEditor.obj.name != obj.name) - history.addToHistory(new HistoryLib.EditedProperty( - objEditor.obj.name, objEditor.objType, modelData[0], - objEditor.obj[modelData[0]], selectedObj - )) - objEditor.obj[modelData[0]] = selectedObj - } else if(baseModel[newIndex] != objEditor.obj[modelData[0]]) { - // Ensuring new property is different to not add useless history entries. - history.addToHistory(new HistoryLib.EditedProperty( - objEditor.obj.name, objEditor.objType, modelData[0], - objEditor.obj[modelData[0]], baseModel[newIndex] - )) - objEditor.obj[modelData[0]] = baseModel[newIndex] - } - // Refreshing - Objects.currentObjects[objEditor.objType][objEditor.objIndex].update() - objectListList.update() - } - } - - // Setting to edit lists or dictionaries (e.g sequences & repartition function values) - Setting.ListSetting { - id: customPropListDict - width: parent.width - height: visible ? implicitHeight : 0 - - visible: paramTypeIn(modelData[1], ['List', 'Dict']) - label: parent.label - //icon: `settings/custom/${parent.icon}.svg` - dictionaryMode: paramTypeIn(modelData[1], ['Dict']) - keyType: dictionaryMode ? modelData[1].keyType : 'string' - valueType: visible ? modelData[1].valueType : 'string' - preKeyLabel: visible ? (dictionaryMode ? modelData[1].preKeyLabel : modelData[1].label).replace(/\{name\}/g, objEditor.obj.name) : '' - postKeyLabel: visible ? (dictionaryMode ? modelData[1].postKeyLabel : '').replace(/\{name\}/g, objEditor.obj.name) : '' - keyRegexp: dictionaryMode ? modelData[1].keyFormat : /^.+$/ - valueRegexp: visible ? modelData[1].format : /^.+$/ - forbidAdding: visible ? modelData[1].forbidAdding : false - - onChanged: { - var exported = exportModel() - history.addToHistory(new HistoryLib.EditedProperty( - objEditor.obj.name, objEditor.objType, modelData[0], - objEditor.obj[modelData[0]], exported - )) - //Objects.currentObjects[objEditor.objType][objEditor.objIndex][modelData[0]] = exported - objEditor.obj[modelData[0]] = exported - //Objects.currentObjects[objEditor.objType][objEditor.objIndex].update() - objEditor.obj.update() - objectListList.update() - } - - Component.onCompleted: { - if(visible) importModel(objEditor.obj[modelData[0]]) - } - } - } - } - } - - /*! - \qmlmethod void EditorDialog::show() - Shows the editor after the object to be edited is set. - */ - function show() { - dlgCustomProperties.model = [] // Reset - let objProps = Objects.types[objEditor.objType].properties() - dlgCustomProperties.model = Object.keys(objProps).map(prop => [prop, objProps[prop]]) // Converted to 2-dimentional array. - objEditor.open() - } -} diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml index f58e496..0d215ab 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectLists.qml @@ -20,11 +20,12 @@ import QtQuick 2.12 import QtQuick.Dialogs 1.3 as D import QtQuick.Controls 2.12 import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting +import eu.ad5001.LogarithmPlotter.ObjectLists.Editor 1.0 as Editor import "../js/objects.js" as Objects /*! \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 synthetically see all objects, while giving the user the ability @@ -113,7 +114,7 @@ ScrollView { } // Object editor - EditorDialog { + Editor.Dialog { id: objEditor } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml index b13a293..ddc73eb 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/ObjectLists/ObjectRow.qml @@ -27,14 +27,13 @@ import "../js/math/latex.js" as LatexJS /*! \qmltype ObjectRow - \inqmlmodule eu.ad5001.LogarithmPlotter + \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 { @@ -42,11 +41,27 @@ Item { 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 - property int minHeight: 40 + /*! + \qmlproperty bool ObjectRow::minHeight + Minimum height of the row. + */ + readonly property int minHeight: 40 height: objDescription.height width: obj.typeList.width diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/LatexExpression.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/LatexExpression.qml deleted file mode 100644 index bc8897c..0000000 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/LatexExpression.qml +++ /dev/null @@ -1,28 +0,0 @@ -/** - * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. - * Copyright (C) 2022 Ad5001 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -import QtQuick 2.12 -import QtQuick.Controls 2.12 - -Image { - id: expr - property string expression - - src: Latex.render(expression).split(',')[0] -}