From 50ebeb4bc8b5a35c2cd4e726432ec46f7b73330e Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Wed, 18 Feb 2026 18:16:29 +0100 Subject: [PATCH 01/23] Added a sample model addiotion group --- src/easyshapes_app.qmlproject | 9 +- src/easyshapes_app.qrc | 166 ++++++++++++++++++ src/easyshapes_app/Gui/ApplicationWindow.qml | 4 +- src/easyshapes_app/Gui/Globals/References.qml | 10 ++ .../Sidebar/Basic/Groups/SampleModel.qml | 65 +++++++ .../SampleModel/Sidebar/Basic/Layout.qml | 8 + .../Sidebar/Basic/Popups/CreateNewModel.qml | 34 ++++ .../Basic/Popups/LoadExistingModel.qml | 34 ++++ 8 files changed, 325 insertions(+), 5 deletions(-) create mode 100644 src/easyshapes_app.qrc create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml diff --git a/src/easyshapes_app.qmlproject b/src/easyshapes_app.qmlproject index ff45ed3..a57d5e8 100644 --- a/src/easyshapes_app.qmlproject +++ b/src/easyshapes_app.qmlproject @@ -1,5 +1,6 @@ import QmlProject 1.1 + Project { mainFile: "easyshapes_app/main.qml" @@ -14,7 +15,7 @@ Project { directory: "easyshapes_app" } QmlFiles { - directory: "../../src/EasyApp" + directory: "../../EasyApp/src/EasyApp" } // Include .js files from specified directory and its subdirectories @@ -22,7 +23,7 @@ Project { directory: "easyshapes_app" } JavaScriptFiles { - directory: "../../src/EasyApp" + directory: "../../EasyApp/src/EasyApp" } // Include Module Definition Files (qmldir), as well as .ts and .qrc @@ -33,9 +34,11 @@ Project { recursive: true } Files { - directory: "../../src/EasyApp" + directory: "../../EasyApp/src/EasyApp" filter: "qmldir;*.ts;*.qrc;*.html" recursive: true } + + mainUiFile: "easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml" } diff --git a/src/easyshapes_app.qrc b/src/easyshapes_app.qrc new file mode 100644 index 0000000..7de6409 --- /dev/null +++ b/src/easyshapes_app.qrc @@ -0,0 +1,166 @@ + + + ../../EasyApp/src/EasyApp/Gui/Animations/ColorReset.qml + ../../EasyApp/src/EasyApp/Gui/Animations/qmldir + ../../EasyApp/src/EasyApp/Gui/Animations/ThemeChange.qml + ../../EasyApp/src/EasyApp/Gui/Animations/TranslationChange.qml + ../../EasyApp/src/EasyApp/Gui/Charts/ChartViewHeatmap2dPlotly.qml + ../../EasyApp/src/EasyApp/Gui/Charts/ChartViewSimple1dPlotly.qml + ../../EasyApp/src/EasyApp/Gui/Charts/Plotly1dLine.qml + ../../EasyApp/src/EasyApp/Gui/Charts/Plotly1dMeasVsCalc.qml + ../../EasyApp/src/EasyApp/Gui/Charts/Plotly2dHeatmap.qml + ../../EasyApp/src/EasyApp/Gui/Charts/Plotly3dScatter.qml + ../../EasyApp/src/EasyApp/Gui/Charts/Plotly3dSurface.qml + ../../EasyApp/src/EasyApp/Gui/Charts/qmldir + ../../EasyApp/src/EasyApp/Gui/Charts/QtCharts1dBase 2.qml + ../../EasyApp/src/EasyApp/Gui/Charts/QtCharts1dBase.qml + ../../EasyApp/src/EasyApp/Gui/Charts/QtCharts1dMeasVsCalc.qml + ../../EasyApp/src/EasyApp/Gui/Charts/QtCharts1dValueAxis.qml + ../../EasyApp/src/EasyApp/Gui/Components/AboutDialog.qml + ../../EasyApp/src/EasyApp/Gui/Components/AppBarCentralTabs.qml + ../../EasyApp/src/EasyApp/Gui/Components/AppBarLeftButtons.qml + ../../EasyApp/src/EasyApp/Gui/Components/AppBarRightButtons.qml + ../../EasyApp/src/EasyApp/Gui/Components/ApplicationWindow.qml + ../../EasyApp/src/EasyApp/Gui/Components/BasicReport.qml + ../../EasyApp/src/EasyApp/Gui/Components/ContentArea.qml + ../../EasyApp/src/EasyApp/Gui/Components/ContentPage.qml + ../../EasyApp/src/EasyApp/Gui/Components/GuideWindow.qml + ../../EasyApp/src/EasyApp/Gui/Components/GuideWindowContainer.qml + ../../EasyApp/src/EasyApp/Gui/Components/JsonListModel.qml + ../../EasyApp/src/EasyApp/Gui/Components/MainContent.qml + ../../EasyApp/src/EasyApp/Gui/Components/PreferencesDialog.qml + ../../EasyApp/src/EasyApp/Gui/Components/ProjectDescriptionDialog.qml + ../../EasyApp/src/EasyApp/Gui/Components/qmldir + ../../EasyApp/src/EasyApp/Gui/Components/SideBar.qml + ../../EasyApp/src/EasyApp/Gui/Components/SideBarColumn.qml + ../../EasyApp/src/EasyApp/Gui/Components/TableView.qml + ../../EasyApp/src/EasyApp/Gui/Components/TableViewAdvancedLabel.qml + ../../EasyApp/src/EasyApp/Gui/Components/TableViewButton.qml + ../../EasyApp/src/EasyApp/Gui/Components/TableViewCheckBox.qml + ../../EasyApp/src/EasyApp/Gui/Components/TableViewComboBox.qml + ../../EasyApp/src/EasyApp/Gui/Components/TableViewDelegate.qml + ../../EasyApp/src/EasyApp/Gui/Components/TableViewHeader.qml + ../../EasyApp/src/EasyApp/Gui/Components/TableViewLabel.qml + ../../EasyApp/src/EasyApp/Gui/Components/TableViewLabelControl.qml + ../../EasyApp/src/EasyApp/Gui/Components/TableViewParameter.qml + ../../EasyApp/src/EasyApp/Gui/Components/TableViewTextInput.qml + ../../EasyApp/src/EasyApp/Gui/Components/TableViewTwoRowsAdvancedLabel.qml + ../../EasyApp/src/EasyApp/Gui/Elements/AppBarTabButton.qml + ../../EasyApp/src/EasyApp/Gui/Elements/ApplicationWindow.qml + ../../EasyApp/src/EasyApp/Gui/Elements/Button.qml + ../../EasyApp/src/EasyApp/Gui/Elements/CheckBox.qml + ../../EasyApp/src/EasyApp/Gui/Elements/CheckIndicator.qml + ../../EasyApp/src/EasyApp/Gui/Elements/ComboBox.qml + ../../EasyApp/src/EasyApp/Gui/Elements/CursorDelegate.qml + ../../EasyApp/src/EasyApp/Gui/Elements/Dialog.qml + ../../EasyApp/src/EasyApp/Gui/Elements/DialogButtonBox.qml + ../../EasyApp/src/EasyApp/Gui/Elements/GroupBox.qml + ../../EasyApp/src/EasyApp/Gui/Elements/GroupButton.qml + ../../EasyApp/src/EasyApp/Gui/Elements/GroupColumn.qml + ../../EasyApp/src/EasyApp/Gui/Elements/GroupRow.qml + ../../EasyApp/src/EasyApp/Gui/Elements/Label.qml + ../../EasyApp/src/EasyApp/Gui/Elements/LinkedImage.qml + ../../EasyApp/src/EasyApp/Gui/Elements/Menu.qml + ../../EasyApp/src/EasyApp/Gui/Elements/MenuItem.qml + ../../EasyApp/src/EasyApp/Gui/Elements/ParamComboBox.qml + ../../EasyApp/src/EasyApp/Gui/Elements/Parameter.qml + ../../EasyApp/src/EasyApp/Gui/Elements/ParamTextField.qml + ../../EasyApp/src/EasyApp/Gui/Elements/qmldir + ../../EasyApp/src/EasyApp/Gui/Elements/RadioButton.qml + ../../EasyApp/src/EasyApp/Gui/Elements/RadioIndicator.qml + ../../EasyApp/src/EasyApp/Gui/Elements/RemoteController.qml + ../../EasyApp/src/EasyApp/Gui/Elements/RemotePointer.qml + ../../EasyApp/src/EasyApp/Gui/Elements/RunningLabel.qml + ../../EasyApp/src/EasyApp/Gui/Elements/ScrollBar.qml + ../../EasyApp/src/EasyApp/Gui/Elements/ScrollIndicator.qml + ../../EasyApp/src/EasyApp/Gui/Elements/SideBarButton.qml + ../../EasyApp/src/EasyApp/Gui/Elements/Slider.qml + ../../EasyApp/src/EasyApp/Gui/Elements/SliderHandle.qml + ../../EasyApp/src/EasyApp/Gui/Elements/SpinBox.qml + ../../EasyApp/src/EasyApp/Gui/Elements/SplashScreen.qml + ../../EasyApp/src/EasyApp/Gui/Elements/StatusBar.qml + ../../EasyApp/src/EasyApp/Gui/Elements/StatusBarItem.qml + ../../EasyApp/src/EasyApp/Gui/Elements/TabBar.qml + ../../EasyApp/src/EasyApp/Gui/Elements/TabButton.qml + ../../EasyApp/src/EasyApp/Gui/Elements/TextArea.qml + ../../EasyApp/src/EasyApp/Gui/Elements/TextField.qml + ../../EasyApp/src/EasyApp/Gui/Elements/TextInput.qml + ../../EasyApp/src/EasyApp/Gui/Elements/ToolButton.qml + ../../EasyApp/src/EasyApp/Gui/Elements/ToolTip.qml + ../../EasyApp/src/EasyApp/Gui/Elements/ToolTipShadow.qml + ../../EasyApp/src/EasyApp/Gui/Globals/qmldir + ../../EasyApp/src/EasyApp/Gui/Globals/Vars.qml + ../../EasyApp/src/EasyApp/Gui/Html/plotly-2.18.0.min.js + ../../EasyApp/src/EasyApp/Gui/Logic/Plotting.js + ../../EasyApp/src/EasyApp/Gui/Logic/ProjectConfig.js + ../../EasyApp/src/EasyApp/Gui/Logic/qmldir + ../../EasyApp/src/EasyApp/Gui/Logic/Translate.js + ../../EasyApp/src/EasyApp/Gui/Logic/Utils.js + ../../EasyApp/src/EasyApp/Gui/Style/Colors.qml + ../../EasyApp/src/EasyApp/Gui/Style/Fonts.qml + ../../EasyApp/src/EasyApp/Gui/Style/qmldir + ../../EasyApp/src/EasyApp/Gui/Style/Sizes.qml + ../../EasyApp/src/EasyApp/Gui/Style/Times.qml + ../../EasyApp/src/EasyApp/Logic/Maintenance/qmldir + ../../EasyApp/src/EasyApp/Logic/Maintenance/Updater.qml + easyshapes_app.qmlproject + easyshapes_app/Backends/MockBackend.qml + easyshapes_app/Backends/MockQml/Analysis.qml + easyshapes_app/Backends/MockQml/Project.qml + easyshapes_app/Backends/MockQml/qmldir + easyshapes_app/Backends/MockQml/Report.qml + easyshapes_app/Backends/MockQml/Status.qml + easyshapes_app/Backends/qmldir + easyshapes_app/Gui/ApplicationWindow.qml + easyshapes_app/Gui/Globals/ApplicationInfo.qml + easyshapes_app/Gui/Globals/BackendWrapper.qml + easyshapes_app/Gui/Globals/qmldir + easyshapes_app/Gui/Globals/References.qml + easyshapes_app/Gui/Pages/Analysis/Layout.qml + easyshapes_app/Gui/Pages/Analysis/MainArea/Chart.qml + easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/GetStarted.qml + easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Layout.qml + easyshapes_app/Gui/Pages/Home/Content.qml + easyshapes_app/Gui/Pages/Home/Popups/About.qml + easyshapes_app/Gui/Pages/Project/Layout.qml + easyshapes_app/Gui/Pages/Project/MainArea/Description.qml + easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/Examples.qml + easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/GetStarted.qml + easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/Recent.qml + easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Layout.qml + easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Popups/OpenCifFile.qml + easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Popups/ProjectDescription.qml + easyshapes_app/Gui/Pages/Project/Sidebar/Extra/Groups/Scrolling.qml + easyshapes_app/Gui/Pages/Project/Sidebar/Extra/Layout.qml + easyshapes_app/Gui/Pages/Project/Sidebar/Text/Layout.qml + easyshapes_app/Gui/Pages/Report/Layout.qml + easyshapes_app/Gui/Pages/Report/MainArea/Summary.qml + easyshapes_app/Gui/Pages/Report/Sidebar/Basic/Groups/Export.qml + easyshapes_app/Gui/Pages/Report/Sidebar/Basic/Layout.qml + easyshapes_app/Gui/Pages/Report/Sidebar/Extra/Groups/Empty.qml + easyshapes_app/Gui/Pages/Report/Sidebar/Extra/Layout.qml + easyshapes_app/Gui/Pages/SampleModel/Layout.qml + easyshapes_app/Gui/Pages/SampleModel/MainArea/GraphsView.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group1.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group4.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml + easyshapes_app/Gui/Pages/Toolbox/Layout.qml + easyshapes_app/Gui/Pages/Toolbox/MainArea/GraphsView.qml + easyshapes_app/Gui/Pages/Toolbox/MainArea/Image.qml + easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaPlain.qml + easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaRich.qml + easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group1.qml + easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group2.qml + easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group3.qml + easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group4.qml + easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Layout.qml + easyshapes_app/Gui/qmldir + easyshapes_app/Gui/StatusBar.qml + easyshapes_app/main.qml + + \ No newline at end of file diff --git a/src/easyshapes_app/Gui/ApplicationWindow.qml b/src/easyshapes_app/Gui/ApplicationWindow.qml index 3996326..c91a5f5 100644 --- a/src/easyshapes_app/Gui/ApplicationWindow.qml +++ b/src/easyshapes_app/Gui/ApplicationWindow.qml @@ -76,8 +76,8 @@ EaComponents.ApplicationWindow { id: sampleModelButton enabled: false fontIcon: 'puzzle-piece' - text: qsTr('Sample model') - ToolTip.text: qsTr('Sample model definition page') + text: qsTr('Sample Model') + ToolTip.text: qsTr('Sample Model definition page') Component.onCompleted: { Globals.References.applicationWindow.appBarCentralTabs.sampleModelButton = sampleModelButton } diff --git a/src/easyshapes_app/Gui/Globals/References.qml b/src/easyshapes_app/Gui/Globals/References.qml index 53be81c..4c0fb98 100644 --- a/src/easyshapes_app/Gui/Globals/References.qml +++ b/src/easyshapes_app/Gui/Globals/References.qml @@ -34,6 +34,16 @@ QtObject { } } }, + 'samplemodel': { + 'sidebar': { + 'basic': { + 'popups': { + 'LoadExistingModel': null, + 'CreateNewModel': null + } + } + } + }, 'analysis': { 'sidebar': { 'basic': { diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml new file mode 100644 index 0000000..5cf49c2 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml @@ -0,0 +1,65 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls +//import QtQuick.Dialogs + +import EasyApp.Gui.Globals as EaGlobals +import EasyApp.Gui.Style as EaStyle +import EasyApp.Gui.Elements as EaElements +import EasyApp.Gui.Components as EaComponents +import EasyApp.Gui.Logic as EaLogic + +import Gui.Globals as Globals + +EaElements.GroupColumn { + + EaElements.TextArea { + placeholderText: 'Sample Model was not loaded.' + enabled: false + } + + Grid { + + columns: 2 + spacing: EaStyle.Sizes.fontPixelSize + + // button 1 + EaElements.SideBarButton { + fontIcon: 'upload' + text: qsTr('Load an existing model') + + onClicked: { + console.debug(`Clicking '${text}' button ::: ${this}`) + Globals.References.pages.samplemodel.sidebar.basic.popups.LoadExistingModel.open() + } + + Loader { + source: '../Popups/LoadExistingModel.qml' + } + } + // button 1 + + + // button 2 + EaElements.SideBarButton { + fontIcon: 'plus-circle' + text: qsTr('Create a new model') + + onClicked: { + console.debug(`Clicking '${text}' button ::: ${this}`) + Globals.References.pages.samplemodel.sidebar.basic.popups.CreateNewModel.open() + } + + Loader { + source: '../Popups/CreateNewModel.qml' + } + } + // button 2 + + + } + +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml index d13c364..7d94fd8 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml @@ -13,6 +13,14 @@ import Gui.Globals as Globals EaComponents.SideBarColumn { + EaElements.GroupBox { + title: qsTr('Add a Model') + icon: 'vial' + collapsed: false + + Loader { source: 'Groups/SampleModel.qml' } + } + EaElements.GroupBox { title: qsTr('Group 1') icon: 'rocket' diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml new file mode 100644 index 0000000..68ee4e4 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +import EasyApp.Gui.Globals as EaGlobals +import EasyApp.Gui.Components as EaComponents +import EasyApp.Gui.Elements as EaElements + +import Gui.Globals as Globals + + + +EaElements.Dialog{ + +    Column { +        EaElements.Label { +            enabled: false +            text: qsTr("Name3") +        } + +        EaElements.Label { +            text: qsTr("Name4") +        } +    } + +    Component.onCompleted: { +        Globals.References.pages.samplemodel.sidebar.basic.popups.CreateNewModel = this +    } + +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml new file mode 100644 index 0000000..b5947eb --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +import EasyApp.Gui.Globals as EaGlobals +import EasyApp.Gui.Components as EaComponents +import EasyApp.Gui.Elements as EaElements + +import Gui.Globals as Globals + + + +EaElements.Dialog{ + +    Column { +        EaElements.Label { +            enabled: false +            text: qsTr("Name") +        } + +        EaElements.Label { +            text: qsTr("Name 2") +        } +    } + +    Component.onCompleted: { +        Globals.References.pages.samplemodel.sidebar.basic.popups.LoadExistingModel = this +    } + +} From 99888620e66a3c5dffa9fd874c86f2bb24c0e4b8 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Wed, 18 Feb 2026 19:08:46 +0100 Subject: [PATCH 02/23] Replace text area with table view in SampleModel --- .../Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml index 5cf49c2..3dfaee1 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml @@ -16,9 +16,9 @@ import Gui.Globals as Globals EaElements.GroupColumn { - EaElements.TextArea { - placeholderText: 'Sample Model was not loaded.' - enabled: false + EaComponents.TableView { + defaultInfoText: qsTr("No models defined") + header: EaComponents.TableViewHeader {} } Grid { From 63532025a377fefddda11f57601ebb5d05424a13 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Thu, 19 Feb 2026 17:06:21 +0100 Subject: [PATCH 03/23] Added a sample model name field in popup --- .../Sidebar/Basic/Popups/CreateNewModel.qml | 52 +++++++++++++++---- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml index 68ee4e4..45b1844 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml @@ -7,6 +7,7 @@ import QtQuick.Controls import QtQuick.Dialogs import EasyApp.Gui.Globals as EaGlobals +import EasyApp.Gui.Style as EaStyle import EasyApp.Gui.Components as EaComponents import EasyApp.Gui.Elements as EaElements @@ -16,19 +17,52 @@ import Gui.Globals as Globals EaElements.Dialog{ -    Column { -        EaElements.Label { -            enabled: false -            text: qsTr("Name3") -        } + property alias sampleModelName: sampleModelNameField.text -        EaElements.Label { -            text: qsTr("Name4") -        } -    } + title: qsTr("Create a new Sample Model") + + property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 + + standardButtons: Dialog.Ok + + Column { + spacing: EaStyle.Sizes.fontPixelSize + Column { + EaElements.Label { + enabled: false + text: qsTr("Name") + } + + EaElements.TextField { + id: sampleModelNameField + + implicitWidth: inputFieldWidth + horizontalAlignment: TextInput.AlignLeft + validator: RegularExpressionValidator { regularExpression: /^[a-zA-Z][a-zA-Z0-9_\-\.]{1,30}$/ } + placeholderText: qsTr("Enter Sample Model name here") + + Keys.onReturnPressed: dialog.accept() + Keys.onEnterPressed: dialog.accept() + } + } + + Column { + EaElements.Label { + enabled: false + text: qsTr("Name3") + } + + EaElements.Label { + text: qsTr("Name4") + } + } + + }     Component.onCompleted: {         Globals.References.pages.samplemodel.sidebar.basic.popups.CreateNewModel = this     } + + } From 2a5c8cd915f7dc24cb73d7c098c67b1a4b5f9a23 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Fri, 20 Feb 2026 16:37:00 +0100 Subject: [PATCH 04/23] Redefined a samplemodel creation popup --- src/easyshapes_app.qrc | 1 + .../Sidebar/Basic/Popups/CreateNewModel.qml | 24 ++++++++-------- src/easyshapes_app/test.qml | 28 +++++++++++++++++++ 3 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 src/easyshapes_app/test.qml diff --git a/src/easyshapes_app.qrc b/src/easyshapes_app.qrc index 7de6409..b6901a2 100644 --- a/src/easyshapes_app.qrc +++ b/src/easyshapes_app.qrc @@ -162,5 +162,6 @@ easyshapes_app/Gui/qmldir easyshapes_app/Gui/StatusBar.qml easyshapes_app/main.qml + easyshapes_app/test.qml \ No newline at end of file diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml index 45b1844..c3dccff 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml @@ -14,8 +14,8 @@ import EasyApp.Gui.Elements as EaElements import Gui.Globals as Globals - EaElements.Dialog{ + id: sampleModelCreationDialog property alias sampleModelName: sampleModelNameField.text @@ -26,7 +26,9 @@ EaElements.Dialog{ standardButtons: Dialog.Ok Column { + spacing: EaStyle.Sizes.fontPixelSize + Column { EaElements.Label { enabled: false @@ -36,10 +38,10 @@ EaElements.Dialog{ EaElements.TextField { id: sampleModelNameField - implicitWidth: inputFieldWidth + implicitWidth: sampleModelCreationDialog.inputFieldWidth horizontalAlignment: TextInput.AlignLeft validator: RegularExpressionValidator { regularExpression: /^[a-zA-Z][a-zA-Z0-9_\-\.]{1,30}$/ } - placeholderText: qsTr("Enter Sample Model name here") + placeholderText: qsTr("(optional) Enter Sample Model name here") Keys.onReturnPressed: dialog.accept() Keys.onEnterPressed: dialog.accept() @@ -49,20 +51,20 @@ EaElements.Dialog{ Column { EaElements.Label { enabled: false - text: qsTr("Name3") + text: qsTr("Choose the underlying structure type") } - EaElements.Label { - text: qsTr("Name4") + EaElements.ComboBox { + implicitWidth: sampleModelCreationDialog.inputFieldWidth + model: ["Ring", "Ball", "Vesicle", "Rod", "Bilayer", "Monolayer", "Lattice"] } } } -    Component.onCompleted: { -        Globals.References.pages.samplemodel.sidebar.basic.popups.CreateNewModel = this -    } - - + Component.onCompleted: { + Globals.References.pages.samplemodel.sidebar.basic.popups.CreateNewModel = this + } } + diff --git a/src/easyshapes_app/test.qml b/src/easyshapes_app/test.qml new file mode 100644 index 0000000..4abf65b --- /dev/null +++ b/src/easyshapes_app/test.qml @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +import EasyApp.Gui.Globals as EaGlobals +import EasyApp.Gui.Style as EaStyle +import EasyApp.Gui.Components as EaComponents +import EasyApp.Gui.Elements as EaElements + +import Gui.Globals as Globals + +ApplicationWindow{ + + width: 800 + height: 600 + visible: true + + Loader { + source: 'Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml' + } + + Component.onCompleted: Globals.References.pages.samplemodel.sidebar.basic.popups.CreateNewModel.open() + +} From 7d85dd34489ec0234458bdb1ee8fb4b76fc694b3 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Wed, 25 Mar 2026 23:08:50 +0100 Subject: [PATCH 05/23] added a new button for saving samples --- src/easyshapes_app/Gui/ApplicationWindow.qml | 2 +- .../Sidebar/Basic/Groups/SampleModel.qml | 103 ++++++++++- .../Sidebar/Basic/Popups/CreateNewModel.qml | 39 +++- .../Basic/Popups/LoadExistingModel.qml | 170 +++++++++++++++++- src/easyshapes_app/test.qml | 162 ++++++++++++++++- 5 files changed, 454 insertions(+), 22 deletions(-) diff --git a/src/easyshapes_app/Gui/ApplicationWindow.qml b/src/easyshapes_app/Gui/ApplicationWindow.qml index c91a5f5..029c1d7 100644 --- a/src/easyshapes_app/Gui/ApplicationWindow.qml +++ b/src/easyshapes_app/Gui/ApplicationWindow.qml @@ -75,7 +75,7 @@ EaComponents.ApplicationWindow { EaElements.AppBarTabButton { id: sampleModelButton enabled: false - fontIcon: 'puzzle-piece' + fontIcon: 'layer-group' text: qsTr('Sample Model') ToolTip.text: qsTr('Sample Model definition page') Component.onCompleted: { diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml index 3dfaee1..c273688 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml @@ -15,21 +15,96 @@ import EasyApp.Gui.Logic as EaLogic import Gui.Globals as Globals EaElements.GroupColumn { + property double buttonWidth: EaStyle.Sizes.sideBarContentWidth * 0.3164 EaComponents.TableView { + id: loadedSampleModelTableView + clip: true + // anchors.fill: parent + defaultInfoText: qsTr("No models defined") - header: EaComponents.TableViewHeader {} + header: EaComponents.TableViewHeader { + EaComponents.TableViewLabel { + id: modelNameColumnName + width: EaStyle.Sizes.fontPixelSize * 8 + text: qsTr("Name") + color: EaStyle.Colors.themeForegroundMinor + } + + EaComponents.TableViewLabel { + id: modelTypeColumnName + width: EaStyle.Sizes.fontPixelSize * 6 + text: qsTr("Type") + color: EaStyle.Colors.themeForegroundMinor + } + + EaComponents.TableViewLabel { + id: modelDescrColumnName + width: EaStyle.Sizes.fontPixelSize * 24 + text: qsTr("Description") + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: ListModel { + id: loadedSambleModelsModel + } + + delegateModelAccess: DelegateModel.ReadWrite + + delegate: EaComponents.TableViewDelegate { + required property int index + required property string name + required property string structure_type + required property string description + + EaComponents.TableViewTextInput { + id: modelNameColumn + width: EaStyle.Sizes.fontPixelSize * 12 + text: name + onEditingFinished: name = text + leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 + } + + EaComponents.TableViewComboBox{ + id: structureTypeColumn + width: EaStyle.Sizes.fontPixelSize * 6 + model: ["Ring", "Ball", "Vesicle", "Rod", "Bilayer", "Monolayer", "Lattice"] + + Component.onCompleted: { + currentIndex = model.indexOf(structure_type) + } + + onActivated: (index) => { + structure_type = model[index] + } + } + + EaComponents.TableViewTextInput { + id: descrColumn + width: EaStyle.Sizes.fontPixelSize * 20 + text: description + onEditingFinished: { + description = text + console.log("descrColumn onEditingFinished") + } + onAccepted: { + console.log("descrColumn onAccepted") + } + } + } } Grid { - - columns: 2 + columns: 3 spacing: EaStyle.Sizes.fontPixelSize + // button 1 EaElements.SideBarButton { fontIcon: 'upload' text: qsTr('Load an existing model') + width: buttonWidth onClicked: { console.debug(`Clicking '${text}' button ::: ${this}`) @@ -38,6 +113,10 @@ EaElements.GroupColumn { Loader { source: '../Popups/LoadExistingModel.qml' + onLoaded: { + item.targetModel = loadedSambleModelsModel + Globals.References.pages.samplemodel.sidebar.basic.popups.LoadExistingModel = item + } } } // button 1 @@ -47,6 +126,7 @@ EaElements.GroupColumn { EaElements.SideBarButton { fontIcon: 'plus-circle' text: qsTr('Create a new model') + width: buttonWidth onClicked: { console.debug(`Clicking '${text}' button ::: ${this}`) @@ -55,11 +135,28 @@ EaElements.GroupColumn { Loader { source: '../Popups/CreateNewModel.qml' + onLoaded: { + item.targetModel = loadedSambleModelsModel + Globals.References.pages.samplemodel.sidebar.basic.popups.CreateNewModel = item + } } } // button 2 + // button 3 + EaElements.SideBarButton { + id: saveModelButton + fontIcon: 'download' + text: qsTr('Save the model') + width: buttonWidth + enabled: loadedSampleModelTableView.model ? loadedSampleModelTableView.model.count > 0 : false + onClicked: { + console.debug(`Clicking '${text}' button ::: ${this}`) + Globals.References.pages.samplemodel.sidebar.basic.popups.LoadExistingModel.availableModelsModel.append(loadedSambleModelsModel.get(0)) + } + } + // button 3 } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml index c3dccff..9502ee3 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml @@ -17,13 +17,28 @@ import Gui.Globals as Globals EaElements.Dialog{ id: sampleModelCreationDialog - property alias sampleModelName: sampleModelNameField.text + property var targetModel title: qsTr("Create a new Sample Model") property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 - standardButtons: Dialog.Ok + standardButtons: Dialog.Ok // | Dialog.Cancel + + onAccepted: { + console.log("Ok Clicked") + + targetModel.clear() + targetModel.append( + { + name: sampleModelNameField.text, + structure_type: sampleModelTypeField.currentText, + description: sampleModelDescrField.text + } + ) + } + onRejected: console.log("Cancel Clicked") + onOpened: console.log("Opened CreateNewModel Clicked") Column { @@ -42,9 +57,6 @@ EaElements.Dialog{ horizontalAlignment: TextInput.AlignLeft validator: RegularExpressionValidator { regularExpression: /^[a-zA-Z][a-zA-Z0-9_\-\.]{1,30}$/ } placeholderText: qsTr("(optional) Enter Sample Model name here") - - Keys.onReturnPressed: dialog.accept() - Keys.onEnterPressed: dialog.accept() } } @@ -55,11 +67,28 @@ EaElements.Dialog{ } EaElements.ComboBox { + id: sampleModelTypeField implicitWidth: sampleModelCreationDialog.inputFieldWidth model: ["Ring", "Ball", "Vesicle", "Rod", "Bilayer", "Monolayer", "Lattice"] } } + Column { + EaElements.Label { + enabled: false + text: qsTr("Description") + } + + EaElements.TextField { + id: sampleModelDescrField + + implicitWidth: sampleModelCreationDialog.inputFieldWidth + horizontalAlignment: TextInput.AlignLeft + validator: RegularExpressionValidator { regularExpression: /^[a-zA-Z][a-zA-Z0-9_\-\.]{1,30}$/ } + placeholderText: qsTr("(optional) Enter Sample Model description here") + } + } + } Component.onCompleted: { diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml index b5947eb..dd6570e 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml @@ -9,26 +9,180 @@ import QtQuick.Dialogs import EasyApp.Gui.Globals as EaGlobals import EasyApp.Gui.Components as EaComponents import EasyApp.Gui.Elements as EaElements +import EasyApp.Gui.Style as EaStyle import Gui.Globals as Globals EaElements.Dialog{ + id: sampleModelLoadDialog + + property var targetModel + + title: qsTr("Load a Sample Model from the Asset Library") + + property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 + + property alias availableModelsModel: availableSambleModelsModel + + standardButtons: Dialog.Ok // | Dialog.Cancel + //leftPadding: 40 + + onAccepted: { + console.log("Ok Clicked") + + var indexes = selectionModel.selectedIndexes + + if (indexes.length > 0) { + var row = indexes[0].row + var item = availableSambleModelsModel.get(row) + + console.log("Selected SampleModel: ", item.name) + + targetModel.clear() + targetModel.append(item) + selectionModel.clear() + } + } + onRejected: { + console.log("Cancel Clicked") + selectionModel.clear() + }     Column { + +         EaElements.Label {             enabled: false -            text: qsTr("Name") +            text: qsTr("Available in the Asset Library")         } -        EaElements.Label { -            text: qsTr("Name 2") -        } -    } + EaComponents.TableView { + clip: true + id: loadModelTableView + defaultInfoText: qsTr("No models found") -    Component.onCompleted: { -        Globals.References.pages.samplemodel.sidebar.basic.popups.LoadExistingModel = this -    } + header: EaComponents.TableViewHeader { + EaComponents.TableViewLabel { + id: modelNameColumnName + width: EaStyle.Sizes.fontPixelSize * 10 + text: qsTr("Name") + color: EaStyle.Colors.themeForegroundMinor + leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 + } + + EaComponents.TableViewLabel { + id: modelTypeColumnName + width: EaStyle.Sizes.fontPixelSize * 6 + text: qsTr("Type") + color: EaStyle.Colors.themeForegroundMinor + } + + EaComponents.TableViewLabel { + id: modelDescrColumnName + width: EaStyle.Sizes.fontPixelSize * 22 + text: qsTr("Description") + color: EaStyle.Colors.themeForegroundMinor + } + } + model: ListModel { + id: availableSambleModelsModel + ListElement { name: "Samle1_aluv"; structure_type: "Vesicle"; description: "In order to avoid a prolonged pro-inflammatory neutrophil response, signaling downstream of an agonist-activated G protein-coupled receptor (GPCR) has to be rapidly terminated. Among the family of GPCR kinases (GRKs) that regulate receptor phosphorylation and signaling termination, GRK2, which is highly expressed by immune cells, plays an important role." } + ListElement { name: "Sample2_nanodisc"; structure_type: "Ring"; description: "The medium chain fatty acid receptor GPR84 as well as formyl peptide receptor 2 (FPR2)" } + ListElement { name: "Sample3_cubosome"; structure_type: "Lattice"; description: "receptors expressed in neutrophils, play a key role in regulating inflammation. In this study, we investigated the effects of GRK2 inhibitors on neutrophil functions induced by GPR84 and FPR2 agonists." } + ListElement { name: "Sample4"; structure_type: "Ring"; description: "GRK2 was shown to be expressed in human neutrophils and analysis of subcellular fractions" } + ListElement { name: "Sample5"; structure_type: "Ball"; description: "revealed a cytosolic localization. The GRK2 inhibitors enhanced and prolonged neutrophil production " } + ListElement { name: "Sample6"; structure_type: "Vesicle"; description: "production of reactive oxygen species (ROS) induced by GPR84- but not FPR2-agonists" } + ListElement { name: "Sample7"; structure_type: "Rod"; description: "suggesting a receptor selective function of GRK2. This suggestion was supported by β-arrestin recruitment data. The ROS production induced by a non β-arrestin recruiting GPR84" } + ListElement { name: "Sample8"; structure_type: "Bilayer"; description: "This suggestion was supported by β-arrestin recruitment data. The ROS production induced by a non β-arrestin recruiting GPR84 agonist was not affected by the GRK2 inhibitor." } + ListElement { name: "Sample9"; structure_type: "Monolayer"; description: "Termination of this β-arrestin independent response relied, similar to the response induced by FPR2 agonists, primarily on the actin cytoskeleton." } + ListElement { name: "Samplewithareallylongname"; structure_type: "Lattice"; description: "In summary, we show that GPR84 utilizes GRK2 in concert with β-arrestin and actin cytoskeleton dependent processes to fine-tune the activity of the ROS generating NADPH-oxidase in neutrophils." } + } + + property var itemSelectionModel: ItemSelectionModel { + id: selectionModel + model: availableSambleModelsModel // ListView.view.model + // model: ListView.view.model + } + + property bool activeSelection: true + // property var itemSelectionModel: activeSelection ? _selectionModel : null + + // function isItemSelected(index) { + // return itemSelectionModel && itemSelectionModel.isSelected( + // itemSelectionModel.model.index(index, 0) + // ) + // } + + delegate: EaComponents.TableViewDelegate { + + required property int index + required property string name + required property string structure_type + required property string description + + // color: { + // if (!ListView.view.highlightSelection) { + // return "whatever I want" + // } + + // const selected = ListView.view.isItemSelected(index) + + // return selected + // ? EaStyle.Colors.themeAccentMinor + // : EaStyle.Colors.themeBackgroundHovered1 + // } + + color: { + if (!ListView.view.activeSelection) { + return index % 2 ? + EaStyle.Colors.themeBackgroundHovered2 : + EaStyle.Colors.themeBackgroundHovered1 + } + + ListView.view.itemSelectionModel.selection // create dependency + + return ListView.view.itemSelectionModel.isSelected( + ListView.view.itemSelectionModel.model.index(index, 0) + ) ? EaStyle.Colors.themeAccentMinor : EaStyle.Colors.themeBackgroundHovered1 + } + + // color: { + // ListView.view.itemSelectionModel.selection // create dependency + // return ListView.view.itemSelectionModel.isSelected( + // ListView.view.itemSelectionModel.model.index(index, 0) + // ) ? EaStyle.Colors.themeAccentMinor : EaStyle.Colors.themeBackgroundHovered1 + // } + + EaComponents.TableViewLabel { + id: modelNameColumn + width: EaStyle.Sizes.fontPixelSize * 10 + text: name + leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 + } + + EaComponents.TableViewLabel { + id: typeColumn + width: EaStyle.Sizes.fontPixelSize * 6 + text: structure_type + } + + EaComponents.TableViewLabel { + id: descrColumn + width: EaStyle.Sizes.fontPixelSize * 22 + text: description + } + + mouseArea.onPressed: (mouse) => { + let idx = ListView.view.itemSelectionModel.model.index(index, 0) + ListView.view.itemSelectionModel.select( + idx, + ItemSelectionModel.ClearAndSelect + ) + } + } + } +    } } diff --git a/src/easyshapes_app/test.qml b/src/easyshapes_app/test.qml index 4abf65b..d452593 100644 --- a/src/easyshapes_app/test.qml +++ b/src/easyshapes_app/test.qml @@ -10,19 +10,171 @@ import EasyApp.Gui.Globals as EaGlobals import EasyApp.Gui.Style as EaStyle import EasyApp.Gui.Components as EaComponents import EasyApp.Gui.Elements as EaElements +import Qt.labs.qmlmodels import Gui.Globals as Globals ApplicationWindow{ - width: 800 - height: 600 + width: 640 + height: 580 + color: EaStyle.Colors.contentBackground visible: true - Loader { - source: 'Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml' + Grid { + spacing: EaStyle.Sizes.fontPixelSize * 4 + leftPadding: 12 + + + Column { + width: 600 + spacing: EaStyle.Sizes.fontPixelSize + + EaElements.ComboBox { + model: [qsTr("Light"), qsTr("Dark"), qsTr("System")] + onActivated: { + if (currentIndex === 0) + EaStyle.Colors.theme = EaStyle.Colors.LightTheme + else if (currentIndex === 1) + EaStyle.Colors.theme = EaStyle.Colors.DarkTheme + else if (currentIndex === 2) + EaStyle.Colors.theme = EaStyle.Colors.SystemTheme + } + Component.onCompleted: { + if (EaStyle.Colors.theme === EaStyle.Colors.LightTheme) + currentIndex = 0 + else if (EaStyle.Colors.theme === EaStyle.Colors.DarkTheme) + currentIndex = 1 + else if (EaStyle.Colors.theme === EaStyle.Colors.SystemTheme) + currentIndex = 2 + } + } + + // groubox to test the element + EaElements.GroupBox { + title: qsTr('Test a group widget') + icon: 'wrench' + collapsed: false + + Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml'} + } + + // Loader { + // source: 'Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml' + // } + + EaComponents.TableView { + id: whatverTable + defaultInfoText: qsTr("No models found") + + + header: EaComponents.TableViewHeader { + EaComponents.TableViewLabel { + id: modelNameColumnName + width: whatverTable.width * 0.25 + text: qsTr("Name") + color: EaStyle.Colors.themeForegroundMinor + leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 + } + + EaComponents.TableViewLabel { + id: modelTypeColumnName + width: whatverTable.width * 0.15 + text: qsTr("Type") + color: EaStyle.Colors.themeForegroundMinor + } + + EaComponents.TableViewLabel { + id: modelDescrColumnName + width: whatverTable.width * 0.6 + text: qsTr("Description") + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: ListModel { + id: availableSambleModelsModel + ListElement { name: "Samle1_aluv"; structure_type: "Vesicle"; description: "In order to avoid a prolonged pro-inflammatory neutrophil response, signaling downstream of an agonist-activated G protein-coupled receptor (GPCR) has to be rapidly terminated. Among the family of GPCR kinases (GRKs) that regulate receptor phosphorylation and signaling termination, GRK2, which is highly expressed by immune cells, plays an important role." } + ListElement { name: "Sample2_nanodisc"; structure_type: "Ring"; description: "The medium chain fatty acid receptor GPR84 as well as formyl peptide receptor 2 (FPR2)" } + ListElement { name: "Sample3_cubosome"; structure_type: "Lattice"; description: "receptors expressed in neutrophils, play a key role in regulating inflammation. In this study, we investigated the effects of GRK2 inhibitors on neutrophil functions induced by GPR84 and FPR2 agonists." } + ListElement { name: "Sample4"; structure_type: "Ring"; description: "GRK2 was shown to be expressed in human neutrophils and analysis of subcellular fractions" } + ListElement { name: "Sample5"; structure_type: "Ball"; description: "revealed a cytosolic localization. The GRK2 inhibitors enhanced and prolonged neutrophil production " } + ListElement { name: "Sample6"; structure_type: "Vesicle"; description: "production of reactive oxygen species (ROS) induced by GPR84- but not FPR2-agonists" } + ListElement { name: "Sample7"; structure_type: "Rod"; description: "suggesting a receptor selective function of GRK2. This suggestion was supported by β-arrestin recruitment data. The ROS production induced by a non β-arrestin recruiting GPR84" } + ListElement { name: "Sample8"; structure_type: "Bilayer"; description: "This suggestion was supported by β-arrestin recruitment data. The ROS production induced by a non β-arrestin recruiting GPR84 agonist was not affected by the GRK2 inhibitor." } + ListElement { name: "Sample9"; structure_type: "Monolayer"; description: "Termination of this β-arrestin independent response relied, similar to the response induced by FPR2 agonists, primarily on the actin cytoskeleton." } + ListElement { name: "Samplewithareallylongname"; structure_type: "Lattice"; description: "In summary, we show that GPR84 utilizes GRK2 in concert with β-arrestin and actin cytoskeleton dependent processes to fine-tune the activity of the ROS generating NADPH-oxidase in neutrophils." } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "end1"; structure_type: "end2"; description: "end3" } + } + + delegate: EaComponents.TableViewDelegate { + required property int index + required property string name + required property string structure_type + required property string description + + EaComponents.TableViewLabel { + id: modelNameColumn + width: whatverTable.width * 0.25 + text: name + } + + EaComponents.TableViewLabel { + id: typeColumn + width: whatverTable.width * 0.15 + text: structure_type + } + + EaComponents.TableViewLabel { + id: descrColumn + width: whatverTable.width * 0.58 + text: description + } + } + + // ScrollBar.vertical: EaElements.ScrollBar { + // policy: ScrollBar.AlwaysOn // ScrollBar.AsNeeded // AlwaysOn + // snapToHeader: true + // } + + // ScrollIndicator.vertical: EaElements.ScrollIndicator {} + } + } } - Component.onCompleted: Globals.References.pages.samplemodel.sidebar.basic.popups.CreateNewModel.open() + + + //Component.onCompleted: Globals.References.pages.samplemodel.sidebar.basic.popups.LoadExistingModel.open() } From d4ef5a6c8944059e7c387eafe7bed0c285ef43c1 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Wed, 22 Apr 2026 11:51:20 +0200 Subject: [PATCH 06/23] updates to mock group components --- src/easyshapes_app.qrc | 12 +- src/easyshapes_app/Gui/Globals/References.qml | 5 +- .../Sidebar/Basic/Groups/Components.qml | 172 +++++++++++++++ .../Sidebar/Basic/Groups/Group4.qml | 18 -- .../Sidebar/Basic/Groups/SampleModel.qml | 67 ++---- .../SampleModel/Sidebar/Basic/Layout.qml | 16 +- .../Basic/Popups/CreateNewComponent.qml | 165 ++++++++++++++ .../Sidebar/Basic/Popups/CreateNewModel.qml | 53 +++-- .../Basic/Popups/LoadExistingComponent.qml | 206 ++++++++++++++++++ .../Sidebar/Basic/Popups/OpenAssetFile.qml | 30 +++ src/easyshapes_app/test.qml | 45 ++-- src/easyshapes_app/test2.qml | 166 ++++++++++++++ 12 files changed, 835 insertions(+), 120 deletions(-) create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml delete mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group4.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml create mode 100644 src/easyshapes_app/test2.qml diff --git a/src/easyshapes_app.qrc b/src/easyshapes_app.qrc index b6901a2..f16d733 100644 --- a/src/easyshapes_app.qrc +++ b/src/easyshapes_app.qrc @@ -6,9 +6,11 @@ ../../EasyApp/src/EasyApp/Gui/Animations/TranslationChange.qml ../../EasyApp/src/EasyApp/Gui/Charts/ChartViewHeatmap2dPlotly.qml ../../EasyApp/src/EasyApp/Gui/Charts/ChartViewSimple1dPlotly.qml + ../../EasyApp/src/EasyApp/Gui/Charts/Plotly1dBarPlot.qml ../../EasyApp/src/EasyApp/Gui/Charts/Plotly1dLine.qml ../../EasyApp/src/EasyApp/Gui/Charts/Plotly1dMeasVsCalc.qml ../../EasyApp/src/EasyApp/Gui/Charts/Plotly2dHeatmap.qml + ../../EasyApp/src/EasyApp/Gui/Charts/Plotly2dPolarHeatmap.qml ../../EasyApp/src/EasyApp/Gui/Charts/Plotly3dScatter.qml ../../EasyApp/src/EasyApp/Gui/Charts/Plotly3dSurface.qml ../../EasyApp/src/EasyApp/Gui/Charts/qmldir @@ -27,6 +29,10 @@ ../../EasyApp/src/EasyApp/Gui/Components/GuideWindow.qml ../../EasyApp/src/EasyApp/Gui/Components/GuideWindowContainer.qml ../../EasyApp/src/EasyApp/Gui/Components/JsonListModel.qml + ../../EasyApp/src/EasyApp/Gui/Components/ListView.qml + ../../EasyApp/src/EasyApp/Gui/Components/ListViewDelegate.qml + ../../EasyApp/src/EasyApp/Gui/Components/ListViewHeader.qml + ../../EasyApp/src/EasyApp/Gui/Components/ListViewTextInput.qml ../../EasyApp/src/EasyApp/Gui/Components/MainContent.qml ../../EasyApp/src/EasyApp/Gui/Components/PreferencesDialog.qml ../../EasyApp/src/EasyApp/Gui/Components/ProjectDescriptionDialog.qml @@ -141,14 +147,17 @@ easyshapes_app/Gui/Pages/Report/Sidebar/Extra/Layout.qml easyshapes_app/Gui/Pages/SampleModel/Layout.qml easyshapes_app/Gui/Pages/SampleModel/MainArea/GraphsView.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group1.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml - easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group4.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml easyshapes_app/Gui/Pages/Toolbox/Layout.qml easyshapes_app/Gui/Pages/Toolbox/MainArea/GraphsView.qml easyshapes_app/Gui/Pages/Toolbox/MainArea/Image.qml @@ -163,5 +172,6 @@ easyshapes_app/Gui/StatusBar.qml easyshapes_app/main.qml easyshapes_app/test.qml + easyshapes_app/test2.qml \ No newline at end of file diff --git a/src/easyshapes_app/Gui/Globals/References.qml b/src/easyshapes_app/Gui/Globals/References.qml index 4c0fb98..3219729 100644 --- a/src/easyshapes_app/Gui/Globals/References.qml +++ b/src/easyshapes_app/Gui/Globals/References.qml @@ -39,7 +39,10 @@ QtObject { 'basic': { 'popups': { 'LoadExistingModel': null, - 'CreateNewModel': null + 'CreateNewModel': null, + 'LoadExistingComponent': null, + 'CreateNewComponent': null, + 'OpenAssetFile': null } } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml new file mode 100644 index 0000000..875413f --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml @@ -0,0 +1,172 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls +//import QtQuick.Dialogs + +import EasyApp.Gui.Globals as EaGlobals +import EasyApp.Gui.Style as EaStyle +import EasyApp.Gui.Elements as EaElements +import EasyApp.Gui.Components as EaComponents +import EasyApp.Gui.Logic as EaLogic + +import Gui.Globals as Globals + +EaElements.GroupColumn { + property double buttonWidth: EaStyle.Sizes.sideBarContentWidth * 0.3164 + + EaComponents.ListView { + id: loadedComponents + + defaultInfoText: qsTr("Load or create components") + + multiSelection: true + + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 2.5, + -1, + EaStyle.Sizes.fontPixelSize * 6, + EaStyle.Sizes.fontPixelSize * 4, + EaStyle.Sizes.fontPixelSize * 4, + EaStyle.Sizes.fontPixelSize * 4, + EaStyle.Sizes.tableRowHeight + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr("№") + color: EaStyle.Colors.themeForegroundMinor + horizontalAlignment: Text.AlignHCenter + } + EaComponents.TableViewLabel { + text: qsTr("Name") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr("Type") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr("Atoms") + color: EaStyle.Colors.themeForegroundMinor + horizontalAlignment: Text.AlignHCenter + } + EaComponents.TableViewLabel { + text: qsTr("Mint") + color: EaStyle.Colors.themeForegroundMinor + horizontalAlignment: Text.AlignHCenter + } + EaComponents.TableViewLabel { + text: qsTr("Mext") + color: EaStyle.Colors.themeForegroundMinor + horizontalAlignment: Text.AlignHCenter + } + EaComponents.TableViewLabel { + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: ListModel { + id: loadedComponentsModel + } + + delegateModelAccess: DelegateModel.ReadWrite + + delegate: EaComponents.ListViewDelegate { + required property int index + required property string name + required property string component_type + required property int mint + required property int mext + required property int atoms + + EaComponents.TableViewLabel { + text: index + 1 + horizontalAlignment: Text.AlignHCenter + enabled: false + } + + EaComponents.ListViewTextInput { + id: modelNameColumn + text: name + onEditingFinished: name = text + } + + EaComponents.TableViewLabel { + text: component_type + enabled: false + } + + EaComponents.ListViewTextInput { + text: atoms + horizontalAlignment: Text.AlignHCenter + onEditingFinished: atoms = parseInt(text) + validator: IntValidator { bottom: 0 } + } + + EaComponents.ListViewTextInput { + text: mint + horizontalAlignment: Text.AlignHCenter + onEditingFinished: mint = parseInt(text) + validator: IntValidator { bottom: 0 } + } + + EaComponents.ListViewTextInput { + text: mext + horizontalAlignment: Text.AlignHCenter + onEditingFinished: mext = parseInt(text) + validator: IntValidator { bottom: 0 } + } + + EaComponents.TableViewButton { + id: deleteRowColumn + fontIcon: "minus-circle" + ToolTip.text: qsTr("Remove this component") + onClicked: loadedComponentsModel.remove(index) + } + } + } + + Grid { + columns: 3 + spacing: EaStyle.Sizes.fontPixelSize + + EaElements.SideBarButton { + fontIcon: 'upload' + text: qsTr('Load component(s)') + width: buttonWidth + onClicked: loadExistingComponentLoader.item.open() + } + + EaElements.SideBarButton { + fontIcon: 'plus-circle' + text: qsTr('Create component') + width: buttonWidth + onClicked: createNewComponentLoader.item.open() + } + + EaElements.SideBarButton { + id: saveModelButton + fontIcon: 'download' + text: qsTr('Save component(s)') + width: buttonWidth + enabled: loadedComponents.model ? loadedComponents.model.count > 0 : false + onClicked: loadExistingComponentLoader.item.availableComponentsModel.append(loadedComponentsModel.get(0)) + } + } + + Loader { + id: loadExistingComponentLoader + source: '../Popups/LoadExistingComponent.qml' + onLoaded: item.targetModel = loadedComponentsModel + } + + Loader { + id: createNewComponentLoader + source: '../Popups/CreateNewComponent.qml' + onLoaded: item.targetModel = loadedComponentsModel + } + +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group4.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group4.qml deleted file mode 100644 index f2e5c14..0000000 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group4.qml +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtQuick.Controls - -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic - -import Gui.Globals as Globals - -EaElements.GroupColumn { - -} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml index c273688..91d07fb 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml @@ -20,9 +20,8 @@ EaElements.GroupColumn { EaComponents.TableView { id: loadedSampleModelTableView clip: true - // anchors.fill: parent - defaultInfoText: qsTr("No models defined") + defaultInfoText: qsTr("Get started by loading or creating a model") header: EaComponents.TableViewHeader { EaComponents.TableViewLabel { id: modelNameColumnName @@ -58,7 +57,7 @@ EaElements.GroupColumn { required property string structure_type required property string description - EaComponents.TableViewTextInput { + EaComponents.ListViewTextInput { id: modelNameColumn width: EaStyle.Sizes.fontPixelSize * 12 text: name @@ -80,7 +79,7 @@ EaElements.GroupColumn { } } - EaComponents.TableViewTextInput { + EaComponents.ListViewTextInput { id: descrColumn width: EaStyle.Sizes.fontPixelSize * 20 text: description @@ -99,64 +98,40 @@ EaElements.GroupColumn { columns: 3 spacing: EaStyle.Sizes.fontPixelSize - - // button 1 EaElements.SideBarButton { fontIcon: 'upload' - text: qsTr('Load an existing model') + text: qsTr('Load model') width: buttonWidth - - onClicked: { - console.debug(`Clicking '${text}' button ::: ${this}`) - Globals.References.pages.samplemodel.sidebar.basic.popups.LoadExistingModel.open() - } - - Loader { - source: '../Popups/LoadExistingModel.qml' - onLoaded: { - item.targetModel = loadedSambleModelsModel - Globals.References.pages.samplemodel.sidebar.basic.popups.LoadExistingModel = item - } - } + onClicked: loadExistingModelLoader.item.open() } - // button 1 - - // button 2 EaElements.SideBarButton { fontIcon: 'plus-circle' - text: qsTr('Create a new model') + text: qsTr('Create model') width: buttonWidth - - onClicked: { - console.debug(`Clicking '${text}' button ::: ${this}`) - Globals.References.pages.samplemodel.sidebar.basic.popups.CreateNewModel.open() - } - - Loader { - source: '../Popups/CreateNewModel.qml' - onLoaded: { - item.targetModel = loadedSambleModelsModel - Globals.References.pages.samplemodel.sidebar.basic.popups.CreateNewModel = item - } - } + onClicked: createNewModelLoader.item.open() } - // button 2 - // button 3 EaElements.SideBarButton { id: saveModelButton fontIcon: 'download' - text: qsTr('Save the model') + text: qsTr('Save model') width: buttonWidth enabled: loadedSampleModelTableView.model ? loadedSampleModelTableView.model.count > 0 : false - - onClicked: { - console.debug(`Clicking '${text}' button ::: ${this}`) - Globals.References.pages.samplemodel.sidebar.basic.popups.LoadExistingModel.availableModelsModel.append(loadedSambleModelsModel.get(0)) - } + onClicked: loadExistingModelLoader.item.availableModelsModel.append(loadedSambleModelsModel.get(0)) } - // button 3 + } + + Loader { + id: loadExistingModelLoader + source: '../Popups/LoadExistingModel.qml' + onLoaded: item.targetModel = loadedSambleModelsModel + } + + Loader { + id: createNewModelLoader + source: '../Popups/CreateNewModel.qml' + onLoaded: item.targetModel = loadedSambleModelsModel } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml index 7d94fd8..420bc12 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml @@ -22,31 +22,31 @@ EaComponents.SideBarColumn { } EaElements.GroupBox { - title: qsTr('Group 1') - icon: 'rocket' + title: qsTr('Components') + icon: 'puzzle-piece' - Loader { source: 'Groups/Group1.qml' } + Loader { source: 'Groups/Components.qml' } } EaElements.GroupBox { - title: qsTr('Group 2') - icon: 'rocket' + title: qsTr('Solution') + icon: 'tint' Loader { source: 'Groups/Group2.qml' } } EaElements.GroupBox { title: qsTr('Group 3') - icon: 'rocket' + icon: 'grip-horizontal' Loader { source: 'Groups/Group3.qml' } } EaElements.GroupBox { - title: qsTr('Group 4') + title: qsTr('Group 1') icon: 'rocket' - Loader { source: 'Groups/Group4.qml' } + Loader { source: 'Groups/Group1.qml' } } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml new file mode 100644 index 0000000..9d03539 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml @@ -0,0 +1,165 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +import EasyApp.Gui.Globals as EaGlobals +import EasyApp.Gui.Style as EaStyle +import EasyApp.Gui.Components as EaComponents +import EasyApp.Gui.Elements as EaElements + +import Gui.Globals as Globals + + +EaElements.Dialog{ + id: componentCreationDialog + + property var targetModel + + title: qsTr("Create a new Component") + + property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 + + standardButtons: Dialog.Ok // | Dialog.Cancel + + onAccepted: { + console.log("Ok Clicked") + + targetModel.append({ + name: componentNameField.text, + component_type: sampleModelTypeField.currentText, + atoms: 42, + mint: 0, + mext: 0 + }) + } + onRejected: console.log("Cancel Clicked") + onOpened: console.log("Opened CreateNewComponent Clicked") + + Component.onCompleted: { + Globals.References.pages.samplemodel.sidebar.basic.popups.CreateNewComponent = this + } + + Column { + + spacing: EaStyle.Sizes.fontPixelSize + + Row { + spacing: EaStyle.Sizes.fontPixelSize + + property int halfFieldWidth: (componentCreationDialog.inputFieldWidth - spacing) / 2 + + Column { + EaElements.Label { + enabled: false + text: qsTr("Name") + } + + EaElements.TextField { + id: componentNameField + + implicitWidth: parent.parent.halfFieldWidth + horizontalAlignment: TextInput.AlignLeft + validator: RegularExpressionValidator { regularExpression: /^[a-zA-Z][a-zA-Z0-9_\-\.]{1,30}$/ } + placeholderText: qsTr("(optional) Enter Component name here") + } + } + + Column { + EaElements.Label { + enabled: false + text: qsTr("Component type") + } + + EaElements.ComboBox { + id: sampleModelTypeField + implicitWidth: parent.parent.halfFieldWidth + model: ["Other", "Lipid", "Surfactant"] + } + } + } + + Column { + EaElements.Label { + enabled: false + text: qsTr("SMILES string") + } + + EaElements.TextField { + implicitWidth: componentCreationDialog.inputFieldWidth + horizontalAlignment: TextInput.AlignLeft + placeholderText: qsTr("(optional) Define component using SMILES") + } + } + + Column { + EaElements.Label { + enabled: false + text: qsTr("Paths") + } + + EaComponents.ListView { + id: filePaths + defaultInfoText: qsTr("No files added") + enabled: true + maxRowCountShow: 2 + width: componentCreationDialog.inputFieldWidth + + columnWidths: [ + -1, + EaStyle.Sizes.tableRowHeight + ] + + scrollBarInteractive: false + + model: ListModel { + id: selectedFilePathsModel + } + + delegate: EaComponents.ListViewDelegate { + required property int index + required property url path + + EaComponents.TableViewLabel { + id: pathColumn + text: path + elide: Text.ElideLeft + horizontalAlignment: Text.Alignleft + + leftPadding: EaStyle.Sizes.fontPixelSize * 0.5 + } + + EaComponents.TableViewButton { + id: deleteRowColumn + fontIcon: "minus-circle" + ToolTip.text: qsTr("Remove this file") + onClicked: selectedFilePathsModel.remove(index) + } + } + } + } + Column { + EaElements.SideBarButton { + fontIcon: 'upload' + text: qsTr('Add files') + width: componentCreationDialog.width * 0.3164 + + onClicked: { + console.debug(`Clicking '${text}' button ::: ${this}`) + Globals.References.pages.samplemodel.sidebar.basic.popups.openAssetFile.open() + } + + Loader { + source: '../Popups/OpenAssetFile.qml' + onLoaded: { + item.targetModel = selectedFilePathsModel + } + } + } + } + } +} + diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml index 9502ee3..9b4ad62 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml @@ -44,32 +44,37 @@ EaElements.Dialog{ spacing: EaStyle.Sizes.fontPixelSize - Column { - EaElements.Label { - enabled: false - text: qsTr("Name") + Row { + id: nameTypeRow + spacing: EaStyle.Sizes.fontPixelSize + + Column { + EaElements.Label { + enabled: false + text: qsTr("Name") + } + + EaElements.TextField { + id: sampleModelNameField + + implicitWidth: (sampleModelCreationDialog.inputFieldWidth - nameTypeRow.spacing) / 2 + horizontalAlignment: TextInput.AlignLeft + validator: RegularExpressionValidator { regularExpression: /^[a-zA-Z][a-zA-Z0-9_\-\.]{1,30}$/ } + placeholderText: qsTr("(optional) Enter Sample Model name here") + } } - EaElements.TextField { - id: sampleModelNameField - - implicitWidth: sampleModelCreationDialog.inputFieldWidth - horizontalAlignment: TextInput.AlignLeft - validator: RegularExpressionValidator { regularExpression: /^[a-zA-Z][a-zA-Z0-9_\-\.]{1,30}$/ } - placeholderText: qsTr("(optional) Enter Sample Model name here") - } - } - - Column { - EaElements.Label { - enabled: false - text: qsTr("Choose the underlying structure type") - } - - EaElements.ComboBox { - id: sampleModelTypeField - implicitWidth: sampleModelCreationDialog.inputFieldWidth - model: ["Ring", "Ball", "Vesicle", "Rod", "Bilayer", "Monolayer", "Lattice"] + Column { + EaElements.Label { + enabled: false + text: qsTr("Structure type") + } + + EaElements.ComboBox { + id: sampleModelTypeField + implicitWidth: (sampleModelCreationDialog.inputFieldWidth - nameTypeRow.spacing) / 2 + model: ["Ring", "Ball", "Vesicle", "Rod", "Bilayer", "Monolayer", "Lattice"] + } } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml new file mode 100644 index 0000000..7010305 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml @@ -0,0 +1,206 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +import EasyApp.Gui.Globals as EaGlobals +import EasyApp.Gui.Components as EaComponents +import EasyApp.Gui.Elements as EaElements +import EasyApp.Gui.Style as EaStyle + +import Gui.Globals as Globals + + + +EaElements.Dialog{ + id: sampleModelLoadDialog + + property var targetModel + + title: qsTr("Load Components from the Asset Library") + + property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 + + property alias availableComponentsModel: availableComponentsModel + + standardButtons: Dialog.Ok // | Dialog.Cancel + + // Fields expected by targetModel (loadedComponentsModel in Components.qml): + // name, component_type, mint, mext, atoms + onAccepted: { + console.log("Ok Clicked") + + var indexes = selectionModel.selectedIndexes + + if (indexes.length > 0) { + var row = indexes[0].row + var item = availableComponentsModel.get(row) + + console.log("Selected Component: ", item.name) + + targetModel.append({ + name: item.name, + component_type: item.component_type, + mint: item.mint, + mext: item.mext, + atoms: item.atoms + }) + selectionModel.clear() + } + } + onRejected: { + console.log("Cancel Clicked") + selectionModel.clear() + } + + Column { + + + EaElements.Label { + enabled: false + text: qsTr("Available in the Asset Library") + } + + EaComponents.TableView { + clip: true + id: loadModelTableView + defaultInfoText: qsTr("No models found") + + header: EaComponents.TableViewHeader { + EaComponents.TableViewLabel { + id: modelNameColumnName + width: EaStyle.Sizes.fontPixelSize * 12 + text: qsTr("Name") + color: EaStyle.Colors.themeForegroundMinor + leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 + } + + EaComponents.TableViewLabel { + id: modelTypeColumnName + width: EaStyle.Sizes.fontPixelSize * 8 + text: qsTr("Type") + color: EaStyle.Colors.themeForegroundMinor + } + + EaComponents.TableViewLabel { + id: modelAtomsColumnName + width: EaStyle.Sizes.fontPixelSize * 6 + text: qsTr("Atoms") + color: EaStyle.Colors.themeForegroundMinor + horizontalAlignment: Text.AlignHCenter + } + + EaComponents.TableViewLabel { + id: modelMintColumnName + width: EaStyle.Sizes.fontPixelSize * 6 + text: qsTr("Mint") + color: EaStyle.Colors.themeForegroundMinor + horizontalAlignment: Text.AlignHCenter + } + + EaComponents.TableViewLabel { + id: modelMextColumnName + width: EaStyle.Sizes.fontPixelSize * 6 + text: qsTr("Mext") + color: EaStyle.Colors.themeForegroundMinor + horizontalAlignment: Text.AlignHCenter + } + } + + model: ListModel { + id: availableComponentsModel + ListElement { name: "DPPC"; component_type: "Lipid"; atoms: 130; mint: 0; mext: 130 } + ListElement { name: "DOPC"; component_type: "Lipid"; atoms: 138; mint: 0; mext: 138 } + ListElement { name: "POPC"; component_type: "Lipid"; atoms: 134; mint: 0; mext: 134 } + ListElement { name: "DMPC"; component_type: "Lipid"; atoms: 118; mint: 0; mext: 118 } + ListElement { name: "Cholesterol"; component_type: "Lipid"; atoms: 74; mint: 0; mext: 74 } + ListElement { name: "SDS"; component_type: "Surfactant"; atoms: 42; mint: 0; mext: 42 } + ListElement { name: "CTAB"; component_type: "Surfactant"; atoms: 62; mint: 0; mext: 62 } + ListElement { name: "Triton-X100"; component_type: "Surfactant"; atoms: 85; mint: 0; mext: 85 } + ListElement { name: "Tween-20"; component_type: "Surfactant"; atoms: 98; mint: 0; mext: 98 } + ListElement { name: "D2O-buffer"; component_type: "Other"; atoms: 3; mint: 0; mext: 3 } + } + + property var itemSelectionModel: ItemSelectionModel { + id: selectionModel + model: availableComponentsModel + } + + property bool activeSelection: true + + delegate: EaComponents.TableViewDelegate { + + required property int index + required property string name + required property string component_type + required property int atoms + required property int mint + required property int mext + + color: { + if (!ListView.view.activeSelection) { + return index % 2 ? + EaStyle.Colors.themeBackgroundHovered2 : + EaStyle.Colors.themeBackgroundHovered1 + } + + ListView.view.itemSelectionModel.selection // create dependency + + return ListView.view.itemSelectionModel.isSelected( + ListView.view.itemSelectionModel.model.index(index, 0) + ) ? EaStyle.Colors.themeAccentMinor : EaStyle.Colors.themeBackgroundHovered1 + } + + // color: { + // ListView.view.itemSelectionModel.selection // create dependency + // return ListView.view.itemSelectionModel.isSelected( + // ListView.view.itemSelectionModel.model.index(index, 0) + // ) ? EaStyle.Colors.themeAccentMinor : EaStyle.Colors.themeBackgroundHovered1 + // } + + EaComponents.TableViewLabel { + id: modelNameColumn + width: EaStyle.Sizes.fontPixelSize * 12 + text: name + leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 + } + + EaComponents.TableViewLabel { + id: typeColumn + width: EaStyle.Sizes.fontPixelSize * 8 + text: component_type + } + + EaComponents.TableViewLabel { + id: atomsColumn + width: EaStyle.Sizes.fontPixelSize * 6 + text: atoms + horizontalAlignment: Text.AlignHCenter + } + EaComponents.TableViewLabel { + id: mintColumn + width: EaStyle.Sizes.fontPixelSize * 6 + text: mint + horizontalAlignment: Text.AlignHCenter + } + EaComponents.TableViewLabel { + id: mextColumn + width: EaStyle.Sizes.fontPixelSize * 6 + text: mext + horizontalAlignment: Text.AlignHCenter + } + + mouseArea.onPressed: (mouse) => { + let idx = ListView.view.itemSelectionModel.model.index(index, 0) + ListView.view.itemSelectionModel.select( + idx, + ItemSelectionModel.ClearAndSelect + ) + } + } + } + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml new file mode 100644 index 0000000..7af31d7 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +import EasyApp.Gui.Globals as EaGlobals +import EasyApp.Gui.Components as EaComponents + +import Gui.Globals as Globals + + +FileDialog{ + fileMode: FileDialog.OpenFiles + nameFilters: ['Any (*)', 'Structure files (*.gro *.pdb .*xyz)', 'Topology files (*.itp)', 'Smiles files (*.sml)'] + + property var targetModel + + onAccepted: { + for (let i = 0; i < selectedFiles.length; ++i) + targetModel.append({ path: selectedFiles[i] }) + } + + Component.onCompleted: { + Globals.References.pages.samplemodel.sidebar.basic.popups.openAssetFile = this + } + +} diff --git a/src/easyshapes_app/test.qml b/src/easyshapes_app/test.qml index d452593..52876a5 100644 --- a/src/easyshapes_app/test.qml +++ b/src/easyshapes_app/test.qml @@ -16,7 +16,7 @@ import Gui.Globals as Globals ApplicationWindow{ - width: 640 + width: 650 height: 580 color: EaStyle.Colors.contentBackground visible: true @@ -56,22 +56,27 @@ ApplicationWindow{ icon: 'wrench' collapsed: false - Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml'} + Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml'} } - // Loader { - // source: 'Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml' - // } - - EaComponents.TableView { + EaComponents.ListView { id: whatverTable defaultInfoText: qsTr("No models found") + enabled: true + + columnWidths: [ + whatverTable.width * 0.25, + whatverTable.width * 0.15, + -1, + ] + scrollBarPolicy: ScrollBar.AlwaysOn // ScrollBar.AsNeeded // ScrollBar.AlwaysOn + scrollBarInteractive: true - header: EaComponents.TableViewHeader { + header: EaComponents.ListViewHeader { EaComponents.TableViewLabel { id: modelNameColumnName - width: whatverTable.width * 0.25 + //width: whatverTable.width * 0.25 text: qsTr("Name") color: EaStyle.Colors.themeForegroundMinor leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 @@ -79,14 +84,14 @@ ApplicationWindow{ EaComponents.TableViewLabel { id: modelTypeColumnName - width: whatverTable.width * 0.15 + //width: whatverTable.width * 0.15 text: qsTr("Type") color: EaStyle.Colors.themeForegroundMinor } EaComponents.TableViewLabel { id: modelDescrColumnName - width: whatverTable.width * 0.6 + //width: whatverTable.width * 0.6 text: qsTr("Description") color: EaStyle.Colors.themeForegroundMinor } @@ -138,37 +143,33 @@ ApplicationWindow{ ListElement { name: "end1"; structure_type: "end2"; description: "end3" } } - delegate: EaComponents.TableViewDelegate { + delegate: EaComponents.ListViewDelegate { required property int index required property string name required property string structure_type required property string description - EaComponents.TableViewLabel { + EaComponents.ListViewTextInput { id: modelNameColumn - width: whatverTable.width * 0.25 + //width: whatverTable.width * 0.25 text: name } EaComponents.TableViewLabel { id: typeColumn - width: whatverTable.width * 0.15 + //width: whatverTable.width * 0.15 text: structure_type + color: "#666" // new disabled } EaComponents.TableViewLabel { id: descrColumn - width: whatverTable.width * 0.58 + //width: whatverTable.width * 0.58 text: description + color: "#555" // old disabled } } - // ScrollBar.vertical: EaElements.ScrollBar { - // policy: ScrollBar.AlwaysOn // ScrollBar.AsNeeded // AlwaysOn - // snapToHeader: true - // } - - // ScrollIndicator.vertical: EaElements.ScrollIndicator {} } } } diff --git a/src/easyshapes_app/test2.qml b/src/easyshapes_app/test2.qml new file mode 100644 index 0000000..82de25c --- /dev/null +++ b/src/easyshapes_app/test2.qml @@ -0,0 +1,166 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +import EasyApp.Gui.Globals as EaGlobals +import EasyApp.Gui.Style as EaStyle +import EasyApp.Gui.Components as EaComponents +import EasyApp.Gui.Elements as EaElements +import Qt.labs.qmlmodels + +import Gui.Globals as Globals + +ApplicationWindow{ + + width: 650 + height: 580 + color: EaStyle.Colors.contentBackground + visible: true + + Grid { + spacing: EaStyle.Sizes.fontPixelSize * 4 + leftPadding: 12 + + + Column { + width: 600 + spacing: EaStyle.Sizes.fontPixelSize + + EaElements.ComboBox { + model: [qsTr("Light"), qsTr("Dark"), qsTr("System")] + onActivated: { + if (currentIndex === 0) + EaStyle.Colors.theme = EaStyle.Colors.LightTheme + else if (currentIndex === 1) + EaStyle.Colors.theme = EaStyle.Colors.DarkTheme + else if (currentIndex === 2) + EaStyle.Colors.theme = EaStyle.Colors.SystemTheme + } + Component.onCompleted: { + if (EaStyle.Colors.theme === EaStyle.Colors.LightTheme) + currentIndex = 0 + else if (EaStyle.Colors.theme === EaStyle.Colors.DarkTheme) + currentIndex = 1 + else if (EaStyle.Colors.theme === EaStyle.Colors.SystemTheme) + currentIndex = 2 + } + } + + EaComponents.TableView { + id: whatverTable + defaultInfoText: qsTr("No models found") + enabled: true + + header: EaComponents.TableViewHeader { + EaComponents.TableViewLabel { + id: modelNameColumnName + width: whatverTable.width * 0.25 + text: qsTr("Name") + color: EaStyle.Colors.themeForegroundMinor + leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 + } + + EaComponents.TableViewLabel { + id: modelTypeColumnName + width: whatverTable.width * 0.15 + text: qsTr("Type") + color: EaStyle.Colors.themeForegroundMinor + } + + EaComponents.TableViewLabel { + id: modelDescrColumnName + width: whatverTable.width * 0.6 + text: qsTr("Description") + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: ListModel { + id: availableSambleModelsModel + ListElement { name: "Samle1_aluv"; structure_type: "Vesicle"; description: "In order to avoid a prolonged pro-inflammatory neutrophil response, signaling downstream of an agonist-activated G protein-coupled receptor (GPCR) has to be rapidly terminated. Among the family of GPCR kinases (GRKs) that regulate receptor phosphorylation and signaling termination, GRK2, which is highly expressed by immune cells, plays an important role." } + ListElement { name: "Sample2_nanodisc"; structure_type: "Ring"; description: "The medium chain fatty acid receptor GPR84 as well as formyl peptide receptor 2 (FPR2)" } + ListElement { name: "Sample3_cubosome"; structure_type: "Lattice"; description: "receptors expressed in neutrophils, play a key role in regulating inflammation. In this study, we investigated the effects of GRK2 inhibitors on neutrophil functions induced by GPR84 and FPR2 agonists." } + ListElement { name: "Sample4"; structure_type: "Ring"; description: "GRK2 was shown to be expressed in human neutrophils and analysis of subcellular fractions" } + ListElement { name: "Sample5"; structure_type: "Ball"; description: "revealed a cytosolic localization. The GRK2 inhibitors enhanced and prolonged neutrophil production " } + ListElement { name: "Sample6"; structure_type: "Vesicle"; description: "production of reactive oxygen species (ROS) induced by GPR84- but not FPR2-agonists" } + ListElement { name: "Sample7"; structure_type: "Rod"; description: "suggesting a receptor selective function of GRK2. This suggestion was supported by β-arrestin recruitment data. The ROS production induced by a non β-arrestin recruiting GPR84" } + ListElement { name: "Sample8"; structure_type: "Bilayer"; description: "This suggestion was supported by β-arrestin recruitment data. The ROS production induced by a non β-arrestin recruiting GPR84 agonist was not affected by the GRK2 inhibitor." } + ListElement { name: "Sample9"; structure_type: "Monolayer"; description: "Termination of this β-arrestin independent response relied, similar to the response induced by FPR2 agonists, primarily on the actin cytoskeleton." } + ListElement { name: "Samplewithareallylongname"; structure_type: "Lattice"; description: "In summary, we show that GPR84 utilizes GRK2 in concert with β-arrestin and actin cytoskeleton dependent processes to fine-tune the activity of the ROS generating NADPH-oxidase in neutrophils." } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "1"; structure_type: "2"; description: "3" } + ListElement { name: "end1"; structure_type: "end2"; description: "end3" } + } + + delegate: EaComponents.TableViewDelegate { + required property int index + required property string name + required property string structure_type + required property string description + + EaComponents.TableViewLabel { + id: modelNameColumn + //width: whatverTable.width * 0.25 + text: name + } + + EaComponents.TableViewLabel { + id: typeColumn + //width: whatverTable.width * 0.15 + text: structure_type + } + + EaComponents.TableViewTextInput { + id: descrColumn + //width: whatverTable.width * 0.58 + text: description + } + } + + // ScrollBar.vertical: EaElements.ScrollBar { + // policy: ScrollBar.AlwaysOn // ScrollBar.AsNeeded // AlwaysOn + // } + + + } + } + } + + + + //Component.onCompleted: Globals.References.pages.samplemodel.sidebar.basic.popups.LoadExistingModel.open() + +} From 156173320b49c71daf5a75fd10250bd30d3a6cf4 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Wed, 22 Apr 2026 13:45:05 +0200 Subject: [PATCH 07/23] code cleanup --- .../Sidebar/Basic/Groups/Components.qml | 6 ++- .../Basic/Popups/CreateNewComponent.qml | 2 +- .../Sidebar/Basic/Popups/CreateNewModel.qml | 2 +- .../Basic/Popups/LoadExistingComponent.qml | 7 --- .../Basic/Popups/LoadExistingModel.qml | 46 ++++--------------- src/easyshapes_app/test.qml | 34 -------------- 6 files changed, 15 insertions(+), 82 deletions(-) diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml index 875413f..0e1dd95 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml @@ -153,7 +153,11 @@ EaElements.GroupColumn { text: qsTr('Save component(s)') width: buttonWidth enabled: loadedComponents.model ? loadedComponents.model.count > 0 : false - onClicked: loadExistingComponentLoader.item.availableComponentsModel.append(loadedComponentsModel.get(0)) + onClicked: { + //loadExistingComponentLoader.item.availableComponentsModel.append(loadedComponentsModel.get(0)) + for (let i = 0; i < loadedComponentsModel.length; ++i) + loadExistingComponentLoader.item.availableComponentsModel.append(loadedComponentsModel.get(i)) + } } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml index 9d03539..fc0e265 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml @@ -23,7 +23,7 @@ EaElements.Dialog{ property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 - standardButtons: Dialog.Ok // | Dialog.Cancel + standardButtons: Dialog.Ok | Dialog.Cancel onAccepted: { console.log("Ok Clicked") diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml index 9b4ad62..67dab16 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml @@ -23,7 +23,7 @@ EaElements.Dialog{ property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 - standardButtons: Dialog.Ok // | Dialog.Cancel + standardButtons: Dialog.Ok | Dialog.Cancel onAccepted: { console.log("Ok Clicked") diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml index 7010305..2f226da 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml @@ -154,13 +154,6 @@ EaElements.Dialog{ ) ? EaStyle.Colors.themeAccentMinor : EaStyle.Colors.themeBackgroundHovered1 } - // color: { - // ListView.view.itemSelectionModel.selection // create dependency - // return ListView.view.itemSelectionModel.isSelected( - // ListView.view.itemSelectionModel.model.index(index, 0) - // ) ? EaStyle.Colors.themeAccentMinor : EaStyle.Colors.themeBackgroundHovered1 - // } - EaComponents.TableViewLabel { id: modelNameColumn width: EaStyle.Sizes.fontPixelSize * 12 diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml index dd6570e..f1a77ec 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml @@ -26,8 +26,7 @@ EaElements.Dialog{ property alias availableModelsModel: availableSambleModelsModel - standardButtons: Dialog.Ok // | Dialog.Cancel - //leftPadding: 40 + standardButtons: Dialog.Ok | Dialog.Cancel onAccepted: { console.log("Ok Clicked") @@ -50,13 +49,11 @@ EaElements.Dialog{ selectionModel.clear() } -    Column { - - -        EaElements.Label { -            enabled: false -            text: qsTr("Available in the Asset Library") -        } + Column { + EaElements.Label { + enabled: false + text: qsTr("Available in the Asset Library") + } EaComponents.TableView { clip: true @@ -103,18 +100,10 @@ EaElements.Dialog{ property var itemSelectionModel: ItemSelectionModel { id: selectionModel - model: availableSambleModelsModel // ListView.view.model - // model: ListView.view.model + model: availableSambleModelsModel } property bool activeSelection: true - // property var itemSelectionModel: activeSelection ? _selectionModel : null - - // function isItemSelected(index) { - // return itemSelectionModel && itemSelectionModel.isSelected( - // itemSelectionModel.model.index(index, 0) - // ) - // } delegate: EaComponents.TableViewDelegate { @@ -123,18 +112,6 @@ EaElements.Dialog{ required property string structure_type required property string description - // color: { - // if (!ListView.view.highlightSelection) { - // return "whatever I want" - // } - - // const selected = ListView.view.isItemSelected(index) - - // return selected - // ? EaStyle.Colors.themeAccentMinor - // : EaStyle.Colors.themeBackgroundHovered1 - // } - color: { if (!ListView.view.activeSelection) { return index % 2 ? @@ -149,13 +126,6 @@ EaElements.Dialog{ ) ? EaStyle.Colors.themeAccentMinor : EaStyle.Colors.themeBackgroundHovered1 } - // color: { - // ListView.view.itemSelectionModel.selection // create dependency - // return ListView.view.itemSelectionModel.isSelected( - // ListView.view.itemSelectionModel.model.index(index, 0) - // ) ? EaStyle.Colors.themeAccentMinor : EaStyle.Colors.themeBackgroundHovered1 - // } - EaComponents.TableViewLabel { id: modelNameColumn width: EaStyle.Sizes.fontPixelSize * 10 @@ -184,5 +154,5 @@ EaElements.Dialog{ } } } -    } + } } diff --git a/src/easyshapes_app/test.qml b/src/easyshapes_app/test.qml index 52876a5..b7bc114 100644 --- a/src/easyshapes_app/test.qml +++ b/src/easyshapes_app/test.qml @@ -76,7 +76,6 @@ ApplicationWindow{ header: EaComponents.ListViewHeader { EaComponents.TableViewLabel { id: modelNameColumnName - //width: whatverTable.width * 0.25 text: qsTr("Name") color: EaStyle.Colors.themeForegroundMinor leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 @@ -84,14 +83,12 @@ ApplicationWindow{ EaComponents.TableViewLabel { id: modelTypeColumnName - //width: whatverTable.width * 0.15 text: qsTr("Type") color: EaStyle.Colors.themeForegroundMinor } EaComponents.TableViewLabel { id: modelDescrColumnName - //width: whatverTable.width * 0.6 text: qsTr("Description") color: EaStyle.Colors.themeForegroundMinor } @@ -112,34 +109,6 @@ ApplicationWindow{ ListElement { name: "1"; structure_type: "2"; description: "3" } ListElement { name: "1"; structure_type: "2"; description: "3" } ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } ListElement { name: "end1"; structure_type: "end2"; description: "end3" } } @@ -151,20 +120,17 @@ ApplicationWindow{ EaComponents.ListViewTextInput { id: modelNameColumn - //width: whatverTable.width * 0.25 text: name } EaComponents.TableViewLabel { id: typeColumn - //width: whatverTable.width * 0.15 text: structure_type color: "#666" // new disabled } EaComponents.TableViewLabel { id: descrColumn - //width: whatverTable.width * 0.58 text: description color: "#555" // old disabled } From 86b901808866919878fc44184c149d22b136e962 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Wed, 22 Apr 2026 15:00:44 +0200 Subject: [PATCH 08/23] Implemented save button for components groupbox --- .../Pages/SampleModel/Sidebar/Basic/Groups/Components.qml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml index 0e1dd95..8b506ab 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml @@ -154,9 +154,11 @@ EaElements.GroupColumn { width: buttonWidth enabled: loadedComponents.model ? loadedComponents.model.count > 0 : false onClicked: { - //loadExistingComponentLoader.item.availableComponentsModel.append(loadedComponentsModel.get(0)) - for (let i = 0; i < loadedComponentsModel.length; ++i) - loadExistingComponentLoader.item.availableComponentsModel.append(loadedComponentsModel.get(i)) + const indexes = loadedComponents.selectedIndexes + for (let i = 0; i < indexes.length; ++i) + loadExistingComponentLoader.item.availableComponentsModel.append( + loadedComponentsModel.get(indexes[i].row) + ) } } } From 8d1ccf3bf1fe43c8c246a7b33107254108cd1ac6 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Wed, 22 Apr 2026 16:00:32 +0200 Subject: [PATCH 09/23] Fixes to the load components popup --- .../Sidebar/Basic/Groups/Components.qml | 3 +- .../Basic/Popups/LoadExistingComponent.qml | 105 ++++++------------ src/easyshapes_app/test.qml | 1 + 3 files changed, 39 insertions(+), 70 deletions(-) diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml index 8b506ab..8c4c6de 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml @@ -14,14 +14,13 @@ import EasyApp.Gui.Logic as EaLogic import Gui.Globals as Globals + EaElements.GroupColumn { property double buttonWidth: EaStyle.Sizes.sideBarContentWidth * 0.3164 EaComponents.ListView { id: loadedComponents - defaultInfoText: qsTr("Load or create components") - multiSelection: true columnWidths: [ diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml index 2f226da..c352c56 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml @@ -14,7 +14,6 @@ import EasyApp.Gui.Style as EaStyle import Gui.Globals as Globals - EaElements.Dialog{ id: sampleModelLoadDialog @@ -26,21 +25,14 @@ EaElements.Dialog{ property alias availableComponentsModel: availableComponentsModel - standardButtons: Dialog.Ok // | Dialog.Cancel + standardButtons: Dialog.Ok | Dialog.Cancel - // Fields expected by targetModel (loadedComponentsModel in Components.qml): - // name, component_type, mint, mext, atoms onAccepted: { - console.log("Ok Clicked") - - var indexes = selectionModel.selectedIndexes - - if (indexes.length > 0) { - var row = indexes[0].row + let selected = loadModelListView.selectedIndexes + for (let i = 0; i < selected.length; ++i) { + var row = selected[i].row var item = availableComponentsModel.get(row) - console.log("Selected Component: ", item.name) - targetModel.append({ name: item.name, component_type: item.component_type, @@ -48,62 +40,64 @@ EaElements.Dialog{ mext: item.mext, atoms: item.atoms }) - selectionModel.clear() } + loadModelListView.clearSelection() } onRejected: { - console.log("Cancel Clicked") - selectionModel.clear() + loadModelListView.clearSelection() } Column { - - EaElements.Label { enabled: false text: qsTr("Available in the Asset Library") } - EaComponents.TableView { - clip: true - id: loadModelTableView + EaComponents.ListView { + id: loadModelListView defaultInfoText: qsTr("No models found") - - header: EaComponents.TableViewHeader { + multiSelection: true + + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 2.5, + -1, + EaStyle.Sizes.fontPixelSize * 8, + EaStyle.Sizes.fontPixelSize * 6, + EaStyle.Sizes.fontPixelSize * 6, + EaStyle.Sizes.fontPixelSize * 6, + EaStyle.Sizes.tableRowHeight, + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr("№") + color: EaStyle.Colors.themeForegroundMinor + horizontalAlignment: Text.AlignHCenter + } EaComponents.TableViewLabel { id: modelNameColumnName - width: EaStyle.Sizes.fontPixelSize * 12 text: qsTr("Name") color: EaStyle.Colors.themeForegroundMinor - leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 } - EaComponents.TableViewLabel { id: modelTypeColumnName - width: EaStyle.Sizes.fontPixelSize * 8 text: qsTr("Type") color: EaStyle.Colors.themeForegroundMinor } - EaComponents.TableViewLabel { id: modelAtomsColumnName - width: EaStyle.Sizes.fontPixelSize * 6 text: qsTr("Atoms") color: EaStyle.Colors.themeForegroundMinor horizontalAlignment: Text.AlignHCenter } - EaComponents.TableViewLabel { id: modelMintColumnName - width: EaStyle.Sizes.fontPixelSize * 6 text: qsTr("Mint") color: EaStyle.Colors.themeForegroundMinor horizontalAlignment: Text.AlignHCenter } - EaComponents.TableViewLabel { id: modelMextColumnName - width: EaStyle.Sizes.fontPixelSize * 6 text: qsTr("Mext") color: EaStyle.Colors.themeForegroundMinor horizontalAlignment: Text.AlignHCenter @@ -124,15 +118,9 @@ EaElements.Dialog{ ListElement { name: "D2O-buffer"; component_type: "Other"; atoms: 3; mint: 0; mext: 3 } } - property var itemSelectionModel: ItemSelectionModel { - id: selectionModel - model: availableComponentsModel - } - - property bool activeSelection: true - - delegate: EaComponents.TableViewDelegate { + delegateModelAccess: DelegateModel.ReadOnly + delegate: EaComponents.ListViewDelegate { required property int index required property string name required property string component_type @@ -140,58 +128,39 @@ EaElements.Dialog{ required property int mint required property int mext - color: { - if (!ListView.view.activeSelection) { - return index % 2 ? - EaStyle.Colors.themeBackgroundHovered2 : - EaStyle.Colors.themeBackgroundHovered1 - } - - ListView.view.itemSelectionModel.selection // create dependency - - return ListView.view.itemSelectionModel.isSelected( - ListView.view.itemSelectionModel.model.index(index, 0) - ) ? EaStyle.Colors.themeAccentMinor : EaStyle.Colors.themeBackgroundHovered1 + EaComponents.TableViewLabel { + text: index + 1 + horizontalAlignment: Text.AlignHCenter + enabled: false } - EaComponents.TableViewLabel { id: modelNameColumn - width: EaStyle.Sizes.fontPixelSize * 12 text: name - leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 } - EaComponents.TableViewLabel { id: typeColumn - width: EaStyle.Sizes.fontPixelSize * 8 text: component_type } - EaComponents.TableViewLabel { id: atomsColumn - width: EaStyle.Sizes.fontPixelSize * 6 text: atoms horizontalAlignment: Text.AlignHCenter } EaComponents.TableViewLabel { id: mintColumn - width: EaStyle.Sizes.fontPixelSize * 6 text: mint horizontalAlignment: Text.AlignHCenter } EaComponents.TableViewLabel { id: mextColumn - width: EaStyle.Sizes.fontPixelSize * 6 text: mext horizontalAlignment: Text.AlignHCenter } - - mouseArea.onPressed: (mouse) => { - let idx = ListView.view.itemSelectionModel.model.index(index, 0) - ListView.view.itemSelectionModel.select( - idx, - ItemSelectionModel.ClearAndSelect - ) + EaComponents.TableViewButton { + id: deleteRowColumn + fontIcon: "minus-circle" + ToolTip.text: qsTr("Remove this component") + onClicked: availableComponentsModel.remove(index) } } } diff --git a/src/easyshapes_app/test.qml b/src/easyshapes_app/test.qml index b7bc114..13ba57d 100644 --- a/src/easyshapes_app/test.qml +++ b/src/easyshapes_app/test.qml @@ -74,6 +74,7 @@ ApplicationWindow{ scrollBarInteractive: true header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { id: modelNameColumnName text: qsTr("Name") From 87a265188fe8312e95b9052214ced1c89371dec2 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Mon, 27 Apr 2026 13:44:40 +0200 Subject: [PATCH 10/23] Basic components and samplemodel code cleanup --- src/easyshapes_app/Gui/ApplicationWindow.qml | 4 +- .../Sidebar/Basic/Groups/SampleModel.qml | 62 ++++-------- .../SampleModel/Sidebar/Basic/Layout.qml | 4 +- .../Basic/Popups/CreateNewComponent.qml | 24 +---- .../Sidebar/Basic/Popups/CreateNewModel.qml | 22 +---- .../Basic/Popups/LoadExistingComponent.qml | 24 +---- .../Basic/Popups/LoadExistingModel.qml | 95 ++++++------------- src/easyshapes_app/test.qml | 1 - 8 files changed, 67 insertions(+), 169 deletions(-) diff --git a/src/easyshapes_app/Gui/ApplicationWindow.qml b/src/easyshapes_app/Gui/ApplicationWindow.qml index 029c1d7..9e21918 100644 --- a/src/easyshapes_app/Gui/ApplicationWindow.qml +++ b/src/easyshapes_app/Gui/ApplicationWindow.qml @@ -75,8 +75,8 @@ EaComponents.ApplicationWindow { EaElements.AppBarTabButton { id: sampleModelButton enabled: false - fontIcon: 'layer-group' - text: qsTr('Sample Model') + fontIcon: 'layer-group' // 'layer-group' 'vials' 'vial' + text: qsTr('Sample Model') // qsTr('Model') ToolTip.text: qsTr('Sample Model definition page') Component.onCompleted: { Globals.References.applicationWindow.appBarCentralTabs.sampleModelButton = sampleModelButton diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml index 91d07fb..7196bd4 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml @@ -17,29 +17,27 @@ import Gui.Globals as Globals EaElements.GroupColumn { property double buttonWidth: EaStyle.Sizes.sideBarContentWidth * 0.3164 - EaComponents.TableView { - id: loadedSampleModelTableView - clip: true - + EaComponents.ListView { + id: loadedSampleModel defaultInfoText: qsTr("Get started by loading or creating a model") - header: EaComponents.TableViewHeader { + multiSelection: false + + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 12, + EaStyle.Sizes.fontPixelSize * 6, + -1 + ] + + header: EaComponents.ListViewHeader { EaComponents.TableViewLabel { - id: modelNameColumnName - width: EaStyle.Sizes.fontPixelSize * 8 text: qsTr("Name") color: EaStyle.Colors.themeForegroundMinor } - EaComponents.TableViewLabel { - id: modelTypeColumnName - width: EaStyle.Sizes.fontPixelSize * 6 text: qsTr("Type") color: EaStyle.Colors.themeForegroundMinor } - EaComponents.TableViewLabel { - id: modelDescrColumnName - width: EaStyle.Sizes.fontPixelSize * 24 text: qsTr("Description") color: EaStyle.Colors.themeForegroundMinor } @@ -51,45 +49,28 @@ EaElements.GroupColumn { delegateModelAccess: DelegateModel.ReadWrite - delegate: EaComponents.TableViewDelegate { + delegate: EaComponents.ListViewDelegate { required property int index required property string name required property string structure_type required property string description EaComponents.ListViewTextInput { - id: modelNameColumn - width: EaStyle.Sizes.fontPixelSize * 12 text: name onEditingFinished: name = text - leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 } - EaComponents.TableViewComboBox{ - id: structureTypeColumn - width: EaStyle.Sizes.fontPixelSize * 6 - model: ["Ring", "Ball", "Vesicle", "Rod", "Bilayer", "Monolayer", "Lattice"] - + model: [qsTr("Ring"), qsTr("Ball"), qsTr("Vesicle"), qsTr("Rod"), qsTr("Bilayer"), qsTr("Monolayer"), qsTr("Lattice")] Component.onCompleted: { currentIndex = model.indexOf(structure_type) } - onActivated: (index) => { structure_type = model[index] } } - EaComponents.ListViewTextInput { - id: descrColumn - width: EaStyle.Sizes.fontPixelSize * 20 text: description - onEditingFinished: { - description = text - console.log("descrColumn onEditingFinished") - } - onAccepted: { - console.log("descrColumn onAccepted") - } + onEditingFinished: description = text } } } @@ -99,25 +80,24 @@ EaElements.GroupColumn { spacing: EaStyle.Sizes.fontPixelSize EaElements.SideBarButton { - fontIcon: 'upload' - text: qsTr('Load model') + fontIcon: "upload" + text: qsTr("Load model") width: buttonWidth onClicked: loadExistingModelLoader.item.open() } EaElements.SideBarButton { - fontIcon: 'plus-circle' - text: qsTr('Create model') + fontIcon: "plus-circle" + text: qsTr("Create model") width: buttonWidth onClicked: createNewModelLoader.item.open() } EaElements.SideBarButton { - id: saveModelButton - fontIcon: 'download' - text: qsTr('Save model') + fontIcon: "download" + text: qsTr("Save model") width: buttonWidth - enabled: loadedSampleModelTableView.model ? loadedSampleModelTableView.model.count > 0 : false + enabled: loadedSampleModel.model && loadedSampleModel.model.count > 0 && loadedSambleModelsModel.get(0).name !== "" onClicked: loadExistingModelLoader.item.availableModelsModel.append(loadedSambleModelsModel.get(0)) } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml index 420bc12..d8a5a7c 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml @@ -14,8 +14,8 @@ import Gui.Globals as Globals EaComponents.SideBarColumn { EaElements.GroupBox { - title: qsTr('Add a Model') - icon: 'vial' + title: qsTr('Model Definition') + icon: 'tag' collapsed: false Loader { source: 'Groups/SampleModel.qml' } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml index fc0e265..eee6a2c 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml @@ -18,16 +18,12 @@ EaElements.Dialog{ id: componentCreationDialog property var targetModel - - title: qsTr("Create a new Component") - property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 + title: qsTr("Create a new Component") standardButtons: Dialog.Ok | Dialog.Cancel onAccepted: { - console.log("Ok Clicked") - targetModel.append({ name: componentNameField.text, component_type: sampleModelTypeField.currentText, @@ -36,31 +32,21 @@ EaElements.Dialog{ mext: 0 }) } - onRejected: console.log("Cancel Clicked") - onOpened: console.log("Opened CreateNewComponent Clicked") - - Component.onCompleted: { - Globals.References.pages.samplemodel.sidebar.basic.popups.CreateNewComponent = this - } Column { - spacing: EaStyle.Sizes.fontPixelSize Row { - spacing: EaStyle.Sizes.fontPixelSize - property int halfFieldWidth: (componentCreationDialog.inputFieldWidth - spacing) / 2 + spacing: EaStyle.Sizes.fontPixelSize Column { EaElements.Label { enabled: false text: qsTr("Name") } - EaElements.TextField { id: componentNameField - implicitWidth: parent.parent.halfFieldWidth horizontalAlignment: TextInput.AlignLeft validator: RegularExpressionValidator { regularExpression: /^[a-zA-Z][a-zA-Z0-9_\-\.]{1,30}$/ } @@ -73,11 +59,10 @@ EaElements.Dialog{ enabled: false text: qsTr("Component type") } - EaElements.ComboBox { id: sampleModelTypeField implicitWidth: parent.parent.halfFieldWidth - model: ["Other", "Lipid", "Surfactant"] + model: [qsTr("Other"), qsTr("Lipid"), qsTr("Surfactant")] } } } @@ -107,14 +92,13 @@ EaElements.Dialog{ enabled: true maxRowCountShow: 2 width: componentCreationDialog.inputFieldWidth + scrollBarInteractive: false columnWidths: [ -1, EaStyle.Sizes.tableRowHeight ] - scrollBarInteractive: false - model: ListModel { id: selectedFilePathsModel } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml index 67dab16..8e91107 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml @@ -18,16 +18,12 @@ EaElements.Dialog{ id: sampleModelCreationDialog property var targetModel - - title: qsTr("Create a new Sample Model") - property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 + title: qsTr("Create a new Sample Model") standardButtons: Dialog.Ok | Dialog.Cancel onAccepted: { - console.log("Ok Clicked") - targetModel.clear() targetModel.append( { @@ -37,11 +33,8 @@ EaElements.Dialog{ } ) } - onRejected: console.log("Cancel Clicked") - onOpened: console.log("Opened CreateNewModel Clicked") Column { - spacing: EaStyle.Sizes.fontPixelSize Row { @@ -53,10 +46,8 @@ EaElements.Dialog{ enabled: false text: qsTr("Name") } - EaElements.TextField { id: sampleModelNameField - implicitWidth: (sampleModelCreationDialog.inputFieldWidth - nameTypeRow.spacing) / 2 horizontalAlignment: TextInput.AlignLeft validator: RegularExpressionValidator { regularExpression: /^[a-zA-Z][a-zA-Z0-9_\-\.]{1,30}$/ } @@ -69,11 +60,10 @@ EaElements.Dialog{ enabled: false text: qsTr("Structure type") } - EaElements.ComboBox { id: sampleModelTypeField implicitWidth: (sampleModelCreationDialog.inputFieldWidth - nameTypeRow.spacing) / 2 - model: ["Ring", "Ball", "Vesicle", "Rod", "Bilayer", "Monolayer", "Lattice"] + model: [qsTr("Ring"), qsTr("Ball"), qsTr("Vesicle"), qsTr("Rod"), qsTr("Bilayer"), qsTr("Monolayer"), qsTr("Lattice")] } } } @@ -83,22 +73,14 @@ EaElements.Dialog{ enabled: false text: qsTr("Description") } - EaElements.TextField { id: sampleModelDescrField - implicitWidth: sampleModelCreationDialog.inputFieldWidth horizontalAlignment: TextInput.AlignLeft validator: RegularExpressionValidator { regularExpression: /^[a-zA-Z][a-zA-Z0-9_\-\.]{1,30}$/ } placeholderText: qsTr("(optional) Enter Sample Model description here") } } - } - - Component.onCompleted: { - Globals.References.pages.samplemodel.sidebar.basic.popups.CreateNewModel = this - } - } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml index c352c56..b95b813 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml @@ -18,17 +18,14 @@ EaElements.Dialog{ id: sampleModelLoadDialog property var targetModel - - title: qsTr("Load Components from the Asset Library") - property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 - property alias availableComponentsModel: availableComponentsModel + title: qsTr("Load Components from the Asset Library") standardButtons: Dialog.Ok | Dialog.Cancel onAccepted: { - let selected = loadModelListView.selectedIndexes + let selected = loadComponentListView.selectedIndexes for (let i = 0; i < selected.length; ++i) { var row = selected[i].row var item = availableComponentsModel.get(row) @@ -41,10 +38,10 @@ EaElements.Dialog{ atoms: item.atoms }) } - loadModelListView.clearSelection() + loadComponentListView.clearSelection() } onRejected: { - loadModelListView.clearSelection() + loadComponentListView.clearSelection() } Column { @@ -54,7 +51,7 @@ EaElements.Dialog{ } EaComponents.ListView { - id: loadModelListView + id: loadComponentListView defaultInfoText: qsTr("No models found") multiSelection: true @@ -75,29 +72,24 @@ EaElements.Dialog{ horizontalAlignment: Text.AlignHCenter } EaComponents.TableViewLabel { - id: modelNameColumnName text: qsTr("Name") color: EaStyle.Colors.themeForegroundMinor } EaComponents.TableViewLabel { - id: modelTypeColumnName text: qsTr("Type") color: EaStyle.Colors.themeForegroundMinor } EaComponents.TableViewLabel { - id: modelAtomsColumnName text: qsTr("Atoms") color: EaStyle.Colors.themeForegroundMinor horizontalAlignment: Text.AlignHCenter } EaComponents.TableViewLabel { - id: modelMintColumnName text: qsTr("Mint") color: EaStyle.Colors.themeForegroundMinor horizontalAlignment: Text.AlignHCenter } EaComponents.TableViewLabel { - id: modelMextColumnName text: qsTr("Mext") color: EaStyle.Colors.themeForegroundMinor horizontalAlignment: Text.AlignHCenter @@ -134,30 +126,24 @@ EaElements.Dialog{ enabled: false } EaComponents.TableViewLabel { - id: modelNameColumn text: name } EaComponents.TableViewLabel { - id: typeColumn text: component_type } EaComponents.TableViewLabel { - id: atomsColumn text: atoms horizontalAlignment: Text.AlignHCenter } EaComponents.TableViewLabel { - id: mintColumn text: mint horizontalAlignment: Text.AlignHCenter } EaComponents.TableViewLabel { - id: mextColumn text: mext horizontalAlignment: Text.AlignHCenter } EaComponents.TableViewButton { - id: deleteRowColumn fontIcon: "minus-circle" ToolTip.text: qsTr("Remove this component") onClicked: availableComponentsModel.remove(index) diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml index f1a77ec..19fdc0b 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml @@ -19,34 +19,26 @@ EaElements.Dialog{ id: sampleModelLoadDialog property var targetModel - - title: qsTr("Load a Sample Model from the Asset Library") - property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 - property alias availableModelsModel: availableSambleModelsModel + title: qsTr("Load a Sample Model from the Asset Library") standardButtons: Dialog.Ok | Dialog.Cancel onAccepted: { - console.log("Ok Clicked") - - var indexes = selectionModel.selectedIndexes + var indexes = loadModelListView.selectedIndexes if (indexes.length > 0) { var row = indexes[0].row var item = availableSambleModelsModel.get(row) - console.log("Selected SampleModel: ", item.name) - targetModel.clear() targetModel.append(item) - selectionModel.clear() + loadModelListView.clearSelection() } } onRejected: { - console.log("Cancel Clicked") - selectionModel.clear() + loadModelListView.clearSelection() } Column { @@ -54,31 +46,33 @@ EaElements.Dialog{ enabled: false text: qsTr("Available in the Asset Library") } - - EaComponents.TableView { - clip: true - id: loadModelTableView + EaComponents.ListView { + id: loadModelListView defaultInfoText: qsTr("No models found") - - header: EaComponents.TableViewHeader { + multiSelection: false + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 2.5, + EaStyle.Sizes.fontPixelSize * 10, + EaStyle.Sizes.fontPixelSize * 6, + -1, + EaStyle.Sizes.tableRowHeight, + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr("№") + color: EaStyle.Colors.themeForegroundMinor + horizontalAlignment: Text.AlignHCenter + } EaComponents.TableViewLabel { - id: modelNameColumnName - width: EaStyle.Sizes.fontPixelSize * 10 text: qsTr("Name") color: EaStyle.Colors.themeForegroundMinor - leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 } - EaComponents.TableViewLabel { - id: modelTypeColumnName - width: EaStyle.Sizes.fontPixelSize * 6 text: qsTr("Type") color: EaStyle.Colors.themeForegroundMinor } - EaComponents.TableViewLabel { - id: modelDescrColumnName - width: EaStyle.Sizes.fontPixelSize * 22 text: qsTr("Description") color: EaStyle.Colors.themeForegroundMinor } @@ -98,59 +92,32 @@ EaElements.Dialog{ ListElement { name: "Samplewithareallylongname"; structure_type: "Lattice"; description: "In summary, we show that GPR84 utilizes GRK2 in concert with β-arrestin and actin cytoskeleton dependent processes to fine-tune the activity of the ROS generating NADPH-oxidase in neutrophils." } } - property var itemSelectionModel: ItemSelectionModel { - id: selectionModel - model: availableSambleModelsModel - } - - property bool activeSelection: true - - delegate: EaComponents.TableViewDelegate { + delegateModelAccess: DelegateModel.ReadOnly + delegate: EaComponents.ListViewDelegate { required property int index required property string name required property string structure_type required property string description - color: { - if (!ListView.view.activeSelection) { - return index % 2 ? - EaStyle.Colors.themeBackgroundHovered2 : - EaStyle.Colors.themeBackgroundHovered1 - } - - ListView.view.itemSelectionModel.selection // create dependency - - return ListView.view.itemSelectionModel.isSelected( - ListView.view.itemSelectionModel.model.index(index, 0) - ) ? EaStyle.Colors.themeAccentMinor : EaStyle.Colors.themeBackgroundHovered1 + EaComponents.TableViewLabel { + text: index + 1 + horizontalAlignment: Text.AlignHCenter + enabled: false } - EaComponents.TableViewLabel { - id: modelNameColumn - width: EaStyle.Sizes.fontPixelSize * 10 text: name - leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 } - EaComponents.TableViewLabel { - id: typeColumn - width: EaStyle.Sizes.fontPixelSize * 6 text: structure_type } - EaComponents.TableViewLabel { - id: descrColumn - width: EaStyle.Sizes.fontPixelSize * 22 text: description } - - mouseArea.onPressed: (mouse) => { - let idx = ListView.view.itemSelectionModel.model.index(index, 0) - ListView.view.itemSelectionModel.select( - idx, - ItemSelectionModel.ClearAndSelect - ) + EaComponents.TableViewButton { + fontIcon: "minus-circle" + ToolTip.text: qsTr("Remove this component") + onClicked: availableSambleModelsModel.remove(index) } } } diff --git a/src/easyshapes_app/test.qml b/src/easyshapes_app/test.qml index 13ba57d..ca63c21 100644 --- a/src/easyshapes_app/test.qml +++ b/src/easyshapes_app/test.qml @@ -25,7 +25,6 @@ ApplicationWindow{ spacing: EaStyle.Sizes.fontPixelSize * 4 leftPadding: 12 - Column { width: 600 spacing: EaStyle.Sizes.fontPixelSize From f0dcdd8d4d2d22f91aa45f9870d5a93194cd6e2c Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Wed, 29 Apr 2026 15:25:16 +0200 Subject: [PATCH 11/23] Made Layers component group --- src/easyshapes_app.qrc | 2 +- src/easyshapes_app/Gui/ApplicationWindow.qml | 2 +- src/easyshapes_app/Gui/Globals/References.qml | 3 + .../Sidebar/Basic/Groups/Components.qml | 10 -- .../Sidebar/Basic/Groups/Group1.qml | 18 -- .../Sidebar/Basic/Groups/Layers.qml | 156 ++++++++++++++++++ .../Sidebar/Basic/Groups/SampleModel.qml | 6 + .../SampleModel/Sidebar/Basic/Layout.qml | 13 +- src/easyshapes_app/test.qml | 2 +- 9 files changed, 175 insertions(+), 37 deletions(-) delete mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group1.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml diff --git a/src/easyshapes_app.qrc b/src/easyshapes_app.qrc index f16d733..0cdd901 100644 --- a/src/easyshapes_app.qrc +++ b/src/easyshapes_app.qrc @@ -148,9 +148,9 @@ easyshapes_app/Gui/Pages/SampleModel/Layout.qml easyshapes_app/Gui/Pages/SampleModel/MainArea/GraphsView.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml - easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group1.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml diff --git a/src/easyshapes_app/Gui/ApplicationWindow.qml b/src/easyshapes_app/Gui/ApplicationWindow.qml index 9e21918..57b54db 100644 --- a/src/easyshapes_app/Gui/ApplicationWindow.qml +++ b/src/easyshapes_app/Gui/ApplicationWindow.qml @@ -75,7 +75,7 @@ EaComponents.ApplicationWindow { EaElements.AppBarTabButton { id: sampleModelButton enabled: false - fontIcon: 'layer-group' // 'layer-group' 'vials' 'vial' + fontIcon: 'vial' // 'layer-group' 'vials' 'vial' text: qsTr('Sample Model') // qsTr('Model') ToolTip.text: qsTr('Sample Model definition page') Component.onCompleted: { diff --git a/src/easyshapes_app/Gui/Globals/References.qml b/src/easyshapes_app/Gui/Globals/References.qml index 3219729..9189a76 100644 --- a/src/easyshapes_app/Gui/Globals/References.qml +++ b/src/easyshapes_app/Gui/Globals/References.qml @@ -43,6 +43,9 @@ QtObject { 'LoadExistingComponent': null, 'CreateNewComponent': null, 'OpenAssetFile': null + }, + 'groups': { + 'sampleModel': null } } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml index 8c4c6de..5c6b0c6 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml @@ -37,7 +37,6 @@ EaElements.GroupColumn { EaComponents.TableViewLabel { text: qsTr("№") color: EaStyle.Colors.themeForegroundMinor - horizontalAlignment: Text.AlignHCenter } EaComponents.TableViewLabel { text: qsTr("Name") @@ -50,17 +49,14 @@ EaElements.GroupColumn { EaComponents.TableViewLabel { text: qsTr("Atoms") color: EaStyle.Colors.themeForegroundMinor - horizontalAlignment: Text.AlignHCenter } EaComponents.TableViewLabel { text: qsTr("Mint") color: EaStyle.Colors.themeForegroundMinor - horizontalAlignment: Text.AlignHCenter } EaComponents.TableViewLabel { text: qsTr("Mext") color: EaStyle.Colors.themeForegroundMinor - horizontalAlignment: Text.AlignHCenter } EaComponents.TableViewLabel { color: EaStyle.Colors.themeForegroundMinor @@ -83,12 +79,10 @@ EaElements.GroupColumn { EaComponents.TableViewLabel { text: index + 1 - horizontalAlignment: Text.AlignHCenter enabled: false } EaComponents.ListViewTextInput { - id: modelNameColumn text: name onEditingFinished: name = text } @@ -100,27 +94,23 @@ EaElements.GroupColumn { EaComponents.ListViewTextInput { text: atoms - horizontalAlignment: Text.AlignHCenter onEditingFinished: atoms = parseInt(text) validator: IntValidator { bottom: 0 } } EaComponents.ListViewTextInput { text: mint - horizontalAlignment: Text.AlignHCenter onEditingFinished: mint = parseInt(text) validator: IntValidator { bottom: 0 } } EaComponents.ListViewTextInput { text: mext - horizontalAlignment: Text.AlignHCenter onEditingFinished: mext = parseInt(text) validator: IntValidator { bottom: 0 } } EaComponents.TableViewButton { - id: deleteRowColumn fontIcon: "minus-circle" ToolTip.text: qsTr("Remove this component") onClicked: loadedComponentsModel.remove(index) diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group1.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group1.qml deleted file mode 100644 index f2e5c14..0000000 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group1.qml +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtQuick.Controls - -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic - -import Gui.Globals as Globals - -EaElements.GroupColumn { - -} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml new file mode 100644 index 0000000..2f151e7 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml @@ -0,0 +1,156 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApp.Gui.Globals as EaGlobals +import EasyApp.Gui.Style as EaStyle +import EasyApp.Gui.Elements as EaElements +import EasyApp.Gui.Components as EaComponents +import EasyApp.Gui.Logic as EaLogic + +import Gui.Globals as Globals + +EaElements.GroupColumn { + property double buttonWidth: EaStyle.Sizes.sideBarContentWidth * 0.3164 + EaComponents.ListView { + id: layers + defaultInfoText: qsTr("Add at least one layer") + selectable: false + + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 2.5, + -1, + EaStyle.Sizes.fontPixelSize * 6, + EaStyle.Sizes.fontPixelSize * 6, + EaStyle.Sizes.tableRowHeight + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr("№") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel {} // filler + EaComponents.TableViewLabel { + text: qsTr("Dmin") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr("Rmin") + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: ListModel { + id: layersModel + ListElement { dmin: 0.25; rmin: 0.5; } + } + + delegateModelAccess: DelegateModel.ReadWrite + + delegate: EaComponents.ListViewDelegate { + required property int index + required property double dmin + required property double rmin + + EaComponents.TableViewLabel { + text: index + 1 + enabled: false + } + EaComponents.TableViewLabel {} // filler + EaComponents.ListViewTextInput { + text: dmin + onEditingFinished: dmin = parseFloat(text) + validator: DoubleValidator { bottom: 0.25 } + } + EaComponents.ListViewTextInput { + text: rmin + onEditingFinished: rmin = parseFloat(text) + validator: DoubleValidator { bottom: 0.25 } + } + EaComponents.TableViewButton { + id: deleteRowColumn + fontIcon: "minus-circle" + ToolTip.text: qsTr("Remove this layer") + onClicked: layersModel.remove(index) + } + } + } + Item { + width: layers.width + height: addLayerButton.height + + EaElements.SideBarButton { + id: addLayerButton + anchors.right: parent.right + anchors.rightMargin: EaStyle.Sizes.tableColumnSpacing + fontIcon: 'plus-circle' + text: qsTr('Add layer') + width: buttonWidth + onClicked: layersModel.append({ dmin: 0.25, rmin: 0.5 }) + } + } + EaComponents.ListView { + id: fractions + defaultInfoText: qsTr("Missing components") + selectionActive: false + + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 6, + -1, + EaStyle.Sizes.fontPixelSize * 8, + EaStyle.Sizes.fontPixelSize * 8, + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr("Present") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel {} // filler + EaComponents.TableViewLabel { + text: qsTr("Component name") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr("Molar ratio") + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: ListModel { + id: fractionsModel + ListElement { name: "POPC"; fracs: 100; present: true } + ListElement { name: "DOPC"; fracs: 100; present: true } + ListElement { name: "DPPC"; fracs: 100; present: true } + } + + delegateModelAccess: DelegateModel.ReadWrite + + delegate: EaComponents.ListViewDelegate { + required property int index + required property string name + required property double fracs + required property bool present + + EaComponents.TableViewCheckBox { + checked: present + onToggled: present = checked + } + EaComponents.TableViewLabel{} // filler + EaComponents.TableViewLabel{ + text: name + enabled: false + } + EaComponents.ListViewTextInput { + text: present ? fracs : 0 + enabled: present + onEditingFinished: fracs = parseFloat(text) + validator: DoubleValidator { bottom: 0 } + } + } + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml index 7196bd4..157c34c 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml @@ -15,7 +15,11 @@ import EasyApp.Gui.Logic as EaLogic import Gui.Globals as Globals EaElements.GroupColumn { + id: root property double buttonWidth: EaStyle.Sizes.sideBarContentWidth * 0.3164 + property string currentStructureType: "" + + Component.onCompleted: Globals.References.pages.samplemodel.sidebar.basic.groups.sampleModel = root EaComponents.ListView { id: loadedSampleModel @@ -45,6 +49,7 @@ EaElements.GroupColumn { model: ListModel { id: loadedSambleModelsModel + onCountChanged: root.currentStructureType = count > 0 ? get(0).structure_type : "" } delegateModelAccess: DelegateModel.ReadWrite @@ -66,6 +71,7 @@ EaElements.GroupColumn { } onActivated: (index) => { structure_type = model[index] + root.currentStructureType = model[index] } } EaComponents.ListViewTextInput { diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml index d8a5a7c..dc0afa0 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml @@ -18,7 +18,7 @@ EaComponents.SideBarColumn { icon: 'tag' collapsed: false - Loader { source: 'Groups/SampleModel.qml' } + Loader { id: sampleModelLoader; source: 'Groups/SampleModel.qml' } } EaElements.GroupBox { @@ -29,14 +29,15 @@ EaComponents.SideBarColumn { } EaElements.GroupBox { - title: qsTr('Solution') - icon: 'tint' + title: qsTr('Layers') + icon: 'layer-group' // 'grip-lines' + visible: sampleModelLoader.item ? sampleModelLoader.item.currentStructureType === 'Ball' : false - Loader { source: 'Groups/Group2.qml' } + Loader { source: 'Groups/Layers.qml' } } EaElements.GroupBox { - title: qsTr('Group 3') + title: qsTr('Solvent') icon: 'grip-horizontal' Loader { source: 'Groups/Group3.qml' } @@ -46,7 +47,7 @@ EaComponents.SideBarColumn { title: qsTr('Group 1') icon: 'rocket' - Loader { source: 'Groups/Group1.qml' } + Loader { source: 'Groups/Group2.qml' } } } diff --git a/src/easyshapes_app/test.qml b/src/easyshapes_app/test.qml index ca63c21..df3ac5d 100644 --- a/src/easyshapes_app/test.qml +++ b/src/easyshapes_app/test.qml @@ -55,7 +55,7 @@ ApplicationWindow{ icon: 'wrench' collapsed: false - Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml'} + Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml'} } EaComponents.ListView { From e0f0388068d307cbc60f4e9b1972afac9149b0e0 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Wed, 29 Apr 2026 16:22:38 +0200 Subject: [PATCH 12/23] Added a label to the fractions listview and made it toggleable based on selected layer --- .../Sidebar/Basic/Groups/Layers.qml | 124 ++++++++++-------- 1 file changed, 67 insertions(+), 57 deletions(-) diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml index 2f151e7..9b5449b 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml @@ -18,7 +18,7 @@ EaElements.GroupColumn { EaComponents.ListView { id: layers defaultInfoText: qsTr("Add at least one layer") - selectable: false + multiSelection: false columnWidths: [ EaStyle.Sizes.fontPixelSize * 2.5, @@ -87,69 +87,79 @@ EaElements.GroupColumn { id: addLayerButton anchors.right: parent.right anchors.rightMargin: EaStyle.Sizes.tableColumnSpacing - fontIcon: 'plus-circle' - text: qsTr('Add layer') + fontIcon: "plus-circle" + text: qsTr("Add layer") width: buttonWidth onClicked: layersModel.append({ dmin: 0.25, rmin: 0.5 }) } } - EaComponents.ListView { - id: fractions - defaultInfoText: qsTr("Missing components") - selectionActive: false - - columnWidths: [ - EaStyle.Sizes.fontPixelSize * 6, - -1, - EaStyle.Sizes.fontPixelSize * 8, - EaStyle.Sizes.fontPixelSize * 8, - ] - - header: EaComponents.ListViewHeader { - EaComponents.TableViewLabel { - text: qsTr("Present") - color: EaStyle.Colors.themeForegroundMinor - } - EaComponents.TableViewLabel {} // filler - EaComponents.TableViewLabel { - text: qsTr("Component name") - color: EaStyle.Colors.themeForegroundMinor - } - EaComponents.TableViewLabel { - text: qsTr("Molar ratio") - color: EaStyle.Colors.themeForegroundMinor - } - } - - model: ListModel { - id: fractionsModel - ListElement { name: "POPC"; fracs: 100; present: true } - ListElement { name: "DOPC"; fracs: 100; present: true } - ListElement { name: "DPPC"; fracs: 100; present: true } + Column { + visible: layers.selectedIndexes.length > 0 + width: parent.width + + EaElements.Label { + id: layerFractionsLabel + enabled: false + text: qsTr("Layer %1 Fractions").arg(layers.selectedIndexes.length > 0 ? layers.selectedIndexes[0].row + 1 : 1) } - - delegateModelAccess: DelegateModel.ReadWrite - - delegate: EaComponents.ListViewDelegate { - required property int index - required property string name - required property double fracs - required property bool present - - EaComponents.TableViewCheckBox { - checked: present - onToggled: present = checked + EaComponents.ListView { + id: fractions + defaultInfoText: qsTr("Missing components") + selectionActive: false + + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 6, + -1, + EaStyle.Sizes.fontPixelSize * 8, + EaStyle.Sizes.fontPixelSize * 8, + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr("Present") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel {} // filler + EaComponents.TableViewLabel { + text: qsTr("Component name") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr("Molar ratio") + color: EaStyle.Colors.themeForegroundMinor + } } - EaComponents.TableViewLabel{} // filler - EaComponents.TableViewLabel{ - text: name - enabled: false + + model: ListModel { + id: fractionsModel + ListElement { name: "POPC"; fracs: 100; present: true } + ListElement { name: "DOPC"; fracs: 100; present: true } + ListElement { name: "DPPC"; fracs: 100; present: true } } - EaComponents.ListViewTextInput { - text: present ? fracs : 0 - enabled: present - onEditingFinished: fracs = parseFloat(text) - validator: DoubleValidator { bottom: 0 } + + delegateModelAccess: DelegateModel.ReadWrite + + delegate: EaComponents.ListViewDelegate { + required property int index + required property string name + required property double fracs + required property bool present + + EaComponents.TableViewCheckBox { + checked: present + onToggled: present = checked + } + EaComponents.TableViewLabel{} // filler + EaComponents.TableViewLabel{ + text: name + enabled: false + } + EaComponents.ListViewTextInput { + text: present ? fracs : 0 + enabled: present + onEditingFinished: fracs = parseFloat(text) + validator: DoubleValidator { bottom: 0 } + } } } } From df34aa3c53282125d3df36a1ff713b585782e7ae Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Wed, 29 Apr 2026 16:50:27 +0200 Subject: [PATCH 13/23] Extracted fractions into a reusable component --- src/easyshapes_app.qrc | 1 + .../Sidebar/Basic/Components/Fractions.qml | 68 +++++++++++++++++++ .../Sidebar/Basic/Groups/Layers.qml | 61 +---------------- 3 files changed, 72 insertions(+), 58 deletions(-) create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml diff --git a/src/easyshapes_app.qrc b/src/easyshapes_app.qrc index 0cdd901..4889665 100644 --- a/src/easyshapes_app.qrc +++ b/src/easyshapes_app.qrc @@ -147,6 +147,7 @@ easyshapes_app/Gui/Pages/Report/Sidebar/Extra/Layout.qml easyshapes_app/Gui/Pages/SampleModel/Layout.qml easyshapes_app/Gui/Pages/SampleModel/MainArea/GraphsView.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml new file mode 100644 index 0000000..e39f2df --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml @@ -0,0 +1,68 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApp.Gui.Style as EaStyle +import EasyApp.Gui.Components as EaComponents + +EaComponents.ListView { + defaultInfoText: qsTr("Missing components") + selectionActive: false + + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 6, + -1, + EaStyle.Sizes.fontPixelSize * 8, + EaStyle.Sizes.fontPixelSize * 8, + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr("Present") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel {} // filler + EaComponents.TableViewLabel { + text: qsTr("Component name") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr("Molar ratio") + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: ListModel { + ListElement { name: "POPC"; fracs: 100; present: true } + ListElement { name: "DOPC"; fracs: 100; present: true } + ListElement { name: "DPPC"; fracs: 100; present: true } + } + + delegateModelAccess: DelegateModel.ReadWrite + + delegate: EaComponents.ListViewDelegate { + required property int index + required property string name + required property double fracs + required property bool present + + EaComponents.TableViewCheckBox { + checked: present + onToggled: present = checked + } + EaComponents.TableViewLabel {} // filler + EaComponents.TableViewLabel { + text: name + enabled: false + } + EaComponents.ListViewTextInput { + text: present ? fracs : 0 + enabled: present + onEditingFinished: fracs = parseFloat(text) + validator: DoubleValidator { bottom: 0 } + } + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml index 9b5449b..1168ec9 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml @@ -13,6 +13,8 @@ import EasyApp.Gui.Logic as EaLogic import Gui.Globals as Globals +import "../Components" as Local + EaElements.GroupColumn { property double buttonWidth: EaStyle.Sizes.sideBarContentWidth * 0.3164 EaComponents.ListView { @@ -102,65 +104,8 @@ EaElements.GroupColumn { enabled: false text: qsTr("Layer %1 Fractions").arg(layers.selectedIndexes.length > 0 ? layers.selectedIndexes[0].row + 1 : 1) } - EaComponents.ListView { + Local.Fractions { id: fractions - defaultInfoText: qsTr("Missing components") - selectionActive: false - - columnWidths: [ - EaStyle.Sizes.fontPixelSize * 6, - -1, - EaStyle.Sizes.fontPixelSize * 8, - EaStyle.Sizes.fontPixelSize * 8, - ] - - header: EaComponents.ListViewHeader { - EaComponents.TableViewLabel { - text: qsTr("Present") - color: EaStyle.Colors.themeForegroundMinor - } - EaComponents.TableViewLabel {} // filler - EaComponents.TableViewLabel { - text: qsTr("Component name") - color: EaStyle.Colors.themeForegroundMinor - } - EaComponents.TableViewLabel { - text: qsTr("Molar ratio") - color: EaStyle.Colors.themeForegroundMinor - } - } - - model: ListModel { - id: fractionsModel - ListElement { name: "POPC"; fracs: 100; present: true } - ListElement { name: "DOPC"; fracs: 100; present: true } - ListElement { name: "DPPC"; fracs: 100; present: true } - } - - delegateModelAccess: DelegateModel.ReadWrite - - delegate: EaComponents.ListViewDelegate { - required property int index - required property string name - required property double fracs - required property bool present - - EaComponents.TableViewCheckBox { - checked: present - onToggled: present = checked - } - EaComponents.TableViewLabel{} // filler - EaComponents.TableViewLabel{ - text: name - enabled: false - } - EaComponents.ListViewTextInput { - text: present ? fracs : 0 - enabled: present - onEditingFinished: fracs = parseFloat(text) - validator: DoubleValidator { bottom: 0 } - } - } } } } From 966c0214539a6deae23dbcaabc14f5b6ed3ac52c Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Thu, 30 Apr 2026 11:11:10 +0200 Subject: [PATCH 14/23] Added lamellae group --- .../Sidebar/Basic/Groups/Lamellae.qml | 162 ++++++++++++++++++ .../SampleModel/Sidebar/Basic/Layout.qml | 8 + src/easyshapes_app/test.qml | 2 +- 3 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml new file mode 100644 index 0000000..e81f1c9 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml @@ -0,0 +1,162 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApp.Gui.Globals as EaGlobals +import EasyApp.Gui.Style as EaStyle +import EasyApp.Gui.Elements as EaElements +import EasyApp.Gui.Components as EaComponents +import EasyApp.Gui.Logic as EaLogic + +import Gui.Globals as Globals + +import "../Components" as Local + +EaElements.GroupColumn { + property double buttonWidth: EaStyle.Sizes.sideBarContentWidth * 0.3164 + + EaComponents.ListView { + id: lamellae + defaultInfoText: qsTr("Add at least one lamella") + multiSelection: false + + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 2.5, + -1, + EaStyle.Sizes.fontPixelSize * 5, + EaStyle.Sizes.fontPixelSize * 5, + EaStyle.Sizes.fontPixelSize * 5, + EaStyle.Sizes.fontPixelSize * 5, + EaStyle.Sizes.tableRowHeight, + EaStyle.Sizes.tableRowHeight + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr("№") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel {} // filler + EaComponents.TableViewLabel { + text: qsTr("Rmin") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr("Inner Dmin") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr("Outer Dmin") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr("Shell") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr("Sym") + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: ListModel { + id: lamellaeModel + ListElement { rmin: 0.5; innerDmin: 0.25; outerDmin: 0.25; shell: 0.5; symmetric: true } + } + + delegateModelAccess: DelegateModel.ReadWrite + + delegate: EaComponents.ListViewDelegate { + required property int index + required property double rmin + required property double innerDmin + required property double outerDmin + required property double shell + required property bool symmetric + + EaComponents.TableViewLabel { + text: index + 1 + enabled: false + } + EaComponents.TableViewLabel {} // filler + EaComponents.ListViewTextInput { + text: rmin + onEditingFinished: rmin = parseFloat(text) + validator: DoubleValidator { bottom: 0.25 } + } + EaComponents.ListViewTextInput { + text: innerDmin + onEditingFinished: innerDmin = parseFloat(text) + validator: DoubleValidator { bottom: 0.25 } + } + EaComponents.ListViewTextInput { + text: symmetric ? innerDmin : outerDmin + enabled: !symmetric + onEditingFinished: outerDmin = parseFloat(text) + validator: DoubleValidator { bottom: 0.25 } + } + EaComponents.ListViewTextInput { + text: shell + onEditingFinished: shell = parseFloat(text) + validator: DoubleValidator { bottom: 0 } + } + EaComponents.TableViewCheckBox { + checked: symmetric + onToggled: symmetric = checked + } + EaComponents.TableViewButton { + id: deleteRowColumn + fontIcon: "minus-circle" + ToolTip.text: qsTr("Remove this lamella") + onClicked: lamellaeModel.remove(index) + } + } + } + + Item { + width: lamellae.width + height: addLamellaButton.height + + EaElements.SideBarButton { + id: addLamellaButton + anchors.right: parent.right + anchors.rightMargin: EaStyle.Sizes.tableColumnSpacing + fontIcon: "plus-circle" + text: qsTr("Add lamella") + width: buttonWidth + onClicked: lamellaeModel.append({ rmin: 0.5, innerDmin: 0.25, outerDmin: 0.25, shell: 0.5, symmetric: true }) + } + } + + Column { + id: fractionsSection + visible: lamellae.selectedIndexes.length > 0 + width: parent.width + + readonly property int selectedRow: lamellae.selectedIndexes.length > 0 ? lamellae.selectedIndexes[0].row : -1 + readonly property bool selectedSymmetric: selectedRow >= 0 && lamellaeModel.get(selectedRow).symmetric + + EaElements.Label { + enabled: false + text: fractionsSection.selectedSymmetric + ? qsTr("Lamella %1 Leaflet Fractions").arg(fractionsSection.selectedRow + 1) + : qsTr("Lamella %1 Inner Leaflet Fractions").arg(fractionsSection.selectedRow + 1) + } + Local.Fractions { + id: innerFractions + } + + EaElements.Label { + visible: !fractionsSection.selectedSymmetric + enabled: false + text: qsTr("Lamella %1 Outer Leaflet Fractions").arg(fractionsSection.selectedRow + 1) + } + Local.Fractions { + id: outerFractions + visible: !fractionsSection.selectedSymmetric + } + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml index dc0afa0..1aa6780 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml @@ -36,6 +36,14 @@ EaComponents.SideBarColumn { Loader { source: 'Groups/Layers.qml' } } + EaElements.GroupBox { + title: qsTr('Lamellae') + icon: 'layer-group' + visible: sampleModelLoader.item ? sampleModelLoader.item.currentStructureType === 'Vesicle' : false + + Loader { source: 'Groups/Lamellae.qml' } + } + EaElements.GroupBox { title: qsTr('Solvent') icon: 'grip-horizontal' diff --git a/src/easyshapes_app/test.qml b/src/easyshapes_app/test.qml index df3ac5d..1905bb0 100644 --- a/src/easyshapes_app/test.qml +++ b/src/easyshapes_app/test.qml @@ -55,7 +55,7 @@ ApplicationWindow{ icon: 'wrench' collapsed: false - Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml'} + Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml'} } EaComponents.ListView { From 970e9d5c06673a744c90738b0a278528eb6a369c Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Fri, 1 May 2026 11:15:11 +0200 Subject: [PATCH 15/23] convert to new EasyApp(lication) --- src/easyshapes_app.qrc | 110 +----------------- src/easyshapes_app/Gui/ApplicationWindow.qml | 6 +- .../Gui/Pages/Analysis/Layout.qml | 8 +- .../Gui/Pages/Analysis/MainArea/Chart.qml | 4 +- .../Sidebar/Basic/Groups/GetStarted.qml | 10 +- .../Pages/Analysis/Sidebar/Basic/Layout.qml | 4 +- src/easyshapes_app/Gui/Pages/Home/Content.qml | 6 +- .../Gui/Pages/Home/Popups/About.qml | 4 +- .../Gui/Pages/Project/Layout.qml | 8 +- .../Pages/Project/MainArea/Description.qml | 4 +- .../Project/Sidebar/Basic/Groups/Examples.qml | 10 +- .../Sidebar/Basic/Groups/GetStarted.qml | 10 +- .../Project/Sidebar/Basic/Groups/Recent.qml | 10 +- .../Pages/Project/Sidebar/Basic/Layout.qml | 4 +- .../Sidebar/Basic/Popups/OpenCifFile.qml | 4 +- .../Basic/Popups/ProjectDescription.qml | 4 +- .../Sidebar/Extra/Groups/Scrolling.qml | 4 +- .../Pages/Project/Sidebar/Extra/Layout.qml | 4 +- .../Gui/Pages/Project/Sidebar/Text/Layout.qml | 4 +- .../Gui/Pages/Report/Layout.qml | 8 +- .../Gui/Pages/Report/MainArea/Summary.qml | 6 +- .../Report/Sidebar/Basic/Groups/Export.qml | 8 +- .../Gui/Pages/Report/Sidebar/Basic/Layout.qml | 4 +- .../Report/Sidebar/Extra/Groups/Empty.qml | 4 +- .../Gui/Pages/Report/Sidebar/Extra/Layout.qml | 4 +- .../Gui/Pages/SampleModel/Layout.qml | 8 +- .../Pages/SampleModel/MainArea/GraphsView.qml | 4 +- .../Sidebar/Basic/Components/Fractions.qml | 4 +- .../Sidebar/Basic/Groups/Components.qml | 10 +- .../Sidebar/Basic/Groups/Group2.qml | 10 +- .../Sidebar/Basic/Groups/Group3.qml | 10 +- .../Sidebar/Basic/Groups/Lamellae.qml | 38 +++--- .../Sidebar/Basic/Groups/Layers.qml | 25 ++-- .../Sidebar/Basic/Groups/SampleModel.qml | 10 +- .../SampleModel/Sidebar/Basic/Layout.qml | 4 +- .../Basic/Popups/CreateNewComponent.qml | 8 +- .../Sidebar/Basic/Popups/CreateNewModel.qml | 8 +- .../Basic/Popups/LoadExistingComponent.qml | 8 +- .../Basic/Popups/LoadExistingModel.qml | 8 +- .../Sidebar/Basic/Popups/OpenAssetFile.qml | 4 +- .../Gui/Pages/Toolbox/Layout.qml | 8 +- .../Gui/Pages/Toolbox/MainArea/GraphsView.qml | 4 +- .../Gui/Pages/Toolbox/MainArea/Image.qml | 4 +- .../Pages/Toolbox/MainArea/TextAreaPlain.qml | 4 +- .../Pages/Toolbox/MainArea/TextAreaRich.qml | 4 +- .../Toolbox/Sidebar/Basic/Groups/Group1.qml | 10 +- .../Toolbox/Sidebar/Basic/Groups/Group2.qml | 10 +- .../Toolbox/Sidebar/Basic/Groups/Group3.qml | 10 +- .../Toolbox/Sidebar/Basic/Groups/Group4.qml | 10 +- .../Pages/Toolbox/Sidebar/Basic/Layout.qml | 4 +- src/easyshapes_app/Gui/StatusBar.qml | 6 +- src/easyshapes_app/test.qml | 10 +- src/easyshapes_app/test2.qml | 8 +- 53 files changed, 197 insertions(+), 306 deletions(-) diff --git a/src/easyshapes_app.qrc b/src/easyshapes_app.qrc index 4889665..525180b 100644 --- a/src/easyshapes_app.qrc +++ b/src/easyshapes_app.qrc @@ -1,114 +1,5 @@ - ../../EasyApp/src/EasyApp/Gui/Animations/ColorReset.qml - ../../EasyApp/src/EasyApp/Gui/Animations/qmldir - ../../EasyApp/src/EasyApp/Gui/Animations/ThemeChange.qml - ../../EasyApp/src/EasyApp/Gui/Animations/TranslationChange.qml - ../../EasyApp/src/EasyApp/Gui/Charts/ChartViewHeatmap2dPlotly.qml - ../../EasyApp/src/EasyApp/Gui/Charts/ChartViewSimple1dPlotly.qml - ../../EasyApp/src/EasyApp/Gui/Charts/Plotly1dBarPlot.qml - ../../EasyApp/src/EasyApp/Gui/Charts/Plotly1dLine.qml - ../../EasyApp/src/EasyApp/Gui/Charts/Plotly1dMeasVsCalc.qml - ../../EasyApp/src/EasyApp/Gui/Charts/Plotly2dHeatmap.qml - ../../EasyApp/src/EasyApp/Gui/Charts/Plotly2dPolarHeatmap.qml - ../../EasyApp/src/EasyApp/Gui/Charts/Plotly3dScatter.qml - ../../EasyApp/src/EasyApp/Gui/Charts/Plotly3dSurface.qml - ../../EasyApp/src/EasyApp/Gui/Charts/qmldir - ../../EasyApp/src/EasyApp/Gui/Charts/QtCharts1dBase 2.qml - ../../EasyApp/src/EasyApp/Gui/Charts/QtCharts1dBase.qml - ../../EasyApp/src/EasyApp/Gui/Charts/QtCharts1dMeasVsCalc.qml - ../../EasyApp/src/EasyApp/Gui/Charts/QtCharts1dValueAxis.qml - ../../EasyApp/src/EasyApp/Gui/Components/AboutDialog.qml - ../../EasyApp/src/EasyApp/Gui/Components/AppBarCentralTabs.qml - ../../EasyApp/src/EasyApp/Gui/Components/AppBarLeftButtons.qml - ../../EasyApp/src/EasyApp/Gui/Components/AppBarRightButtons.qml - ../../EasyApp/src/EasyApp/Gui/Components/ApplicationWindow.qml - ../../EasyApp/src/EasyApp/Gui/Components/BasicReport.qml - ../../EasyApp/src/EasyApp/Gui/Components/ContentArea.qml - ../../EasyApp/src/EasyApp/Gui/Components/ContentPage.qml - ../../EasyApp/src/EasyApp/Gui/Components/GuideWindow.qml - ../../EasyApp/src/EasyApp/Gui/Components/GuideWindowContainer.qml - ../../EasyApp/src/EasyApp/Gui/Components/JsonListModel.qml - ../../EasyApp/src/EasyApp/Gui/Components/ListView.qml - ../../EasyApp/src/EasyApp/Gui/Components/ListViewDelegate.qml - ../../EasyApp/src/EasyApp/Gui/Components/ListViewHeader.qml - ../../EasyApp/src/EasyApp/Gui/Components/ListViewTextInput.qml - ../../EasyApp/src/EasyApp/Gui/Components/MainContent.qml - ../../EasyApp/src/EasyApp/Gui/Components/PreferencesDialog.qml - ../../EasyApp/src/EasyApp/Gui/Components/ProjectDescriptionDialog.qml - ../../EasyApp/src/EasyApp/Gui/Components/qmldir - ../../EasyApp/src/EasyApp/Gui/Components/SideBar.qml - ../../EasyApp/src/EasyApp/Gui/Components/SideBarColumn.qml - ../../EasyApp/src/EasyApp/Gui/Components/TableView.qml - ../../EasyApp/src/EasyApp/Gui/Components/TableViewAdvancedLabel.qml - ../../EasyApp/src/EasyApp/Gui/Components/TableViewButton.qml - ../../EasyApp/src/EasyApp/Gui/Components/TableViewCheckBox.qml - ../../EasyApp/src/EasyApp/Gui/Components/TableViewComboBox.qml - ../../EasyApp/src/EasyApp/Gui/Components/TableViewDelegate.qml - ../../EasyApp/src/EasyApp/Gui/Components/TableViewHeader.qml - ../../EasyApp/src/EasyApp/Gui/Components/TableViewLabel.qml - ../../EasyApp/src/EasyApp/Gui/Components/TableViewLabelControl.qml - ../../EasyApp/src/EasyApp/Gui/Components/TableViewParameter.qml - ../../EasyApp/src/EasyApp/Gui/Components/TableViewTextInput.qml - ../../EasyApp/src/EasyApp/Gui/Components/TableViewTwoRowsAdvancedLabel.qml - ../../EasyApp/src/EasyApp/Gui/Elements/AppBarTabButton.qml - ../../EasyApp/src/EasyApp/Gui/Elements/ApplicationWindow.qml - ../../EasyApp/src/EasyApp/Gui/Elements/Button.qml - ../../EasyApp/src/EasyApp/Gui/Elements/CheckBox.qml - ../../EasyApp/src/EasyApp/Gui/Elements/CheckIndicator.qml - ../../EasyApp/src/EasyApp/Gui/Elements/ComboBox.qml - ../../EasyApp/src/EasyApp/Gui/Elements/CursorDelegate.qml - ../../EasyApp/src/EasyApp/Gui/Elements/Dialog.qml - ../../EasyApp/src/EasyApp/Gui/Elements/DialogButtonBox.qml - ../../EasyApp/src/EasyApp/Gui/Elements/GroupBox.qml - ../../EasyApp/src/EasyApp/Gui/Elements/GroupButton.qml - ../../EasyApp/src/EasyApp/Gui/Elements/GroupColumn.qml - ../../EasyApp/src/EasyApp/Gui/Elements/GroupRow.qml - ../../EasyApp/src/EasyApp/Gui/Elements/Label.qml - ../../EasyApp/src/EasyApp/Gui/Elements/LinkedImage.qml - ../../EasyApp/src/EasyApp/Gui/Elements/Menu.qml - ../../EasyApp/src/EasyApp/Gui/Elements/MenuItem.qml - ../../EasyApp/src/EasyApp/Gui/Elements/ParamComboBox.qml - ../../EasyApp/src/EasyApp/Gui/Elements/Parameter.qml - ../../EasyApp/src/EasyApp/Gui/Elements/ParamTextField.qml - ../../EasyApp/src/EasyApp/Gui/Elements/qmldir - ../../EasyApp/src/EasyApp/Gui/Elements/RadioButton.qml - ../../EasyApp/src/EasyApp/Gui/Elements/RadioIndicator.qml - ../../EasyApp/src/EasyApp/Gui/Elements/RemoteController.qml - ../../EasyApp/src/EasyApp/Gui/Elements/RemotePointer.qml - ../../EasyApp/src/EasyApp/Gui/Elements/RunningLabel.qml - ../../EasyApp/src/EasyApp/Gui/Elements/ScrollBar.qml - ../../EasyApp/src/EasyApp/Gui/Elements/ScrollIndicator.qml - ../../EasyApp/src/EasyApp/Gui/Elements/SideBarButton.qml - ../../EasyApp/src/EasyApp/Gui/Elements/Slider.qml - ../../EasyApp/src/EasyApp/Gui/Elements/SliderHandle.qml - ../../EasyApp/src/EasyApp/Gui/Elements/SpinBox.qml - ../../EasyApp/src/EasyApp/Gui/Elements/SplashScreen.qml - ../../EasyApp/src/EasyApp/Gui/Elements/StatusBar.qml - ../../EasyApp/src/EasyApp/Gui/Elements/StatusBarItem.qml - ../../EasyApp/src/EasyApp/Gui/Elements/TabBar.qml - ../../EasyApp/src/EasyApp/Gui/Elements/TabButton.qml - ../../EasyApp/src/EasyApp/Gui/Elements/TextArea.qml - ../../EasyApp/src/EasyApp/Gui/Elements/TextField.qml - ../../EasyApp/src/EasyApp/Gui/Elements/TextInput.qml - ../../EasyApp/src/EasyApp/Gui/Elements/ToolButton.qml - ../../EasyApp/src/EasyApp/Gui/Elements/ToolTip.qml - ../../EasyApp/src/EasyApp/Gui/Elements/ToolTipShadow.qml - ../../EasyApp/src/EasyApp/Gui/Globals/qmldir - ../../EasyApp/src/EasyApp/Gui/Globals/Vars.qml - ../../EasyApp/src/EasyApp/Gui/Html/plotly-2.18.0.min.js - ../../EasyApp/src/EasyApp/Gui/Logic/Plotting.js - ../../EasyApp/src/EasyApp/Gui/Logic/ProjectConfig.js - ../../EasyApp/src/EasyApp/Gui/Logic/qmldir - ../../EasyApp/src/EasyApp/Gui/Logic/Translate.js - ../../EasyApp/src/EasyApp/Gui/Logic/Utils.js - ../../EasyApp/src/EasyApp/Gui/Style/Colors.qml - ../../EasyApp/src/EasyApp/Gui/Style/Fonts.qml - ../../EasyApp/src/EasyApp/Gui/Style/qmldir - ../../EasyApp/src/EasyApp/Gui/Style/Sizes.qml - ../../EasyApp/src/EasyApp/Gui/Style/Times.qml - ../../EasyApp/src/EasyApp/Logic/Maintenance/qmldir - ../../EasyApp/src/EasyApp/Logic/Maintenance/Updater.qml easyshapes_app.qmlproject easyshapes_app/Backends/MockBackend.qml easyshapes_app/Backends/MockQml/Analysis.qml @@ -151,6 +42,7 @@ easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml diff --git a/src/easyshapes_app/Gui/ApplicationWindow.qml b/src/easyshapes_app/Gui/ApplicationWindow.qml index 57b54db..eb05838 100644 --- a/src/easyshapes_app/Gui/ApplicationWindow.qml +++ b/src/easyshapes_app/Gui/ApplicationWindow.qml @@ -5,9 +5,9 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents import Gui as Gui import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Analysis/Layout.qml b/src/easyshapes_app/Gui/Pages/Analysis/Layout.qml index 4c9d546..3315766 100644 --- a/src/easyshapes_app/Gui/Pages/Analysis/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/Analysis/Layout.qml @@ -5,10 +5,10 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Analysis/MainArea/Chart.qml b/src/easyshapes_app/Gui/Pages/Analysis/MainArea/Chart.qml index 4f8ce10..1d07269 100644 --- a/src/easyshapes_app/Gui/Pages/Analysis/MainArea/Chart.qml +++ b/src/easyshapes_app/Gui/Pages/Analysis/MainArea/Chart.qml @@ -5,8 +5,8 @@ import QtQuick import QtGraphs -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/GetStarted.qml b/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/GetStarted.qml index 7b73f23..a9d1be1 100644 --- a/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/GetStarted.qml +++ b/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/GetStarted.qml @@ -5,11 +5,11 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Layout.qml index e59ca3c..ea6ddaf 100644 --- a/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Layout.qml @@ -5,8 +5,8 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Home/Content.qml b/src/easyshapes_app/Gui/Pages/Home/Content.qml index e0b7a19..420851d 100644 --- a/src/easyshapes_app/Gui/Pages/Home/Content.qml +++ b/src/easyshapes_app/Gui/Pages/Home/Content.qml @@ -4,9 +4,9 @@ import QtQuick -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Home/Popups/About.qml b/src/easyshapes_app/Gui/Pages/Home/Popups/About.qml index 11815fd..c1af059 100644 --- a/src/easyshapes_app/Gui/Pages/Home/Popups/About.qml +++ b/src/easyshapes_app/Gui/Pages/Home/Popups/About.qml @@ -4,8 +4,8 @@ import QtQuick -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Project/Layout.qml b/src/easyshapes_app/Gui/Pages/Project/Layout.qml index 6ebbb95..f7c6116 100644 --- a/src/easyshapes_app/Gui/Pages/Project/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/Project/Layout.qml @@ -5,10 +5,10 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Project/MainArea/Description.qml b/src/easyshapes_app/Gui/Pages/Project/MainArea/Description.qml index 8ce72b2..eab134f 100644 --- a/src/easyshapes_app/Gui/Pages/Project/MainArea/Description.qml +++ b/src/easyshapes_app/Gui/Pages/Project/MainArea/Description.qml @@ -4,8 +4,8 @@ import QtQuick -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/Examples.qml b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/Examples.qml index 065031c..bfd3695 100644 --- a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/Examples.qml +++ b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/Examples.qml @@ -5,11 +5,11 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/GetStarted.qml b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/GetStarted.qml index cb1ab18..83e643d 100644 --- a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/GetStarted.qml +++ b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/GetStarted.qml @@ -6,11 +6,11 @@ import QtQuick import QtQuick.Controls //import QtQuick.Dialogs -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/Recent.qml b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/Recent.qml index 8357f95..e9158c1 100644 --- a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/Recent.qml +++ b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Groups/Recent.qml @@ -6,11 +6,11 @@ import QtQuick import QtQuick.Controls import QtCore -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Layout.qml index 23952b4..0cdbc68 100644 --- a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Layout.qml @@ -5,8 +5,8 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Popups/OpenCifFile.qml b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Popups/OpenCifFile.qml index 649bb8a..29580d6 100644 --- a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Popups/OpenCifFile.qml +++ b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Popups/OpenCifFile.qml @@ -6,8 +6,8 @@ import QtQuick import QtQuick.Controls import QtQuick.Dialogs -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Popups/ProjectDescription.qml b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Popups/ProjectDescription.qml index dcc2277..68d21c2 100644 --- a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Popups/ProjectDescription.qml +++ b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Basic/Popups/ProjectDescription.qml @@ -5,8 +5,8 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Extra/Groups/Scrolling.qml b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Extra/Groups/Scrolling.qml index 4bc8920..5521228 100644 --- a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Extra/Groups/Scrolling.qml +++ b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Extra/Groups/Scrolling.qml @@ -4,8 +4,8 @@ import QtQuick -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements Column { diff --git a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Extra/Layout.qml b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Extra/Layout.qml index 273d95a..fd00806 100644 --- a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Extra/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Extra/Layout.qml @@ -5,8 +5,8 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Text/Layout.qml b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Text/Layout.qml index 3c9c9d6..9c4629b 100644 --- a/src/easyshapes_app/Gui/Pages/Project/Sidebar/Text/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/Project/Sidebar/Text/Layout.qml @@ -4,8 +4,8 @@ import QtQuick -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents EaComponents.SideBarColumn {} diff --git a/src/easyshapes_app/Gui/Pages/Report/Layout.qml b/src/easyshapes_app/Gui/Pages/Report/Layout.qml index 3beddbd..6604f52 100644 --- a/src/easyshapes_app/Gui/Pages/Report/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/Report/Layout.qml @@ -5,10 +5,10 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Report/MainArea/Summary.qml b/src/easyshapes_app/Gui/Pages/Report/MainArea/Summary.qml index 0168ba3..8c1bcd4 100644 --- a/src/easyshapes_app/Gui/Pages/Report/MainArea/Summary.qml +++ b/src/easyshapes_app/Gui/Pages/Report/MainArea/Summary.qml @@ -5,9 +5,9 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Report/Sidebar/Basic/Groups/Export.qml b/src/easyshapes_app/Gui/Pages/Report/Sidebar/Basic/Groups/Export.qml index e80a6b4..7cc971b 100644 --- a/src/easyshapes_app/Gui/Pages/Report/Sidebar/Basic/Groups/Export.qml +++ b/src/easyshapes_app/Gui/Pages/Report/Sidebar/Basic/Groups/Export.qml @@ -7,10 +7,10 @@ import QtQuick.Controls import QtQuick.Dialogs import QtCore -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Report/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/Report/Sidebar/Basic/Layout.qml index 472d957..059d6de 100644 --- a/src/easyshapes_app/Gui/Pages/Report/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/Report/Sidebar/Basic/Layout.qml @@ -4,8 +4,8 @@ import QtQuick -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Report/Sidebar/Extra/Groups/Empty.qml b/src/easyshapes_app/Gui/Pages/Report/Sidebar/Extra/Groups/Empty.qml index 9f47804..4401fe7 100644 --- a/src/easyshapes_app/Gui/Pages/Report/Sidebar/Extra/Groups/Empty.qml +++ b/src/easyshapes_app/Gui/Pages/Report/Sidebar/Extra/Groups/Empty.qml @@ -4,8 +4,8 @@ import QtQuick -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements Column {} diff --git a/src/easyshapes_app/Gui/Pages/Report/Sidebar/Extra/Layout.qml b/src/easyshapes_app/Gui/Pages/Report/Sidebar/Extra/Layout.qml index ef2a2ed..7219c46 100644 --- a/src/easyshapes_app/Gui/Pages/Report/Sidebar/Extra/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/Report/Sidebar/Extra/Layout.qml @@ -5,8 +5,8 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Layout.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Layout.qml index ac5e6e4..193d1f9 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Layout.qml @@ -5,10 +5,10 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/MainArea/GraphsView.qml b/src/easyshapes_app/Gui/Pages/SampleModel/MainArea/GraphsView.qml index 9f2fd2d..276dfff 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/MainArea/GraphsView.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/MainArea/GraphsView.qml @@ -5,8 +5,8 @@ import QtQuick import QtGraphs -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml index e39f2df..eb17efb 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml @@ -5,8 +5,8 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Components as EaComponents EaComponents.ListView { defaultInfoText: qsTr("Missing components") diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml index 5c6b0c6..bc23d6f 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml @@ -6,11 +6,11 @@ import QtQuick import QtQuick.Controls //import QtQuick.Dialogs -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml index f2e5c14..af615cc 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml @@ -5,11 +5,11 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml index f2e5c14..af615cc 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml @@ -5,11 +5,11 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml index e81f1c9..65a20de 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml @@ -5,11 +5,11 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals @@ -24,14 +24,13 @@ EaElements.GroupColumn { multiSelection: false columnWidths: [ - EaStyle.Sizes.fontPixelSize * 2.5, - -1, - EaStyle.Sizes.fontPixelSize * 5, - EaStyle.Sizes.fontPixelSize * 5, - EaStyle.Sizes.fontPixelSize * 5, - EaStyle.Sizes.fontPixelSize * 5, - EaStyle.Sizes.tableRowHeight, - EaStyle.Sizes.tableRowHeight + EaStyle.Sizes.tableColumnAuto, // № + EaStyle.Sizes.tableColumnAuto, // Rmin, nm + EaStyle.Sizes.tableColumnAuto, // Inner Dmin, nm + EaStyle.Sizes.tableColumnAuto, // Outer Dmin, nm + EaStyle.Sizes.tableColumnAuto, // Shell thickness, nm + EaStyle.Sizes.tableColumnAuto, // Symmetric (checkbox) + EaStyle.Sizes.tableRowHeight // delete button ] header: EaComponents.ListViewHeader { @@ -39,27 +38,27 @@ EaElements.GroupColumn { text: qsTr("№") color: EaStyle.Colors.themeForegroundMinor } - EaComponents.TableViewLabel {} // filler EaComponents.TableViewLabel { - text: qsTr("Rmin") + text: qsTr("Rmin, nm") color: EaStyle.Colors.themeForegroundMinor } EaComponents.TableViewLabel { - text: qsTr("Inner Dmin") + text: qsTr("Inner Dmin, nm") color: EaStyle.Colors.themeForegroundMinor } EaComponents.TableViewLabel { - text: qsTr("Outer Dmin") + text: qsTr("Outer Dmin, nm") color: EaStyle.Colors.themeForegroundMinor } EaComponents.TableViewLabel { - text: qsTr("Shell") + text: qsTr("Shell thickness, nm") color: EaStyle.Colors.themeForegroundMinor } EaComponents.TableViewLabel { - text: qsTr("Sym") + text: qsTr("Symmetric") color: EaStyle.Colors.themeForegroundMinor } + EaComponents.TableViewLabel {} } model: ListModel { @@ -81,7 +80,6 @@ EaElements.GroupColumn { text: index + 1 enabled: false } - EaComponents.TableViewLabel {} // filler EaComponents.ListViewTextInput { text: rmin onEditingFinished: rmin = parseFloat(text) diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml index 1168ec9..6b8fc1a 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml @@ -5,11 +5,11 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals @@ -23,11 +23,11 @@ EaElements.GroupColumn { multiSelection: false columnWidths: [ - EaStyle.Sizes.fontPixelSize * 2.5, - -1, - EaStyle.Sizes.fontPixelSize * 6, - EaStyle.Sizes.fontPixelSize * 6, - EaStyle.Sizes.tableRowHeight + EaStyle.Sizes.tableColumnAuto, // № + EaStyle.Sizes.tableColumnFlex, // filler + EaStyle.Sizes.tableColumnAuto, // Dmin, nm + EaStyle.Sizes.tableColumnAuto, // Rmin, nm + EaStyle.Sizes.tableRowHeight // delete button ] header: EaComponents.ListViewHeader { @@ -37,13 +37,14 @@ EaElements.GroupColumn { } EaComponents.TableViewLabel {} // filler EaComponents.TableViewLabel { - text: qsTr("Dmin") + text: qsTr("Dmin, nm") color: EaStyle.Colors.themeForegroundMinor } EaComponents.TableViewLabel { - text: qsTr("Rmin") + text: qsTr("Rmin, nm") color: EaStyle.Colors.themeForegroundMinor } + EaComponents.TableViewLabel {} } model: ListModel { diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml index 157c34c..8816d91 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml @@ -6,11 +6,11 @@ import QtQuick import QtQuick.Controls //import QtQuick.Dialogs -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml index 1aa6780..75f4967 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml @@ -5,8 +5,8 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml index eee6a2c..6c0ac06 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml @@ -6,10 +6,10 @@ import QtQuick import QtQuick.Controls import QtQuick.Dialogs -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml index 8e91107..09d397a 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml @@ -6,10 +6,10 @@ import QtQuick import QtQuick.Controls import QtQuick.Dialogs -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml index b95b813..a666182 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml @@ -6,10 +6,10 @@ import QtQuick import QtQuick.Controls import QtQuick.Dialogs -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml index 19fdc0b..da29ecf 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml @@ -6,10 +6,10 @@ import QtQuick import QtQuick.Controls import QtQuick.Dialogs -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml index 7af31d7..4664933 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml @@ -6,8 +6,8 @@ import QtQuick import QtQuick.Controls import QtQuick.Dialogs -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/Layout.qml b/src/easyshapes_app/Gui/Pages/Toolbox/Layout.qml index 360aa6f..cec9465 100644 --- a/src/easyshapes_app/Gui/Pages/Toolbox/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/Toolbox/Layout.qml @@ -5,10 +5,10 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/GraphsView.qml b/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/GraphsView.qml index 9f2fd2d..276dfff 100644 --- a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/GraphsView.qml +++ b/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/GraphsView.qml @@ -5,8 +5,8 @@ import QtQuick import QtGraphs -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/Image.qml b/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/Image.qml index fa89bc8..045b3c7 100644 --- a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/Image.qml +++ b/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/Image.qml @@ -5,8 +5,8 @@ import QtQuick import QtGraphs -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaPlain.qml b/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaPlain.qml index 9d1b2e8..8adbf68 100644 --- a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaPlain.qml +++ b/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaPlain.qml @@ -5,8 +5,8 @@ import QtQuick import QtGraphs -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaRich.qml b/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaRich.qml index 7a04f57..377af9f 100644 --- a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaRich.qml +++ b/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaRich.qml @@ -5,8 +5,8 @@ import QtQuick import QtGraphs -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group1.qml b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group1.qml index f177a50..6fd6687 100644 --- a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group1.qml +++ b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group1.qml @@ -5,11 +5,11 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group2.qml b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group2.qml index 585ee24..04299dd 100644 --- a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group2.qml +++ b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group2.qml @@ -5,11 +5,11 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group3.qml b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group3.qml index f57f027..b32087f 100644 --- a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group3.qml +++ b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group3.qml @@ -5,11 +5,11 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group4.qml b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group4.qml index a3d5b92..42e891f 100644 --- a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group4.qml +++ b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group4.qml @@ -5,11 +5,11 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Logic as EaLogic import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Layout.qml index 5e16781..ad4c6ca 100644 --- a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Layout.qml @@ -5,8 +5,8 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/Gui/StatusBar.qml b/src/easyshapes_app/Gui/StatusBar.qml index 2bd91f9..8f1b73a 100644 --- a/src/easyshapes_app/Gui/StatusBar.qml +++ b/src/easyshapes_app/Gui/StatusBar.qml @@ -5,9 +5,9 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents import Gui.Globals as Globals diff --git a/src/easyshapes_app/test.qml b/src/easyshapes_app/test.qml index 1905bb0..6f03656 100644 --- a/src/easyshapes_app/test.qml +++ b/src/easyshapes_app/test.qml @@ -6,10 +6,10 @@ import QtQuick import QtQuick.Controls import QtQuick.Dialogs -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements import Qt.labs.qmlmodels import Gui.Globals as Globals @@ -55,7 +55,7 @@ ApplicationWindow{ icon: 'wrench' collapsed: false - Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml'} + Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml'} } EaComponents.ListView { diff --git a/src/easyshapes_app/test2.qml b/src/easyshapes_app/test2.qml index 82de25c..4468ba5 100644 --- a/src/easyshapes_app/test2.qml +++ b/src/easyshapes_app/test2.qml @@ -6,10 +6,10 @@ import QtQuick import QtQuick.Controls import QtQuick.Dialogs -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Components as EaComponents -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements import Qt.labs.qmlmodels import Gui.Globals as Globals From d2f8c81162224a34ee06724b5eae12efb3156bbb Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Fri, 1 May 2026 12:04:49 +0200 Subject: [PATCH 16/23] separate columns for fractions groups in lamella --- .../Sidebar/Basic/Components/Fractions.qml | 2 +- .../Sidebar/Basic/Groups/Lamellae.qml | 49 +++++++++++-------- src/easyshapes_app/test.qml | 2 +- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml index eb17efb..3bec9d2 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml @@ -30,7 +30,7 @@ EaComponents.ListView { color: EaStyle.Colors.themeForegroundMinor } EaComponents.TableViewLabel { - text: qsTr("Molar ratio") + text: qsTr("Mole ratio") color: EaStyle.Colors.themeForegroundMinor } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml index 65a20de..966bdc8 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml @@ -43,11 +43,11 @@ EaElements.GroupColumn { color: EaStyle.Colors.themeForegroundMinor } EaComponents.TableViewLabel { - text: qsTr("Inner Dmin, nm") + text: qsTr("Inner dmin, nm") color: EaStyle.Colors.themeForegroundMinor } EaComponents.TableViewLabel { - text: qsTr("Outer Dmin, nm") + text: qsTr("Outer dmin, nm") color: EaStyle.Colors.themeForegroundMinor } EaComponents.TableViewLabel { @@ -63,7 +63,7 @@ EaElements.GroupColumn { model: ListModel { id: lamellaeModel - ListElement { rmin: 0.5; innerDmin: 0.25; outerDmin: 0.25; shell: 0.5; symmetric: true } + ListElement { rmin: 0.5; innerDmin: 0.25; outerDmin: 0.3; shell: 0.5; symmetric: true } } delegateModelAccess: DelegateModel.ReadWrite @@ -91,8 +91,7 @@ EaElements.GroupColumn { validator: DoubleValidator { bottom: 0.25 } } EaComponents.ListViewTextInput { - text: symmetric ? innerDmin : outerDmin - enabled: !symmetric + text: outerDmin onEditingFinished: outerDmin = parseFloat(text) validator: DoubleValidator { bottom: 0.25 } } @@ -125,7 +124,7 @@ EaElements.GroupColumn { fontIcon: "plus-circle" text: qsTr("Add lamella") width: buttonWidth - onClicked: lamellaeModel.append({ rmin: 0.5, innerDmin: 0.25, outerDmin: 0.25, shell: 0.5, symmetric: true }) + onClicked: lamellaeModel.append({ rmin: 0.5, innerDmin: 0.25, outerDmin: 0.3, shell: 0.5, symmetric: true }) } } @@ -133,28 +132,36 @@ EaElements.GroupColumn { id: fractionsSection visible: lamellae.selectedIndexes.length > 0 width: parent.width + spacing: EaStyle.Sizes.groupBoxSpacing readonly property int selectedRow: lamellae.selectedIndexes.length > 0 ? lamellae.selectedIndexes[0].row : -1 readonly property bool selectedSymmetric: selectedRow >= 0 && lamellaeModel.get(selectedRow).symmetric - EaElements.Label { - enabled: false - text: fractionsSection.selectedSymmetric - ? qsTr("Lamella %1 Leaflet Fractions").arg(fractionsSection.selectedRow + 1) - : qsTr("Lamella %1 Inner Leaflet Fractions").arg(fractionsSection.selectedRow + 1) - } - Local.Fractions { - id: innerFractions - } + Column { + width: parent.width - EaElements.Label { - visible: !fractionsSection.selectedSymmetric - enabled: false - text: qsTr("Lamella %1 Outer Leaflet Fractions").arg(fractionsSection.selectedRow + 1) + EaElements.Label { + enabled: false + text: fractionsSection.selectedSymmetric + ? qsTr("Lamella %1 Fractions").arg(fractionsSection.selectedRow + 1) + : qsTr("Lamella %1 Inner Leaflet Fractions").arg(fractionsSection.selectedRow + 1) + } + Local.Fractions { + id: innerFractions + } } - Local.Fractions { - id: outerFractions + + Column { + width: parent.width visible: !fractionsSection.selectedSymmetric + + EaElements.Label { + enabled: false + text: qsTr("Lamella %1 Outer Leaflet Fractions").arg(fractionsSection.selectedRow + 1) + } + Local.Fractions { + id: outerFractions + } } } } diff --git a/src/easyshapes_app/test.qml b/src/easyshapes_app/test.qml index 6f03656..8f55d2d 100644 --- a/src/easyshapes_app/test.qml +++ b/src/easyshapes_app/test.qml @@ -55,7 +55,7 @@ ApplicationWindow{ icon: 'wrench' collapsed: false - Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml'} + Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml'} } EaComponents.ListView { From 23c4765d68b020c37fb210ea43e66aaaebe53e34 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Mon, 4 May 2026 16:17:49 +0200 Subject: [PATCH 17/23] Transfering the sample model's model to mock qml backend --- src/easyshapes_app.qrc | 1 + src/easyshapes_app/Backends/MockBackend.qml | 1 + .../Backends/MockQml/SampleModel.qml | 78 +++++++++++++++++++ src/easyshapes_app/Backends/MockQml/qmldir | 1 + .../Gui/Globals/BackendWrapper.qml | 18 +++++ .../Sidebar/Basic/Groups/SampleModel.qml | 39 ++++------ .../SampleModel/Sidebar/Basic/Layout.qml | 4 +- .../Sidebar/Basic/Popups/CreateNewModel.qml | 16 ++-- .../Basic/Popups/LoadExistingModel.qml | 27 ++----- 9 files changed, 126 insertions(+), 59 deletions(-) create mode 100644 src/easyshapes_app/Backends/MockQml/SampleModel.qml diff --git a/src/easyshapes_app.qrc b/src/easyshapes_app.qrc index 525180b..dc88980 100644 --- a/src/easyshapes_app.qrc +++ b/src/easyshapes_app.qrc @@ -6,6 +6,7 @@ easyshapes_app/Backends/MockQml/Project.qml easyshapes_app/Backends/MockQml/qmldir easyshapes_app/Backends/MockQml/Report.qml + easyshapes_app/Backends/MockQml/SampleModel.qml easyshapes_app/Backends/MockQml/Status.qml easyshapes_app/Backends/qmldir easyshapes_app/Gui/ApplicationWindow.qml diff --git a/src/easyshapes_app/Backends/MockBackend.qml b/src/easyshapes_app/Backends/MockBackend.qml index f911028..a83c9a1 100644 --- a/src/easyshapes_app/Backends/MockBackend.qml +++ b/src/easyshapes_app/Backends/MockBackend.qml @@ -12,6 +12,7 @@ import Backends.MockQml as MockLogic QtObject { property var project: MockLogic.Project + property var sampleModel: MockLogic.SampleModel property var analysis: MockLogic.Analysis property var status: MockLogic.Status property var report: MockLogic.Report diff --git a/src/easyshapes_app/Backends/MockQml/SampleModel.qml b/src/easyshapes_app/Backends/MockQml/SampleModel.qml new file mode 100644 index 0000000..9ba09d1 --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/SampleModel.qml @@ -0,0 +1,78 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + +QtObject { + + property bool created: false + + // Loaded sample model — JS array of length 0 or 1. + // Capacity is one by convention (single record), but the value is + // exposed as an array so QML ListView can consume it directly + // (Qt 6 ListView only supports int / ListModel / QAbstractItemModel / JS array). + // Element shape: { name, structure_type, description } + property var loaded: [] + + readonly property var structureTypes: [ + 'Ring', 'Ball', 'Vesicle', 'Rod', 'Bilayer', 'Monolayer', 'Lattice' + ] + + readonly property string currentStructureType: loaded.length > 0 ? loaded[0].structure_type : '' + + // Catalog of saveable/loadable models (asset library). + // ListModel mirrors the Python QAbstractListModel with roles + // (name, structure_type, description) so delegate code is identical + // for both real and mock backends, and ItemSelectionModel works. + readonly property var availableModels: ListModel { + ListElement { name: 'Samle1_aluv'; structure_type: 'Vesicle'; description: 'In order to avoid a prolonged pro-inflammatory neutrophil response, signaling downstream of an agonist-activated G protein-coupled receptor (GPCR) has to be rapidly terminated. Among the family of GPCR kinases (GRKs) that regulate receptor phosphorylation and signaling termination, GRK2, which is highly expressed by immune cells, plays an important role.' } + ListElement { name: 'Sample2_nanodisc'; structure_type: 'Ring'; description: 'The medium chain fatty acid receptor GPR84 as well as formyl peptide receptor 2 (FPR2)' } + ListElement { name: 'Sample3_cubosome'; structure_type: 'Lattice'; description: 'receptors expressed in neutrophils, play a key role in regulating inflammation. In this study, we investigated the effects of GRK2 inhibitors on neutrophil functions induced by GPR84 and FPR2 agonists.' } + ListElement { name: 'Sample4'; structure_type: 'Ring'; description: 'GRK2 was shown to be expressed in human neutrophils and analysis of subcellular fractions' } + ListElement { name: 'Sample5'; structure_type: 'Ball'; description: 'revealed a cytosolic localization. The GRK2 inhibitors enhanced and prolonged neutrophil production ' } + ListElement { name: 'Sample6'; structure_type: 'Vesicle'; description: 'production of reactive oxygen species (ROS) induced by GPR84- but not FPR2-agonists' } + ListElement { name: 'Sample7'; structure_type: 'Rod'; description: 'suggesting a receptor selective function of GRK2. This suggestion was supported by β-arrestin recruitment data. The ROS production induced by a non β-arrestin recruiting GPR84' } + ListElement { name: 'Sample8'; structure_type: 'Bilayer'; description: 'This suggestion was supported by β-arrestin recruitment data. The ROS production induced by a non β-arrestin recruiting GPR84 agonist was not affected by the GRK2 inhibitor.' } + ListElement { name: 'Sample9'; structure_type: 'Monolayer'; description: 'Termination of this β-arrestin independent response relied, similar to the response induced by FPR2 agonists, primarily on the actin cytoskeleton.' } + ListElement { name: 'Samplewithareallylongname'; structure_type: 'Lattice'; description: 'In summary, we show that GPR84 utilizes GRK2 in concert with β-arrestin and actin cytoskeleton dependent processes to fine-tune the activity of the ROS generating NADPH-oxidase in neutrophils.' } + } + + function setLoaded(model) { + console.debug(`Loading sample model '${model.name}'`) + loaded = [{ + name: model.name, + structure_type: model.structure_type, + description: model.description + }] + created = true + } + + function updateField(field, value) { + if (loaded.length === 0) return + loaded[0][field] = value + } + + function clear() { + loaded = [] + created = false + } + + function saveToCatalog() { + if (loaded.length === 0 || !loaded[0].name) return + availableModels.append({ + name: loaded[0].name, + structure_type: loaded[0].structure_type, + description: loaded[0].description + }) + console.debug(`Saved sample model '${loaded[0].name}' to catalog`) + } + + function removeFromCatalog(index) { + if (index < 0 || index >= availableModels.count) return + availableModels.remove(index) + } + +} diff --git a/src/easyshapes_app/Backends/MockQml/qmldir b/src/easyshapes_app/Backends/MockQml/qmldir index 7ee148e..5f3167d 100644 --- a/src/easyshapes_app/Backends/MockQml/qmldir +++ b/src/easyshapes_app/Backends/MockQml/qmldir @@ -1,6 +1,7 @@ module MockQml singleton Project Project.qml +singleton SampleModel SampleModel.qml singleton Analysis Analysis.qml singleton Report Report.qml singleton Status Status.qml diff --git a/src/easyshapes_app/Gui/Globals/BackendWrapper.qml b/src/easyshapes_app/Gui/Globals/BackendWrapper.qml index e8529b3..4fd1950 100644 --- a/src/easyshapes_app/Gui/Globals/BackendWrapper.qml +++ b/src/easyshapes_app/Gui/Globals/BackendWrapper.qml @@ -56,6 +56,24 @@ QtObject { function projectSave() { activeBackend.project.save() } function projectEditInfo(path, new_value) { activeBackend.project.editInfo(path, new_value) } + //////////////////// + // Sample Model page + //////////////////// + + readonly property var sampleModelLoaded: activeBackend.sampleModel.loaded + readonly property var sampleModelAvailable: activeBackend.sampleModel.availableModels + readonly property var sampleModelStructureTypes: activeBackend.sampleModel.structureTypes + readonly property string sampleModelCurrentStructureType: activeBackend.sampleModel.currentStructureType + + property bool sampleModelCreated: activeBackend.sampleModel.created + onSampleModelCreatedChanged: activeBackend.sampleModel.created = sampleModelCreated + + function sampleModelSetLoaded(model) { activeBackend.sampleModel.setLoaded(model) } + function sampleModelUpdateField(field, value) { activeBackend.sampleModel.updateField(field, value) } + function sampleModelClear() { activeBackend.sampleModel.clear() } + function sampleModelSaveToCatalog() { activeBackend.sampleModel.saveToCatalog() } + function sampleModelRemoveFromCatalog(index) { activeBackend.sampleModel.removeFromCatalog(index) } + //////////////// // Analysis page //////////////// diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml index 8816d91..3aa2999 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml @@ -4,7 +4,6 @@ import QtQuick import QtQuick.Controls -//import QtQuick.Dialogs import EasyApplication.Gui.Globals as EaGlobals import EasyApplication.Gui.Style as EaStyle @@ -17,7 +16,6 @@ import Gui.Globals as Globals EaElements.GroupColumn { id: root property double buttonWidth: EaStyle.Sizes.sideBarContentWidth * 0.3164 - property string currentStructureType: "" Component.onCompleted: Globals.References.pages.samplemodel.sidebar.basic.groups.sampleModel = root @@ -47,36 +45,28 @@ EaElements.GroupColumn { } } - model: ListModel { - id: loadedSambleModelsModel - onCountChanged: root.currentStructureType = count > 0 ? get(0).structure_type : "" - } - - delegateModelAccess: DelegateModel.ReadWrite + model: Globals.BackendWrapper.sampleModelLoaded delegate: EaComponents.ListViewDelegate { + required property var modelData required property int index - required property string name - required property string structure_type - required property string description EaComponents.ListViewTextInput { - text: name - onEditingFinished: name = text + text: modelData ? modelData.name : '' + onEditingFinished: Globals.BackendWrapper.sampleModelUpdateField('name', text) } - EaComponents.TableViewComboBox{ - model: [qsTr("Ring"), qsTr("Ball"), qsTr("Vesicle"), qsTr("Rod"), qsTr("Bilayer"), qsTr("Monolayer"), qsTr("Lattice")] + EaComponents.TableViewComboBox { + model: Globals.BackendWrapper.sampleModelStructureTypes Component.onCompleted: { - currentIndex = model.indexOf(structure_type) + currentIndex = model.indexOf(modelData.structure_type) } - onActivated: (index) => { - structure_type = model[index] - root.currentStructureType = model[index] + onActivated: (i) => { + Globals.BackendWrapper.sampleModelUpdateField('structure_type', model[i]) } } EaComponents.ListViewTextInput { - text: description - onEditingFinished: description = text + text: modelData ? modelData.description : '' + onEditingFinished: Globals.BackendWrapper.sampleModelUpdateField('description', text) } } } @@ -103,21 +93,20 @@ EaElements.GroupColumn { fontIcon: "download" text: qsTr("Save model") width: buttonWidth - enabled: loadedSampleModel.model && loadedSampleModel.model.count > 0 && loadedSambleModelsModel.get(0).name !== "" - onClicked: loadExistingModelLoader.item.availableModelsModel.append(loadedSambleModelsModel.get(0)) + enabled: Globals.BackendWrapper.sampleModelLoaded.length > 0 + && Globals.BackendWrapper.sampleModelLoaded[0].name !== "" + onClicked: Globals.BackendWrapper.sampleModelSaveToCatalog() } } Loader { id: loadExistingModelLoader source: '../Popups/LoadExistingModel.qml' - onLoaded: item.targetModel = loadedSambleModelsModel } Loader { id: createNewModelLoader source: '../Popups/CreateNewModel.qml' - onLoaded: item.targetModel = loadedSambleModelsModel } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml index 75f4967..3f61d10 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml @@ -31,7 +31,7 @@ EaComponents.SideBarColumn { EaElements.GroupBox { title: qsTr('Layers') icon: 'layer-group' // 'grip-lines' - visible: sampleModelLoader.item ? sampleModelLoader.item.currentStructureType === 'Ball' : false + visible: Globals.BackendWrapper.sampleModelCurrentStructureType === 'Ball' Loader { source: 'Groups/Layers.qml' } } @@ -39,7 +39,7 @@ EaComponents.SideBarColumn { EaElements.GroupBox { title: qsTr('Lamellae') icon: 'layer-group' - visible: sampleModelLoader.item ? sampleModelLoader.item.currentStructureType === 'Vesicle' : false + visible: Globals.BackendWrapper.sampleModelCurrentStructureType === 'Vesicle' Loader { source: 'Groups/Lamellae.qml' } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml index 09d397a..39a6fe4 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml @@ -17,21 +17,17 @@ import Gui.Globals as Globals EaElements.Dialog{ id: sampleModelCreationDialog - property var targetModel property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 title: qsTr("Create a new Sample Model") standardButtons: Dialog.Ok | Dialog.Cancel onAccepted: { - targetModel.clear() - targetModel.append( - { - name: sampleModelNameField.text, - structure_type: sampleModelTypeField.currentText, - description: sampleModelDescrField.text - } - ) + Globals.BackendWrapper.sampleModelSetLoaded({ + name: sampleModelNameField.text, + structure_type: sampleModelTypeField.currentText, + description: sampleModelDescrField.text + }) } Column { @@ -63,7 +59,7 @@ EaElements.Dialog{ EaElements.ComboBox { id: sampleModelTypeField implicitWidth: (sampleModelCreationDialog.inputFieldWidth - nameTypeRow.spacing) / 2 - model: [qsTr("Ring"), qsTr("Ball"), qsTr("Vesicle"), qsTr("Rod"), qsTr("Bilayer"), qsTr("Monolayer"), qsTr("Lattice")] + model: Globals.BackendWrapper.sampleModelStructureTypes } } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml index da29ecf..73e8542 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml @@ -18,9 +18,7 @@ import Gui.Globals as Globals EaElements.Dialog{ id: sampleModelLoadDialog - property var targetModel property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 - property alias availableModelsModel: availableSambleModelsModel title: qsTr("Load a Sample Model from the Asset Library") standardButtons: Dialog.Ok | Dialog.Cancel @@ -30,10 +28,8 @@ EaElements.Dialog{ if (indexes.length > 0) { var row = indexes[0].row - var item = availableSambleModelsModel.get(row) - - targetModel.clear() - targetModel.append(item) + var item = Globals.BackendWrapper.sampleModelAvailable.get(row) + Globals.BackendWrapper.sampleModelSetLoaded(item) loadModelListView.clearSelection() } } @@ -76,23 +72,10 @@ EaElements.Dialog{ text: qsTr("Description") color: EaStyle.Colors.themeForegroundMinor } + EaComponents.TableViewLabel {} // filler } - model: ListModel { - id: availableSambleModelsModel - ListElement { name: "Samle1_aluv"; structure_type: "Vesicle"; description: "In order to avoid a prolonged pro-inflammatory neutrophil response, signaling downstream of an agonist-activated G protein-coupled receptor (GPCR) has to be rapidly terminated. Among the family of GPCR kinases (GRKs) that regulate receptor phosphorylation and signaling termination, GRK2, which is highly expressed by immune cells, plays an important role." } - ListElement { name: "Sample2_nanodisc"; structure_type: "Ring"; description: "The medium chain fatty acid receptor GPR84 as well as formyl peptide receptor 2 (FPR2)" } - ListElement { name: "Sample3_cubosome"; structure_type: "Lattice"; description: "receptors expressed in neutrophils, play a key role in regulating inflammation. In this study, we investigated the effects of GRK2 inhibitors on neutrophil functions induced by GPR84 and FPR2 agonists." } - ListElement { name: "Sample4"; structure_type: "Ring"; description: "GRK2 was shown to be expressed in human neutrophils and analysis of subcellular fractions" } - ListElement { name: "Sample5"; structure_type: "Ball"; description: "revealed a cytosolic localization. The GRK2 inhibitors enhanced and prolonged neutrophil production " } - ListElement { name: "Sample6"; structure_type: "Vesicle"; description: "production of reactive oxygen species (ROS) induced by GPR84- but not FPR2-agonists" } - ListElement { name: "Sample7"; structure_type: "Rod"; description: "suggesting a receptor selective function of GRK2. This suggestion was supported by β-arrestin recruitment data. The ROS production induced by a non β-arrestin recruiting GPR84" } - ListElement { name: "Sample8"; structure_type: "Bilayer"; description: "This suggestion was supported by β-arrestin recruitment data. The ROS production induced by a non β-arrestin recruiting GPR84 agonist was not affected by the GRK2 inhibitor." } - ListElement { name: "Sample9"; structure_type: "Monolayer"; description: "Termination of this β-arrestin independent response relied, similar to the response induced by FPR2 agonists, primarily on the actin cytoskeleton." } - ListElement { name: "Samplewithareallylongname"; structure_type: "Lattice"; description: "In summary, we show that GPR84 utilizes GRK2 in concert with β-arrestin and actin cytoskeleton dependent processes to fine-tune the activity of the ROS generating NADPH-oxidase in neutrophils." } - } - - delegateModelAccess: DelegateModel.ReadOnly + model: Globals.BackendWrapper.sampleModelAvailable delegate: EaComponents.ListViewDelegate { required property int index @@ -117,7 +100,7 @@ EaElements.Dialog{ EaComponents.TableViewButton { fontIcon: "minus-circle" ToolTip.text: qsTr("Remove this component") - onClicked: availableSambleModelsModel.remove(index) + onClicked: Globals.BackendWrapper.sampleModelRemoveFromCatalog(index) } } } From 2e0b32ee28bb6dd8dddf8879ce7704146c0658a0 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Wed, 6 May 2026 16:28:45 +0200 Subject: [PATCH 18/23] Added structure definition groups --- src/easyshapes_app.qrc | 20 ++ src/easyshapes_app/Backends/MockBackend.qml | 31 +++ .../Backends/MockQml/BallStructure.qml | 14 ++ .../Backends/MockQml/BilayerStructure.qml | 14 ++ .../Backends/MockQml/Components.qml | 58 ++++++ .../Backends/MockQml/Fractions.qml | 69 +++++++ .../Backends/MockQml/Lamellae.qml | 136 ++++++++++++++ .../Backends/MockQml/LatticeStructure.qml | 69 +++++++ .../Backends/MockQml/Layers.qml | 91 +++++++++ .../Backends/MockQml/MonolayerStructure.qml | 14 ++ .../Backends/MockQml/RingStructure.qml | 17 ++ .../Backends/MockQml/RodStructure.qml | 16 ++ .../Backends/MockQml/SampleModel.qml | 9 +- .../Backends/MockQml/VesicleStructure.qml | 14 ++ src/easyshapes_app/Backends/MockQml/qmldir | 11 ++ .../Gui/Globals/BackendWrapper.qml | 100 +++++++++- .../Sidebar/Basic/Components/Fractions.qml | 13 +- .../Sidebar/Basic/Groups/BallStructure.qml | 51 +++++ .../Sidebar/Basic/Groups/BilayerStructure.qml | 60 ++++++ .../Sidebar/Basic/Groups/Components.qml | 16 +- .../Sidebar/Basic/Groups/Lamellae.qml | 43 +++-- .../Sidebar/Basic/Groups/LatticeStructure.qml | 177 ++++++++++++++++++ .../Sidebar/Basic/Groups/Layers.qml | 30 +-- .../Basic/Groups/MonolayerStructure.qml | 60 ++++++ .../Sidebar/Basic/Groups/RingStructure.qml | 89 +++++++++ .../Sidebar/Basic/Groups/RodStructure.qml | 79 ++++++++ .../Sidebar/Basic/Groups/VesicleStructure.qml | 51 +++++ .../SampleModel/Sidebar/Basic/Layout.qml | 56 ++++++ .../Basic/Popups/CreateNewComponent.qml | 12 +- .../Basic/Popups/CreateNewSubstructure.qml | 119 ++++++++++++ .../Basic/Popups/LoadExistingComponent.qml | 3 +- .../Basic/Popups/LoadExistingSubstructure.qml | 107 +++++++++++ .../Sidebar/Basic/Popups/OpenAssetFile.qml | 4 +- src/easyshapes_app/test.qml | 86 +-------- 34 files changed, 1606 insertions(+), 133 deletions(-) create mode 100644 src/easyshapes_app/Backends/MockQml/BallStructure.qml create mode 100644 src/easyshapes_app/Backends/MockQml/BilayerStructure.qml create mode 100644 src/easyshapes_app/Backends/MockQml/Components.qml create mode 100644 src/easyshapes_app/Backends/MockQml/Fractions.qml create mode 100644 src/easyshapes_app/Backends/MockQml/Lamellae.qml create mode 100644 src/easyshapes_app/Backends/MockQml/LatticeStructure.qml create mode 100644 src/easyshapes_app/Backends/MockQml/Layers.qml create mode 100644 src/easyshapes_app/Backends/MockQml/MonolayerStructure.qml create mode 100644 src/easyshapes_app/Backends/MockQml/RingStructure.qml create mode 100644 src/easyshapes_app/Backends/MockQml/RodStructure.qml create mode 100644 src/easyshapes_app/Backends/MockQml/VesicleStructure.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/BallStructure.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/BilayerStructure.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/MonolayerStructure.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/RingStructure.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/RodStructure.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/VesicleStructure.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewSubstructure.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingSubstructure.qml diff --git a/src/easyshapes_app.qrc b/src/easyshapes_app.qrc index dc88980..41fbf8a 100644 --- a/src/easyshapes_app.qrc +++ b/src/easyshapes_app.qrc @@ -3,11 +3,22 @@ easyshapes_app.qmlproject easyshapes_app/Backends/MockBackend.qml easyshapes_app/Backends/MockQml/Analysis.qml + easyshapes_app/Backends/MockQml/BallStructure.qml + easyshapes_app/Backends/MockQml/BilayerStructure.qml + easyshapes_app/Backends/MockQml/Components.qml + easyshapes_app/Backends/MockQml/Fractions.qml + easyshapes_app/Backends/MockQml/Lamellae.qml + easyshapes_app/Backends/MockQml/LatticeStructure.qml + easyshapes_app/Backends/MockQml/Layers.qml + easyshapes_app/Backends/MockQml/MonolayerStructure.qml easyshapes_app/Backends/MockQml/Project.qml easyshapes_app/Backends/MockQml/qmldir easyshapes_app/Backends/MockQml/Report.qml + easyshapes_app/Backends/MockQml/RingStructure.qml + easyshapes_app/Backends/MockQml/RodStructure.qml easyshapes_app/Backends/MockQml/SampleModel.qml easyshapes_app/Backends/MockQml/Status.qml + easyshapes_app/Backends/MockQml/VesicleStructure.qml easyshapes_app/Backends/qmldir easyshapes_app/Gui/ApplicationWindow.qml easyshapes_app/Gui/Globals/ApplicationInfo.qml @@ -40,17 +51,26 @@ easyshapes_app/Gui/Pages/SampleModel/Layout.qml easyshapes_app/Gui/Pages/SampleModel/MainArea/GraphsView.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/BallStructure.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/BilayerStructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/MonolayerStructure.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/RingStructure.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/RodStructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/VesicleStructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewSubstructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingSubstructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml easyshapes_app/Gui/Pages/Toolbox/Layout.qml easyshapes_app/Gui/Pages/Toolbox/MainArea/GraphsView.qml diff --git a/src/easyshapes_app/Backends/MockBackend.qml b/src/easyshapes_app/Backends/MockBackend.qml index a83c9a1..c994427 100644 --- a/src/easyshapes_app/Backends/MockBackend.qml +++ b/src/easyshapes_app/Backends/MockBackend.qml @@ -13,8 +13,39 @@ QtObject { property var project: MockLogic.Project property var sampleModel: MockLogic.SampleModel + property var components: MockLogic.Components + // Default fractions set tied to the shared component list. + // Used as the fallback for the Fractions sidebar component when no + // per-row override is set. + property var fractions: MockLogic.Fractions { source: MockLogic.Components.loaded } + // Layers owns one Fractions instance per layer (per-row state) and + // shares the same component source so names stay in sync with the + // global components list. + property var layers: MockLogic.Layers + // Lamellae owns distinct inner/outer Fractions instances per lamella. + property var lamellae: MockLogic.Lamellae + // Ring structure parameters (single record, edited inline). + property var ringStructure: MockLogic.RingStructure + // Ball structure parameters (single record, edited inline). + property var ballStructure: MockLogic.BallStructure + // Vesicle structure parameters (single record, edited inline). + property var vesicleStructure: MockLogic.VesicleStructure + // Rod structure parameters (single record, edited inline). + property var rodStructure: MockLogic.RodStructure + // Bilayer structure parameters (single record, edited inline). + property var bilayerStructure: MockLogic.BilayerStructure + // Monolayer structure parameters (single record, edited inline). + property var monolayerStructure: MockLogic.MonolayerStructure + // Lattice structure parameters (single record, edited inline) plus a + // single-record substructure with its own asset library. + property var latticeStructure: MockLogic.LatticeStructure property var analysis: MockLogic.Analysis property var status: MockLogic.Status property var report: MockLogic.Report + Component.onCompleted: { + layers.fractionsSource = MockLogic.Components.loaded + lamellae.fractionsSource = MockLogic.Components.loaded + } + } diff --git a/src/easyshapes_app/Backends/MockQml/BallStructure.qml b/src/easyshapes_app/Backends/MockQml/BallStructure.qml new file mode 100644 index 0000000..8b89830 --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/BallStructure.qml @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +QtObject { + property bool fxz: false + property bool rev: false + property string fill: 'FIBO' +} diff --git a/src/easyshapes_app/Backends/MockQml/BilayerStructure.qml b/src/easyshapes_app/Backends/MockQml/BilayerStructure.qml new file mode 100644 index 0000000..c4dd28c --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/BilayerStructure.qml @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +QtObject { + property double zsep: 0.0 + property int nside: 1 + property double dmin: 0.5 +} diff --git a/src/easyshapes_app/Backends/MockQml/Components.qml b/src/easyshapes_app/Backends/MockQml/Components.qml new file mode 100644 index 0000000..d75cfdb --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/Components.qml @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + +QtObject { + + // Working set of components currently loaded into the sample model. + // ListModel (not JS array) so EaComponents.ListView's ItemSelectionModel + // can drive Ctrl/Shift multi-selection, and so role-based delegate + // properties (`required property string name` etc.) bind correctly. + // Roles: name, component_type, atoms, mint, mext. + readonly property var loaded: ListModel { + id: loadedComponentsModel + } + + // File paths staged while creating a new component. + // Roles: path. + readonly property var pendingFilePaths: ListModel { + id: pendingFilePathsModel + } + + function appendItem(item) { + loadedComponentsModel.append({ + name: item.name, + component_type: item.component_type, + atoms: item.atoms, + mint: item.mint, + mext: item.mext + }) + } + + function removeItem(index) { + if (index < 0 || index >= loadedComponentsModel.count) return + loadedComponentsModel.remove(index) + } + + function clear() { + loadedComponentsModel.clear() + } + + function appendPendingFilePath(path) { + pendingFilePathsModel.append({ path: path }) + } + + function removePendingFilePath(index) { + if (index < 0 || index >= pendingFilePathsModel.count) return + pendingFilePathsModel.remove(index) + } + + function clearPendingFilePaths() { + pendingFilePathsModel.clear() + } + +} diff --git a/src/easyshapes_app/Backends/MockQml/Fractions.qml b/src/easyshapes_app/Backends/MockQml/Fractions.qml new file mode 100644 index 0000000..2daaef2 --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/Fractions.qml @@ -0,0 +1,69 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick + + +// Fractions backend object — instantiable, NOT a singleton. +// One instance per layer/lamella. Tracks the shared component list via +// `source` and adds per-instance `fracs` / `present` state. Sync between +// `source` and the exposed `model` is owned here so GUI consumers only +// bind `model` and read/write roles via DelegateModel.ReadWrite. +QtObject { + id: root + + // Source list of components this fractions set tracks. + // Typically `MockLogic.Components.loaded`. May be reassigned. + property var source: null + + // ListModel exposed to the GUI ListView. + // Roles: name (mirrored from source), fracs (per-instance), + // present (per-instance). + readonly property var model: ListModel { id: backing } + + Component.onCompleted: rebuild() + onSourceChanged: rebuild() + + // Internal sync. Surgical inserts/removes preserve the per-instance + // fracs/present state of unaffected rows; full rebuild only on reset + // or source reassignment. + property var __sync: Connections { + target: root.source + + function onRowsInserted(parent, first, last) { + for (let i = first; i <= last; ++i) { + const c = root.source.get(i) + backing.insert(i, { name: c.name, fracs: 100, present: true }) + } + } + function onRowsRemoved(parent, first, last) { + for (let i = last; i >= first; --i) backing.remove(i) + } + function onDataChanged(topLeft, bottomRight, roles) { + for (let i = topLeft.row; i <= bottomRight.row; ++i) { + backing.setProperty(i, 'name', root.source.get(i).name) + } + } + function onModelReset() { root.rebuild() } + } + + function rebuild() { + backing.clear() + if (!source) return + for (let i = 0; i < source.count; ++i) { + const c = source.get(i) + backing.append({ name: c.name, fracs: 100, present: true }) + } + } + + function setFracs(index, value) { + if (index < 0 || index >= backing.count) return + backing.setProperty(index, 'fracs', value) + } + + function setPresent(index, value) { + if (index < 0 || index >= backing.count) return + backing.setProperty(index, 'present', value) + } +} diff --git a/src/easyshapes_app/Backends/MockQml/Lamellae.qml b/src/easyshapes_app/Backends/MockQml/Lamellae.qml new file mode 100644 index 0000000..df7012e --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/Lamellae.qml @@ -0,0 +1,136 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +// Pattern D backend (multi-row list with selection) for lamellae, plus +// parallel arrays of per-lamella Fractions instances. Each lamella owns +// distinct inner and outer leaflet fractions so asymmetric lamellae can +// diverge without leaking state between leaflets. +QtObject { + id: root + + // Source of components shared with every leaflet's Fractions instance. + // Each leaflet keeps its own per-instance fracs/present state but + // mirrors the same component name list. + property var fractionsSource: null + + // Table of lamellae. Roles: rmin, innerDmin, outerDmin, shell, symmetric. + readonly property var items: ListModel { + id: lamellaeModel + ListElement { rmin: 0.5; innerDmin: 0.25; outerDmin: 0.3; shell: 0.5; symmetric: true } + } + + // Parallel arrays of Fractions QtObjects, one inner and one outer + // leaflet instance per lamella. + property var innerFractionsInstances: [] + property var outerFractionsInstances: [] + property int itemsRevision: 0 + property int fractionsRevision: 0 + + property var __fractionsComponent: null + + Component.onCompleted: { + __fractionsComponent = Qt.createComponent(Qt.resolvedUrl("Fractions.qml")) + if (__fractionsComponent.status !== Component.Ready) { + console.warn("Lamellae: failed to load Fractions.qml:", __fractionsComponent.errorString()) + return + } + const inner = [] + const outer = [] + for (let i = 0; i < lamellaeModel.count; ++i) { + inner.push(__createFractions()) + outer.push(__createFractions()) + } + innerFractionsInstances = inner + outerFractionsInstances = outer + itemsRevision++ + fractionsRevision++ + } + + function __createFractions() { + // Bind (don't snapshot) so per-instance Fractions follow later + // assignments to root.fractionsSource — singleton init order is + // not deterministic, so the source may be set after this runs. + const f = __fractionsComponent.createObject(root) + f.source = Qt.binding(function() { return root.fractionsSource }) + return f + } + + function appendItem(item) { + lamellaeModel.append({ + rmin: item.rmin, + innerDmin: item.innerDmin, + outerDmin: item.outerDmin, + shell: item.shell, + symmetric: item.symmetric + }) + + const inner = innerFractionsInstances.slice() + const outer = outerFractionsInstances.slice() + inner.push(__createFractions()) + outer.push(__createFractions()) + innerFractionsInstances = inner + outerFractionsInstances = outer + itemsRevision++ + fractionsRevision++ + } + + function removeItem(index) { + if (index < 0 || index >= lamellaeModel.count) return + lamellaeModel.remove(index) + + const inner = innerFractionsInstances.slice() + const outer = outerFractionsInstances.slice() + const removedInner = inner.splice(index, 1)[0] + const removedOuter = outer.splice(index, 1)[0] + if (removedInner) removedInner.destroy() + if (removedOuter) removedOuter.destroy() + innerFractionsInstances = inner + outerFractionsInstances = outer + itemsRevision++ + fractionsRevision++ + } + + function setRmin(index, value) { + if (index < 0 || index >= lamellaeModel.count) return + lamellaeModel.setProperty(index, 'rmin', value) + } + + function setInnerDmin(index, value) { + if (index < 0 || index >= lamellaeModel.count) return + lamellaeModel.setProperty(index, 'innerDmin', value) + } + + function setOuterDmin(index, value) { + if (index < 0 || index >= lamellaeModel.count) return + lamellaeModel.setProperty(index, 'outerDmin', value) + } + + function setShell(index, value) { + if (index < 0 || index >= lamellaeModel.count) return + lamellaeModel.setProperty(index, 'shell', value) + } + + function setSymmetric(index, value) { + if (index < 0 || index >= lamellaeModel.count) return + lamellaeModel.setProperty(index, 'symmetric', value) + itemsRevision++ + } + + function innerFractionsModelAt(index) { + if (index < 0 || index >= innerFractionsInstances.length) return null + const f = innerFractionsInstances[index] + return f ? f.model : null + } + + function outerFractionsModelAt(index) { + if (index < 0 || index >= outerFractionsInstances.length) return null + const f = outerFractionsInstances[index] + return f ? f.model : null + } +} diff --git a/src/easyshapes_app/Backends/MockQml/LatticeStructure.qml b/src/easyshapes_app/Backends/MockQml/LatticeStructure.qml new file mode 100644 index 0000000..c274952 --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/LatticeStructure.qml @@ -0,0 +1,69 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +QtObject { + property double alpha: 0.0 + property double theta: 0.0 + property double sbuff: 1.0 + property string latticeType: 'LAT1' + property int nlatx: 1 + property int nlaty: 1 + property int nlatz: 1 + + readonly property var latticeTypes: ['LAT1', 'LAT2', 'LAT3'] + + readonly property var substructureTypes: [ + 'Ring', 'Ball', 'Vesicle', 'Rod', 'Bilayer', 'Monolayer' + ] + + // Loaded substructure — JS array of length 0 or 1, mirroring the + // SampleModel `loaded` shape so EaComponents.ListView can consume it. + // Element shape: { name, structure_type, description, file_path }. + property var substructureLoaded: [] + + readonly property var availableSubstructures: ListModel { + ListElement { name: 'CubicSeed'; structure_type: 'Ball'; description: 'Spherical seed for cubic packing' } + ListElement { name: 'HexRing'; structure_type: 'Ring'; description: 'Ring substructure for hexagonal lattice' } + ListElement { name: 'BilayerTile'; structure_type: 'Bilayer'; description: 'Planar tile for stacked lattices' } + ListElement { name: 'RodSeed'; structure_type: 'Rod'; description: 'Rod-shaped seed' } + ListElement { name: 'VesicleSeed'; structure_type: 'Vesicle'; description: 'Vesicle seed for hollow lattices' } + } + + function setSubstructureLoaded(item) { + substructureLoaded = [{ + name: item.name, + structure_type: item.structure_type, + description: item.description, + file_path: item.file_path !== undefined ? item.file_path : '' + }] + } + + function updateSubstructureField(field, value) { + if (substructureLoaded.length === 0) return + substructureLoaded[0][field] = value + } + + function clearSubstructure() { + substructureLoaded = [] + } + + function saveSubstructureToCatalog() { + if (substructureLoaded.length === 0 || !substructureLoaded[0].name) return + availableSubstructures.append({ + name: substructureLoaded[0].name, + structure_type: substructureLoaded[0].structure_type, + description: substructureLoaded[0].description + }) + } + + function removeSubstructureFromCatalog(index) { + if (index < 0 || index >= availableSubstructures.count) return + availableSubstructures.remove(index) + } +} diff --git a/src/easyshapes_app/Backends/MockQml/Layers.qml b/src/easyshapes_app/Backends/MockQml/Layers.qml new file mode 100644 index 0000000..19cbbb2 --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/Layers.qml @@ -0,0 +1,91 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +// Pattern D backend (multi-row list with selection) for layers, plus a +// parallel JS array of per-layer Fractions instances. ListElement only +// accepts literal scalars, so the Fractions QtObjects can't live inside +// the ListModel rows — they're maintained in lockstep here. +QtObject { + id: root + + // Source of components shared with every layer's Fractions instance. + // Each layer keeps its own per-instance fracs/present state but + // mirrors the same name list. + property var fractionsSource: null + + // Table of layers. Roles: dmin, rmin. + readonly property var items: ListModel { + id: layersModel + ListElement { dmin: 0.25; rmin: 0.5 } + } + + // Parallel array of Fractions QtObjects, one per layer. + // Bumping the revision token triggers rebinding for `var` consumers, + // since rebuilding the array reference (not its contents) is what + // QML actually signals on. + property var fractionsInstances: [] + property int fractionsRevision: 0 + + property var __fractionsComponent: null + + Component.onCompleted: { + __fractionsComponent = Qt.createComponent(Qt.resolvedUrl("Fractions.qml")) + if (__fractionsComponent.status !== Component.Ready) { + console.warn("Layers: failed to load Fractions.qml:", __fractionsComponent.errorString()) + return + } + const arr = [] + for (let i = 0; i < layersModel.count; ++i) arr.push(__createFractions()) + fractionsInstances = arr + fractionsRevision++ + } + + function __createFractions() { + // Bind (don't snapshot) so per-instance Fractions follow later + // assignments to root.fractionsSource — singleton init order is + // not deterministic, so the source may be set after this runs. + const f = __fractionsComponent.createObject(root) + f.source = Qt.binding(function() { return root.fractionsSource }) + return f + } + + function appendItem(item) { + layersModel.append({ dmin: item.dmin, rmin: item.rmin }) + const arr = fractionsInstances.slice() + arr.push(__createFractions()) + fractionsInstances = arr + fractionsRevision++ + } + + function removeItem(index) { + if (index < 0 || index >= layersModel.count) return + layersModel.remove(index) + const arr = fractionsInstances.slice() + const removed = arr.splice(index, 1)[0] + if (removed) removed.destroy() + fractionsInstances = arr + fractionsRevision++ + } + + function setDmin(index, value) { + if (index < 0 || index >= layersModel.count) return + layersModel.setProperty(index, 'dmin', value) + } + + function setRmin(index, value) { + if (index < 0 || index >= layersModel.count) return + layersModel.setProperty(index, 'rmin', value) + } + + function fractionsModelAt(index) { + if (index < 0 || index >= fractionsInstances.length) return null + const f = fractionsInstances[index] + return f ? f.model : null + } +} diff --git a/src/easyshapes_app/Backends/MockQml/MonolayerStructure.qml b/src/easyshapes_app/Backends/MockQml/MonolayerStructure.qml new file mode 100644 index 0000000..c4dd28c --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/MonolayerStructure.qml @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +QtObject { + property double zsep: 0.0 + property int nside: 1 + property double dmin: 0.5 +} diff --git a/src/easyshapes_app/Backends/MockQml/RingStructure.qml b/src/easyshapes_app/Backends/MockQml/RingStructure.qml new file mode 100644 index 0000000..1ec3975 --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/RingStructure.qml @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +QtObject { + property double dmin: 0.5 + property double rmin: 0.25 + property double alpha: 0.0 + property double theta: 0.0 + property double fxz: 0.0 + property double rev: 0.0 +} diff --git a/src/easyshapes_app/Backends/MockQml/RodStructure.qml b/src/easyshapes_app/Backends/MockQml/RodStructure.qml new file mode 100644 index 0000000..5c0770f --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/RodStructure.qml @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +QtObject { + property double dmin: 0.5 + property double rmin: 0.25 + property int turns: 1 + property bool fxz: false + property bool rev: false +} diff --git a/src/easyshapes_app/Backends/MockQml/SampleModel.qml b/src/easyshapes_app/Backends/MockQml/SampleModel.qml index 9ba09d1..7fef0d2 100644 --- a/src/easyshapes_app/Backends/MockQml/SampleModel.qml +++ b/src/easyshapes_app/Backends/MockQml/SampleModel.qml @@ -21,7 +21,12 @@ QtObject { 'Ring', 'Ball', 'Vesicle', 'Rod', 'Bilayer', 'Monolayer', 'Lattice' ] - readonly property string currentStructureType: loaded.length > 0 ? loaded[0].structure_type : '' + // Externally-observed structure type. Decoupled from `loaded` because + // updateField mutates `loaded[0]` in place (preserving the row delegate + // and any focused TextInput) and that mutation does NOT fire loadedChanged. + // The wrapper writes this property whenever structure_type is updated; + // setLoaded/clear keep it in sync with the active record. + property string currentStructureType: '' // Catalog of saveable/loadable models (asset library). // ListModel mirrors the Python QAbstractListModel with roles @@ -47,6 +52,7 @@ QtObject { structure_type: model.structure_type, description: model.description }] + currentStructureType = model.structure_type created = true } @@ -57,6 +63,7 @@ QtObject { function clear() { loaded = [] + currentStructureType = '' created = false } diff --git a/src/easyshapes_app/Backends/MockQml/VesicleStructure.qml b/src/easyshapes_app/Backends/MockQml/VesicleStructure.qml new file mode 100644 index 0000000..8b89830 --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/VesicleStructure.qml @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +QtObject { + property bool fxz: false + property bool rev: false + property string fill: 'FIBO' +} diff --git a/src/easyshapes_app/Backends/MockQml/qmldir b/src/easyshapes_app/Backends/MockQml/qmldir index 5f3167d..04d6591 100644 --- a/src/easyshapes_app/Backends/MockQml/qmldir +++ b/src/easyshapes_app/Backends/MockQml/qmldir @@ -2,6 +2,17 @@ module MockQml singleton Project Project.qml singleton SampleModel SampleModel.qml +singleton Components Components.qml +Fractions Fractions.qml +singleton Layers Layers.qml +singleton Lamellae Lamellae.qml +singleton RingStructure RingStructure.qml +singleton BallStructure BallStructure.qml +singleton VesicleStructure VesicleStructure.qml +singleton RodStructure RodStructure.qml +singleton BilayerStructure BilayerStructure.qml +singleton MonolayerStructure MonolayerStructure.qml +singleton LatticeStructure LatticeStructure.qml singleton Analysis Analysis.qml singleton Report Report.qml singleton Status Status.qml diff --git a/src/easyshapes_app/Gui/Globals/BackendWrapper.qml b/src/easyshapes_app/Gui/Globals/BackendWrapper.qml index 4fd1950..d83d2e4 100644 --- a/src/easyshapes_app/Gui/Globals/BackendWrapper.qml +++ b/src/easyshapes_app/Gui/Globals/BackendWrapper.qml @@ -69,11 +69,109 @@ QtObject { onSampleModelCreatedChanged: activeBackend.sampleModel.created = sampleModelCreated function sampleModelSetLoaded(model) { activeBackend.sampleModel.setLoaded(model) } - function sampleModelUpdateField(field, value) { activeBackend.sampleModel.updateField(field, value) } + function sampleModelUpdateField(field, value) { + activeBackend.sampleModel.updateField(field, value) + // updateField mutates `loaded[0]` in place to avoid recreating the + // ListView delegate (which would steal focus from any field being + // edited). The trade-off is that `loadedChanged` doesn't fire, so + // bindings derived from `loaded` won't re-evaluate. Mirror the + // structure_type into its own property here so visibility bindings + // (Layers/Lamellae GroupBoxes) update. + if (field === 'structure_type') activeBackend.sampleModel.currentStructureType = value + } function sampleModelClear() { activeBackend.sampleModel.clear() } function sampleModelSaveToCatalog() { activeBackend.sampleModel.saveToCatalog() } function sampleModelRemoveFromCatalog(index) { activeBackend.sampleModel.removeFromCatalog(index) } + // Components group (Sample Model sidebar) + readonly property var componentsLoaded: activeBackend.components.loaded + readonly property var componentsPendingFilePaths: activeBackend.components.pendingFilePaths + + function componentsAppend(item) { activeBackend.components.appendItem(item) } + function componentsRemove(index) { activeBackend.components.removeItem(index) } + function componentsClear() { activeBackend.components.clear() } + function componentsAppendPendingFilePath(path) { activeBackend.components.appendPendingFilePath(path) } + function componentsRemovePendingFilePath(index) { activeBackend.components.removePendingFilePath(index) } + function componentsClearPendingFilePaths() { activeBackend.components.clearPendingFilePaths() } + + // Global default Fractions set (fallback for the Fractions sidebar + // component). Layers/Lamellae do NOT use this — see the per-row + // fraction accessors below. + readonly property var fractionsModel: activeBackend.fractions.model + + function fractionsSetFracs(index, value) { activeBackend.fractions.setFracs(index, value) } + function fractionsSetPresent(index, value) { activeBackend.fractions.setPresent(index, value) } + + // Layers (Sample Model sidebar). One Fractions instance per layer is + // owned by the backend; the GUI binds the fractions list of the + // currently-selected layer via layersFractionsModelAt(row). + readonly property var layersItems: activeBackend.layers.items + readonly property int layersFractionsRevision: activeBackend.layers.fractionsRevision + + function layersAppend(item) { activeBackend.layers.appendItem(item) } + function layersRemove(index) { activeBackend.layers.removeItem(index) } + function layersSetDmin(index, value) { activeBackend.layers.setDmin(index, value) } + function layersSetRmin(index, value) { activeBackend.layers.setRmin(index, value) } + // Callers binding through this must also reference layersFractionsRevision + // in their binding body to re-evaluate when rows are inserted/removed. + function layersFractionsModelAt(index) { return activeBackend.layers.fractionsModelAt(index) } + + // Lamellae (Sample Model sidebar). One inner and one outer Fractions + // instance are owned per lamella; asymmetric lamellae bind both models. + readonly property var lamellaeItems: activeBackend.lamellae.items + readonly property int lamellaeItemsRevision: activeBackend.lamellae.itemsRevision + readonly property int lamellaeFractionsRevision: activeBackend.lamellae.fractionsRevision + + function lamellaeAppend(item) { activeBackend.lamellae.appendItem(item) } + function lamellaeRemove(index) { activeBackend.lamellae.removeItem(index) } + function lamellaeSetRmin(index, value) { activeBackend.lamellae.setRmin(index, value) } + function lamellaeSetInnerDmin(index, value) { activeBackend.lamellae.setInnerDmin(index, value) } + function lamellaeSetOuterDmin(index, value) { activeBackend.lamellae.setOuterDmin(index, value) } + function lamellaeSetShell(index, value) { activeBackend.lamellae.setShell(index, value) } + function lamellaeSetSymmetric(index, value) { activeBackend.lamellae.setSymmetric(index, value) } + // Callers binding through these must also reference lamellaeFractionsRevision + // in their binding body to re-evaluate when rows are inserted/removed. + function lamellaeInnerFractionsModelAt(index) { return activeBackend.lamellae.innerFractionsModelAt(index) } + function lamellaeOuterFractionsModelAt(index) { return activeBackend.lamellae.outerFractionsModelAt(index) } + + // Ring structure (Sample Model sidebar). Single-record fielded form + // shown only when sampleModelCurrentStructureType === 'Ring'. + readonly property var ringStructure: activeBackend.ringStructure + + // Ball structure (Sample Model sidebar). Single-record fielded form + // shown only when sampleModelCurrentStructureType === 'Ball'. + readonly property var ballStructure: activeBackend.ballStructure + + // Vesicle structure (Sample Model sidebar). Single-record fielded form + // shown only when sampleModelCurrentStructureType === 'Vesicle'. + readonly property var vesicleStructure: activeBackend.vesicleStructure + + // Rod structure (Sample Model sidebar). Single-record fielded form + // shown only when sampleModelCurrentStructureType === 'Rod'. + readonly property var rodStructure: activeBackend.rodStructure + + // Bilayer structure (Sample Model sidebar). Single-record fielded form + // shown only when sampleModelCurrentStructureType === 'Bilayer'. + readonly property var bilayerStructure: activeBackend.bilayerStructure + + // Monolayer structure (Sample Model sidebar). Single-record fielded form + // shown only when sampleModelCurrentStructureType === 'Monolayer'. + readonly property var monolayerStructure: activeBackend.monolayerStructure + + // Lattice structure (Sample Model sidebar). Single-record fielded form + // shown only when sampleModelCurrentStructureType === 'Lattice'. The + // substructure slot mirrors the SampleModel loaded/available shape, so + // the embedded list/popups follow the same recipe. + readonly property var latticeStructure: activeBackend.latticeStructure + readonly property var latticeSubstructureLoaded: activeBackend.latticeStructure.substructureLoaded + readonly property var latticeSubstructureAvailable: activeBackend.latticeStructure.availableSubstructures + readonly property var latticeSubstructureTypes: activeBackend.latticeStructure.substructureTypes + + function latticeSubstructureSetLoaded(item) { activeBackend.latticeStructure.setSubstructureLoaded(item) } + function latticeSubstructureClear() { activeBackend.latticeStructure.clearSubstructure() } + function latticeSubstructureSaveToCatalog() { activeBackend.latticeStructure.saveSubstructureToCatalog() } + function latticeSubstructureRemoveFromCatalog(index) { activeBackend.latticeStructure.removeSubstructureFromCatalog(index) } + //////////////// // Analysis page //////////////// diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml index 3bec9d2..f4924ab 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml @@ -8,7 +8,14 @@ import QtQuick.Controls import EasyApplication.Gui.Style as EaStyle import EasyApplication.Gui.Components as EaComponents +import Gui.Globals as Globals + + EaComponents.ListView { + // Override to bind a per-row Fractions backend (e.g. layer/lamella). + // Defaults to the global Fractions set on the wrapper. + property var fractionsModel: Globals.BackendWrapper.fractionsModel + defaultInfoText: qsTr("Missing components") selectionActive: false @@ -35,11 +42,7 @@ EaComponents.ListView { } } - model: ListModel { - ListElement { name: "POPC"; fracs: 100; present: true } - ListElement { name: "DOPC"; fracs: 100; present: true } - ListElement { name: "DPPC"; fracs: 100; present: true } - } + model: fractionsModel delegateModelAccess: DelegateModel.ReadWrite diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/BallStructure.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/BallStructure.qml new file mode 100644 index 0000000..829e7df --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/BallStructure.qml @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements + +import Gui.Globals as Globals + + +EaElements.GroupColumn { + + Row { + property real itemWidth: EaStyle.Sizes.sideBarContentWidth * 0.2 + spacing: EaStyle.Sizes.fontPixelSize * 2 + + Column { + width: parent.itemWidth + + EaElements.Label { + enabled: false + text: qsTr('Fill') + } + EaElements.ComboBox { + width: parent.width + model: ['FIBO', 'RINGS', 'RINGS0'] + Component.onCompleted: { + currentIndex = model.indexOf(Globals.BackendWrapper.ballStructure.fill) + } + onActivated: (i) => { + Globals.BackendWrapper.ballStructure.fill = model[i] + } + } + } + EaElements.CheckBox { + height: EaStyle.Sizes.fontPixelSize * 5 + text: qsTr('Fxz') + checked: Globals.BackendWrapper.ballStructure.fxz + onToggled: Globals.BackendWrapper.ballStructure.fxz = checked + } + EaElements.CheckBox { + height: EaStyle.Sizes.fontPixelSize * 5 + text: qsTr('Rev') + checked: Globals.BackendWrapper.ballStructure.rev + onToggled: Globals.BackendWrapper.ballStructure.rev = checked + } + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/BilayerStructure.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/BilayerStructure.qml new file mode 100644 index 0000000..fd53d7a --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/BilayerStructure.qml @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements + +import Gui.Globals as Globals + +import "../Components" as Local + + +EaElements.GroupColumn { + + Row { + property real itemWidth: EaStyle.Sizes.sideBarContentWidth * 0.27 + spacing: (EaStyle.Sizes.sideBarContentWidth - (itemWidth * 3)) / 2 + + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Zsep') + units: 'nm' + validator: DoubleValidator { bottom: 0 } + text: Globals.BackendWrapper.bilayerStructure.zsep + onEditingFinished: Globals.BackendWrapper.bilayerStructure.zsep = parseFloat(text) + } + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Nside') + text: Globals.BackendWrapper.bilayerStructure.nside + validator: IntValidator { bottom: 1 } + onEditingFinished: Globals.BackendWrapper.bilayerStructure.nside = parseInt(text) + } + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Dmin') + units: 'nm' + validator: DoubleValidator { bottom: 0.5 } + text: Globals.BackendWrapper.bilayerStructure.dmin + onEditingFinished: Globals.BackendWrapper.bilayerStructure.dmin = parseFloat(text) + } + } + + Column { + width: parent.width + + EaElements.Label { + enabled: false + text: qsTr('Bilayer Fractions') + } + + Local.Fractions { + id: bilayerFractions + } + } + +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml index bc23d6f..9bd2a0e 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml @@ -63,9 +63,7 @@ EaElements.GroupColumn { } } - model: ListModel { - id: loadedComponentsModel - } + model: Globals.BackendWrapper.componentsLoaded delegateModelAccess: DelegateModel.ReadWrite @@ -113,7 +111,7 @@ EaElements.GroupColumn { EaComponents.TableViewButton { fontIcon: "minus-circle" ToolTip.text: qsTr("Remove this component") - onClicked: loadedComponentsModel.remove(index) + onClicked: Globals.BackendWrapper.componentsRemove(index) } } } @@ -131,7 +129,7 @@ EaElements.GroupColumn { EaElements.SideBarButton { fontIcon: 'plus-circle' - text: qsTr('Create component') + text: qsTr('Import component') width: buttonWidth onClicked: createNewComponentLoader.item.open() } @@ -141,12 +139,14 @@ EaElements.GroupColumn { fontIcon: 'download' text: qsTr('Save component(s)') width: buttonWidth - enabled: loadedComponents.model ? loadedComponents.model.count > 0 : false + enabled: Globals.BackendWrapper.componentsLoaded + ? Globals.BackendWrapper.componentsLoaded.count > 0 + : false onClicked: { const indexes = loadedComponents.selectedIndexes for (let i = 0; i < indexes.length; ++i) loadExistingComponentLoader.item.availableComponentsModel.append( - loadedComponentsModel.get(indexes[i].row) + Globals.BackendWrapper.componentsLoaded.get(indexes[i].row) ) } } @@ -155,13 +155,11 @@ EaElements.GroupColumn { Loader { id: loadExistingComponentLoader source: '../Popups/LoadExistingComponent.qml' - onLoaded: item.targetModel = loadedComponentsModel } Loader { id: createNewComponentLoader source: '../Popups/CreateNewComponent.qml' - onLoaded: item.targetModel = loadedComponentsModel } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml index 966bdc8..97064e0 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml @@ -61,10 +61,7 @@ EaElements.GroupColumn { EaComponents.TableViewLabel {} } - model: ListModel { - id: lamellaeModel - ListElement { rmin: 0.5; innerDmin: 0.25; outerDmin: 0.3; shell: 0.5; symmetric: true } - } + model: Globals.BackendWrapper.lamellaeItems delegateModelAccess: DelegateModel.ReadWrite @@ -82,33 +79,34 @@ EaElements.GroupColumn { } EaComponents.ListViewTextInput { text: rmin - onEditingFinished: rmin = parseFloat(text) + onEditingFinished: Globals.BackendWrapper.lamellaeSetRmin(index, parseFloat(text)) validator: DoubleValidator { bottom: 0.25 } } EaComponents.ListViewTextInput { text: innerDmin - onEditingFinished: innerDmin = parseFloat(text) + onEditingFinished: Globals.BackendWrapper.lamellaeSetInnerDmin(index, parseFloat(text)) validator: DoubleValidator { bottom: 0.25 } } EaComponents.ListViewTextInput { - text: outerDmin - onEditingFinished: outerDmin = parseFloat(text) + text: symmetric ? innerDmin : outerDmin + enabled: !symmetric + onEditingFinished: Globals.BackendWrapper.lamellaeSetOuterDmin(index, parseFloat(text)) validator: DoubleValidator { bottom: 0.25 } } EaComponents.ListViewTextInput { text: shell - onEditingFinished: shell = parseFloat(text) + onEditingFinished: Globals.BackendWrapper.lamellaeSetShell(index, parseFloat(text)) validator: DoubleValidator { bottom: 0 } } EaComponents.TableViewCheckBox { checked: symmetric - onToggled: symmetric = checked + onToggled: Globals.BackendWrapper.lamellaeSetSymmetric(index, checked) } EaComponents.TableViewButton { id: deleteRowColumn fontIcon: "minus-circle" ToolTip.text: qsTr("Remove this lamella") - onClicked: lamellaeModel.remove(index) + onClicked: Globals.BackendWrapper.lamellaeRemove(index) } } } @@ -124,7 +122,7 @@ EaElements.GroupColumn { fontIcon: "plus-circle" text: qsTr("Add lamella") width: buttonWidth - onClicked: lamellaeModel.append({ rmin: 0.5, innerDmin: 0.25, outerDmin: 0.3, shell: 0.5, symmetric: true }) + onClicked: Globals.BackendWrapper.lamellaeAppend({ rmin: 0.5, innerDmin: 0.25, outerDmin: 0.3, shell: 0.5, symmetric: true }) } } @@ -135,7 +133,24 @@ EaElements.GroupColumn { spacing: EaStyle.Sizes.groupBoxSpacing readonly property int selectedRow: lamellae.selectedIndexes.length > 0 ? lamellae.selectedIndexes[0].row : -1 - readonly property bool selectedSymmetric: selectedRow >= 0 && lamellaeModel.get(selectedRow).symmetric + readonly property bool selectedSymmetric: { + // Touch the revision token so this binding re-evaluates when + // the selected row's symmetric flag changes. + void Globals.BackendWrapper.lamellaeItemsRevision + return selectedRow >= 0 && selectedRow < Globals.BackendWrapper.lamellaeItems.count + ? Globals.BackendWrapper.lamellaeItems.get(selectedRow).symmetric + : true + } + readonly property var selectedInnerFractionsModel: { + // Touch the revision token so this binding re-evaluates when + // the per-lamella Fractions arrays are rebuilt. + void Globals.BackendWrapper.lamellaeFractionsRevision + return selectedRow >= 0 ? Globals.BackendWrapper.lamellaeInnerFractionsModelAt(selectedRow) : null + } + readonly property var selectedOuterFractionsModel: { + void Globals.BackendWrapper.lamellaeFractionsRevision + return selectedRow >= 0 ? Globals.BackendWrapper.lamellaeOuterFractionsModelAt(selectedRow) : null + } Column { width: parent.width @@ -148,6 +163,7 @@ EaElements.GroupColumn { } Local.Fractions { id: innerFractions + fractionsModel: fractionsSection.selectedInnerFractionsModel } } @@ -161,6 +177,7 @@ EaElements.GroupColumn { } Local.Fractions { id: outerFractions + fractionsModel: fractionsSection.selectedOuterFractionsModel } } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml new file mode 100644 index 0000000..b617e62 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml @@ -0,0 +1,177 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents + +import Gui.Globals as Globals + + +EaElements.GroupColumn { + Row { + property real itemWidth: EaStyle.Sizes.sideBarContentWidth * 0.3 + spacing: (EaStyle.Sizes.sideBarContentWidth - (itemWidth * 3)) / 2 + + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Alpha') + units: '⚬' + validator: DoubleValidator { bottom: 0; top: 360 } + text: Globals.BackendWrapper.latticeStructure.alpha + onEditingFinished: Globals.BackendWrapper.latticeStructure.alpha = parseFloat(text) + } + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Theta') + units: '⚬' + validator: DoubleValidator { bottom: 0; top: 180 } + text: Globals.BackendWrapper.latticeStructure.theta + onEditingFinished: Globals.BackendWrapper.latticeStructure.theta = parseFloat(text) + } + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Sbuff') + units: 'nm' + validator: DoubleValidator { bottom: 0 } + text: Globals.BackendWrapper.latticeStructure.sbuff + onEditingFinished: Globals.BackendWrapper.latticeStructure.sbuff = parseFloat(text) + } + } + + Row { + property real itemWidth: EaStyle.Sizes.sideBarContentWidth * 0.2 + spacing: (EaStyle.Sizes.sideBarContentWidth - (itemWidth * 4)) / 3 + + + Column { + width: parent.itemWidth + + EaElements.Label { + enabled: false + text: qsTr('Type') + } + EaElements.ComboBox { + width: parent.width + model: Globals.BackendWrapper.latticeStructure.latticeTypes + Component.onCompleted: { + currentIndex = model.indexOf(Globals.BackendWrapper.latticeStructure.latticeType) + } + onActivated: (i) => { + Globals.BackendWrapper.latticeStructure.latticeType = model[i] + } + } + } + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Nlatx') + validator: IntValidator { bottom: 1 } + text: Globals.BackendWrapper.latticeStructure.nlatx + onEditingFinished: Globals.BackendWrapper.latticeStructure.nlatx = parseInt(text) + } + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Nlaty') + validator: IntValidator { bottom: 1 } + text: Globals.BackendWrapper.latticeStructure.nlaty + onEditingFinished: Globals.BackendWrapper.latticeStructure.nlaty = parseInt(text) + } + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Nlatz') + validator: IntValidator { bottom: 1 } + text: Globals.BackendWrapper.latticeStructure.nlatz + onEditingFinished: Globals.BackendWrapper.latticeStructure.nlatz = parseInt(text) + } + + } + + Column { + width: parent.width + + EaElements.Label { + enabled: false + text: qsTr('Substructure') + } + + EaComponents.ListView { + id: loadedSubstructure + defaultInfoText: qsTr('Load or create a substructure') + multiSelection: false + + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 12, + EaStyle.Sizes.fontPixelSize * 6, + -1 + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr('Name') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr('Type') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr('Description') + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: Globals.BackendWrapper.latticeSubstructureLoaded + + delegate: EaComponents.ListViewDelegate { + required property var modelData + required property int index + + EaComponents.TableViewLabel { + text: modelData ? modelData.name : '' + enabled: false + } + EaComponents.TableViewLabel { + text: modelData ? modelData.structure_type : '' + enabled: false + } + EaComponents.TableViewLabel { + text: modelData ? modelData.description : '' + enabled: false + } + } + } + } + + Row { + property double buttonWidth: (sideBarContentWidth - fontPixelSize) / 2 + spacing: EaStyle.Sizes.fontPixelSize + + EaElements.SideBarButton { + fontIcon: 'upload' + text: qsTr('Load structure') + width: buttonWidth + onClicked: loadExistingSubstructureLoader.item.open() + } + + EaElements.SideBarButton { + fontIcon: 'plus-circle' + text: qsTr('Import structure') + width: buttonWidth + onClicked: createNewSubstructureLoader.item.open() + } + } + + Loader { + id: loadExistingSubstructureLoader + source: '../Popups/LoadExistingSubstructure.qml' + } + + Loader { + id: createNewSubstructureLoader + source: '../Popups/CreateNewSubstructure.qml' + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml index 6b8fc1a..59e3643 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml @@ -17,6 +17,7 @@ import "../Components" as Local EaElements.GroupColumn { property double buttonWidth: EaStyle.Sizes.sideBarContentWidth * 0.3164 + EaComponents.ListView { id: layers defaultInfoText: qsTr("Add at least one layer") @@ -47,10 +48,7 @@ EaElements.GroupColumn { EaComponents.TableViewLabel {} } - model: ListModel { - id: layersModel - ListElement { dmin: 0.25; rmin: 0.5; } - } + model: Globals.BackendWrapper.layersItems delegateModelAccess: DelegateModel.ReadWrite @@ -66,19 +64,19 @@ EaElements.GroupColumn { EaComponents.TableViewLabel {} // filler EaComponents.ListViewTextInput { text: dmin - onEditingFinished: dmin = parseFloat(text) - validator: DoubleValidator { bottom: 0.25 } + onEditingFinished: Globals.BackendWrapper.layersSetDmin(index, parseFloat(text)) + validator: DoubleValidator { bottom: 0.25 } } EaComponents.ListViewTextInput { text: rmin - onEditingFinished: rmin = parseFloat(text) - validator: DoubleValidator { bottom: 0.25 } + onEditingFinished: Globals.BackendWrapper.layersSetRmin(index, parseFloat(text)) + validator: DoubleValidator { bottom: 0.25 } } EaComponents.TableViewButton { id: deleteRowColumn fontIcon: "minus-circle" ToolTip.text: qsTr("Remove this layer") - onClicked: layersModel.remove(index) + onClicked: Globals.BackendWrapper.layersRemove(index) } } } @@ -93,20 +91,30 @@ EaElements.GroupColumn { fontIcon: "plus-circle" text: qsTr("Add layer") width: buttonWidth - onClicked: layersModel.append({ dmin: 0.25, rmin: 0.5 }) + onClicked: Globals.BackendWrapper.layersAppend({ dmin: 0.25, rmin: 0.5 }) } } Column { + id: fractionsSection visible: layers.selectedIndexes.length > 0 width: parent.width + readonly property int selectedRow: layers.selectedIndexes.length > 0 ? layers.selectedIndexes[0].row : -1 + readonly property var selectedFractionsModel: { + // Touch the revision token so this binding re-evaluates when + // the per-layer Fractions array is rebuilt. + void Globals.BackendWrapper.layersFractionsRevision + return selectedRow >= 0 ? Globals.BackendWrapper.layersFractionsModelAt(selectedRow) : null + } + EaElements.Label { id: layerFractionsLabel enabled: false - text: qsTr("Layer %1 Fractions").arg(layers.selectedIndexes.length > 0 ? layers.selectedIndexes[0].row + 1 : 1) + text: qsTr("Layer %1 Fractions").arg(fractionsSection.selectedRow >= 0 ? fractionsSection.selectedRow + 1 : 1) } Local.Fractions { id: fractions + fractionsModel: fractionsSection.selectedFractionsModel } } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/MonolayerStructure.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/MonolayerStructure.qml new file mode 100644 index 0000000..45c5b40 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/MonolayerStructure.qml @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements + +import Gui.Globals as Globals + +import "../Components" as Local + + +EaElements.GroupColumn { + + Row { + property real itemWidth: EaStyle.Sizes.sideBarContentWidth * 0.27 + spacing: (EaStyle.Sizes.sideBarContentWidth - (itemWidth * 3)) / 2 + + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Zsep') + units: 'nm' + validator: DoubleValidator { bottom: 0 } + text: Globals.BackendWrapper.monolayerStructure.zsep + onEditingFinished: Globals.BackendWrapper.monolayerStructure.zsep = parseFloat(text) + } + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Nside') + text: Globals.BackendWrapper.monolayerStructure.nside + validator: IntValidator { bottom: 1 } + onEditingFinished: Globals.BackendWrapper.monolayerStructure.nside = parseInt(text) + } + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Dmin') + units: 'nm' + validator: DoubleValidator { bottom: 0.5 } + text: Globals.BackendWrapper.monolayerStructure.dmin + onEditingFinished: Globals.BackendWrapper.monolayerStructure.dmin = parseFloat(text) + } + } + + Column { + width: parent.width + + EaElements.Label { + enabled: false + text: qsTr('Monolayer Fractions') + } + + Local.Fractions { + id: monolayerFractions + } + } + +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/RingStructure.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/RingStructure.qml new file mode 100644 index 0000000..8c44e0a --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/RingStructure.qml @@ -0,0 +1,89 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements + +import Gui.Globals as Globals + +import "../Components" as Local + + +EaElements.GroupColumn { + + Row { + property real itemWidth: EaStyle.Sizes.sideBarContentWidth * 0.2 + spacing: (EaStyle.Sizes.sideBarContentWidth - (itemWidth * 4)) / 3 + + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Dmin') + units: 'nm' + validator: DoubleValidator { bottom: 0.5 } + text: Globals.BackendWrapper.ringStructure.dmin + onEditingFinished: Globals.BackendWrapper.ringStructure.dmin = parseFloat(text) + } + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Rmin') + units: 'nm' + validator: DoubleValidator { bottom: 0.25 } + text: Globals.BackendWrapper.ringStructure.rmin + onEditingFinished: Globals.BackendWrapper.ringStructure.rmin = parseFloat(text) + } + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Alpha') + text: Globals.BackendWrapper.ringStructure.alpha + validator: DoubleValidator { bottom: 0; top: 360 } + units: '⚬' + onEditingFinished: Globals.BackendWrapper.ringStructure.alpha = parseFloat(text) + } + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Theta') + text: Globals.BackendWrapper.ringStructure.theta + validator: DoubleValidator { bottom: 0; top: 180 } + units: '⚬' + onEditingFinished: Globals.BackendWrapper.ringStructure.theta = parseFloat(text) + } + } + Row { + spacing: EaStyle.Sizes.fontPixelSize + + EaElements.CheckBox { + width: EaStyle.Sizes.sideBarContentWidth * 0.15 + height: EaStyle.Sizes.fontPixelSize * 3 + text: qsTr('Fxz') + checked: Globals.BackendWrapper.ringStructure.fxz + onToggled: Globals.BackendWrapper.ringStructure.fxz = checked + } + EaElements.CheckBox { + width: EaStyle.Sizes.sideBarContentWidth * 0.15 + height: EaStyle.Sizes.fontPixelSize * 3 + text: qsTr('Rev') + checked: Globals.BackendWrapper.ringStructure.rev + onToggled: Globals.BackendWrapper.ringStructure.rev = checked + } + } + + Column { + width: parent.width + + EaElements.Label { + enabled: false + text: qsTr('Ring Fractions') + } + + Local.Fractions { + id: ringFractions + } + } + + + +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/RodStructure.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/RodStructure.qml new file mode 100644 index 0000000..9974c71 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/RodStructure.qml @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements + +import Gui.Globals as Globals + +import "../Components" as Local + + +EaElements.GroupColumn { + + Row { + property real itemWidth: EaStyle.Sizes.sideBarContentWidth * 0.27 + spacing: (EaStyle.Sizes.sideBarContentWidth - (itemWidth * 3)) / 2 + + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Dmin') + units: 'nm' + validator: DoubleValidator { bottom: 0.5 } + text: Globals.BackendWrapper.rodStructure.dmin + onEditingFinished: Globals.BackendWrapper.rodStructure.dmin = parseFloat(text) + } + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Rmin') + units: 'nm' + validator: DoubleValidator { bottom: 0.25 } + text: Globals.BackendWrapper.rodStructure.rmin + onEditingFinished: Globals.BackendWrapper.rodStructure.rmin = parseFloat(text) + } + EaElements.Parameter { + width: parent.itemWidth + title: qsTr('Turns') + text: Globals.BackendWrapper.rodStructure.turns + validator: IntValidator { bottom: 1 } + onEditingFinished: Globals.BackendWrapper.rodStructure.turns = parseInt(text) + } + } + + Row { + spacing: EaStyle.Sizes.fontPixelSize + + EaElements.CheckBox { + width: EaStyle.Sizes.sideBarContentWidth * 0.15 + height: EaStyle.Sizes.fontPixelSize * 3 + text: qsTr('Fxz') + checked: Globals.BackendWrapper.rodStructure.fxz + onToggled: Globals.BackendWrapper.rodStructure.fxz = checked + } + EaElements.CheckBox { + width: EaStyle.Sizes.sideBarContentWidth * 0.15 + height: EaStyle.Sizes.fontPixelSize * 3 + text: qsTr('Rev') + checked: Globals.BackendWrapper.rodStructure.rev + onToggled: Globals.BackendWrapper.rodStructure.rev = checked + } + } + + Column { + width: parent.width + + EaElements.Label { + enabled: false + text: qsTr('Rod Fractions') + } + + Local.Fractions { + id: rodFractions + } + } + +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/VesicleStructure.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/VesicleStructure.qml new file mode 100644 index 0000000..829e7df --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/VesicleStructure.qml @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements + +import Gui.Globals as Globals + + +EaElements.GroupColumn { + + Row { + property real itemWidth: EaStyle.Sizes.sideBarContentWidth * 0.2 + spacing: EaStyle.Sizes.fontPixelSize * 2 + + Column { + width: parent.itemWidth + + EaElements.Label { + enabled: false + text: qsTr('Fill') + } + EaElements.ComboBox { + width: parent.width + model: ['FIBO', 'RINGS', 'RINGS0'] + Component.onCompleted: { + currentIndex = model.indexOf(Globals.BackendWrapper.ballStructure.fill) + } + onActivated: (i) => { + Globals.BackendWrapper.ballStructure.fill = model[i] + } + } + } + EaElements.CheckBox { + height: EaStyle.Sizes.fontPixelSize * 5 + text: qsTr('Fxz') + checked: Globals.BackendWrapper.ballStructure.fxz + onToggled: Globals.BackendWrapper.ballStructure.fxz = checked + } + EaElements.CheckBox { + height: EaStyle.Sizes.fontPixelSize * 5 + text: qsTr('Rev') + checked: Globals.BackendWrapper.ballStructure.rev + onToggled: Globals.BackendWrapper.ballStructure.rev = checked + } + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml index 3f61d10..d294390 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml @@ -28,6 +28,62 @@ EaComponents.SideBarColumn { Loader { source: 'Groups/Components.qml' } } + EaElements.GroupBox { + title: qsTr('Ring Structure Definition') + icon: 'vector-square' + visible: Globals.BackendWrapper.sampleModelCurrentStructureType === 'Ring' + + Loader { source: 'Groups/RingStructure.qml' } + } + + EaElements.GroupBox { + title: qsTr('Ball Structure Definition') + icon: 'vector-square' + visible: Globals.BackendWrapper.sampleModelCurrentStructureType === 'Ball' + + Loader { source: 'Groups/BallStructure.qml' } + } + + EaElements.GroupBox { + title: qsTr('Vesicle Structure Definition') + icon: 'vector-square' + visible: Globals.BackendWrapper.sampleModelCurrentStructureType === 'Vesicle' + + Loader { source: 'Groups/VesicleStructure.qml' } + } + + EaElements.GroupBox { + title: qsTr('Rod Structure Definition') + icon: 'vector-square' + visible: Globals.BackendWrapper.sampleModelCurrentStructureType === 'Rod' + + Loader { source: 'Groups/RodStructure.qml' } + } + + EaElements.GroupBox { + title: qsTr('Bilayer Structure Definition') + icon: 'vector-square' + visible: Globals.BackendWrapper.sampleModelCurrentStructureType === 'Bilayer' + + Loader { source: 'Groups/BilayerStructure.qml' } + } + + EaElements.GroupBox { + title: qsTr('Monolayer Structure Definition') + icon: 'vector-square' + visible: Globals.BackendWrapper.sampleModelCurrentStructureType === 'Monolayer' + + Loader { source: 'Groups/MonolayerStructure.qml' } + } + + EaElements.GroupBox { + title: qsTr('Lattice Structure Definition') + icon: 'vector-square' + visible: Globals.BackendWrapper.sampleModelCurrentStructureType === 'Lattice' + + Loader { source: 'Groups/LatticeStructure.qml' } + } + EaElements.GroupBox { title: qsTr('Layers') icon: 'layer-group' // 'grip-lines' diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml index 6c0ac06..cf82267 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml @@ -17,14 +17,13 @@ import Gui.Globals as Globals EaElements.Dialog{ id: componentCreationDialog - property var targetModel property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 title: qsTr("Create a new Component") standardButtons: Dialog.Ok | Dialog.Cancel onAccepted: { - targetModel.append({ + Globals.BackendWrapper.componentsAppend({ name: componentNameField.text, component_type: sampleModelTypeField.currentText, atoms: 42, @@ -99,9 +98,7 @@ EaElements.Dialog{ EaStyle.Sizes.tableRowHeight ] - model: ListModel { - id: selectedFilePathsModel - } + model: Globals.BackendWrapper.componentsPendingFilePaths delegate: EaComponents.ListViewDelegate { required property int index @@ -120,7 +117,7 @@ EaElements.Dialog{ id: deleteRowColumn fontIcon: "minus-circle" ToolTip.text: qsTr("Remove this file") - onClicked: selectedFilePathsModel.remove(index) + onClicked: Globals.BackendWrapper.componentsRemovePendingFilePath(index) } } } @@ -138,9 +135,6 @@ EaElements.Dialog{ Loader { source: '../Popups/OpenAssetFile.qml' - onLoaded: { - item.targetModel = selectedFilePathsModel - } } } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewSubstructure.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewSubstructure.qml new file mode 100644 index 0000000..1d7c7e4 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewSubstructure.qml @@ -0,0 +1,119 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements + +import Gui.Globals as Globals + + +EaElements.Dialog{ + id: substructureCreationDialog + + property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 + + title: qsTr("Create a new Substructure") + standardButtons: Dialog.Ok | Dialog.Cancel + + onAccepted: { + Globals.BackendWrapper.latticeSubstructureSetLoaded({ + name: substructureNameField.text, + structure_type: substructureTypeField.currentText, + description: substructureDescrField.text, + file_path: substructureFileField.text + }) + } + + Column { + spacing: EaStyle.Sizes.fontPixelSize + + Row { + id: nameTypeRow + spacing: EaStyle.Sizes.fontPixelSize + + Column { + EaElements.Label { + enabled: false + text: qsTr("Name") + } + EaElements.TextField { + id: substructureNameField + implicitWidth: (substructureCreationDialog.inputFieldWidth - nameTypeRow.spacing) / 2 + horizontalAlignment: TextInput.AlignLeft + validator: RegularExpressionValidator { regularExpression: /^[a-zA-Z][a-zA-Z0-9_\-\.]{1,30}$/ } + placeholderText: qsTr("(optional) Enter Substructure name here") + } + } + + Column { + EaElements.Label { + enabled: false + text: qsTr("Structure type") + } + EaElements.ComboBox { + id: substructureTypeField + implicitWidth: (substructureCreationDialog.inputFieldWidth - nameTypeRow.spacing) / 2 + model: Globals.BackendWrapper.latticeSubstructureTypes + } + } + } + + Column { + EaElements.Label { + enabled: false + text: qsTr("Description") + } + EaElements.TextField { + id: substructureDescrField + implicitWidth: substructureCreationDialog.inputFieldWidth + horizontalAlignment: TextInput.AlignLeft + validator: RegularExpressionValidator { regularExpression: /^[a-zA-Z][a-zA-Z0-9_\-\.]{1,30}$/ } + placeholderText: qsTr("(optional) Enter Substructure description here") + } + } + + Column { + EaElements.Label { + enabled: false + text: qsTr("File") + } + + Row { + id: fileRow + spacing: EaStyle.Sizes.fontPixelSize + + EaElements.TextField { + id: substructureFileField + implicitWidth: substructureCreationDialog.inputFieldWidth + - browseFileButton.width + - fileRow.spacing + horizontalAlignment: TextInput.AlignLeft + placeholderText: qsTr("(optional) Choose a single structure file") + readOnly: true + } + + EaElements.SideBarButton { + id: browseFileButton + fontIcon: 'upload' + text: qsTr('Browse…') + width: substructureCreationDialog.inputFieldWidth * 0.2 + onClicked: substructureFilePicker.open() + } + } + + FileDialog { + id: substructureFilePicker + fileMode: FileDialog.OpenFile + nameFilters: ['Any (*)', 'Structure files (*.gro *.pdb *.xyz)', 'Topology files (*.itp)'] + onAccepted: substructureFileField.text = selectedFile + } + } + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml index a666182..0209f82 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml @@ -17,7 +17,6 @@ import Gui.Globals as Globals EaElements.Dialog{ id: sampleModelLoadDialog - property var targetModel property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 property alias availableComponentsModel: availableComponentsModel @@ -30,7 +29,7 @@ EaElements.Dialog{ var row = selected[i].row var item = availableComponentsModel.get(row) - targetModel.append({ + Globals.BackendWrapper.componentsAppend({ name: item.name, component_type: item.component_type, mint: item.mint, diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingSubstructure.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingSubstructure.qml new file mode 100644 index 0000000..61b896d --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingSubstructure.qml @@ -0,0 +1,107 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle + +import Gui.Globals as Globals + + +EaElements.Dialog{ + id: substructureLoadDialog + + property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 + + title: qsTr("Load a Substructure from the Asset Library") + standardButtons: Dialog.Ok | Dialog.Cancel + + onAccepted: { + var indexes = loadSubstructureListView.selectedIndexes + + if (indexes.length > 0) { + var row = indexes[0].row + var item = Globals.BackendWrapper.latticeSubstructureAvailable.get(row) + Globals.BackendWrapper.latticeSubstructureSetLoaded(item) + loadSubstructureListView.clearSelection() + } + } + onRejected: { + loadSubstructureListView.clearSelection() + } + + Column { + EaElements.Label { + enabled: false + text: qsTr("Available in the Asset Library") + } + EaComponents.ListView { + id: loadSubstructureListView + defaultInfoText: qsTr("No substructures found") + multiSelection: false + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 2.5, + EaStyle.Sizes.fontPixelSize * 10, + EaStyle.Sizes.fontPixelSize * 6, + -1, + EaStyle.Sizes.tableRowHeight, + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr("№") + color: EaStyle.Colors.themeForegroundMinor + horizontalAlignment: Text.AlignHCenter + } + EaComponents.TableViewLabel { + text: qsTr("Name") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr("Type") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr("Description") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel {} // filler + } + + model: Globals.BackendWrapper.latticeSubstructureAvailable + + delegate: EaComponents.ListViewDelegate { + required property int index + required property string name + required property string structure_type + required property string description + + EaComponents.TableViewLabel { + text: index + 1 + horizontalAlignment: Text.AlignHCenter + enabled: false + } + EaComponents.TableViewLabel { + text: name + } + EaComponents.TableViewLabel { + text: structure_type + } + EaComponents.TableViewLabel { + text: description + } + EaComponents.TableViewButton { + fontIcon: "minus-circle" + ToolTip.text: qsTr("Remove this substructure") + onClicked: Globals.BackendWrapper.latticeSubstructureRemoveFromCatalog(index) + } + } + } + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml index 4664933..d22023d 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml @@ -16,11 +16,9 @@ FileDialog{ fileMode: FileDialog.OpenFiles nameFilters: ['Any (*)', 'Structure files (*.gro *.pdb .*xyz)', 'Topology files (*.itp)', 'Smiles files (*.sml)'] - property var targetModel - onAccepted: { for (let i = 0; i < selectedFiles.length; ++i) - targetModel.append({ path: selectedFiles[i] }) + Globals.BackendWrapper.componentsAppendPendingFilePath(selectedFiles[i]) } Component.onCompleted: { diff --git a/src/easyshapes_app/test.qml b/src/easyshapes_app/test.qml index 8f55d2d..60ceb50 100644 --- a/src/easyshapes_app/test.qml +++ b/src/easyshapes_app/test.qml @@ -17,7 +17,7 @@ import Gui.Globals as Globals ApplicationWindow{ width: 650 - height: 580 + height: 680 color: EaStyle.Colors.contentBackground visible: true @@ -55,87 +55,15 @@ ApplicationWindow{ icon: 'wrench' collapsed: false - Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml'} + Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/BilayerStructure.qml'} } - EaComponents.ListView { - id: whatverTable - defaultInfoText: qsTr("No models found") - enabled: true - - columnWidths: [ - whatverTable.width * 0.25, - whatverTable.width * 0.15, - -1, - ] - - scrollBarPolicy: ScrollBar.AlwaysOn // ScrollBar.AsNeeded // ScrollBar.AlwaysOn - scrollBarInteractive: true - - header: EaComponents.ListViewHeader { - - EaComponents.TableViewLabel { - id: modelNameColumnName - text: qsTr("Name") - color: EaStyle.Colors.themeForegroundMinor - leftPadding: EaStyle.Sizes.fontPixelSize * 0.7 - } - - EaComponents.TableViewLabel { - id: modelTypeColumnName - text: qsTr("Type") - color: EaStyle.Colors.themeForegroundMinor - } - - EaComponents.TableViewLabel { - id: modelDescrColumnName - text: qsTr("Description") - color: EaStyle.Colors.themeForegroundMinor - } - } - - model: ListModel { - id: availableSambleModelsModel - ListElement { name: "Samle1_aluv"; structure_type: "Vesicle"; description: "In order to avoid a prolonged pro-inflammatory neutrophil response, signaling downstream of an agonist-activated G protein-coupled receptor (GPCR) has to be rapidly terminated. Among the family of GPCR kinases (GRKs) that regulate receptor phosphorylation and signaling termination, GRK2, which is highly expressed by immune cells, plays an important role." } - ListElement { name: "Sample2_nanodisc"; structure_type: "Ring"; description: "The medium chain fatty acid receptor GPR84 as well as formyl peptide receptor 2 (FPR2)" } - ListElement { name: "Sample3_cubosome"; structure_type: "Lattice"; description: "receptors expressed in neutrophils, play a key role in regulating inflammation. In this study, we investigated the effects of GRK2 inhibitors on neutrophil functions induced by GPR84 and FPR2 agonists." } - ListElement { name: "Sample4"; structure_type: "Ring"; description: "GRK2 was shown to be expressed in human neutrophils and analysis of subcellular fractions" } - ListElement { name: "Sample5"; structure_type: "Ball"; description: "revealed a cytosolic localization. The GRK2 inhibitors enhanced and prolonged neutrophil production " } - ListElement { name: "Sample6"; structure_type: "Vesicle"; description: "production of reactive oxygen species (ROS) induced by GPR84- but not FPR2-agonists" } - ListElement { name: "Sample7"; structure_type: "Rod"; description: "suggesting a receptor selective function of GRK2. This suggestion was supported by β-arrestin recruitment data. The ROS production induced by a non β-arrestin recruiting GPR84" } - ListElement { name: "Sample8"; structure_type: "Bilayer"; description: "This suggestion was supported by β-arrestin recruitment data. The ROS production induced by a non β-arrestin recruiting GPR84 agonist was not affected by the GRK2 inhibitor." } - ListElement { name: "Sample9"; structure_type: "Monolayer"; description: "Termination of this β-arrestin independent response relied, similar to the response induced by FPR2 agonists, primarily on the actin cytoskeleton." } - ListElement { name: "Samplewithareallylongname"; structure_type: "Lattice"; description: "In summary, we show that GPR84 utilizes GRK2 in concert with β-arrestin and actin cytoskeleton dependent processes to fine-tune the activity of the ROS generating NADPH-oxidase in neutrophils." } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "1"; structure_type: "2"; description: "3" } - ListElement { name: "end1"; structure_type: "end2"; description: "end3" } - } - - delegate: EaComponents.ListViewDelegate { - required property int index - required property string name - required property string structure_type - required property string description - - EaComponents.ListViewTextInput { - id: modelNameColumn - text: name - } - - EaComponents.TableViewLabel { - id: typeColumn - text: structure_type - color: "#666" // new disabled - } - - EaComponents.TableViewLabel { - id: descrColumn - text: description - color: "#555" // old disabled - } - } + EaElements.GroupBox { + title: qsTr('Test a group widget') + icon: 'wrench' + collapsed: false + Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/RingStructure.qml'} } } } From a000a7be0d7c8ef6f1db01d5ddc3b8cfacf07c76 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Wed, 6 May 2026 16:33:23 +0200 Subject: [PATCH 19/23] fix button widths in lattice structure definition --- .../SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml index b617e62..7fe2454 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml @@ -13,6 +13,7 @@ import Gui.Globals as Globals EaElements.GroupColumn { + Row { property real itemWidth: EaStyle.Sizes.sideBarContentWidth * 0.3 spacing: (EaStyle.Sizes.sideBarContentWidth - (itemWidth * 3)) / 2 @@ -147,20 +148,21 @@ EaElements.GroupColumn { } Row { - property double buttonWidth: (sideBarContentWidth - fontPixelSize) / 2 + id: buttonRow + property double buttonWidth: (EaStyle.Sizes.sideBarContentWidth - EaStyle.Sizes.fontPixelSize) / 2 spacing: EaStyle.Sizes.fontPixelSize EaElements.SideBarButton { fontIcon: 'upload' text: qsTr('Load structure') - width: buttonWidth + width: buttonRow.buttonWidth onClicked: loadExistingSubstructureLoader.item.open() } EaElements.SideBarButton { fontIcon: 'plus-circle' text: qsTr('Import structure') - width: buttonWidth + width: buttonRow.buttonWidth onClicked: createNewSubstructureLoader.item.open() } } From 7613f438da171ad6f9104e31b8bef54c60c33795 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Fri, 8 May 2026 15:38:28 +0200 Subject: [PATCH 20/23] solution mock --- src/easyshapes_app.qrc | 7 +- src/easyshapes_app/Backends/MockBackend.qml | 3 + .../Backends/MockQml/Fractions.qml | 4 +- src/easyshapes_app/Backends/MockQml/Ions.qml | 57 +++++ .../Backends/MockQml/Solution.qml | 116 +++++++++ src/easyshapes_app/Backends/MockQml/qmldir | 2 + .../Gui/Globals/BackendWrapper.qml | 34 +++ .../Sidebar/Basic/Groups/Group3.qml | 18 -- .../Sidebar/Basic/Groups/Lamellae.qml | 3 +- .../Sidebar/Basic/Groups/LatticeStructure.qml | 2 +- .../Sidebar/Basic/Groups/SampleModel.qml | 2 +- .../Sidebar/Basic/Groups/Solution.qml | 241 ++++++++++++++++++ .../SampleModel/Sidebar/Basic/Layout.qml | 6 +- .../Sidebar/Basic/Popups/CreateNewSolvent.qml | 118 +++++++++ .../Sidebar/Basic/Popups/LoadExistingIon.qml | 94 +++++++ .../Basic/Popups/LoadExistingSolvent.qml | 101 ++++++++ src/easyshapes_app/test.qml | 10 +- 17 files changed, 781 insertions(+), 37 deletions(-) create mode 100644 src/easyshapes_app/Backends/MockQml/Ions.qml create mode 100644 src/easyshapes_app/Backends/MockQml/Solution.qml delete mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewSolvent.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingIon.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingSolvent.qml diff --git a/src/easyshapes_app.qrc b/src/easyshapes_app.qrc index 41fbf8a..5a4d8c3 100644 --- a/src/easyshapes_app.qrc +++ b/src/easyshapes_app.qrc @@ -7,6 +7,7 @@ easyshapes_app/Backends/MockQml/BilayerStructure.qml easyshapes_app/Backends/MockQml/Components.qml easyshapes_app/Backends/MockQml/Fractions.qml + easyshapes_app/Backends/MockQml/Ions.qml easyshapes_app/Backends/MockQml/Lamellae.qml easyshapes_app/Backends/MockQml/LatticeStructure.qml easyshapes_app/Backends/MockQml/Layers.qml @@ -17,6 +18,7 @@ easyshapes_app/Backends/MockQml/RingStructure.qml easyshapes_app/Backends/MockQml/RodStructure.qml easyshapes_app/Backends/MockQml/SampleModel.qml + easyshapes_app/Backends/MockQml/Solution.qml easyshapes_app/Backends/MockQml/Status.qml easyshapes_app/Backends/MockQml/VesicleStructure.qml easyshapes_app/Backends/qmldir @@ -55,7 +57,6 @@ easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/BilayerStructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml - easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml @@ -63,13 +64,17 @@ easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/RingStructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/RodStructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/VesicleStructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewComponent.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewModel.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewSolvent.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewSubstructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingComponent.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingIon.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingModel.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingSolvent.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingSubstructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml easyshapes_app/Gui/Pages/Toolbox/Layout.qml diff --git a/src/easyshapes_app/Backends/MockBackend.qml b/src/easyshapes_app/Backends/MockBackend.qml index c994427..a250da0 100644 --- a/src/easyshapes_app/Backends/MockBackend.qml +++ b/src/easyshapes_app/Backends/MockBackend.qml @@ -39,6 +39,9 @@ QtObject { // Lattice structure parameters (single record, edited inline) plus a // single-record substructure with its own asset library. property var latticeStructure: MockLogic.LatticeStructure + // Solution group: solution (single-record, TIP3 default) + ions (max 2 rows). + property var solution: MockLogic.Solution + property var ions: MockLogic.Ions property var analysis: MockLogic.Analysis property var status: MockLogic.Status property var report: MockLogic.Report diff --git a/src/easyshapes_app/Backends/MockQml/Fractions.qml b/src/easyshapes_app/Backends/MockQml/Fractions.qml index 2daaef2..92599eb 100644 --- a/src/easyshapes_app/Backends/MockQml/Fractions.qml +++ b/src/easyshapes_app/Backends/MockQml/Fractions.qml @@ -34,7 +34,7 @@ QtObject { function onRowsInserted(parent, first, last) { for (let i = first; i <= last; ++i) { const c = root.source.get(i) - backing.insert(i, { name: c.name, fracs: 100, present: true }) + backing.insert(i, { name: c.name, fracs: 1, present: true }) } } function onRowsRemoved(parent, first, last) { @@ -53,7 +53,7 @@ QtObject { if (!source) return for (let i = 0; i < source.count; ++i) { const c = source.get(i) - backing.append({ name: c.name, fracs: 100, present: true }) + backing.append({ name: c.name, fracs: 1, present: true }) } } diff --git a/src/easyshapes_app/Backends/MockQml/Ions.qml b/src/easyshapes_app/Backends/MockQml/Ions.qml new file mode 100644 index 0000000..73ed1c3 --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/Ions.qml @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +QtObject { + + // Loaded ions — at most 2 rows. ListModel so the chip Repeater rebinds + // on append/remove without manual reassignment. Roles: name. + readonly property var loaded: ListModel { + id: loadedIonsModel + } + + readonly property var available: ListModel { + ListElement { name: 'NA+' } + ListElement { name: 'CL-' } + ListElement { name: 'K+' } + ListElement { name: 'CA2+' } + ListElement { name: 'MG2+' } + ListElement { name: 'ZN2+' } + } + + // Hard cap at the backend layer. The button row also disables itself, + // but mocks must not be the only place enforcing the rule. + readonly property int maxIons: 2 + + function appendItem(item) { + if (loadedIonsModel.count >= maxIons) return + loadedIonsModel.append({ name: item.name }) + } + + function removeItem(index) { + if (index < 0 || index >= loadedIonsModel.count) return + loadedIonsModel.remove(index) + } + + function clear() { + loadedIonsModel.clear() + } + + function saveToCatalog() { + for (let i = 0; i < loadedIonsModel.count; ++i) { + const row = loadedIonsModel.get(i) + if (!row.name) continue + available.append({ name: row.name }) + } + } + + function removeFromCatalog(index) { + if (index < 0 || index >= available.count) return + available.remove(index) + } +} diff --git a/src/easyshapes_app/Backends/MockQml/Solution.qml b/src/easyshapes_app/Backends/MockQml/Solution.qml new file mode 100644 index 0000000..940f661 --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/Solution.qml @@ -0,0 +1,116 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +QtObject { + + readonly property var solutionTypes: ['other', 'water_3site', 'water_4site', 'water_5site', 'protic_polar', 'halogenated', 'denaturant'] + + property var loaded: [{ + name: 'TIP3P', + solvent_type: 'water_3site', + description: '3-site model standard with AMBER and CHARMM. Uses spc216.gro coordinates.', + file_path: '' + }] + + readonly property var available: ListModel { + id: solventModel + + ListElement { + name: "SPC" + solvent_type: "water_3site" + description: "Simple Point Charge water. Use spc216.gro with -ci. Standard for GROMOS force fields." + } + ListElement { + name: "SPC/E" + solvent_type: "water_3site" + description: "Extended SPC with self-polarization correction. Uses spc216.gro coordinates." + } + ListElement { + name: "TIP3P" + solvent_type: "water_3site" + description: "3-site model standard with AMBER and CHARMM. Uses spc216.gro coordinates." + } + ListElement { + name: "TIP4P" + solvent_type: "water_4site" + description: "4-site water with virtual site. Use tip4p.gro." + } + ListElement { + name: "TIP4P-Ew" + solvent_type: "water_4site" + description: "TIP4P optimized for Ewald summation. Available in AMBER ports." + } + ListElement { + name: "TIP4P/2005" + solvent_type: "water_4site" + description: "Reparameterized TIP4P with excellent bulk properties. Shipped with recent GROMACS." + } + ListElement { + name: "TIP5P" + solvent_type: "water_5site" + description: "5-site model with lone-pair virtual sites. Use tip5p.gro." + } + ListElement { + name: "TIP5PE" + solvent_type: "water_5site" + description: "TIP5P variant for Ewald electrostatics." + } + + ListElement { + name: "Methanol" + solvent_type: "protic_polar" + description: "CH3OH. Equilibrated box methanol.gro shipped with GROMACS (OPLS-AA)." + } + ListElement { + name: "1,2-Dichloroethane" + solvent_type: "halogenated" + description: "ClCH2CH2Ch. Equilibrated box ClCH2CH2Ch.gro included for OPLS-AA." + } + + ListElement { + name: "Urea" + solvent_type: "denaturant" + description: "Equilibrated urea box urea.gro shipped with GROMACS for cosolvent simulations." + } + } + + function setLoaded(item) { + loaded = [{ + name: item.name, + solvent_type: item.solvent_type, + description: item.description, + file_path: item.file_path !== undefined ? item.file_path : '' + }] + } + + // Mutate loaded[0] in place — same trick as SampleModel.updateField — so + // the ListView delegate and any focused TextInput survive the edit. + function updateField(field, value) { + if (loaded.length === 0) return + loaded[0][field] = value + } + + function clear() { + loaded = [] + } + + function saveToCatalog() { + if (loaded.length === 0 || !loaded[0].name) return + available.append({ + name: loaded[0].name, + solvent_type: loaded[0].solvent_type, + description: loaded[0].description + }) + } + + function removeFromCatalog(index) { + if (index < 0 || index >= available.count) return + available.remove(index) + } +} diff --git a/src/easyshapes_app/Backends/MockQml/qmldir b/src/easyshapes_app/Backends/MockQml/qmldir index 04d6591..3894fee 100644 --- a/src/easyshapes_app/Backends/MockQml/qmldir +++ b/src/easyshapes_app/Backends/MockQml/qmldir @@ -13,6 +13,8 @@ singleton RodStructure RodStructure.qml singleton BilayerStructure BilayerStructure.qml singleton MonolayerStructure MonolayerStructure.qml singleton LatticeStructure LatticeStructure.qml +singleton Solution Solution.qml +singleton Ions Ions.qml singleton Analysis Analysis.qml singleton Report Report.qml singleton Status Status.qml diff --git a/src/easyshapes_app/Gui/Globals/BackendWrapper.qml b/src/easyshapes_app/Gui/Globals/BackendWrapper.qml index d83d2e4..80c5f73 100644 --- a/src/easyshapes_app/Gui/Globals/BackendWrapper.qml +++ b/src/easyshapes_app/Gui/Globals/BackendWrapper.qml @@ -172,6 +172,40 @@ QtObject { function latticeSubstructureSaveToCatalog() { activeBackend.latticeStructure.saveSubstructureToCatalog() } function latticeSubstructureRemoveFromCatalog(index) { activeBackend.latticeStructure.removeSubstructureFromCatalog(index) } + // Solution group (Sample Model sidebar). Two backend-owned slots: + // * solution — single-record JS array (capacity 0 or 1), TIP3 by default. + // * ions — ListModel with at most 2 rows, name only. + + readonly property var solutionLoaded: activeBackend.solution.loaded + readonly property var solutionAvailable: activeBackend.solution.available + readonly property var solutionTypes: activeBackend.solution.solutionTypes + + function solutionSetLoaded(item) { activeBackend.solution.setLoaded(item) } + function solutionUpdateField(field, value) { activeBackend.solution.updateField(field, value) } + function solutionClear() { activeBackend.solution.clear() } + function solutionSaveToCatalog() { activeBackend.solution.saveToCatalog() } + function solutionRemoveFromCatalog(index) { activeBackend.solution.removeFromCatalog(index) } + + // Solvent aliases — same backend object, used by the solvent table popup files. + readonly property var solventLoaded: activeBackend.solution.loaded + readonly property var solventAvailable: activeBackend.solution.available + readonly property var solventTypes: activeBackend.solution.solutionTypes + + function solventSetLoaded(item) { activeBackend.solution.setLoaded(item) } + function solventUpdateField(field, value) { activeBackend.solution.updateField(field, value) } + function solventClear() { activeBackend.solution.clear() } + function solventSaveToCatalog() { activeBackend.solution.saveToCatalog() } + function solventRemoveFromCatalog(index) { activeBackend.solution.removeFromCatalog(index) } + + readonly property var ionsLoaded: activeBackend.ions.loaded + readonly property var ionsAvailable: activeBackend.ions.available + + function ionsAppend(item) { activeBackend.ions.appendItem(item) } + function ionsRemove(index) { activeBackend.ions.removeItem(index) } + function ionsClear() { activeBackend.ions.clear() } + function ionsSaveToCatalog() { activeBackend.ions.saveToCatalog() } + function ionsRemoveFromCatalog(index) { activeBackend.ions.removeFromCatalog(index) } + //////////////// // Analysis page //////////////// diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml deleted file mode 100644 index af615cc..0000000 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group3.qml +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtQuick.Controls - -import EasyApplication.Gui.Globals as EaGlobals -import EasyApplication.Gui.Style as EaStyle -import EasyApplication.Gui.Elements as EaElements -import EasyApplication.Gui.Components as EaComponents -import EasyApplication.Gui.Logic as EaLogic - -import Gui.Globals as Globals - -EaElements.GroupColumn { - -} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml index 97064e0..4f4432c 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml @@ -88,8 +88,7 @@ EaElements.GroupColumn { validator: DoubleValidator { bottom: 0.25 } } EaComponents.ListViewTextInput { - text: symmetric ? innerDmin : outerDmin - enabled: !symmetric + text: outerDmin onEditingFinished: Globals.BackendWrapper.lamellaeSetOuterDmin(index, parseFloat(text)) validator: DoubleValidator { bottom: 0.25 } } diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml index 7fe2454..a546a26 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml @@ -106,7 +106,7 @@ EaElements.GroupColumn { columnWidths: [ EaStyle.Sizes.fontPixelSize * 12, - EaStyle.Sizes.fontPixelSize * 6, + EaStyle.Sizes.fontPixelSize * 7, -1 ] diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml index 3aa2999..f8cf33e 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/SampleModel.qml @@ -26,7 +26,7 @@ EaElements.GroupColumn { columnWidths: [ EaStyle.Sizes.fontPixelSize * 12, - EaStyle.Sizes.fontPixelSize * 6, + EaStyle.Sizes.fontPixelSize * 7, -1 ] diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml new file mode 100644 index 0000000..0e68005 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml @@ -0,0 +1,241 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents + +import Gui.Globals as Globals + + +EaElements.GroupColumn { + id: root + property double buttonWidth: (EaStyle.Sizes.sideBarContentWidth - (EaStyle.Sizes.fontPixelSize * 2) ) / 3 + + Column { + width: EaStyle.Sizes.sideBarContentWidth * 0.5 + + EaElements.Label { + enabled: false + text: qsTr('Solvent') + } + + EaComponents.ListView { + id: loadedSolvent + defaultInfoText: qsTr('Load or import a solvent') + multiSelection: false + + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 7, + EaStyle.Sizes.fontPixelSize * 8, + -1 + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr('Name') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr('Type') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr('Description') + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: Globals.BackendWrapper.solutionLoaded + + delegate: EaComponents.ListViewDelegate { + required property var modelData + required property int index + + EaComponents.ListViewTextInput { + text: modelData ? modelData.name : '' + onEditingFinished: Globals.BackendWrapper.solventUpdateField('name', text) + } + EaComponents.TableViewComboBox { + model: Globals.BackendWrapper.solventTypes + Component.onCompleted: { + currentIndex = model.indexOf(modelData.solvent_type) + } + onActivated: (i) => { + Globals.BackendWrapper.solventUpdateField('solvent_type', model[i]) + } + } + EaComponents.ListViewTextInput { + text: modelData ? modelData.description : '' + onEditingFinished: Globals.BackendWrapper.solventUpdateField('description', text) + } + } + } + } + + Grid { + columns: 3 + spacing: EaStyle.Sizes.fontPixelSize + + EaElements.SideBarButton { + fontIcon: 'upload' + text: qsTr('Load solvent') + width: buttonWidth + onClicked: loadExistingSolvent.item.open() + } + + EaElements.SideBarButton { + fontIcon: 'plus-circle' + text: qsTr('Import solvent') + width: buttonWidth + onClicked: createNewSolvent.item.open() + } + + EaElements.SideBarButton { + fontIcon: 'download' + text: qsTr('Save solvent') + width: buttonWidth + enabled: Globals.BackendWrapper.solventLoaded.length > 0 + && Globals.BackendWrapper.solventLoaded[0].name !== "" + onClicked: Globals.BackendWrapper.solventSaveToCatalog() + } + } + + Row { + spacing: EaStyle.Sizes.fontPixelSize + + Column { + width: EaStyle.Sizes.sideBarContentWidth / 3 + spacing: EaStyle.Sizes.fontPixelSize * 0.5 + + EaElements.Label { + enabled: false + text: qsTr('Ions') + } + + Row { + id: ionChipRow + spacing: EaStyle.Sizes.fontPixelSize + height: EaStyle.Sizes.fontPixelSize * 2 + width: buttonWidth + + EaElements.Label { + visible: ionChipRow.ionCount === 0 + enabled: false + text: qsTr('No ions loaded') + anchors.verticalCenter: parent.verticalCenter + } + + readonly property int ionCount: + Globals.BackendWrapper.ionsLoaded + ? Globals.BackendWrapper.ionsLoaded.count + : 0 + + Repeater { + model: Globals.BackendWrapper.ionsLoaded + + delegate: Rectangle { + required property int index + required property string name + + height: ionChipRow.height + width: (ionChipRow.width - ionChipRow.spacing) / 2 + radius: height / 2 + color: EaStyle.Colors.appBarBackground + border.color: EaStyle.Colors.appBarComboBoxBorder + border.width: 1 + + Row { + anchors.fill: parent + anchors.leftMargin: EaStyle.Sizes.fontPixelSize + anchors.rightMargin: chipRemove.width + EaStyle.Sizes.fontPixelSize * 0.25 + spacing: EaStyle.Sizes.fontPixelSize * 0.25 + + EaElements.Label { + id: chipLabel + text: name + anchors.verticalCenter: parent.verticalCenter + } + } + + EaElements.ToolButton { + id: chipRemove + width: EaStyle.Sizes.toolButtonHeight * 0.4 + height: EaStyle.Sizes.toolButtonHeight * 0.4 + anchors.right: parent.right + anchors.rightMargin: EaStyle.Sizes.fontPixelSize * 0.6 + anchors.verticalCenter: parent.verticalCenter + ToolTip.text: qsTr('Remove this ion') + onClicked: Globals.BackendWrapper.ionsRemove(index) + + contentItem: Text { + text: 'X' + font.family: EaStyle.Fonts.fontFamily + font.pixelSize: EaStyle.Sizes.fontPixelSize + color: chipRemove.hovered + ? EaStyle.Colors.themeForegroundHovered + : EaStyle.Colors.themeForegroundMinor + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + } + } + } + } + + EaElements.SideBarButton { + fontIcon: 'upload' + text: qsTr('Load ion') + width: buttonWidth + enabled: ionChipRow.ionCount < 2 + onClicked: loadExistingIonLoader.item.open() + } + } + + Column { + width: EaStyle.Sizes.sideBarContentWidth / 3 + spacing: EaStyle.Sizes.fontPixelSize * 0.5 + + EaElements.Label { + enabled: false + text: qsTr('Amount') + } + EaElements.TextField { + id: ionAmountField + width: parent.width + enabled: !matchStructureCheck.checked + placeholderText: qsTr('Set the amount of selected ions') + validator: IntValidator { bottom: 0 } + } + EaElements.CheckBox { + id: matchStructureCheck + text: qsTr('Match components') + checked: false + onCheckedChanged: { + if (checked) { + ionAmountField.text = '' + ionAmountField.placeholderText = 'Will match the structure components' + } + else ionAmountField.placeholderText = 'Set the amount of ions' + } + } + } + } + + Loader { + id: loadExistingSolvent + source: '../Popups/LoadExistingSolvent.qml' + } + Loader { + id: createNewSolvent + source: '../Popups/CreateNewSolvent.qml' + } + Loader { + id: loadExistingIonLoader + source: '../Popups/LoadExistingIon.qml' + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml index d294390..2c4ddce 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml @@ -101,10 +101,10 @@ EaComponents.SideBarColumn { } EaElements.GroupBox { - title: qsTr('Solvent') - icon: 'grip-horizontal' + title: qsTr('Solution') + icon: 'flask' - Loader { source: 'Groups/Group3.qml' } + Loader { source: 'Groups/Solution.qml' } } EaElements.GroupBox { diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewSolvent.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewSolvent.qml new file mode 100644 index 0000000..0855279 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/CreateNewSolvent.qml @@ -0,0 +1,118 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements + +import Gui.Globals as Globals + + +EaElements.Dialog { + id: solventCreationDialog + + property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 + + title: qsTr("Import a new Solvent") + standardButtons: Dialog.Ok | Dialog.Cancel + + onAccepted: { + Globals.BackendWrapper.solventSetLoaded({ + name: solventNameField.text, + solvent_type: solventTypeField.currentText, + description: solventDescrField.text, + file_path: solventFileField.text + }) + } + + Column { + spacing: EaStyle.Sizes.fontPixelSize + + Row { + id: nameTypeRow + spacing: EaStyle.Sizes.fontPixelSize + + Column { + EaElements.Label { + enabled: false + text: qsTr("Name") + } + EaElements.TextField { + id: solventNameField + implicitWidth: (solventCreationDialog.inputFieldWidth - nameTypeRow.spacing) / 2 + horizontalAlignment: TextInput.AlignLeft + validator: RegularExpressionValidator { regularExpression: /^[a-zA-Z][a-zA-Z0-9_\-\.\/]{1,30}$/ } + placeholderText: qsTr("(optional) Enter Solvent name here") + } + } + + Column { + EaElements.Label { + enabled: false + text: qsTr("Solvent type") + } + EaElements.ComboBox { + id: solventTypeField + implicitWidth: (solventCreationDialog.inputFieldWidth - nameTypeRow.spacing) / 2 + model: Globals.BackendWrapper.solventTypes + } + } + } + + Column { + EaElements.Label { + enabled: false + text: qsTr("Description") + } + EaElements.TextField { + id: solventDescrField + implicitWidth: solventCreationDialog.inputFieldWidth + horizontalAlignment: TextInput.AlignLeft + placeholderText: qsTr("(optional) Enter Solvent description here") + } + } + + Column { + EaElements.Label { + enabled: false + text: qsTr("File") + } + + Row { + id: fileRow + spacing: EaStyle.Sizes.fontPixelSize + + EaElements.TextField { + id: solventFileField + implicitWidth: solventCreationDialog.inputFieldWidth + - browseFileButton.width + - fileRow.spacing + horizontalAlignment: TextInput.AlignLeft + placeholderText: qsTr("(optional) Choose a single solvent file") + readOnly: true + } + + EaElements.SideBarButton { + id: browseFileButton + fontIcon: 'upload' + text: qsTr('Browse…') + width: solventCreationDialog.inputFieldWidth * 0.2 + onClicked: solventFilePicker.open() + } + } + + FileDialog { + id: solventFilePicker + fileMode: FileDialog.OpenFile + nameFilters: ['Any (*)', 'Structure files (*.gro *.pdb *.xyz)', 'Topology files (*.itp)'] + onAccepted: solventFileField.text = selectedFile + } + } + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingIon.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingIon.qml new file mode 100644 index 0000000..de267fb --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingIon.qml @@ -0,0 +1,94 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements + +import Gui.Globals as Globals + + +EaElements.Dialog { + id: ionLoadDialog + + property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 25 + + title: qsTr("Load an Ion from the Asset Library") + standardButtons: Dialog.Ok | Dialog.Cancel + + // Block confirmation when the slot is full or no row is selected. + Component.onCompleted: { + var ok = standardButton(Dialog.Ok) + if (ok) { + ok.enabled = Qt.binding(function () { + if (!Globals.BackendWrapper.ionsLoaded + || Globals.BackendWrapper.ionsLoaded.count >= 2) return false + return loadIonListView.selectedIndexes.length > 0 + }) + } + } + + onAccepted: { + var indexes = loadIonListView.selectedIndexes + + if (indexes.length > 0) { + var row = indexes[0].row + var item = Globals.BackendWrapper.ionsAvailable.get(row) + Globals.BackendWrapper.ionsAppend({ name: item.name }) + loadIonListView.clearSelection() + } + } + onRejected: { + loadIonListView.clearSelection() + } + + Column { + EaElements.Label { + enabled: false + text: qsTr("Available in the Asset Library") + } + EaComponents.ListView { + id: loadIonListView + defaultInfoText: qsTr("No ions found") + multiSelection: false + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 2.5, + -1, + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr("№") + color: EaStyle.Colors.themeForegroundMinor + horizontalAlignment: Text.AlignHCenter + } + EaComponents.TableViewLabel { + text: qsTr("Name") + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: Globals.BackendWrapper.ionsAvailable + + delegate: EaComponents.ListViewDelegate { + required property int index + required property string name + + EaComponents.TableViewLabel { + text: index + 1 + horizontalAlignment: Text.AlignHCenter + enabled: false + } + EaComponents.TableViewLabel { + text: name + } + } + } + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingSolvent.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingSolvent.qml new file mode 100644 index 0000000..0e0c3ff --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingSolvent.qml @@ -0,0 +1,101 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Components as EaComponents +import EasyApplication.Gui.Elements as EaElements + +import Gui.Globals as Globals + + +EaElements.Dialog { + id: solventLoadDialog + + property int inputFieldWidth: EaStyle.Sizes.fontPixelSize * 35 + + title: qsTr("Load a Solvent from the Asset Library") + standardButtons: Dialog.Ok | Dialog.Cancel + + onAccepted: { + var indexes = loadSolventListView.selectedIndexes + + if (indexes.length > 0) { + var row = indexes[0].row + var item = Globals.BackendWrapper.solventAvailable.get(row) + Globals.BackendWrapper.solventSetLoaded(item) + loadSolventListView.clearSelection() + } + } + onRejected: { + loadSolventListView.clearSelection() + } + + Column { + EaElements.Label { + enabled: false + text: qsTr("Available in the Asset Library") + } + EaComponents.ListView { + id: loadSolventListView + defaultInfoText: qsTr("No solvents found") + multiSelection: false + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 2.5, + EaStyle.Sizes.fontPixelSize * 10, + EaStyle.Sizes.fontPixelSize * 6, + -1, + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr("№") + color: EaStyle.Colors.themeForegroundMinor + horizontalAlignment: Text.AlignHCenter + } + EaComponents.TableViewLabel { + text: qsTr("Name") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr("Type") + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr("Description") + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: Globals.BackendWrapper.solventAvailable + + delegate: EaComponents.ListViewDelegate { + required property int index + required property string name + required property string solvent_type + required property string description + + EaComponents.TableViewLabel { + text: index + 1 + horizontalAlignment: Text.AlignHCenter + enabled: false + } + EaComponents.TableViewLabel { + text: name + } + EaComponents.TableViewLabel { + text: solvent_type + } + EaComponents.TableViewLabel { + text: description + ToolTip.text: description + } + } + } + } +} diff --git a/src/easyshapes_app/test.qml b/src/easyshapes_app/test.qml index 60ceb50..09cdc99 100644 --- a/src/easyshapes_app/test.qml +++ b/src/easyshapes_app/test.qml @@ -55,15 +55,7 @@ ApplicationWindow{ icon: 'wrench' collapsed: false - Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/BilayerStructure.qml'} - } - - EaElements.GroupBox { - title: qsTr('Test a group widget') - icon: 'wrench' - collapsed: false - - Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/RingStructure.qml'} + Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml'} } } } From 4727be32f89532bbc113fcf73c55d02263cd0487 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Wed, 20 May 2026 15:59:38 +0200 Subject: [PATCH 21/23] adjusted solvent ions columns --- src/easyshapes_app.qmlproject | 8 +- src/easyshapes_app.qrc | 109 ++++++++++++++++++ .../Sidebar/Basic/Groups/Solution.qml | 72 +++++++----- src/easyshapes_app/test.qml | 23 +++- 4 files changed, 174 insertions(+), 38 deletions(-) diff --git a/src/easyshapes_app.qmlproject b/src/easyshapes_app.qmlproject index a57d5e8..1c9f27c 100644 --- a/src/easyshapes_app.qmlproject +++ b/src/easyshapes_app.qmlproject @@ -7,7 +7,7 @@ Project { // List of module and plugin directories passed to QML runtime importPaths: [ "easyshapes_app", - "../../EasyApp/src", // EasyApp + "../../EasyApp/src", // EasyApplication ] // Include .qml files from specified directory and its subdirectories @@ -15,7 +15,7 @@ Project { directory: "easyshapes_app" } QmlFiles { - directory: "../../EasyApp/src/EasyApp" + directory: "../../EasyApp/src/EasyApplication" } // Include .js files from specified directory and its subdirectories @@ -23,7 +23,7 @@ Project { directory: "easyshapes_app" } JavaScriptFiles { - directory: "../../EasyApp/src/EasyApp" + directory: "../../EasyApp/src/EasyApplication" } // Include Module Definition Files (qmldir), as well as .ts and .qrc @@ -34,7 +34,7 @@ Project { recursive: true } Files { - directory: "../../EasyApp/src/EasyApp" + directory: "../../EasyApp/src/EasyApplication" filter: "qmldir;*.ts;*.qrc;*.html" recursive: true } diff --git a/src/easyshapes_app.qrc b/src/easyshapes_app.qrc index 5a4d8c3..a0e7631 100644 --- a/src/easyshapes_app.qrc +++ b/src/easyshapes_app.qrc @@ -1,5 +1,114 @@ + ../../EasyApp/src/EasyApplication/Gui/Animations/ColorReset.qml + ../../EasyApp/src/EasyApplication/Gui/Animations/qmldir + ../../EasyApp/src/EasyApplication/Gui/Animations/ThemeChange.qml + ../../EasyApp/src/EasyApplication/Gui/Animations/TranslationChange.qml + ../../EasyApp/src/EasyApplication/Gui/Charts/ChartViewHeatmap2dPlotly.qml + ../../EasyApp/src/EasyApplication/Gui/Charts/ChartViewSimple1dPlotly.qml + ../../EasyApp/src/EasyApplication/Gui/Charts/Plotly1dBarPlot.qml + ../../EasyApp/src/EasyApplication/Gui/Charts/Plotly1dLine.qml + ../../EasyApp/src/EasyApplication/Gui/Charts/Plotly1dMeasVsCalc.qml + ../../EasyApp/src/EasyApplication/Gui/Charts/Plotly2dHeatmap.qml + ../../EasyApp/src/EasyApplication/Gui/Charts/Plotly2dPolarHeatmap.qml + ../../EasyApp/src/EasyApplication/Gui/Charts/Plotly3dScatter.qml + ../../EasyApp/src/EasyApplication/Gui/Charts/Plotly3dSurface.qml + ../../EasyApp/src/EasyApplication/Gui/Charts/qmldir + ../../EasyApp/src/EasyApplication/Gui/Charts/QtCharts1dBase 2.qml + ../../EasyApp/src/EasyApplication/Gui/Charts/QtCharts1dBase.qml + ../../EasyApp/src/EasyApplication/Gui/Charts/QtCharts1dMeasVsCalc.qml + ../../EasyApp/src/EasyApplication/Gui/Charts/QtCharts1dValueAxis.qml + ../../EasyApp/src/EasyApplication/Gui/Components/AboutDialog.qml + ../../EasyApp/src/EasyApplication/Gui/Components/AppBarCentralTabs.qml + ../../EasyApp/src/EasyApplication/Gui/Components/AppBarLeftButtons.qml + ../../EasyApp/src/EasyApplication/Gui/Components/AppBarRightButtons.qml + ../../EasyApp/src/EasyApplication/Gui/Components/ApplicationWindow.qml + ../../EasyApp/src/EasyApplication/Gui/Components/BasicReport.qml + ../../EasyApp/src/EasyApplication/Gui/Components/ContentArea.qml + ../../EasyApp/src/EasyApplication/Gui/Components/ContentPage.qml + ../../EasyApp/src/EasyApplication/Gui/Components/GuideWindow.qml + ../../EasyApp/src/EasyApplication/Gui/Components/GuideWindowContainer.qml + ../../EasyApp/src/EasyApplication/Gui/Components/JsonListModel.qml + ../../EasyApp/src/EasyApplication/Gui/Components/ListView.qml + ../../EasyApp/src/EasyApplication/Gui/Components/ListViewDelegate.qml + ../../EasyApp/src/EasyApplication/Gui/Components/ListViewHeader.qml + ../../EasyApp/src/EasyApplication/Gui/Components/ListViewTextInput.qml + ../../EasyApp/src/EasyApplication/Gui/Components/MainContent.qml + ../../EasyApp/src/EasyApplication/Gui/Components/PreferencesDialog.qml + ../../EasyApp/src/EasyApplication/Gui/Components/ProjectDescriptionDialog.qml + ../../EasyApp/src/EasyApplication/Gui/Components/qmldir + ../../EasyApp/src/EasyApplication/Gui/Components/SideBar.qml + ../../EasyApp/src/EasyApplication/Gui/Components/SideBarColumn.qml + ../../EasyApp/src/EasyApplication/Gui/Components/TableView.qml + ../../EasyApp/src/EasyApplication/Gui/Components/TableViewAdvancedLabel.qml + ../../EasyApp/src/EasyApplication/Gui/Components/TableViewButton.qml + ../../EasyApp/src/EasyApplication/Gui/Components/TableViewCheckBox.qml + ../../EasyApp/src/EasyApplication/Gui/Components/TableViewComboBox.qml + ../../EasyApp/src/EasyApplication/Gui/Components/TableViewDelegate.qml + ../../EasyApp/src/EasyApplication/Gui/Components/TableViewHeader.qml + ../../EasyApp/src/EasyApplication/Gui/Components/TableViewLabel.qml + ../../EasyApp/src/EasyApplication/Gui/Components/TableViewLabelControl.qml + ../../EasyApp/src/EasyApplication/Gui/Components/TableViewParameter.qml + ../../EasyApp/src/EasyApplication/Gui/Components/TableViewTextInput.qml + ../../EasyApp/src/EasyApplication/Gui/Components/TableViewTwoRowsAdvancedLabel.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/AppBarTabButton.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/ApplicationWindow.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/Button.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/CheckBox.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/CheckIndicator.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/ComboBox.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/CursorDelegate.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/Dialog.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/DialogButtonBox.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/GroupBox.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/GroupButton.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/GroupColumn.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/GroupRow.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/Label.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/LinkedImage.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/Menu.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/MenuItem.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/ParamComboBox.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/Parameter.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/ParamTextField.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/qmldir + ../../EasyApp/src/EasyApplication/Gui/Elements/RadioButton.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/RadioIndicator.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/RemoteController.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/RemotePointer.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/RunningLabel.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/ScrollBar.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/ScrollIndicator.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/SideBarButton.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/Slider.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/SliderHandle.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/SpinBox.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/SplashScreen.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/StatusBar.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/StatusBarItem.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/TabBar.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/TabButton.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/TextArea.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/TextField.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/TextInput.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/ToolButton.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/ToolTip.qml + ../../EasyApp/src/EasyApplication/Gui/Elements/ToolTipShadow.qml + ../../EasyApp/src/EasyApplication/Gui/Globals/qmldir + ../../EasyApp/src/EasyApplication/Gui/Globals/Vars.qml + ../../EasyApp/src/EasyApplication/Gui/Html/plotly-2.18.0.min.js + ../../EasyApp/src/EasyApplication/Gui/Logic/Plotting.js + ../../EasyApp/src/EasyApplication/Gui/Logic/ProjectConfig.js + ../../EasyApp/src/EasyApplication/Gui/Logic/qmldir + ../../EasyApp/src/EasyApplication/Gui/Logic/Translate.js + ../../EasyApp/src/EasyApplication/Gui/Logic/Utils.js + ../../EasyApp/src/EasyApplication/Gui/Style/Colors.qml + ../../EasyApp/src/EasyApplication/Gui/Style/Fonts.qml + ../../EasyApp/src/EasyApplication/Gui/Style/qmldir + ../../EasyApp/src/EasyApplication/Gui/Style/Sizes.qml + ../../EasyApp/src/EasyApplication/Gui/Style/Times.qml + ../../EasyApp/src/EasyApplication/Logic/Maintenance/qmldir + ../../EasyApp/src/EasyApplication/Logic/Maintenance/Updater.qml easyshapes_app.qmlproject easyshapes_app/Backends/MockBackend.qml easyshapes_app/Backends/MockQml/Analysis.qml diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml index 0e68005..9ed62bf 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml @@ -5,6 +5,7 @@ import QtQuick import QtQuick.Controls +import EasyApplication.Gui.Globals as EaGlobals import EasyApplication.Gui.Style as EaStyle import EasyApplication.Gui.Elements as EaElements import EasyApplication.Gui.Components as EaComponents @@ -110,7 +111,7 @@ EaElements.GroupColumn { Column { width: EaStyle.Sizes.sideBarContentWidth / 3 - spacing: EaStyle.Sizes.fontPixelSize * 0.5 + spacing: EaStyle.Sizes.fontPixelSize EaElements.Label { enabled: false @@ -119,7 +120,7 @@ EaElements.GroupColumn { Row { id: ionChipRow - spacing: EaStyle.Sizes.fontPixelSize + spacing: EaStyle.Sizes.fontPixelSize * 0.5 height: EaStyle.Sizes.fontPixelSize * 2 width: buttonWidth @@ -142,8 +143,12 @@ EaElements.GroupColumn { required property int index required property string name - height: ionChipRow.height - width: (ionChipRow.width - ionChipRow.spacing) / 2 + height: chipLabel.implicitHeight * 2 + width: EaStyle.Sizes.fontPixelSize + + chipLabel.implicitWidth + + EaStyle.Sizes.fontPixelSize + + chipRemove.width + + EaStyle.Sizes.fontPixelSize * 0.6 radius: height / 2 color: EaStyle.Colors.appBarBackground border.color: EaStyle.Colors.appBarComboBoxBorder @@ -162,25 +167,30 @@ EaElements.GroupColumn { } } - EaElements.ToolButton { + EaElements.Label { id: chipRemove - width: EaStyle.Sizes.toolButtonHeight * 0.4 - height: EaStyle.Sizes.toolButtonHeight * 0.4 + text: '×' + font.pixelSize: EaStyle.Sizes.fontPixelSize * 1.4 + color: chipRemoveArea.containsMouse + ? EaStyle.Colors.themeForegroundHovered + : EaStyle.Colors.themeForegroundMinor anchors.right: parent.right anchors.rightMargin: EaStyle.Sizes.fontPixelSize * 0.6 anchors.verticalCenter: parent.verticalCenter - ToolTip.text: qsTr('Remove this ion') - onClicked: Globals.BackendWrapper.ionsRemove(index) - - contentItem: Text { - text: 'X' - font.family: EaStyle.Fonts.fontFamily - font.pixelSize: EaStyle.Sizes.fontPixelSize - color: chipRemove.hovered - ? EaStyle.Colors.themeForegroundHovered - : EaStyle.Colors.themeForegroundMinor - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter + + MouseArea { + id: chipRemoveArea + anchors.fill: parent + anchors.margins: -EaStyle.Sizes.fontPixelSize * 0.3 + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: Globals.BackendWrapper.ionsRemove(index) + } + + EaElements.ToolTip { + text: qsTr('Remove this ion') + visible: chipRemoveArea.containsMouse + && EaGlobals.Vars.showToolTips } } } @@ -198,18 +208,22 @@ EaElements.GroupColumn { Column { width: EaStyle.Sizes.sideBarContentWidth / 3 - spacing: EaStyle.Sizes.fontPixelSize * 0.5 + spacing: EaStyle.Sizes.fontPixelSize - EaElements.Label { - enabled: false - text: qsTr('Amount') - } - EaElements.TextField { - id: ionAmountField + Column { width: parent.width - enabled: !matchStructureCheck.checked - placeholderText: qsTr('Set the amount of selected ions') - validator: IntValidator { bottom: 0 } + + EaElements.Label { + enabled: false + text: qsTr('Amount') + } + EaElements.TextField { + id: ionAmountField + width: parent.width + enabled: !matchStructureCheck.checked + placeholderText: qsTr('Set the amount of selected ions') + validator: IntValidator { bottom: 0 } + } } EaElements.CheckBox { id: matchStructureCheck diff --git a/src/easyshapes_app/test.qml b/src/easyshapes_app/test.qml index 09cdc99..cb4d953 100644 --- a/src/easyshapes_app/test.qml +++ b/src/easyshapes_app/test.qml @@ -50,12 +50,25 @@ ApplicationWindow{ } // groubox to test the element - EaElements.GroupBox { - title: qsTr('Test a group widget') - icon: 'wrench' - collapsed: false + // EaElements.GroupBox { + // title: qsTr('Test a group widget') + // icon: 'wrench' + // collapsed: false - Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml'} + // Loader { source: 'Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml'} + // } + + EaElements.Pill { + text: "text" + } + + EaElements.Pill { + text: "fontIcon" + fontIcon: "atom" + } + + EaElements.Pill { + text: "superlongtext why can't I hold all this text in my hands" } } } From 20c7ba6af7b768cffa4dce51325b79b48e7d5983 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Wed, 20 May 2026 16:16:25 +0200 Subject: [PATCH 22/23] adjusted solvent ions columns further --- .../Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml index 9ed62bf..5f3bb0f 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Solution.qml @@ -143,7 +143,7 @@ EaElements.GroupColumn { required property int index required property string name - height: chipLabel.implicitHeight * 2 + height: ionChipRow.height width: EaStyle.Sizes.fontPixelSize + chipLabel.implicitWidth + EaStyle.Sizes.fontPixelSize From 4fffb3d2299903581a8613ba802c9c3e5f1276a9 Mon Sep 17 00:00:00 2001 From: Ales Kutsepau Date: Fri, 22 May 2026 17:04:43 +0200 Subject: [PATCH 23/23] added advanced controls to sample model and basic analysis tab --- src/easyshapes_app.qrc | 24 +-- src/easyshapes_app/Backends/MockBackend.qml | 8 + .../Backends/MockQml/AnalysisConfig.qml | 88 +++++++++ .../Backends/MockQml/ComponentsFiles.qml | 101 +++++++++++ .../Backends/MockQml/PositionRestraints.qml | 93 ++++++++++ .../Backends/MockQml/StructureFiles.qml | 43 +++++ src/easyshapes_app/Backends/MockQml/qmldir | 4 + src/easyshapes_app/Gui/ApplicationWindow.qml | 13 +- .../Gui/Globals/BackendWrapper.qml | 48 +++++ .../Sidebar/Basic/Groups/AnalysisConfig.qml | 151 ++++++++++++++++ .../Sidebar/Basic/Groups/GetStarted.qml | 52 ------ .../Pages/Analysis/Sidebar/Basic/Layout.qml | 25 ++- .../Basic/Popups/AddAnalysisConfigFiles.qml | 23 +++ .../Gui/Pages/SampleModel/Layout.qml | 6 +- .../Advanced/Groups/ComponentsFiles.qml | 169 ++++++++++++++++++ .../Advanced/Groups/PositionRestraints.qml | 100 +++++++++++ .../Advanced/Groups/StructureFiles.qml | 95 ++++++++++ .../SampleModel/Sidebar/Advanced/Layout.qml | 36 ++++ .../Advanced/Popups/AddComponentFiles.qml | 25 +++ .../Advanced/Popups/ReplaceStructure.qml | 11 ++ .../Sidebar/Basic/Groups/Group2.qml | 18 -- .../SampleModel/Sidebar/Basic/Layout.qml | 20 ++- .../Gui/Pages/Toolbox/Layout.qml | 50 ------ .../Gui/Pages/Toolbox/MainArea/GraphsView.qml | 87 --------- .../Gui/Pages/Toolbox/MainArea/Image.qml | 18 -- .../Pages/Toolbox/MainArea/TextAreaPlain.qml | 22 --- .../Pages/Toolbox/MainArea/TextAreaRich.qml | 31 ---- .../Toolbox/Sidebar/Basic/Groups/Group1.qml | 16 -- .../Toolbox/Sidebar/Basic/Groups/Group2.qml | 30 ---- .../Toolbox/Sidebar/Basic/Groups/Group3.qml | 43 ----- .../Toolbox/Sidebar/Basic/Groups/Group4.qml | 30 ---- .../Pages/Toolbox/Sidebar/Basic/Layout.qml | 45 ----- 32 files changed, 1050 insertions(+), 475 deletions(-) create mode 100644 src/easyshapes_app/Backends/MockQml/AnalysisConfig.qml create mode 100644 src/easyshapes_app/Backends/MockQml/ComponentsFiles.qml create mode 100644 src/easyshapes_app/Backends/MockQml/PositionRestraints.qml create mode 100644 src/easyshapes_app/Backends/MockQml/StructureFiles.qml create mode 100644 src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/AnalysisConfig.qml delete mode 100644 src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/GetStarted.qml create mode 100644 src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Popups/AddAnalysisConfigFiles.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/ComponentsFiles.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/PositionRestraints.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/StructureFiles.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Layout.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Popups/AddComponentFiles.qml create mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Popups/ReplaceStructure.qml delete mode 100644 src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml delete mode 100644 src/easyshapes_app/Gui/Pages/Toolbox/Layout.qml delete mode 100644 src/easyshapes_app/Gui/Pages/Toolbox/MainArea/GraphsView.qml delete mode 100644 src/easyshapes_app/Gui/Pages/Toolbox/MainArea/Image.qml delete mode 100644 src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaPlain.qml delete mode 100644 src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaRich.qml delete mode 100644 src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group1.qml delete mode 100644 src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group2.qml delete mode 100644 src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group3.qml delete mode 100644 src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group4.qml delete mode 100644 src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Layout.qml diff --git a/src/easyshapes_app.qrc b/src/easyshapes_app.qrc index a0e7631..a69b8b4 100644 --- a/src/easyshapes_app.qrc +++ b/src/easyshapes_app.qrc @@ -112,15 +112,18 @@ easyshapes_app.qmlproject easyshapes_app/Backends/MockBackend.qml easyshapes_app/Backends/MockQml/Analysis.qml + easyshapes_app/Backends/MockQml/AnalysisConfig.qml easyshapes_app/Backends/MockQml/BallStructure.qml easyshapes_app/Backends/MockQml/BilayerStructure.qml easyshapes_app/Backends/MockQml/Components.qml + easyshapes_app/Backends/MockQml/ComponentsFiles.qml easyshapes_app/Backends/MockQml/Fractions.qml easyshapes_app/Backends/MockQml/Ions.qml easyshapes_app/Backends/MockQml/Lamellae.qml easyshapes_app/Backends/MockQml/LatticeStructure.qml easyshapes_app/Backends/MockQml/Layers.qml easyshapes_app/Backends/MockQml/MonolayerStructure.qml + easyshapes_app/Backends/MockQml/PositionRestraints.qml easyshapes_app/Backends/MockQml/Project.qml easyshapes_app/Backends/MockQml/qmldir easyshapes_app/Backends/MockQml/Report.qml @@ -129,6 +132,7 @@ easyshapes_app/Backends/MockQml/SampleModel.qml easyshapes_app/Backends/MockQml/Solution.qml easyshapes_app/Backends/MockQml/Status.qml + easyshapes_app/Backends/MockQml/StructureFiles.qml easyshapes_app/Backends/MockQml/VesicleStructure.qml easyshapes_app/Backends/qmldir easyshapes_app/Gui/ApplicationWindow.qml @@ -138,8 +142,9 @@ easyshapes_app/Gui/Globals/References.qml easyshapes_app/Gui/Pages/Analysis/Layout.qml easyshapes_app/Gui/Pages/Analysis/MainArea/Chart.qml - easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/GetStarted.qml + easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/AnalysisConfig.qml easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Layout.qml + easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Popups/AddAnalysisConfigFiles.qml easyshapes_app/Gui/Pages/Home/Content.qml easyshapes_app/Gui/Pages/Home/Popups/About.qml easyshapes_app/Gui/Pages/Project/Layout.qml @@ -161,11 +166,16 @@ easyshapes_app/Gui/Pages/Report/Sidebar/Extra/Layout.qml easyshapes_app/Gui/Pages/SampleModel/Layout.qml easyshapes_app/Gui/Pages/SampleModel/MainArea/GraphsView.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/ComponentsFiles.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/PositionRestraints.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/StructureFiles.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Layout.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Popups/AddComponentFiles.qml + easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Popups/ReplaceStructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Components/Fractions.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/BallStructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/BilayerStructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Components.qml - easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Lamellae.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/LatticeStructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Layers.qml @@ -186,16 +196,6 @@ easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingSolvent.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/LoadExistingSubstructure.qml easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Popups/OpenAssetFile.qml - easyshapes_app/Gui/Pages/Toolbox/Layout.qml - easyshapes_app/Gui/Pages/Toolbox/MainArea/GraphsView.qml - easyshapes_app/Gui/Pages/Toolbox/MainArea/Image.qml - easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaPlain.qml - easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaRich.qml - easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group1.qml - easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group2.qml - easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group3.qml - easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group4.qml - easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Layout.qml easyshapes_app/Gui/qmldir easyshapes_app/Gui/StatusBar.qml easyshapes_app/main.qml diff --git a/src/easyshapes_app/Backends/MockBackend.qml b/src/easyshapes_app/Backends/MockBackend.qml index a250da0..81ea03a 100644 --- a/src/easyshapes_app/Backends/MockBackend.qml +++ b/src/easyshapes_app/Backends/MockBackend.qml @@ -14,6 +14,10 @@ QtObject { property var project: MockLogic.Project property var sampleModel: MockLogic.SampleModel property var components: MockLogic.Components + // Advanced sidebar (Sample Model page) domain singletons. + property var componentsFiles: MockLogic.ComponentsFiles + property var positionRestraints: MockLogic.PositionRestraints + property var structureFiles: MockLogic.StructureFiles // Default fractions set tied to the shared component list. // Used as the fallback for the Fractions sidebar component when no // per-row override is set. @@ -43,12 +47,16 @@ QtObject { property var solution: MockLogic.Solution property var ions: MockLogic.Ions property var analysis: MockLogic.Analysis + // Analysis page — equilibration configuration (config files + force + // field + step range), driving the Equilibrate action. + property var analysisConfig: MockLogic.AnalysisConfig property var status: MockLogic.Status property var report: MockLogic.Report Component.onCompleted: { layers.fractionsSource = MockLogic.Components.loaded lamellae.fractionsSource = MockLogic.Components.loaded + positionRestraints.source = MockLogic.Components.loaded } } diff --git a/src/easyshapes_app/Backends/MockQml/AnalysisConfig.qml b/src/easyshapes_app/Backends/MockQml/AnalysisConfig.qml new file mode 100644 index 0000000..eabbd5b --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/AnalysisConfig.qml @@ -0,0 +1,88 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +// Analysis page — equilibration configuration. +// +// Holds: +// * configFiles — Pattern D ListModel of .mdp paths (delete + edit per row). +// * forceFields — JS array of selectable force-field labels (no edits). +// * forceField — currently chosen entry from forceFields. +// * startStep / stopStep — inclusive integer bounds driving which mdp +// files participate in equilibration (defaults 0..6, matching the +// seeded equil0.mdp..equil6.mdp set). +QtObject { + + readonly property var configFiles: ListModel { + id: configFilesModel + ListElement { path: 'analysis/equil0.mdp' } + ListElement { path: 'analysis/equil1.mdp' } + ListElement { path: 'analysis/equil2.mdp' } + ListElement { path: 'analysis/equil3.mdp' } + ListElement { path: 'analysis/equil4.mdp' } + ListElement { path: 'analysis/equil5.mdp' } + ListElement { path: 'analysis/equil6.mdp' } + } + + readonly property var forceFields: [ + 'CHARMM36', + 'CHARMM27', + 'AMBER99SB-ILDN', + 'AMBER14SB', + 'OPLS-AA/L', + 'GROMOS54a7', + 'MARTINI 3', + 'MARTINI 2.2', + 'GAFF' + ] + + property string forceField: 'CHARMM36' + + property int startStep: 0 + property int stopStep: 6 + + function appendFile(item) { + configFilesModel.append({ path: item.path || '' }) + } + + function appendPath(path) { + configFilesModel.append({ path: path }) + } + + function removeFile(index) { + if (index < 0 || index >= configFilesModel.count) return + configFilesModel.remove(index) + } + + function clearFiles() { configFilesModel.clear() } + + // Mock placeholder for opening the file in an editor. + function editFile(index) { + if (index < 0 || index >= configFilesModel.count) return + console.debug('AnalysisConfig.editFile:', configFilesModel.get(index).path) + } + + function setForceField(value) { + if (forceField === value) return + forceField = value + } + + function setStartStep(value) { + const v = Math.max(0, parseInt(value)) + if (isNaN(v) || startStep === v) return + startStep = v + if (stopStep < startStep) stopStep = startStep + } + + function setStopStep(value) { + const v = Math.max(0, parseInt(value)) + if (isNaN(v) || stopStep === v) return + stopStep = v + if (startStep > stopStep) startStep = stopStep + } +} diff --git a/src/easyshapes_app/Backends/MockQml/ComponentsFiles.qml b/src/easyshapes_app/Backends/MockQml/ComponentsFiles.qml new file mode 100644 index 0000000..65f3b06 --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/ComponentsFiles.qml @@ -0,0 +1,101 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +// Pattern D backend (multi-row list with selection) for the per-component +// file list shown in the Advanced sidebar of the Sample Model page. +// +// The full state is a map of {componentName -> [paths]}. The UI only ever +// sees one component's file list at a time, so we keep that as a single +// ListModel (`files`) and repopulate it whenever the user picks a different +// component through `selectComponent(name)`. Storing the active list as a +// ListModel (rather than a JS array) keeps role-based delegate properties +// and ItemSelectionModel-driven selection working — see QML_MOCKUP_BACKEND +// Pattern D for the rationale. +QtObject { + id: root + + // Name of the component whose files are currently being shown. + // Empty string means no selection — `files` is then empty. + property string selectedComponent: '' + + // Internal map: componentName -> JS array of file paths. Mutations go + // through __syncBack() so the map stays consistent with the ListModel. + property var filesByComponent: ({ + 'DPPC': [ + 'assets/components/DPPC.itp', + 'assets/components/DPPC.gro', + 'assets/components/DPPC.pdb' + ], + 'DOPC': [ + 'assets/components/DOPC.itp', + 'assets/components/DOPC.gro' + ], + 'POPC': [ + 'assets/components/POPC.itp' + ] + }) + + // Active file list for `selectedComponent`. Roles: path. + readonly property var files: ListModel { + id: filesModel + } + + function selectComponent(name) { + if (selectedComponent === name) return + selectedComponent = name + filesModel.clear() + const list = filesByComponent[name] || [] + for (let i = 0; i < list.length; ++i) { + filesModel.append({ path: list[i] }) + } + } + + function appendFile(path) { + if (selectedComponent === '') return + filesModel.append({ path: path }) + __syncBack() + } + + function removeFile(index) { + if (index < 0 || index >= filesModel.count) return + filesModel.remove(index) + __syncBack() + } + + // Export the whole selected component (all its files). Mock backend + // just logs — the real backend will write to disk. + function exportComponent() { + if (selectedComponent === '') return + console.debug('ComponentsFiles.exportComponent:', selectedComponent, + JSON.stringify(filesByComponent[selectedComponent] || [])) + } + + // Persist the current file list for the selected component. Mock just + // mirrors filesModel back into filesByComponent — already kept in sync, + // so this is a no-op for the mock other than the debug print. + function save() { + if (selectedComponent === '') return + __syncBack() + console.debug('ComponentsFiles.save:', selectedComponent, + JSON.stringify(filesByComponent[selectedComponent])) + } + + function __syncBack() { + if (selectedComponent === '') return + const arr = [] + for (let i = 0; i < filesModel.count; ++i) { + arr.push(filesModel.get(i).path) + } + // Reassign the map so the `filesByComponent` property emits its + // Changed signal — keeps any future bindings on the map honest. + const copy = Object.assign({}, filesByComponent) + copy[selectedComponent] = arr + filesByComponent = copy + } +} diff --git a/src/easyshapes_app/Backends/MockQml/PositionRestraints.qml b/src/easyshapes_app/Backends/MockQml/PositionRestraints.qml new file mode 100644 index 0000000..0ea67aa --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/PositionRestraints.qml @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +// Pattern D backend (multi-row list with selection) for position restraints +// shown in the Advanced sidebar of the Sample Model page. +// +// Rows are derived from the shared Components list: one restraint row per +// loaded component, with the component name mirrored read-only and the +// atom / p_form / geom / radius / f_constant fields owned here. Sync is +// surgical so editing one component doesn't reset the others' state. +// +// Roles: component_name, atom, p_form, geom, radius, f_constant. +QtObject { + id: root + + // Shared component list this mirrors. Wired by MockBackend at startup; + // kept as a property (rather than a hard import) to side-step singleton + // init-order quirks — same approach as Layers/Lamellae fractionsSource. + property var source: null + + readonly property var items: ListModel { id: itemsModel } + + onSourceChanged: rebuild() + + property var __sync: Connections { + target: root.source + + function onRowsInserted(parent, first, last) { + for (let i = first; i <= last; ++i) { + const c = root.source.get(i) + itemsModel.insert(i, { + component_name: c.name, + atom: 1, + p_form: 1, + geom: 1, + radius: 0.5, + f_constant: 'POSRES_FC_LIP' + }) + } + } + function onRowsRemoved(parent, first, last) { + for (let i = last; i >= first; --i) itemsModel.remove(i) + } + function onDataChanged(topLeft, bottomRight, roles) { + for (let i = topLeft.row; i <= bottomRight.row; ++i) { + itemsModel.setProperty(i, 'component_name', root.source.get(i).name) + } + } + function onModelReset() { root.rebuild() } + } + + function rebuild() { + itemsModel.clear() + if (!source) return + for (let i = 0; i < source.count; ++i) { + const c = source.get(i) + itemsModel.append({ + component_name: c.name, + atom: 1, + p_form: 1, + geom: 1, + radius: 0.5, + f_constant: 'POSRES_FC_LIP' + }) + } + } + + function setAtom(index, value) { + if (index < 0 || index >= itemsModel.count) return + itemsModel.setProperty(index, 'atom', value) + } + + function setPForm(index, value) { + if (index < 0 || index >= itemsModel.count) return + itemsModel.setProperty(index, 'p_form', value) + } + + function setGeom(index, value) { + if (index < 0 || index >= itemsModel.count) return + itemsModel.setProperty(index, 'geom', value) + } + + function setRadius(index, value) { + if (index < 0 || index >= itemsModel.count) return + itemsModel.setProperty(index, 'radius', value) + } +} diff --git a/src/easyshapes_app/Backends/MockQml/StructureFiles.qml b/src/easyshapes_app/Backends/MockQml/StructureFiles.qml new file mode 100644 index 0000000..61838eb --- /dev/null +++ b/src/easyshapes_app/Backends/MockQml/StructureFiles.qml @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +pragma Singleton + +import QtQuick + + +// Pattern D backend (multi-row list with selection) for structure files +// shown in the Advanced sidebar of the Sample Model page. +// Roles: path. +QtObject { + + readonly property var files: ListModel { + id: filesModel + ListElement { path: 'structure/topology.top' } + ListElement { path: 'structure/coordinates.gro' } + ListElement { path: 'structure/serialized.dat' } + } + + function appendItem(item) { + filesModel.append({ path: item.path || '' }) + } + + function appendPath(path) { + filesModel.append({ path: path }) + } + + function removeItem(index) { + if (index < 0 || index >= filesModel.count) return + filesModel.remove(index) + } + + function clear() { + filesModel.clear() + } + + // Mock placeholder — real backend will persist to the asset library. + function saveToLib() { + console.debug('StructureFiles.saveToLib: paths=' + filesModel.count) + } +} diff --git a/src/easyshapes_app/Backends/MockQml/qmldir b/src/easyshapes_app/Backends/MockQml/qmldir index 3894fee..580dcd6 100644 --- a/src/easyshapes_app/Backends/MockQml/qmldir +++ b/src/easyshapes_app/Backends/MockQml/qmldir @@ -3,6 +3,9 @@ module MockQml singleton Project Project.qml singleton SampleModel SampleModel.qml singleton Components Components.qml +singleton ComponentsFiles ComponentsFiles.qml +singleton PositionRestraints PositionRestraints.qml +singleton StructureFiles StructureFiles.qml Fractions Fractions.qml singleton Layers Layers.qml singleton Lamellae Lamellae.qml @@ -16,5 +19,6 @@ singleton LatticeStructure LatticeStructure.qml singleton Solution Solution.qml singleton Ions Ions.qml singleton Analysis Analysis.qml +singleton AnalysisConfig AnalysisConfig.qml singleton Report Report.qml singleton Status Status.qml diff --git a/src/easyshapes_app/Gui/ApplicationWindow.qml b/src/easyshapes_app/Gui/ApplicationWindow.qml index eb05838..149e8f9 100644 --- a/src/easyshapes_app/Gui/ApplicationWindow.qml +++ b/src/easyshapes_app/Gui/ApplicationWindow.qml @@ -108,16 +108,8 @@ EaComponents.ApplicationWindow { Component.onCompleted: { Globals.References.applicationWindow.appBarCentralTabs.summaryButton = summaryButton } - }, - // Summary page - - // Toolbox page - EaElements.AppBarTabButton { - fontIcon: 'toolbox' - text: qsTr('Toolbox') - ToolTip.text: qsTr('Toolbox with common widgets') } - // Toolbox page + // Summary page ] @@ -131,8 +123,7 @@ EaComponents.ApplicationWindow { Loader { source: 'Pages/Project/Layout.qml' }, Loader { source: 'Pages/SampleModel/Layout.qml' }, Loader { source: 'Pages/Analysis/Layout.qml' }, - Loader { source: 'Pages/Report/Layout.qml' }, - Loader { source: 'Pages/Toolbox/Layout.qml' } + Loader { source: 'Pages/Report/Layout.qml' } ] ///////////// diff --git a/src/easyshapes_app/Gui/Globals/BackendWrapper.qml b/src/easyshapes_app/Gui/Globals/BackendWrapper.qml index 80c5f73..bdcfba1 100644 --- a/src/easyshapes_app/Gui/Globals/BackendWrapper.qml +++ b/src/easyshapes_app/Gui/Globals/BackendWrapper.qml @@ -206,6 +206,39 @@ QtObject { function ionsSaveToCatalog() { activeBackend.ions.saveToCatalog() } function ionsRemoveFromCatalog(index) { activeBackend.ions.removeFromCatalog(index) } + // Components Files (Sample Model Advanced sidebar). Per-component file + // list driven by `componentsFilesSelectedComponent`; switching the + // selection repopulates `componentsFilesFiles`. + readonly property var componentsFilesFiles: activeBackend.componentsFiles.files + readonly property string componentsFilesSelectedComponent: activeBackend.componentsFiles.selectedComponent + + function componentsFilesSelect(name) { activeBackend.componentsFiles.selectComponent(name) } + function componentsFilesAppend(path) { activeBackend.componentsFiles.appendFile(path) } + function componentsFilesRemove(index) { activeBackend.componentsFiles.removeFile(index) } + function componentsFilesExportComponent() { activeBackend.componentsFiles.exportComponent() } + function componentsFilesSave() { activeBackend.componentsFiles.save() } + + // Position Restraints (Sample Model Advanced sidebar). One row per + // loaded component (mirrored from componentsLoaded); component_name is + // read-only here. f_constant is fixed to POSRES_FC_LIP for the mock. + readonly property var positionRestraintsItems: activeBackend.positionRestraints.items + + function positionRestraintsSetAtom(index, value) { activeBackend.positionRestraints.setAtom(index, value) } + function positionRestraintsSetPForm(index, value) { activeBackend.positionRestraints.setPForm(index, value) } + function positionRestraintsSetGeom(index, value) { activeBackend.positionRestraints.setGeom(index, value) } + function positionRestraintsSetRadius(index, value) { activeBackend.positionRestraints.setRadius(index, value) } + + // Structure Files (Sample Model Advanced sidebar). List of structure- + // related files plus actions for saving the set to the asset library + // and re-seeding structure parameters from a serialized data file. + readonly property var structureFilesFiles: activeBackend.structureFiles.files + + function structureFilesAppend(item) { activeBackend.structureFiles.appendItem(item) } + function structureFilesAppendPath(path) { activeBackend.structureFiles.appendPath(path) } + function structureFilesRemove(index) { activeBackend.structureFiles.removeItem(index) } + function structureFilesClear() { activeBackend.structureFiles.clear() } + function structureFilesSaveToLib() { activeBackend.structureFiles.saveToLib() } + //////////////// // Analysis page //////////////// @@ -213,6 +246,21 @@ QtObject { // All the properties and methods related to the analysis page // are defined directly in the Backends/MockQml/Analysis.qml !!! + // Analysis configuration group — equilibration .mdp files, the chosen + // force field, and the inclusive [start, stop] step range. + readonly property var analysisConfigFiles: activeBackend.analysisConfig.configFiles + readonly property var analysisConfigForceFields: activeBackend.analysisConfig.forceFields + readonly property string analysisConfigForceField: activeBackend.analysisConfig.forceField + readonly property int analysisConfigStartStep: activeBackend.analysisConfig.startStep + readonly property int analysisConfigStopStep: activeBackend.analysisConfig.stopStep + + function analysisConfigAppendPath(path) { activeBackend.analysisConfig.appendPath(path) } + function analysisConfigRemoveFile(index) { activeBackend.analysisConfig.removeFile(index) } + function analysisConfigEditFile(index) { activeBackend.analysisConfig.editFile(index) } + function analysisConfigSetForceField(value) { activeBackend.analysisConfig.setForceField(value) } + function analysisConfigSetStartStep(value) { activeBackend.analysisConfig.setStartStep(value) } + function analysisConfigSetStopStep(value) { activeBackend.analysisConfig.setStopStep(value) } + /////////////// // Summary page /////////////// diff --git a/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/AnalysisConfig.qml b/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/AnalysisConfig.qml new file mode 100644 index 0000000..03eb8f4 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/AnalysisConfig.qml @@ -0,0 +1,151 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents + +import Gui.Globals as Globals + + +EaElements.GroupColumn { + + EaComponents.ListView { + id: configFilesList + defaultInfoText: qsTr('No configuration files added') + multiSelection: false + + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 2.5, + -1, + EaStyle.Sizes.tableRowHeight, + EaStyle.Sizes.tableRowHeight + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr('№') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr('Path') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: Globals.BackendWrapper.analysisConfigFiles + + delegateModelAccess: DelegateModel.ReadWrite + + delegate: EaComponents.ListViewDelegate { + required property int index + required property string path + + EaComponents.TableViewLabel { + text: index + 1 + enabled: false + } + EaComponents.TableViewLabel { + text: path + elide: Text.ElideLeft + } + EaComponents.TableViewButton { + fontIcon: 'edit' + ToolTip.text: qsTr('Edit this file') + onClicked: Globals.BackendWrapper.analysisConfigEditFile(index) + } + EaComponents.TableViewButton { + fontIcon: 'minus-circle' + ToolTip.text: qsTr('Remove this file') + onClicked: Globals.BackendWrapper.analysisConfigRemoveFile(index) + } + } + } + + EaElements.SideBarButton { + fontIcon: 'plus-circle' + text: qsTr('Add file(s)') + width: EaStyle.Sizes.sideBarContentWidth * 0.48 + ToolTip.text: qsTr('Pick one or more .mdp files from disk') + onClicked: addFilesLoader.item.open() + } + + // ForceField selector on the left, step-range pair on the right. + Row { + spacing: EaStyle.Sizes.fontPixelSize + property real halfWidth: (EaStyle.Sizes.sideBarContentWidth - spacing) / 2 + property real fieldWidth: (halfWidth - EaStyle.Sizes.fontPixelSize * 0.5) / 2 + + EaElements.ComboBox { + id: forceFieldSelector + width: parent.halfWidth + topInset: forceFieldLabel.height + topPadding: topInset + padding + model: Globals.BackendWrapper.analysisConfigForceFields + currentIndex: Math.max( + 0, + Globals.BackendWrapper.analysisConfigForceFields.indexOf( + Globals.BackendWrapper.analysisConfigForceField)) + onActivated: (i) => Globals.BackendWrapper.analysisConfigSetForceField( + Globals.BackendWrapper.analysisConfigForceFields[i]) + + EaElements.Label { + id: forceFieldLabel + text: qsTr('ForceField') + } + } + + Row { + spacing: EaStyle.Sizes.fontPixelSize * 0.5 + + EaElements.TextField { + id: startStepField + width: parent.parent.fieldWidth + topInset: startStepLabel.height + topPadding: topInset + padding + horizontalAlignment: TextInput.AlignLeft + inputMethodHints: Qt.ImhDigitsOnly + validator: IntValidator { bottom: 0 } + text: Globals.BackendWrapper.analysisConfigStartStep + onEditingFinished: Globals.BackendWrapper.analysisConfigSetStartStep(text) + + EaElements.Label { + id: startStepLabel + text: qsTr('Start step') + } + } + + EaElements.TextField { + id: stopStepField + width: parent.parent.fieldWidth + topInset: stopStepLabel.height + topPadding: topInset + padding + horizontalAlignment: TextInput.AlignLeft + inputMethodHints: Qt.ImhDigitsOnly + validator: IntValidator { bottom: 0 } + text: Globals.BackendWrapper.analysisConfigStopStep + onEditingFinished: Globals.BackendWrapper.analysisConfigSetStopStep(text) + + EaElements.Label { + id: stopStepLabel + text: qsTr('Stop step') + } + } + } + } + + Loader { + id: addFilesLoader + source: '../Popups/AddAnalysisConfigFiles.qml' + } +} diff --git a/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/GetStarted.qml b/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/GetStarted.qml deleted file mode 100644 index a9d1be1..0000000 --- a/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Groups/GetStarted.qml +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtQuick.Controls - -import EasyApplication.Gui.Globals as EaGlobals -import EasyApplication.Gui.Style as EaStyle -import EasyApplication.Gui.Elements as EaElements -import EasyApplication.Gui.Components as EaComponents -import EasyApplication.Gui.Logic as EaLogic - -import Gui.Globals as Globals - -EaElements.GroupColumn { - - // 1st row - EaElements.GroupRow { - spacing: EaStyle.Sizes.fontPixelSize - - // button - EaElements.SideBarButton { - id: generateDataButton - - fontIcon: 'plus-circle' - text: qsTr('Generate new data') - - onClicked: { - console.debug(`Clicking '${text}' button ::: ${this}`) - Globals.BackendWrapper.activeBackend.analysis.generateData() - } - } - // button - - // text input - EaElements.ParamTextField { - height: generateDataButton.height - - inputMethodHints: Qt.ImhDigitsOnly - - value: Globals.BackendWrapper.activeBackend.analysis.dataSize - units: 'points' - - onTextChanged: { - Globals.BackendWrapper.activeBackend.analysis.dataSize = text - } - } - // text input - } - // 1st row -} diff --git a/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Layout.qml index ea6ddaf..d647b5b 100644 --- a/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Layout.qml @@ -5,6 +5,7 @@ import QtQuick import QtQuick.Controls +import EasyApplication.Gui.Style as EaStyle import EasyApplication.Gui.Elements as EaElements import EasyApplication.Gui.Components as EaComponents @@ -14,11 +15,29 @@ import Gui.Globals as Globals EaComponents.SideBarColumn { EaElements.GroupBox { - title: qsTr('Get started') - icon: 'rocket' + title: qsTr('Equilibration setup') + icon: 'sliders-h' collapsed: false - Loader { source: 'Groups/GetStarted.qml' } + Loader { source: 'Groups/AnalysisConfig.qml' } + } + + // Centered "Equilibrate" call-to-action below the groups. + Item { + width: parent.width + height: equilibrateButton.height + EaStyle.Sizes.fontPixelSize + + EaElements.SideBarButton { + id: equilibrateButton + anchors.centerIn: parent + text: qsTr('Equilibrate') + fontIcon: 'magic' + width: EaStyle.Sizes.sideBarContentWidth + enabled: Globals.BackendWrapper.analysisConfigFiles + ? Globals.BackendWrapper.analysisConfigFiles.count > 0 + : false + onClicked: console.debug('Equilibrate clicked') + } } } diff --git a/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Popups/AddAnalysisConfigFiles.qml b/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Popups/AddAnalysisConfigFiles.qml new file mode 100644 index 0000000..34cc2ce --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/Analysis/Sidebar/Basic/Popups/AddAnalysisConfigFiles.qml @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Dialogs + +import Gui.Globals as Globals + + +FileDialog { + fileMode: FileDialog.OpenFiles + nameFilters: [ + 'GROMACS run parameter files (*.mdp)', + 'Any (*)' + ] + + onAccepted: { + for (let i = 0; i < selectedFiles.length; ++i) { + Globals.BackendWrapper.analysisConfigAppendPath(selectedFiles[i].toString()) + } + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Layout.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Layout.qml index 193d1f9..0450c67 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Layout.qml @@ -27,11 +27,13 @@ EaComponents.ContentPage { sideBar: EaComponents.SideBar { tabs: [ - EaElements.TabButton { text: qsTr('Basic controls') } + EaElements.TabButton { text: qsTr('Basic controls') }, + EaElements.TabButton { text: qsTr('Advanced controls') } ] items: [ - Loader { source: 'Sidebar/Basic/Layout.qml' } + Loader { source: 'Sidebar/Basic/Layout.qml' }, + Loader { source: 'Sidebar/Advanced/Layout.qml' } ] continueButton.text: qsTr('Continue') diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/ComponentsFiles.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/ComponentsFiles.qml new file mode 100644 index 0000000..53681f7 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/ComponentsFiles.qml @@ -0,0 +1,169 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents + +import Gui.Globals as Globals + + +EaElements.GroupColumn { + property double buttonWidth: EaStyle.Sizes.sideBarContentWidth * 0.3164 + + // ComboBox + empty-state placeholder share a single slot so the layout + // doesn't reflow between the two states. The ComboBox is hidden (not + // just disabled) when there are no components because its popup keeps + // an ElevationEffect that leaks a soft shadow when the model is empty. + readonly property int componentsCount: + Globals.BackendWrapper.componentsLoaded + ? Globals.BackendWrapper.componentsLoaded.count + : 0 + + EaElements.ComboBox { + id: componentSelector + visible: componentsCount > 0 + width: EaStyle.Sizes.sideBarContentWidth + topInset: componentLabel.height + topPadding: topInset + padding + textRole: 'name' + model: Globals.BackendWrapper.componentsLoaded + + EaElements.Label { + id: componentLabel + text: qsTr('Component') + } + + onActivated: (i) => { + const row = Globals.BackendWrapper.componentsLoaded.get(i) + if (row) Globals.BackendWrapper.componentsFilesSelect(row.name) + } + + // Seed the selection from the currently-selected component, or the + // first component once the model populates. + function syncFromBackend() { + const total = componentsCount + if (total === 0) { + currentIndex = -1 + return + } + const sel = Globals.BackendWrapper.componentsFilesSelectedComponent + if (sel !== '') { + for (let i = 0; i < total; ++i) { + if (Globals.BackendWrapper.componentsLoaded.get(i).name === sel) { + currentIndex = i + return + } + } + } + currentIndex = 0 + const row = Globals.BackendWrapper.componentsLoaded.get(0) + if (row) Globals.BackendWrapper.componentsFilesSelect(row.name) + } + + Component.onCompleted: syncFromBackend() + // Re-seed when the user adds the first component on the Basic tab. + Connections { + target: Globals.BackendWrapper.componentsLoaded + function onCountChanged() { componentSelector.syncFromBackend() } + } + } + + EaElements.Label { + visible: componentsCount === 0 + enabled: false + width: EaStyle.Sizes.sideBarContentWidth + text: qsTr('Load a component on the Basic controls tab to manage its files here.') + wrapMode: Text.WordWrap + } + + EaComponents.ListView { + id: componentFilesList + defaultInfoText: qsTr('No files associated with this component') + multiSelection: false + + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 2.5, + -1, + EaStyle.Sizes.tableRowHeight + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr('№') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr('Path') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: Globals.BackendWrapper.componentsFilesFiles + + delegateModelAccess: DelegateModel.ReadWrite + + delegate: EaComponents.ListViewDelegate { + required property int index + required property string path + + EaComponents.TableViewLabel { + text: index + 1 + enabled: false + } + EaComponents.TableViewLabel { + text: path + elide: Text.ElideLeft + } + EaComponents.TableViewButton { + fontIcon: 'minus-circle' + ToolTip.text: qsTr('Remove this file') + onClicked: Globals.BackendWrapper.componentsFilesRemove(index) + } + } + } + + Grid { + columns: 3 + spacing: EaStyle.Sizes.fontPixelSize + + EaElements.SideBarButton { + fontIcon: 'plus-circle' + text: qsTr('Add new file(s)') + width: buttonWidth + ToolTip.text: qsTr('Pick one or more files from disk and add them to this component') + enabled: Globals.BackendWrapper.componentsFilesSelectedComponent !== '' + onClicked: addFilesLoader.item.open() + } + + EaElements.SideBarButton { + fontIcon: 'file-export' + text: qsTr('Export component') + width: buttonWidth + ToolTip.text: qsTr('Export the selected component to disk') + enabled: Globals.BackendWrapper.componentsFilesSelectedComponent !== '' + onClicked: Globals.BackendWrapper.componentsFilesExportComponent() + } + + EaElements.SideBarButton { + fontIcon: 'save' + text: qsTr('Save') + width: buttonWidth + ToolTip.text: qsTr('Save the file list for this component') + enabled: Globals.BackendWrapper.componentsFilesSelectedComponent !== '' + onClicked: Globals.BackendWrapper.componentsFilesSave() + } + } + + Loader { + id: addFilesLoader + source: '../Popups/AddComponentFiles.qml' + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/PositionRestraints.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/PositionRestraints.qml new file mode 100644 index 0000000..c30d7be --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/PositionRestraints.qml @@ -0,0 +1,100 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents + +import Gui.Globals as Globals + + +EaElements.GroupColumn { + + EaComponents.ListView { + id: positionRestraintsList + defaultInfoText: qsTr('No position restraints defined') + multiSelection: false + + columnWidths: [ + -1, + EaStyle.Sizes.fontPixelSize * 4, + EaStyle.Sizes.fontPixelSize * 4, + EaStyle.Sizes.fontPixelSize * 4, + EaStyle.Sizes.fontPixelSize * 5, + EaStyle.Sizes.fontPixelSize * 8 + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr('Component') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr('Atom') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr('P. form') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr('Geom.') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr('Radius') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr('F. constant') + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: Globals.BackendWrapper.positionRestraintsItems + + delegateModelAccess: DelegateModel.ReadWrite + + delegate: EaComponents.ListViewDelegate { + required property int index + required property string component_name + required property int atom + required property int p_form + required property int geom + required property double radius + required property string f_constant + + EaComponents.TableViewLabel { + text: component_name + } + EaComponents.ListViewTextInput { + text: atom + validator: IntValidator { bottom: 0 } + onEditingFinished: Globals.BackendWrapper.positionRestraintsSetAtom(index, parseInt(text)) + } + EaComponents.ListViewTextInput { + text: p_form + validator: IntValidator { bottom: 0 } + onEditingFinished: Globals.BackendWrapper.positionRestraintsSetPForm(index, parseInt(text)) + } + EaComponents.ListViewTextInput { + text: geom + validator: IntValidator { bottom: 0 } + onEditingFinished: Globals.BackendWrapper.positionRestraintsSetGeom(index, parseInt(text)) + } + EaComponents.ListViewTextInput { + text: radius + validator: DoubleValidator { bottom: 0 } + onEditingFinished: Globals.BackendWrapper.positionRestraintsSetRadius(index, parseFloat(text)) + } + EaComponents.TableViewLabel { + text: f_constant + enabled: false + } + } + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/StructureFiles.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/StructureFiles.qml new file mode 100644 index 0000000..41820e5 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Groups/StructureFiles.qml @@ -0,0 +1,95 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents + +import Gui.Globals as Globals + + +EaElements.GroupColumn { + property double buttonWidth: EaStyle.Sizes.sideBarContentWidth * 0.48 + + EaComponents.ListView { + id: structureFilesList + defaultInfoText: qsTr('No structure files available') + multiSelection: false + + columnWidths: [ + EaStyle.Sizes.fontPixelSize * 2.5, + -1, + EaStyle.Sizes.tableRowHeight + ] + + header: EaComponents.ListViewHeader { + EaComponents.TableViewLabel { + text: qsTr('№') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + text: qsTr('File') + color: EaStyle.Colors.themeForegroundMinor + } + EaComponents.TableViewLabel { + color: EaStyle.Colors.themeForegroundMinor + } + } + + model: Globals.BackendWrapper.structureFilesFiles + + delegateModelAccess: DelegateModel.ReadWrite + + delegate: EaComponents.ListViewDelegate { + required property int index + required property string path + + EaComponents.TableViewLabel { + text: index + 1 + enabled: false + } + EaComponents.TableViewLabel { + text: path + elide: Text.ElideLeft + } + EaComponents.TableViewButton { + fontIcon: 'minus-circle' + ToolTip.text: qsTr('Remove this file') + onClicked: Globals.BackendWrapper.structureFilesRemove(index) + } + } + } + + Grid { + columns: 2 + spacing: EaStyle.Sizes.fontPixelSize + + EaElements.SideBarButton { + fontIcon: 'save' + text: qsTr('Save to lib') + width: buttonWidth + ToolTip.text: qsTr('Save the current structure files to the asset library') + enabled: Globals.BackendWrapper.structureFilesFiles + ? Globals.BackendWrapper.structureFilesFiles.count > 0 + : false + onClicked: Globals.BackendWrapper.structureFilesSaveToLib() + } + + EaElements.SideBarButton { + fontIcon: 'folder-open' + text: qsTr('Replace structure') + width: buttonWidth + ToolTip.text: qsTr('Pick a directory to replace the current structure with') + onClicked: replaceStructureLoader.item.open() + } + } + + Loader { + id: replaceStructureLoader + source: '../Popups/ReplaceStructure.qml' + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Layout.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Layout.qml new file mode 100644 index 0000000..a3341e0 --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Layout.qml @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Controls + +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents + + +EaComponents.SideBarColumn { + + EaElements.GroupBox { + title: qsTr('Components Files') + icon: 'file-alt' + collapsed: false + + Loader { source: 'Groups/ComponentsFiles.qml' } + } + + EaElements.GroupBox { + title: qsTr('Position Restraints') + icon: 'thumbtack' + + Loader { source: 'Groups/PositionRestraints.qml' } + } + + EaElements.GroupBox { + title: qsTr('Structure Files') + icon: 'folder-open' + + Loader { source: 'Groups/StructureFiles.qml' } + } + +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Popups/AddComponentFiles.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Popups/AddComponentFiles.qml new file mode 100644 index 0000000..9c641da --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Popups/AddComponentFiles.qml @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Dialogs + +import Gui.Globals as Globals + + +FileDialog { + fileMode: FileDialog.OpenFiles + nameFilters: [ + 'Any (*)', + 'Structure files (*.gro *.pdb *.xyz)', + 'Topology files (*.itp)', + 'Smiles files (*.sml)' + ] + + onAccepted: { + for (let i = 0; i < selectedFiles.length; ++i) { + Globals.BackendWrapper.componentsFilesAppend(selectedFiles[i].toString()) + } + } +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Popups/ReplaceStructure.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Popups/ReplaceStructure.qml new file mode 100644 index 0000000..66fe84e --- /dev/null +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Advanced/Popups/ReplaceStructure.qml @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: 2024 EasyApp contributors +// SPDX-License-Identifier: BSD-3-Clause +// © 2024 Contributors to the EasyApp project + +import QtQuick +import QtQuick.Dialogs + + +FolderDialog { + title: qsTr('Select a directory to replace the structure with') +} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml deleted file mode 100644 index af615cc..0000000 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Groups/Group2.qml +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtQuick.Controls - -import EasyApplication.Gui.Globals as EaGlobals -import EasyApplication.Gui.Style as EaStyle -import EasyApplication.Gui.Elements as EaElements -import EasyApplication.Gui.Components as EaComponents -import EasyApplication.Gui.Logic as EaLogic - -import Gui.Globals as Globals - -EaElements.GroupColumn { - -} diff --git a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml index 2c4ddce..400bc4c 100644 --- a/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml +++ b/src/easyshapes_app/Gui/Pages/SampleModel/Sidebar/Basic/Layout.qml @@ -5,6 +5,7 @@ import QtQuick import QtQuick.Controls +import EasyApplication.Gui.Style as EaStyle import EasyApplication.Gui.Elements as EaElements import EasyApplication.Gui.Components as EaComponents @@ -107,11 +108,20 @@ EaComponents.SideBarColumn { Loader { source: 'Groups/Solution.qml' } } - EaElements.GroupBox { - title: qsTr('Group 1') - icon: 'rocket' - - Loader { source: 'Groups/Group2.qml' } + // Centered "Assemble" call-to-action below the groups. + Item { + width: parent.width + height: assembleButton.height + EaStyle.Sizes.fontPixelSize + + EaElements.SideBarButton { + id: assembleButton + anchors.centerIn: parent + text: qsTr('Assemble') + fontIcon: 'cubes' + width: EaStyle.Sizes.sideBarContentWidth + enabled: Globals.BackendWrapper.sampleModelLoaded.length > 0 + onClicked: console.debug('Assemble clicked') + } } } diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/Layout.qml b/src/easyshapes_app/Gui/Pages/Toolbox/Layout.qml deleted file mode 100644 index cec9465..0000000 --- a/src/easyshapes_app/Gui/Pages/Toolbox/Layout.qml +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtQuick.Controls - -import EasyApplication.Gui.Style as EaStyle -import EasyApplication.Gui.Globals as EaGlobals -import EasyApplication.Gui.Elements as EaElements -import EasyApplication.Gui.Components as EaComponents - -import Gui.Globals as Globals - - -EaComponents.ContentPage { - - mainView: EaComponents.MainContent { - tabs: [ - EaElements.TabButton { text: qsTr('Image') }, - EaElements.TabButton { text: qsTr('EaElements.GraphsView') }, - EaElements.TabButton { text: qsTr('EaElements.TextArea (Plain)') }, - EaElements.TabButton { text: qsTr('EaElements.TextArea (Rich)') } - ] - - items: [ - Loader { source: 'MainArea/Image.qml' }, - Loader { source: 'MainArea/GraphsView.qml' }, - Loader { source: 'MainArea/TextAreaPlain.qml' }, - Loader { source: 'MainArea/TextAreaRich.qml' } - ] - } - - sideBar: EaComponents.SideBar { - tabs: [ - EaElements.TabButton { text: qsTr('Basic controls') } - ] - - items: [ - Loader { source: 'Sidebar/Basic/Layout.qml' } - ] - - continueButton.visible: false - - } - - Component.onCompleted: console.debug(`Toolbox page loaded ::: ${this}`) - Component.onDestruction: console.debug(`Toolbox page destroyed ::: ${this}`) - -} diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/GraphsView.qml b/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/GraphsView.qml deleted file mode 100644 index 276dfff..0000000 --- a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/GraphsView.qml +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtGraphs - -import EasyApplication.Gui.Style as EaStyle -import EasyApplication.Gui.Elements as EaElements - -import Gui.Globals as Globals - - -GraphsView { - anchors.fill: parent - - marginTop: EaStyle.Sizes.fontPixelSize * 2 - marginBottom: EaStyle.Sizes.fontPixelSize * 2 - marginLeft: EaStyle.Sizes.fontPixelSize - marginRight: EaStyle.Sizes.fontPixelSize * 2 - - zoomAreaEnabled: true - - // theme - theme: GraphsTheme { - backgroundColor: EaStyle.Colors.chartBackground - plotAreaBackgroundColor: EaStyle.Colors.chartBackground - - axisX.mainColor: EaStyle.Colors.chartGridLine - axisX.mainWidth: 0 - - axisY.mainColor: EaStyle.Colors.chartGridLine - axisY.mainWidth: 0 - - gridVisible: true - grid.mainWidth: 1 - grid.subWidth: 0 - grid.mainColor: EaStyle.Colors.chartGridLine - grid.subColor: EaStyle.Colors.chartMinorGridLine - - labelFont.family: EaStyle.Fonts.fontFamily - labelFont.pixelSize: EaStyle.Sizes.fontPixelSize - labelTextColor: EaStyle.Colors.chartLabels - } - // theme - - // axisX - axisX: ValueAxis { - labelDelegate: TextEdit { - horizontalAlignment: TextInput.AlignHCenter - verticalAlignment: Text.AlignVCenter - bottomPadding: EaStyle.Sizes.fontPixelSize - color: EaStyle.Colors.chartLabels - } - - titleText: 'x' - min: 0 - max: 100 - } - // axisX - - // axisY - axisY: ValueAxis { - labelDelegate: TextEdit { - horizontalAlignment: TextInput.AlignRight - verticalAlignment: Text.AlignVCenter - rightPadding: -EaStyle.Sizes.fontPixelSize - color: EaStyle.Colors.chartLabels - } - - titleText: 'y' - min: -2 - max: 2 - } - // axisY - - // lineSeries - LineSeries { - color: 'red' - - XYPoint { x: 0; y: -1 } - XYPoint { x: 50; y: 1.5 } - XYPoint { x: 100; y: -0.5 } - } - // lineSeries - -} diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/Image.qml b/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/Image.qml deleted file mode 100644 index 045b3c7..0000000 --- a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/Image.qml +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtGraphs - -import EasyApplication.Gui.Style as EaStyle -import EasyApplication.Gui.Elements as EaElements - -import Gui.Globals as Globals - -Image { - - fillMode: Image.PreserveAspectFit - source: "../../../Resources/Images/structure.png" - -} diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaPlain.qml b/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaPlain.qml deleted file mode 100644 index 8adbf68..0000000 --- a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaPlain.qml +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtGraphs - -import EasyApplication.Gui.Style as EaStyle -import EasyApplication.Gui.Elements as EaElements - -import Gui.Globals as Globals - - -EaElements.TextArea { - text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, -sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. -Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris -nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in -reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla -pariatur. Excepteur sint occaecat cupidatat non proident, sunt in -culpa qui officia deserunt mollit anim id est laborum.' -} diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaRich.qml b/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaRich.qml deleted file mode 100644 index 377af9f..0000000 --- a/src/easyshapes_app/Gui/Pages/Toolbox/MainArea/TextAreaRich.qml +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtGraphs - -import EasyApplication.Gui.Style as EaStyle -import EasyApplication.Gui.Elements as EaElements - -import Gui.Globals as Globals - - -EaElements.TextArea { - textFormat: TextEdit.RichText - - text: '

- Lorem ipsum dolor sit amet, consectetur adipiscing elit, - sed do eiusmod tempor incididunt ut labore et dolore
magna aliqua. - Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris - nisi ut aliquip ex ea
commodo consequat. -

- -

- Duis aute irure dolor in - reprehenderit in voluptate velit esse cillum dolore eu fugiat - nulla pariatur.
- Excepteur sint occaecat cupidatat non proident, sunt in - culpa qui officia deserunt mollit anim id est laborum. -

' -} diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group1.qml b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group1.qml deleted file mode 100644 index 6fd6687..0000000 --- a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group1.qml +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtQuick.Controls - -import EasyApplication.Gui.Globals as EaGlobals -import EasyApplication.Gui.Style as EaStyle -import EasyApplication.Gui.Elements as EaElements -import EasyApplication.Gui.Components as EaComponents -import EasyApplication.Gui.Logic as EaLogic - -import Gui.Globals as Globals - -EaElements.GroupColumn {} diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group2.qml b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group2.qml deleted file mode 100644 index 04299dd..0000000 --- a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group2.qml +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtQuick.Controls - -import EasyApplication.Gui.Globals as EaGlobals -import EasyApplication.Gui.Style as EaStyle -import EasyApplication.Gui.Elements as EaElements -import EasyApplication.Gui.Components as EaComponents -import EasyApplication.Gui.Logic as EaLogic - -import Gui.Globals as Globals - -EaElements.GroupColumn { - - EaElements.Label { - text: "EaElements.Label" - } - - EaElements.TextInput { - text: 'EaElements.TextInput' - } - - EaElements.TextField { - text: 'EaElements.TextField' - } - -} diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group3.qml b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group3.qml deleted file mode 100644 index b32087f..0000000 --- a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group3.qml +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtQuick.Controls - -import EasyApplication.Gui.Globals as EaGlobals -import EasyApplication.Gui.Style as EaStyle -import EasyApplication.Gui.Elements as EaElements -import EasyApplication.Gui.Components as EaComponents -import EasyApplication.Gui.Logic as EaLogic - -import Gui.Globals as Globals - -EaElements.GroupColumn { - - EaElements.ComboBox { - model: ["EaElements.ComboBox 1", "EaElements.ComboBox 2", "EaElements.ComboBox 3"] - } - - Column { - EaElements.RadioButton { - checked: true - text: qsTr("EaElements.RadioButton 1") - } - EaElements.RadioButton { - text: qsTr("EaElements.RadioButton 2") - } - } - - Column { - spacing: 10 - EaElements.CheckBox { - checked: true - text: qsTr("EaElements.CheckBox 1") - } - EaElements.CheckBox { - text: qsTr("EaElements.CheckBox 2") - } - } - -} diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group4.qml b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group4.qml deleted file mode 100644 index 42e891f..0000000 --- a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Groups/Group4.qml +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtQuick.Controls - -import EasyApplication.Gui.Globals as EaGlobals -import EasyApplication.Gui.Style as EaStyle -import EasyApplication.Gui.Elements as EaElements -import EasyApplication.Gui.Components as EaComponents -import EasyApplication.Gui.Logic as EaLogic - -import Gui.Globals as Globals - -EaElements.GroupColumn { - - - EaElements.SideBarButton { - fontIcon: 'plus-circle' - text: 'EaElements.SideBarButton' - } - - EaElements.Slider { - from: 1 - value: 25 - to: 100 - } - -} diff --git a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Layout.qml b/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Layout.qml deleted file mode 100644 index ad4c6ca..0000000 --- a/src/easyshapes_app/Gui/Pages/Toolbox/Sidebar/Basic/Layout.qml +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-FileCopyrightText: 2024 EasyApp contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2024 Contributors to the EasyApp project - -import QtQuick -import QtQuick.Controls - -import EasyApplication.Gui.Elements as EaElements -import EasyApplication.Gui.Components as EaComponents - -import Gui.Globals as Globals - - -EaComponents.SideBarColumn { - - EaElements.GroupBox { - title: qsTr('Group 1: Empty') - icon: 'rocket' - - Loader { source: 'Groups/Group1.qml' } - } - - EaElements.GroupBox { - title: qsTr('Group 2: Label, TextInput, TextField') - icon: 'rocket' - collapsed: false - - Loader { source: 'Groups/Group2.qml' } - } - - EaElements.GroupBox { - title: qsTr('Group 3: ComboBox, RadioButton, CheckBox') - icon: 'rocket' - - Loader { source: 'Groups/Group3.qml' } - } - - EaElements.GroupBox { - title: qsTr('Group 4: SidebarButton, Slider') - icon: 'rocket' - - Loader { source: 'Groups/Group4.qml' } - } - -}