From 00a440754c7982121ea3602e6c981b1c02f2afa6 Mon Sep 17 00:00:00 2001 From: EndrII Date: Mon, 17 Feb 2025 13:48:52 +0100 Subject: [PATCH] added new models storages --- CMake | 2 +- CMakeLists.txt | 20 +- Examples/CMakeLists.txt | 2 +- Examples/src/main.cpp | 2 +- Examples/src/main.qml | 2 +- ViewSolutions/CMakeLists.txt | 3 +- .../src/ViewSolutionsModule/ActivityPage.qml | 42 +++ .../ViewSolutionsModule/ActivityProcessor.qml | 313 ++++++++++++++++++ .../ActivityProcessorHeader.qml | 106 ++++++ .../src/ViewSolutionsModule/ImageView.qml | 7 + .../ViewPortDelegatBase.qml | 7 + .../ViewPortGradientPage.qml | 7 + .../src/ViewSolutionsModule/ViewPortPage.qml | 7 + .../ViewPortStaticGradientPage.qml | 7 + .../ViewPortStaticPage.qml | 7 + .../ViewSolutionsControl.qml | 7 + ViewSolutions/src/ViewSolutionsModule/qmldir | 3 + ViewSolutions/src/ViewSolutionsResources.qrc | 3 + ViewSolutions/src/basehashmodel.cpp | 2 + ViewSolutions/src/basehashmodel.h | 188 +++++++++++ ViewSolutions/src/baselistmodel.h | 145 ++++++++ ViewSolutions/src/colorpicker.cpp | 7 + ViewSolutions/src/colorpicker.h | 7 + ViewSolutions/src/iguitokensmodel.cpp | 23 ++ ViewSolutions/src/iguitokensmodel.h | 140 ++++++++ ViewSolutions/src/imodel.cpp | 30 ++ ViewSolutions/src/imodel.h | 69 ++++ ViewSolutions/src/listviewmodel.cpp | 9 +- ViewSolutions/src/listviewmodel.h | 7 + ViewSolutions/src/modelstorage.cpp | 41 +++ ViewSolutions/src/modelstorage.h | 61 ++++ ViewSolutions/src/qmlcolorpicker.cpp | 80 ++--- ViewSolutions/src/qmlcolorpicker.h | 29 +- ViewSolutions/src/variantlistmodel.h | 23 ++ ViewSolutions/src/viewsolutions.cpp | 35 +- ViewSolutions/src/viewsolutions.h | 17 +- 36 files changed, 1378 insertions(+), 82 deletions(-) create mode 100644 ViewSolutions/src/ViewSolutionsModule/ActivityPage.qml create mode 100644 ViewSolutions/src/ViewSolutionsModule/ActivityProcessor.qml create mode 100644 ViewSolutions/src/ViewSolutionsModule/ActivityProcessorHeader.qml create mode 100644 ViewSolutions/src/basehashmodel.cpp create mode 100644 ViewSolutions/src/basehashmodel.h create mode 100644 ViewSolutions/src/baselistmodel.h create mode 100644 ViewSolutions/src/iguitokensmodel.cpp create mode 100644 ViewSolutions/src/iguitokensmodel.h create mode 100644 ViewSolutions/src/imodel.cpp create mode 100644 ViewSolutions/src/imodel.h create mode 100644 ViewSolutions/src/modelstorage.cpp create mode 100644 ViewSolutions/src/modelstorage.h create mode 100644 ViewSolutions/src/variantlistmodel.h diff --git a/CMake b/CMake index c144d4d..f96d16e 160000 --- a/CMake +++ b/CMake @@ -1 +1 @@ -Subproject commit c144d4d957bf63dafe9c2798b4660168cbd848e4 +Subproject commit f96d16ec9be058fc35f3966e0a8dfe7d62ad3fb1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b2f811..d2fa71f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2018-2021 QuasarApp. +# Copyright (C) 2018-2025 QuasarApp. # Distributed under the lgplv3 software license, see the accompanying # Everyone is permitted to copy and distribute verbatim copies # of this license document, but changing it is not allowed. @@ -14,20 +14,13 @@ if(TARGET ${PROJECT_NAME}) endif() -if ( NOT DEFINED VIEWSOLUTIONS_EXAMPLES ) - set(VIEWSOLUTIONS_EXAMPLES ON) - - if (DEFINED TARGET_PLATFORM_TOOLCHAIN) - if (${TARGET_PLATFORM_TOOLCHAIN} STREQUAL "wasm32") - set(VIEWSOLUTIONS_EXAMPLES OFF) - endif() - endif() - - if (ANDROID) - set(VIEWSOLUTIONS_EXAMPLES OFF) - endif() +if (ANDROID OR IOS) + option(VIEWSOLUTIONS_EXAMPLES "Build examples" OFF) +else() + option(VIEWSOLUTIONS_EXAMPLES "Build examples" ON) endif() + include(CMake/QuasarApp.cmake) find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Quick QuickControls2 REQUIRED) @@ -36,7 +29,6 @@ find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick QuickControls2 REQUIRED add_subdirectory(ViewSolutions) if (VIEWSOLUTIONS_EXAMPLES ) - message("DISABLE_EXAMPLES = ${DISABLE_EXAMPLES}") add_subdirectory(Examples) endif() diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index 804a889..432e37b 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2018-2021 QuasarApp. +# Copyright (C) 2018-2025 QuasarApp. # Distributed under the lgplv3 software license, see the accompanying # Everyone is permitted to copy and distribute verbatim copies # of this license document, but changing it is not allowed. diff --git a/Examples/src/main.cpp b/Examples/src/main.cpp index 8c77fd4..83b35f1 100644 --- a/Examples/src/main.cpp +++ b/Examples/src/main.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** # -# Copyright (C) 2018-2021 QuasarApp. +# Copyright (C) 2018-2025 QuasarApp. # Distributed under the lgplv3 software license, see the accompanying # Everyone is permitted to copy and distribute verbatim copies # of this license document, but changing it is not allowed. diff --git a/Examples/src/main.qml b/Examples/src/main.qml index ab8022f..e7383ef 100644 --- a/Examples/src/main.qml +++ b/Examples/src/main.qml @@ -1,7 +1,7 @@ /**************************************************************************** ** # -# Copyright (C) 2018-2021 QuasarApp. +# Copyright (C) 2018-2025 QuasarApp. # Distributed under the lgplv3 software license, see the accompanying # Everyone is permitted to copy and distribute verbatim copies # of this license document, but changing it is not allowed. diff --git a/ViewSolutions/CMakeLists.txt b/ViewSolutions/CMakeLists.txt index ae3ebb1..d995886 100644 --- a/ViewSolutions/CMakeLists.txt +++ b/ViewSolutions/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2018-2021 QuasarApp. +# Copyright (C) 2018-2025 QuasarApp. # Distributed under the lgplv3 software license, see the accompanying # Everyone is permitted to copy and distribute verbatim copies # of this license document, but changing it is not allowed. @@ -18,6 +18,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) file(GLOB SOURCE_CPP "src/*.cpp" + "src/*.h" "src/*.qrc" ) diff --git a/ViewSolutions/src/ViewSolutionsModule/ActivityPage.qml b/ViewSolutions/src/ViewSolutionsModule/ActivityPage.qml new file mode 100644 index 0000000..1a6eba6 --- /dev/null +++ b/ViewSolutions/src/ViewSolutionsModule/ActivityPage.qml @@ -0,0 +1,42 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +import QtQuick +import QtQuick.Controls + +Control { + property string title: "" + property string subTitle: "" + + // shows the back button with text + property bool isFullBackButton: false + property bool buttonBack: true + + // shows close button on the ActivityProcessor header + property bool closeButton: true + property bool closeButtonBorder: false + // attach to this property link to ActivityProcessor (if is it not to abble atomaticaly) + property var activityProcessorLink: null + + // emit this signal when you finish work on this page. The ActivityProcessor will inoke pop method. + signal finish(); + + // invoked by ActivityProcessor when the will be invoked resetState of ActivityProcessor + property var resetState: () => {} + + // this is lambda function with required action of this page. + // If is it not null then MainActivityProcessor will execute this action and forbide distroy this UI. + property var requireAction: null + + // This is call back function, If this function exists its will be called before pop object from main activity, but if requireAction is null. + // Note: this field will fill if you add callback function on newActivityWithProp, newActivity or newActivityFromComponent functions! + property var activityCallBack: () => {} + property bool saveChangesInUnsaved: false + + topPadding: 24 +} diff --git a/ViewSolutions/src/ViewSolutionsModule/ActivityProcessor.qml b/ViewSolutions/src/ViewSolutionsModule/ActivityProcessor.qml new file mode 100644 index 0000000..04409be --- /dev/null +++ b/ViewSolutions/src/ViewSolutionsModule/ActivityProcessor.qml @@ -0,0 +1,313 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +import QtQuick +import QtQuick.Controls + +Pane { + id: root + + // use Comonent delegates only + property alias initialItem: stackView.initialItem + property alias currentItem: stackView.currentItem + property alias titlesAligh: headerView.titlesAligh + property bool cache: true + property bool enableHeader: true + + padding: 0 + clip: true + + background: Item{} + + contentItem: Page { + id: contentPage + + padding: 0 + background: Item{} + + header: ActivityProcessorHeader { + id: headerView + visible: root.enableHeader + title: { + if (root.enableHeader && stackView.currentItem && stackView.currentItem.title) { + return stackView.currentItem.title + } + + return "" + } + + subTitle: { + if (root.enableHeader && stackView.currentItem && stackView.currentItem.subTitle) { + return stackView.currentItem.subTitle + } + return "" + + } + backButton: root.enableHeader && stackView.depth > 1 && (stackView.currentItem && stackView.currentItem.buttonBack) + fullBackButton: root.enableHeader && (stackView.currentItem && stackView.currentItem.isFullBackButton) + + closeButton: root.enableHeader && (stackView.currentItem && stackView.currentItem.closeButton) + closeButtonBorder: root.enableHeader && (stackView.currentItem && stackView.currentItem.closeButtonBorder) + titlesAligh: Text.AlignLeft + onBackClicked: { + popItem() + } + + onCloseClicked: { + popupProcessor.close() + } + } + + contentItem: StackView { + Connections { + target: (stackView.currentItem && stackView.currentItem.finish)? stackView.currentItem : null + + function onFinish() { + popItem(); + } + } + + padding: 0 + id: stackView + + implicitWidth: stackView.currentItem.implicitWidth + implicitHeight: stackView.currentItem.implicitHeight + + property int durationAnimation: 400 + popEnter: Transition { + ParallelAnimation { + NumberAnimation { + properties: "opacity" + from: 0 + to: 1 + duration: stackView.durationAnimation + } + NumberAnimation { + properties: "x" + from: (stackView.mirrored ? -1 : 1) * -stackView.width + to: 0 + duration: stackView.durationAnimation + easing.type: Easing.OutCubic + } + } + } + + popExit: Transition { + ParallelAnimation { + NumberAnimation { + properties: "opacity" + from: 1 + to: 0 + duration: stackView.durationAnimation / 2 + } + NumberAnimation { + properties: "x" + from: 0 + to: (stackView.mirrored ? -1 : 1) * stackView.width + duration: stackView.durationAnimation + easing.type: Easing.OutCubic + } + } + } + + pushEnter: Transition { + ParallelAnimation { + NumberAnimation { + properties: "opacity" + from: 0 + to: 1 + duration: stackView.durationAnimation + } + NumberAnimation { + properties: "x" + from: (stackView.mirrored ? -1 : 1) * stackView.width + to: 0 + duration: stackView.durationAnimation + easing.type: Easing.OutCubic + } + } + } + + pushExit: Transition { + ParallelAnimation { + NumberAnimation { + properties: "opacity" + from: 1 + to: 0 + duration: stackView.durationAnimation / 2 + } + NumberAnimation { + properties: "x" + from: 0 + to: (stackView.mirrored ? -1 : 1) * -stackView.width + duration: stackView.durationAnimation + easing.type: Easing.OutCubic + } + } + } + } + } + + // create new activity from component with model activityModel, after drop this activity will be called callback function + // Note The callback function works only with ActivityPage childs. + function newActivityFromComponent(component, activityModel, callback) { + var activity = component.createObject(stackView); + if (activity === null) { + // Error Handling + console.error("Error creating Activity object. " + component.errorString()); + return; + } + + if (activityModel && typeof(activity.model) != "undefined") { + activity.model = activityModel; + } + + + if (typeof(activity.activityCallBack) === "function" + && typeof(callback) === "function") { + activity.activityCallBack = callback; + } + stackView.push(activity); + + return activity; + } + + // create new activity from file with model activityModel, after drop this activity will be called callback function + // Note The callback function works only with ActivityPage childs. + function newActivity(viewFile, activityModel, callback) { + + if (!viewFile || !viewFile.length) { + console.error("Failed to create activity. view object is invalid"); + return; + } + + var component = Qt.createComponent(viewFile); + + if (component.status === Component.Ready) { + + + var activity = component.createObject(stackView); + if (activity === null) { + // Error Handling + console.error("Error creating Activity object"); + return; + } + + if (activityModel && typeof(activity.model) != "undefined") { + activity.model = activityModel; + } + + + stackView.push(activity); + + if (typeof(activity.activityCallBack) === "function" + && typeof(callback) === "function") { + activity.activityCallBack = callback; + } + return activity; + + } else if (component.status === Component.Error) { + // Error Handling + console.log("Error loading component:", component.errorString()); + } + } + + // create new activity from file with custom propery list "properties", after drop this activity will be called callback function + // Note The callback function works only with ActivityPage childs. + function newActivityWithProp(viewFile, properties, callback) { + + if (!viewFile || !viewFile.length) { + console.error("Failed to create activity. view object is invalid"); + return; + } + + var component = Qt.createComponent(viewFile); + + if (component.status === Component.Ready) { + + var activity = component.createObject(stackView, properties); + if (activity === null) { + // Error Handling + console.error("Error creating Activity object"); + return; + } + + stackView.push(activity); + + if (typeof(activity.activityCallBack) === "function" + && typeof(callback) === "function") { + activity.activityCallBack = callback; + } + return activity; + + } else if (component.status === Component.Error) { + // Error Handling + console.log("Error loading component:", component.errorString()); + } + } + + // create new activity from component with custom propery list "properties", after drop this activity will be called callback function + // Note The callback function works only with ActivityPage childs. + function newActivityFromComponentWithProp(component, properties, callback) { + + var activity = component.createObject(stackView, properties); + if (activity === null) { + // Error Handling + console.error("Error creating Activity object. " + component.errorString()); + return; + } + + stackView.push(activity); + + if (typeof(activity.activityCallBack) === "function" + && typeof(callback) === "function") { + activity.activityCallBack = callback; + } + + return activity; + } + + function popItem() { + let actionRequire = stackView.currentItem && stackView.currentItem.requireAction && stackView.currentItem.requireAction(); + + if (actionRequire) { + return false; + } + + var item = stackView.pop(); + if (item) { + if (item.activityCallBack) { + item.activityCallBack() + } + item.destroy(1000); + } + + return true; + } + + function resetState() { + if (cache && stackView.depth < 3) { + + // About limitation: the stackView.pop can't change focus to first element if the elements depth bigger then 2. + + while(stackView.depth > 1) { + if (!popItem()) { + break; + } + } + if (stackView.currentItem && typeof(stackView.currentItem.resetState) === "function") { + stackView.currentItem.resetState(); + } + + } else { + stackView.clear() + stackView.push(stackView.initialItem) + } + } + +} diff --git a/ViewSolutions/src/ViewSolutionsModule/ActivityProcessorHeader.qml b/ViewSolutions/src/ViewSolutionsModule/ActivityProcessorHeader.qml new file mode 100644 index 0000000..c8d5f81 --- /dev/null +++ b/ViewSolutions/src/ViewSolutionsModule/ActivityProcessorHeader.qml @@ -0,0 +1,106 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +GridLayout { + + id: root + property int titlesAligh: Text.AlignHCenter + + property font titlesFont: tokensModel.font_title_uppercase + property alias rightSubtitleWidget: rightSubtitleControl.contentItem + + property bool closeButtonBorder: true + property string title: "" + property bool titleUppercase: true + property string subTitle: "" + property bool backButton: false + property bool fullBackButton: false + property bool closeButton: false + property int headerRowHeight: 40 + + signal backClicked() + signal closeClicked() + + columns: 3 + + Item { + implicitWidth: headerRowHeight + visible: !backButton && titlesAligh === Text.AlignHCenter + } + + Button { + + // Layout.alignment: Qt.AlignLeft + visible: backButton + icon: (root.fullBackButton)? "qrc:/assets/icons/arrowleft_tac.svg" + :"qrc:/assets/icons/arrowleft.svg" + fontColor: tokensModel.color_text_secondary + backgroundBorderColor: tokensModel.color_border_secondary + isFlat: !root.fullBackButton + text: root.fullBackButton? qsTr("Go Back"): "" + Layout.preferredHeight: 24 + Layout.preferredWidth: (root.fullBackButton)? implicitWidth: 24 + leftPadding: (root.fullBackButton)? 16 : padding + rightPadding: (root.fullBackButton)? 16 :padding + baseHeaght: 16 + padding: 4 + customFocusPolicy: Qt.NoFocus + + onClicked: { + backClicked() + } + } + + Text { + id: centralTitle + text: (titleUppercase)? root.title.toUpperCase(): root.title + horizontalAlignment: root.titlesAligh + font: titlesFont + Layout.fillWidth: true; + Layout.preferredHeight: 40 + } + + ToolButton { + Layout.alignment: Qt.AlignRight + icon: "qrc:/assets/icons/dismiss.svg" + onClicked: closeClicked() + visible: root.closeButton + isFlat: !closeButtonBorder + + padding: 10 + baseHeaght: 20 + bordersSize: 2 + customFocusPolicy: Qt.NoFocus + implicitHeight: headerRowHeight + } + + Text { + Layout.row: 1 + Layout.column: (backButton || titlesAligh === Text.AlignHCenter)? 1 : 0 + + Layout.minimumHeight: 16 + visible: root.subTitle.length + wrapMode: Text.WordWrap + elide: Text.ElideNone + Layout.fillWidth: true; + text: root.subTitle + color: tokensModel.color_text_tertiary + font: tokensModel.font_subtitle_2 + horizontalAlignment: centralTitle.horizontalAlignment + } + + Control { + id: rightSubtitleControl + Layout.row: 1 + Layout.column: 2 + + } +} diff --git a/ViewSolutions/src/ViewSolutionsModule/ImageView.qml b/ViewSolutions/src/ViewSolutionsModule/ImageView.qml index b5a4b81..af92719 100644 --- a/ViewSolutions/src/ViewSolutionsModule/ImageView.qml +++ b/ViewSolutions/src/ViewSolutionsModule/ImageView.qml @@ -1,3 +1,10 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + import QtQuick 2.15 import QtQuick.Layouts 1.14 import QtQuick.Controls 2.15 diff --git a/ViewSolutions/src/ViewSolutionsModule/ViewPortDelegatBase.qml b/ViewSolutions/src/ViewSolutionsModule/ViewPortDelegatBase.qml index d0b87ac..6570b8d 100644 --- a/ViewSolutions/src/ViewSolutionsModule/ViewPortDelegatBase.qml +++ b/ViewSolutions/src/ViewSolutionsModule/ViewPortDelegatBase.qml @@ -1,3 +1,10 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + import QtQuick 2.15 import QtQuick.Layouts 1.14 import QtQuick.Controls 2.15 diff --git a/ViewSolutions/src/ViewSolutionsModule/ViewPortGradientPage.qml b/ViewSolutions/src/ViewSolutionsModule/ViewPortGradientPage.qml index c488635..990455d 100644 --- a/ViewSolutions/src/ViewSolutionsModule/ViewPortGradientPage.qml +++ b/ViewSolutions/src/ViewSolutionsModule/ViewPortGradientPage.qml @@ -1,3 +1,10 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + import QtQuick 2.15 import QtQuick.Layouts 1.14 import QtQuick.Controls 2.15 diff --git a/ViewSolutions/src/ViewSolutionsModule/ViewPortPage.qml b/ViewSolutions/src/ViewSolutionsModule/ViewPortPage.qml index fbb2fcf..aa8922a 100644 --- a/ViewSolutions/src/ViewSolutionsModule/ViewPortPage.qml +++ b/ViewSolutions/src/ViewSolutionsModule/ViewPortPage.qml @@ -1,3 +1,10 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + import QtQuick 2.15 import QtQuick.Layouts 1.14 import QtQuick.Controls 2.15 diff --git a/ViewSolutions/src/ViewSolutionsModule/ViewPortStaticGradientPage.qml b/ViewSolutions/src/ViewSolutionsModule/ViewPortStaticGradientPage.qml index 126f91d..1715153 100644 --- a/ViewSolutions/src/ViewSolutionsModule/ViewPortStaticGradientPage.qml +++ b/ViewSolutions/src/ViewSolutionsModule/ViewPortStaticGradientPage.qml @@ -1,3 +1,10 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + import QtQuick 2.15 import QtQuick.Layouts 1.15 import QtQuick.Controls 2.15 diff --git a/ViewSolutions/src/ViewSolutionsModule/ViewPortStaticPage.qml b/ViewSolutions/src/ViewSolutionsModule/ViewPortStaticPage.qml index 4473d87..ce1dc8a 100644 --- a/ViewSolutions/src/ViewSolutionsModule/ViewPortStaticPage.qml +++ b/ViewSolutions/src/ViewSolutionsModule/ViewPortStaticPage.qml @@ -1,3 +1,10 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + import QtQuick 2.15 import QtQuick.Layouts 1.15 import QtQuick.Controls 2.15 diff --git a/ViewSolutions/src/ViewSolutionsModule/ViewSolutionsControl.qml b/ViewSolutions/src/ViewSolutionsModule/ViewSolutionsControl.qml index 37f5c59..6851012 100644 --- a/ViewSolutions/src/ViewSolutionsModule/ViewSolutionsControl.qml +++ b/ViewSolutions/src/ViewSolutionsModule/ViewSolutionsControl.qml @@ -1,3 +1,10 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + import QtQuick 2.15 import QtQuick.Layouts 1.15 import QtQuick.Controls 2.15 diff --git a/ViewSolutions/src/ViewSolutionsModule/qmldir b/ViewSolutions/src/ViewSolutionsModule/qmldir index 07e46e3..80985fd 100644 --- a/ViewSolutions/src/ViewSolutionsModule/qmldir +++ b/ViewSolutions/src/ViewSolutionsModule/qmldir @@ -1,4 +1,7 @@ module ViewSolutionsModule +ActivityPage 1.0 ActivityPage.qml +ActivityProcessor 1.0 ActivityProcessor.qml +ActivityProcessorHeader 1.0 ActivityProcessorHeader.qml ImageView 1.0 ImageView.qml ViewPortDelegatBase 1.0 ViewPortDelegatBase.qml ViewPortPage 1.0 ViewPortPage.qml diff --git a/ViewSolutions/src/ViewSolutionsResources.qrc b/ViewSolutions/src/ViewSolutionsResources.qrc index 2431968..2b80125 100644 --- a/ViewSolutions/src/ViewSolutionsResources.qrc +++ b/ViewSolutions/src/ViewSolutionsResources.qrc @@ -8,6 +8,9 @@ ViewSolutionsModule/ViewPortStaticPage.qml ViewSolutionsModule/ViewPortStaticGradientPage.qml ViewSolutionsModule/ViewSolutionsControl.qml + ViewSolutionsModule/ActivityProcessorHeader.qml + ViewSolutionsModule/ActivityProcessor.qml + ViewSolutionsModule/ActivityPage.qml diff --git a/ViewSolutions/src/basehashmodel.cpp b/ViewSolutions/src/basehashmodel.cpp new file mode 100644 index 0000000..812112a --- /dev/null +++ b/ViewSolutions/src/basehashmodel.cpp @@ -0,0 +1,2 @@ +#include "basehashmodel.h" + diff --git a/ViewSolutions/src/basehashmodel.h b/ViewSolutions/src/basehashmodel.h new file mode 100644 index 0000000..6b0fdab --- /dev/null +++ b/ViewSolutions/src/basehashmodel.h @@ -0,0 +1,188 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef BASEHASHMODEL_H +#define BASEHASHMODEL_H +#include +#include + +namespace ViewSolutions { + +/** + * @tparam KEY - is type of hash table key, + * @tparam DATA - is main stored delegate model of all list items. + + * @brief The BaseHashModel class is base class of all GUI list models + * + * Conceptions and using rooles + * * All models should provides delegate models base of qobject + * * If model require fast solution just implement BaseListModel model + * + * + * @note to access to delegate model use Qt::EditRole role: available in qml by delegateModel keyword + * @example : + * ``` + * class VariantListModel: public BaseHashModel +{ + Q_OBJECT + +public: + VariantListModel(QObject* ptr = nullptr): BaseListModel(ptr){}; +}; +} + * ``` + * + * @note The BaseHashModel is not support Qml space, to short access in qml use the @a BaseListModel + */ +template +class BaseHashModel: public QAbstractListModel +{ + +public: + BaseHashModel(QObject* parent = nullptr): QAbstractListModel(parent) { + + } + + int rowCount(const QModelIndex &parent) const override { + return m_data.size(); + } + + QHash roleNames() const override { + QHash roles; + roles[Qt::EditRole] = "delegateModel"; + return roles; + } + + QVariant data(const QModelIndex &index, int role) const override { + if (index.isValid() && role == Qt::EditRole) { + + auto iter = std::next(m_data.begin(), index.row()); + if (iter == m_data.end()) { + return {}; + } + + if constexpr (std::is_same_v) { + return *iter; + } else if constexpr(std::is_base_of_v) { + QQmlEngine::setObjectOwnership(*iter, QQmlEngine::CppOwnership); + + return QVariant::fromValue(*iter); + + } else if constexpr (std::is_same_v> || + std::is_base_of_v) { + QObject* ptr = iter->get(); + + QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership); + return QVariant::fromValue(ptr); + } else { + return QVariant::fromValue(*iter); + + } + } + + return {}; + } + + /** + * @brief getByKey returns value by key + * @param key + * @return + */ + virtual QVariant getByKey(const KEY& key) { + auto&& val = m_data.value(key); + if constexpr (std::is_same_v) { + return val; + } else if constexpr(std::is_base_of_v) { + QQmlEngine::setObjectOwnership(val, QQmlEngine::CppOwnership); + + return QVariant::fromValue(val); + + } else if constexpr (std::is_base_of_v, DATA>) { + QObject* ptr = val.get(); + + QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership); + return QVariant::fromValue(ptr); + } else { + return QVariant::fromValue(val); + + } + + return {}; + } + + const QHash& dateList() const { + return m_data; + } + + /** + * @brief setByKey update delegate by key + * @param key + * @param data + */ + virtual void setByKey(const KEY& key, const DATA& data) { + auto&& iter = m_data.find(key); + if (iter != m_data.end() || *iter != data) { + + int insertIdx = std::distance(m_data.begin(), m_data.insert(key, data)); + emit dataChanged(index(insertIdx, 0), + index(insertIdx, 0)); + } + } + + virtual void removeByKey(const KEY& key) { + auto&& iter = m_data.find(key); + if (iter != m_data.end()) { + + int removeIdx = std::distance(m_data.begin(), iter); + beginRemoveRows(QModelIndex{}, removeIdx, removeIdx); + m_data.erase(iter); + endRemoveRows(); + } + } + + /** + * @brief setDataList sets new date of model, and reset all model; + * @param newData + */ + void setDataList(const QHash &newData) { + + const int diff = newData.size() - m_data.size(); + + if (diff > 0) { + beginInsertRows(QModelIndex{}, m_data.size(), m_data.size() + diff - 1); + m_data = newData; + endInsertRows(); + + emit dataChanged(index(0, 0), + index(m_data.size() - diff - 1, 0)); + } else if (diff == 0) { + m_data = newData; + + emit dataChanged(index(0, 0), + index(m_data.size() - diff - 1, 0)); + } else { + beginRemoveRows(QModelIndex{}, m_data.size() + diff, m_data.size() - 1); + m_data = newData; + + endRemoveRows(); + + emit dataChanged(index(0, 0), + index(m_data.size() - 1, 0)); + } + } + +private: + QHash m_data; + +}; + + + +} + + +#endif // BASEHASHMODEL_H diff --git a/ViewSolutions/src/baselistmodel.h b/ViewSolutions/src/baselistmodel.h new file mode 100644 index 0000000..f2d580f --- /dev/null +++ b/ViewSolutions/src/baselistmodel.h @@ -0,0 +1,145 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef BASELISTMODEL_H +#define BASELISTMODEL_H + +#include +#include + +namespace ViewSolutions { + +class __PrvateBaseListModel : public QAbstractListModel{ + Q_OBJECT +protected: + __PrvateBaseListModel(QObject* parent = nullptr): QAbstractListModel(parent){} +signals: + void listDateChanged(); +}; + + +#define BASE_LIST_MODEL_DATA_PROPERTY(Type) \ +Q_PROPERTY(QList listDate READ dateList WRITE setDataList NOTIFY listDateChanged FINAL) + + +/** + * @tparam TYPE - is main stored delegate model of all list items. + * @brief The BaseListModel class is base class of all GUI list models + * + * Conceptions and using rooles + * * All models should provides delegate models base of qobject + * * If model require fast solution just implement BaseListModel model + * + * + * @note to access to delegate model use Qt::EditRole role: available in qml by delegateModel keyword + * @example : + * ``` + * class VariantListModel: public BaseListModel +{ + Q_OBJECT + BASE_LIST_MODEL_DATA_PROPERTY(QVariant) + +public: + VariantListModel(QObject* ptr = nullptr): BaseListModel(ptr){}; +}; +} + * ``` + */ +template +class BaseListModel: public __PrvateBaseListModel +{ + +public: + BaseListModel(QObject* parent = nullptr): __PrvateBaseListModel(parent) { + + } + + int rowCount(const QModelIndex &parent) const override { + return m_data.size(); + } + + QHash roleNames() const override { + QHash roles; + roles[Qt::EditRole] = "delegateModel"; + return roles; + } + + QVariant data(const QModelIndex &index, int role) const override { + if (index.isValid() && + index.row() < m_data.size() && + m_data.size() && + role == Qt::EditRole) { + + if constexpr (std::is_same_v) { + return m_data[index.row()]; + } else if constexpr(std::is_base_of_v) { + QQmlEngine::setObjectOwnership(m_data[index.row()], QQmlEngine::CppOwnership); + + return QVariant::fromValue(m_data[index.row()]); + + } else if constexpr (std::is_same_v> || + std::is_base_of_v) { + QObject* ptr = m_data[index.row()].get(); + + QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership); + return QVariant::fromValue(ptr); + } else { + return QVariant::fromValue(m_data[index.row()]); + + } + } + + return {}; + } + + /** + * @brief setDataList sets new date of model, and reset all model; + * @param newData + */ + Q_INVOKABLE void setDataList(const QList &newData) { + + const int diff = newData.size() - m_data.size(); + + if (diff > 0) { + beginInsertRows(QModelIndex{}, m_data.size(), m_data.size() + diff - 1); + m_data = newData; + endInsertRows(); + + emit dataChanged(index(0, 0), + index(m_data.size() - diff - 1, 0)); + } else if (diff == 0) { + m_data = newData; + + emit dataChanged(index(0, 0), + index(m_data.size() - diff - 1, 0)); + } else { + beginRemoveRows(QModelIndex{}, m_data.size() + diff, m_data.size() - 1); + m_data = newData; + + endRemoveRows(); + + emit dataChanged(index(0, 0), + index(m_data.size() - 1, 0)); + } + + emit listDateChanged(); + + } + + Q_INVOKABLE const QList& dateList() const { + return m_data; + } + +private: + QList m_data; + +}; + + + +} +#endif // BASELISTMODEL_H diff --git a/ViewSolutions/src/colorpicker.cpp b/ViewSolutions/src/colorpicker.cpp index c792c17..0bbefd0 100644 --- a/ViewSolutions/src/colorpicker.cpp +++ b/ViewSolutions/src/colorpicker.cpp @@ -1,3 +1,10 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + #include "colorpicker.h" #include diff --git a/ViewSolutions/src/colorpicker.h b/ViewSolutions/src/colorpicker.h index a512f00..cc05f2e 100644 --- a/ViewSolutions/src/colorpicker.h +++ b/ViewSolutions/src/colorpicker.h @@ -1,3 +1,10 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + #ifndef COLORPICKER_H #define COLORPICKER_H #include "viewsolutions_global.h" diff --git a/ViewSolutions/src/iguitokensmodel.cpp b/ViewSolutions/src/iguitokensmodel.cpp new file mode 100644 index 0000000..a8697fb --- /dev/null +++ b/ViewSolutions/src/iguitokensmodel.cpp @@ -0,0 +1,23 @@ +//# +//# Copyright (C) 2024-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "iguitokensmodel.h" + +namespace ViewSolutions { + +iGUITokensModel::iGUITokensModel() {} + +QString iGUITokensModel::modelId() const { + return "GUITokens"; +} + +QColor &iGUITokensModel::addTransporent(QColor &input, float alpha) const { + input.setAlphaF(alpha); + return input; +} + +} diff --git a/ViewSolutions/src/iguitokensmodel.h b/ViewSolutions/src/iguitokensmodel.h new file mode 100644 index 0000000..21e0ded --- /dev/null +++ b/ViewSolutions/src/iguitokensmodel.h @@ -0,0 +1,140 @@ +//# +//# Copyright (C) 2024-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef IGUITOKENSMODEL_H +#define IGUITOKENSMODEL_H + +#include "imodel.h" +#include +#include +#include + +namespace ViewSolutions { + +/** + * @brief The Tokens class is general global instanke of all QML constans used in the App. + */ +class VIEWSOLUTION_EXPORT iGUITokensModel: public QObject, public iModel +{ + Q_OBJECT + + // colors contants + Q_PROPERTY(QColor color_accent_primary READ color_surface_accent_primary CONSTANT FINAL) + + Q_PROPERTY(QColor color_accent_secondary READ color_surface_accent_secondary CONSTANT FINAL) + Q_PROPERTY(QColor color_accent_error READ color_surface_accent_error CONSTANT FINAL) + Q_PROPERTY(QColor color_accent_success READ color_surface_accent_success CONSTANT FINAL) + + Q_PROPERTY(QColor color_text_primary READ color_text_primary CONSTANT FINAL) + Q_PROPERTY(QColor color_text_secondary READ color_text_secondary CONSTANT FINAL) + Q_PROPERTY(QColor color_text_tertiary READ color_text_tertiary CONSTANT FINAL) + + Q_PROPERTY(QColor color_text_disabled READ color_text_disabled CONSTANT FINAL) + Q_PROPERTY(QColor color_border_primary READ color_border_primary CONSTANT FINAL) + Q_PROPERTY(QColor color_border_secondary READ color_border_secondary CONSTANT FINAL) + Q_PROPERTY(QColor color_border_disabled READ color_border_disabled CONSTANT FINAL) + Q_PROPERTY(QColor color_devider_dark READ color_devider_dark CONSTANT FINAL) + Q_PROPERTY(QColor color_devider_white READ color_devider_white CONSTANT FINAL) + + //states_colors_constants: + Q_PROPERTY(QColor pressed_focused READ pressed_focused CONSTANT FINAL) + Q_PROPERTY(QColor hover READ hover CONSTANT FINAL) + + // fonts + Q_PROPERTY(QFont font_caption_1 READ font_caption_1 CONSTANT FINAL) + Q_PROPERTY(QFont font_caption_2 READ font_caption_2 CONSTANT FINAL) + Q_PROPERTY(QFont font_caption_3 READ font_caption_3 CONSTANT FINAL) + + Q_PROPERTY(QFont font_body_1 READ font_body_1 CONSTANT FINAL) + Q_PROPERTY(QFont font_body_2 READ font_body_2 CONSTANT FINAL) + Q_PROPERTY(QFont font_body_large READ font_body_large CONSTANT FINAL) + Q_PROPERTY(QFont font_subtitle_1 READ font_subtitle_1 CONSTANT FINAL) + Q_PROPERTY(QFont font_subtitle_2 READ font_subtitle_2 CONSTANT FINAL) + Q_PROPERTY(QFont font_subtitle_large READ font_subtitle_large CONSTANT FINAL) + Q_PROPERTY(QFont font_subtitle_x_large READ font_subtitle_x_large CONSTANT FINAL) + Q_PROPERTY(QFont font_subtitle_uppercase READ font_subtitle_uppercase CONSTANT FINAL) + + Q_PROPERTY(QFont font_title_1 READ font_title_1 CONSTANT FINAL) + Q_PROPERTY(QFont font_title_1_secondary READ font_title_1_secondary CONSTANT FINAL) + + Q_PROPERTY(QFont font_title_2 READ font_title_2 CONSTANT FINAL) + Q_PROPERTY(QFont font_title_3 READ font_title_3 CONSTANT FINAL) + Q_PROPERTY(QFont font_title_3_secondary READ font_title_3_secondary CONSTANT FINAL) + + Q_PROPERTY(QFont font_title_strong READ font_title_strong CONSTANT FINAL) + Q_PROPERTY(QFont font_title_large READ font_title_large CONSTANT FINAL) + Q_PROPERTY(QFont font_title_x_large READ font_title_x_large CONSTANT FINAL) + Q_PROPERTY(QFont font_title_uppercase READ font_title_uppercase CONSTANT FINAL) + Q_PROPERTY(QFont font_botton_1 READ font_botton_1 CONSTANT FINAL) + Q_PROPERTY(QFont font_botton_2 READ font_botton_2 CONSTANT FINAL) + Q_PROPERTY(QFont font_bubble READ font_bubble CONSTANT FINAL) + + +public: + explicit iGUITokensModel(); + virtual QColor color_surface_accent_primary() const = 0; + virtual QColor color_surface_accent_secondary() const = 0; + virtual QColor color_surface_accent_error() const = 0; + virtual QColor color_surface_accent_success() const = 0; + + virtual QColor color_text_primary() const = 0; + virtual QColor color_text_secondary() const = 0; + virtual QColor color_text_tertiary() const = 0; + + virtual QColor color_text_disabled() const = 0; + virtual QColor color_border_primary() const = 0; + virtual QColor color_border_secondary() const = 0; + virtual QColor color_border_disabled() const = 0; + virtual QColor color_devider_dark() const = 0; + virtual QColor color_devider_white() const = 0; + + virtual QColor pressed_focused() const = 0; + virtual QColor hover() const = 0; + + virtual QFont font_caption_1() const = 0; + virtual QFont font_caption_2() const = 0; + virtual QFont font_caption_3() const = 0; + + virtual QFont font_body_1() const = 0; + virtual QFont font_body_2() const = 0; + virtual QFont font_body_large() const = 0; + virtual QFont font_subtitle_1() const = 0; + virtual QFont font_subtitle_2() const = 0; + virtual QFont font_subtitle_large() const = 0; + virtual QFont font_subtitle_x_large() const = 0; + virtual QFont font_subtitle_uppercase() const = 0; + virtual QFont font_title_1() const = 0; + virtual QFont font_title_1_secondary() const = 0; + + virtual QFont font_title_2() const = 0; + + virtual QFont font_title_3() const = 0; + virtual QFont font_title_3_secondary() const = 0; + + virtual QFont font_title_strong() const = 0; + virtual QFont font_title_large() const = 0; + virtual QFont font_title_x_large() const = 0; + virtual QFont font_title_uppercase() const = 0; + virtual QFont font_botton_1() const = 0; + virtual QFont font_botton_2() const = 0; + virtual QFont font_bubble() const = 0; + + // iModel interface +public: + QString modelId() const; + +protected: + /** + * @brief addTransporent This method add alpha chennel to the color. + * @param input input link to color + * @param alpha alphachennol factor from 0 to 1. + * @return color with new alpha chennel. + */ + QColor& addTransporent(QColor& input, float alpha) const; +}; +} +#endif // IGUITOKENSMODEL_H diff --git a/ViewSolutions/src/imodel.cpp b/ViewSolutions/src/imodel.cpp new file mode 100644 index 0000000..e0ac335 --- /dev/null +++ b/ViewSolutions/src/imodel.cpp @@ -0,0 +1,30 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "imodel.h" + +#include + +namespace ViewSolutions { + + +const QWeakPointer &iModel::storage() const { + return m_storage; +} + +QQmlApplicationEngine *iModel::engine() const { + if (auto&& storage = m_storage.lock()) { + return storage->engine(); + } + + return nullptr; +} + +void iModel::initStorage(const QWeakPointer &newStorage) { + m_storage = newStorage; +} +} diff --git a/ViewSolutions/src/imodel.h b/ViewSolutions/src/imodel.h new file mode 100644 index 0000000..828141f --- /dev/null +++ b/ViewSolutions/src/imodel.h @@ -0,0 +1,69 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef IMODEL_H +#define IMODEL_H + +#include +#include +#include +#include "viewsolutions_global.h" + + +namespace ViewSolutions { + +class ModelStorage; + +/** + * @brief The iModel class is base model for GUI models. Works with @a ModelStorage. + * All models after adding can get access to any othe models that located on same storage object. + */ +class VIEWSOLUTION_EXPORT iModel +{ +public: + iModel() = default; + virtual ~iModel() = default; + + /** + * @brief modelId returns text model id. override this method to provide access to model in qml or other models. + * @return model id. + */ + virtual QString modelId() const = 0; + + /** + * @brief storage returns storage object. this method return context of the model's storage. + * @return storage object. + */ + const QWeakPointer& storage() const; + + /** + * @brief engine returns qml engine. + * @return qml engine. + * @note can be return nullptr if the models system initialized without qml engine. + * @note this method convert weak pointer to shared pointer, + * so you can use it without any restrictions, + * but it may be slowly then dirrect access. + */ + QQmlApplicationEngine * engine() const; + +protected: + + /** + * @brief initStorage This method is called by storage object after adding model to storage. + * @param newStorage is storage object. + */ + virtual void initStorage(const QWeakPointer& newStorage); + +private: + + QWeakPointer m_storage; + + friend class ModelStorage; +}; + +} +#endif // IMODEL_H diff --git a/ViewSolutions/src/listviewmodel.cpp b/ViewSolutions/src/listviewmodel.cpp index 21bcd7a..e4cfbf5 100644 --- a/ViewSolutions/src/listviewmodel.cpp +++ b/ViewSolutions/src/listviewmodel.cpp @@ -1,3 +1,10 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + #include "listviewmodel.h" namespace ViewSolutions { @@ -77,7 +84,7 @@ void ListViewModel::addSource(QObject* data) { } void ListViewModel::clear(bool fast) { - for (auto i : qAsConst(_data)) { + for (auto i : std::as_const(_data)) { if (fast) { i->deleteLater(); } else { diff --git a/ViewSolutions/src/listviewmodel.h b/ViewSolutions/src/listviewmodel.h index eb7a5ed..e5653b6 100644 --- a/ViewSolutions/src/listviewmodel.h +++ b/ViewSolutions/src/listviewmodel.h @@ -1,3 +1,10 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + #ifndef LISTVIEWMODEL_H #define LISTVIEWMODEL_H #include diff --git a/ViewSolutions/src/modelstorage.cpp b/ViewSolutions/src/modelstorage.cpp new file mode 100644 index 0000000..f946223 --- /dev/null +++ b/ViewSolutions/src/modelstorage.cpp @@ -0,0 +1,41 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "modelstorage.h" + +#include + +namespace ViewSolutions { + +ModelStorage::ModelStorage(QQmlApplicationEngine *engine) { + QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); + _engine = engine; +} + +bool ModelStorage::addModel(const QSharedPointer &model) { + if (_storage.contains(model->modelId())) { + return false; + } + + if (QObject* qobject = dynamic_cast(model.get())) { + QQmlEngine::setObjectOwnership(qobject, QQmlEngine::CppOwnership); + } + + _storage[model->modelId()] = model; + model->initStorage(sharedFromThis().toWeakRef()); + + return true; +} + +QObject* ModelStorage::getModel(const QString &modeId) const { + return dynamic_cast(_storage.value(modeId).get()); +} + +QQmlApplicationEngine *ModelStorage::engine() const { + return _engine; +} +} diff --git a/ViewSolutions/src/modelstorage.h b/ViewSolutions/src/modelstorage.h new file mode 100644 index 0000000..5a72d6f --- /dev/null +++ b/ViewSolutions/src/modelstorage.h @@ -0,0 +1,61 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef MODELSTORAGE_H +#define MODELSTORAGE_H + +#include "imodel.h" + +#include +#include +#include + +namespace ViewSolutions { + +/** + * @brief The ModelStorage class main model storage object. Provide access to all models in the application. + */ +class VIEWSOLUTION_EXPORT ModelStorage: public QObject, public QEnableSharedFromThis +{ + Q_OBJECT +public: + ModelStorage(QQmlApplicationEngine* engine = nullptr); + + /** + * @brief addModel adds new model into storage. + * @param model is model object. + * @return true if model added succesfful, if model alredy exists or model is invalid return false. + * @note All valid models should be inherited from QObject, and inited using a QSharedPointer::create() method. + */ + bool addModel(const QSharedPointer& model); + + /** + * @brief getModel This method isible on The QML and using for gettings required GUI models. + * @param modeId This is id of required model. + * @return model raw pointer. + */ + Q_INVOKABLE QObject* getModel(const QString& modeId) const; + + template + QSharedPointer get(const QString& modeId) const { + return _storage.value(modeId).staticCast(); + } + + /** + * @brief engine returns context qml engine. + * @return qml engine. + */ + QQmlApplicationEngine *engine() const; + +private: + QHash> _storage; + QQmlApplicationEngine * _engine = nullptr; +}; + +} + +#endif // MODELSTORAGE_H diff --git a/ViewSolutions/src/qmlcolorpicker.cpp b/ViewSolutions/src/qmlcolorpicker.cpp index 928ceae..09b53a4 100644 --- a/ViewSolutions/src/qmlcolorpicker.cpp +++ b/ViewSolutions/src/qmlcolorpicker.cpp @@ -1,3 +1,11 @@ + +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + #include "qmlcolorpicker.h" #include @@ -9,62 +17,58 @@ QMLColorPicker::QMLColorPicker(QObject *parent) : } -QMLColorPicker *ViewSolutions::QMLColorPicker::instance() { - static auto ints = new QMLColorPicker(); - return ints; -} - QColor QMLColorPicker::pick(const QString &img) const { if (img.left(6) == "image:") { int urlBegin = img.indexOf('/', 8); QString id = img.mid(8, urlBegin - 8); - if (!_engine) - return {}; + if (auto eng = engine()) { + QQuickImageProvider* provider = dynamic_cast(eng->imageProvider(id)); - QQuickImageProvider* provider = dynamic_cast(_engine->imageProvider(id)); - - if (!provider) { - return {}; - } - - QString url = img.mid(urlBegin + 1); - - if (provider->imageType() & QQmlImageProviderBase::ImageResponse) { - auto async = static_cast(provider); - auto textureFacrory = async->requestImageResponse(url, {})->textureFactory(); - - if (!textureFacrory) { + if (!provider) { return {}; } - QColor responce = ColorPicker::pick(textureFacrory->image()); + QString url = img.mid(urlBegin + 1); - delete textureFacrory; + if (provider->imageType() & QQmlImageProviderBase::ImageResponse) { + auto async = static_cast(provider); + auto textureFacrory = async->requestImageResponse(url, {})->textureFactory(); - return responce; + if (!textureFacrory) { + return {}; + } + + QColor responce = ColorPicker::pick(textureFacrory->image()); + + delete textureFacrory; + + return responce; + } + + if (provider->imageType() & QQmlImageProviderBase::Texture) { + return ColorPicker::pick(provider->requestTexture(url, nullptr, {})->image()); + } + + if (provider->imageType() & QQmlImageProviderBase::Pixmap) { + return ColorPicker::pick(provider->requestPixmap(url, nullptr, {}).toImage()); + } + + if (provider->imageType() & QQmlImageProviderBase::Image) { + return ColorPicker::pick(provider->requestImage(url, nullptr, {})); + } + + return {}; } - if (provider->imageType() & QQmlImageProviderBase::Texture) { - return ColorPicker::pick(provider->requestTexture(url, nullptr, {})->image()); - } - - if (provider->imageType() & QQmlImageProviderBase::Pixmap) { - return ColorPicker::pick(provider->requestPixmap(url, nullptr, {}).toImage()); - } - - if (provider->imageType() & QQmlImageProviderBase::Image) { - return ColorPicker::pick(provider->requestImage(url, nullptr, {})); - } - - return {}; } return ColorPicker::pick(img); } -void QMLColorPicker::setEngine(QQmlApplicationEngine *engine) { - _engine = engine; +QString QMLColorPicker::modelId() const { + return "ColorPicker"; } + } diff --git a/ViewSolutions/src/qmlcolorpicker.h b/ViewSolutions/src/qmlcolorpicker.h index 8eba381..3cf8c4d 100644 --- a/ViewSolutions/src/qmlcolorpicker.h +++ b/ViewSolutions/src/qmlcolorpicker.h @@ -1,42 +1,43 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + #ifndef QMLCOLORPICKER_H #define QMLCOLORPICKER_H #include "colorpicker.h" #include +#include -class QQmlApplicationEngine; namespace ViewSolutions { /** * @brief The QMLColorPicker class - Qml wrapper for ColorPicker class. */ -class VIEWSOLUTION_EXPORT QMLColorPicker : public QObject, private ColorPicker +class VIEWSOLUTION_EXPORT QMLColorPicker : public QObject, public iModel, private ColorPicker { Q_OBJECT public: explicit QMLColorPicker(QObject *parent = nullptr); - /** - * @brief instance This method return instance object of the QMLColorPicker setvice. - * @return Static instance of this ColorPicker. - */ - static QMLColorPicker* instance(); + /** * @brief pick This is override function for qml. * @param img This is path to image. * @return General color of image. */ - Q_INVOKABLE QColor pick(const QString &img) const; + Q_INVOKABLE QColor pick(const QString &img) const; /** - * @brief setEngine This method set qml engine for working with image providers. - * @param engine This is new engine. + * @brief instance This is singleton instance of QMLColorPicker. + * @return */ - void setEngine(QQmlApplicationEngine *engine); + QString modelId() const override; -private: - - QQmlApplicationEngine *_engine = nullptr; }; + } #endif // QMLCOLORPICKER_H diff --git a/ViewSolutions/src/variantlistmodel.h b/ViewSolutions/src/variantlistmodel.h new file mode 100644 index 0000000..5b81ffa --- /dev/null +++ b/ViewSolutions/src/variantlistmodel.h @@ -0,0 +1,23 @@ +#ifndef VARIANTLISTMODEL_H +#define VARIANTLISTMODEL_H + +#include "baselistmodel.h" + + +namespace ViewSolutions { + +/** + * @brief The VariantListModel class is universal implementation for all atomic types. + */ +class VariantListModel: public BaseListModel +{ + Q_OBJECT + BASE_LIST_MODEL_DATA_PROPERTY(QVariant) + +public: + VariantListModel(QObject* ptr = nullptr): BaseListModel(ptr){}; +}; + +} + +#endif // VARIANTLISTMODEL_H diff --git a/ViewSolutions/src/viewsolutions.cpp b/ViewSolutions/src/viewsolutions.cpp index ef74ce5..7c848dc 100644 --- a/ViewSolutions/src/viewsolutions.cpp +++ b/ViewSolutions/src/viewsolutions.cpp @@ -1,29 +1,50 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "variantlistmodel.h" #include "viewsolutions.h" #include #include #include #include #include +#include namespace ViewSolutions { -bool init(QQmlApplicationEngine *engine) { +QSharedPointer init(QQmlApplicationEngine *engine) { if (!engine) - return false; + return nullptr; auto root = engine->rootContext(); if (!root) - return false; + return nullptr; initResources(); engine->addImportPath(":/"); - auto picker = QMLColorPicker::instance(); - picker->setEngine(engine); - root->setContextProperty("colorPicker", picker); - return true; + auto&& storage = QSharedPointer::create(engine); + QQmlEngine::setObjectOwnership(storage.get(), QQmlEngine::CppOwnership); + + root->setContextProperty("modelsStorage", storage.get()); + + auto&& picker = QSharedPointer::create(); + storage->addModel(picker); + + // to-do - remove + root->setContextProperty("colorPicker", picker.get()); + + qRegisterMetaType("VariantListModel"); + + + + return storage; } } diff --git a/ViewSolutions/src/viewsolutions.h b/ViewSolutions/src/viewsolutions.h index 80777df..d2ec9ba 100644 --- a/ViewSolutions/src/viewsolutions.h +++ b/ViewSolutions/src/viewsolutions.h @@ -1,6 +1,14 @@ +//# +//# Copyright (C) 2020-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + #ifndef VIEWSOLUTIONS_H #define VIEWSOLUTIONS_H +#include "modelstorage.h" #include "viewsolutions_global.h" class QQmlApplicationEngine; @@ -15,10 +23,13 @@ inline void initResources() { Q_INIT_RESOURCE(ViewSolutionsResources); } * @brief the ViewSolutions namespace */ namespace ViewSolutions { + /** - * @brief init this method import all qml resources to your project. - */ - bool VIEWSOLUTION_EXPORT init(QQmlApplicationEngine *engine); + * @brief init this method import all qml resources to your project. + * @param engine is QQmlApplicationEngine object. + * @return gui model storage object. + */ +QSharedPointer init(QQmlApplicationEngine *engine); } #endif // VIEWSOLUTIONS_H