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..b6f1c42
--- /dev/null
+++ b/ViewSolutions/src/ViewSolutionsModule/ActivityPage.qml
@@ -0,0 +1,38 @@
+//#
+//# 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: ""
+
+ // shows the back button with text
+ property bool buttonBack: true
+
+ // shows close button on the ActivityProcessor header
+ property bool closeButton: true
+ // 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
+
+}
diff --git a/ViewSolutions/src/ViewSolutionsModule/ActivityProcessor.qml b/ViewSolutions/src/ViewSolutionsModule/ActivityProcessor.qml
new file mode 100644
index 0000000..00364c7
--- /dev/null
+++ b/ViewSolutions/src/ViewSolutionsModule/ActivityProcessor.qml
@@ -0,0 +1,298 @@
+//#
+//# 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
+
+Page {
+ id: root
+
+ // use Comonent delegates only
+ property alias initialItem: stackView.initialItem
+ property alias currentItem: stackView.currentItem
+ property int titlesAligh: Text.AlignLeft
+
+ property alias depth: stackView.depth
+ property bool cache: true
+ property bool enableHeader: true
+
+ padding: 0
+ clip: true
+
+ background: Item{}
+
+ header: ActivityProcessorHeader {
+ id: headerView
+ visible: root.enableHeader
+ title: {
+ if (root.enableHeader && stackView.currentItem && stackView.currentItem.title) {
+ return stackView.currentItem.title
+ }
+
+ return ""
+ }
+
+ backButton: root.enableHeader && stackView.depth > 1 && (stackView.currentItem && stackView.currentItem.buttonBack)
+
+ closeButton: root.enableHeader && (stackView.currentItem && stackView.currentItem.closeButton)
+ titlesAligh: root.titlesAligh
+ onBackClicked: {
+ root.popItem()
+ }
+
+ }
+
+ contentItem: StackView {
+ id: stackView
+
+ Connections {
+ target: (stackView.currentItem && stackView.currentItem.finish)? stackView.currentItem : null
+
+ function onFinish() {
+ root.popItem()
+ }
+ }
+
+ padding: 0
+
+ implicitWidth: (stackView.currentItem)? stackView.currentItem.implicitWidth: 0
+ implicitHeight: (stackView.currentItem)? stackView.currentItem.implicitHeight: 0
+
+ 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..c7b3aca
--- /dev/null
+++ b/ViewSolutions/src/ViewSolutionsModule/ActivityProcessorHeader.qml
@@ -0,0 +1,58 @@
+//#
+//# 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
+
+
+ToolBar {
+
+ id: root
+ property int titlesAligh: Text.AlignHCenter
+
+ property string title: ""
+ property bool titleUppercase: true
+ property bool backButton: false
+ property bool closeButton: false
+
+ signal backClicked()
+ signal closeClicked()
+
+ contentItem: RowLayout {
+
+
+ ToolButton {
+
+ visible: root.backButton
+ text: "<<"
+
+ onClicked: {
+ root.backClicked()
+ }
+ }
+
+ Text {
+ id: centralTitle
+ text: (root.titleUppercase)? root.title.toUpperCase(): root.title
+ horizontalAlignment: root.titlesAligh
+ Layout.fillWidth: true;
+
+ }
+
+ ToolButton {
+ Layout.alignment: Qt.AlignRight
+ text: "x"
+ onClicked: root.closeClicked()
+ visible: root.closeButton
+
+ }
+
+ }
+}
+
+
diff --git a/ViewSolutions/src/ViewSolutionsModule/ImageView.qml b/ViewSolutions/src/ViewSolutionsModule/ImageView.qml
index b5a4b81..5613063 100644
--- a/ViewSolutions/src/ViewSolutionsModule/ImageView.qml
+++ b/ViewSolutions/src/ViewSolutionsModule/ImageView.qml
@@ -1,47 +1,56 @@
-import QtQuick 2.15
-import QtQuick.Layouts 1.14
-import QtQuick.Controls 2.15
-import QtQuick.Controls.Material 2.15
-import QtQuick.Controls.Universal 2.15
+//#
+//# 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.
+//#
-Item {
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+import QtQuick.Controls.Material
+import QtQuick.Controls.Universal
+import QtQuick.Effects
+
+AbstractButton {
id: root
property string source: ""
property alias imagesource: sourceImg
- property string text: ""
- property bool hover: false
- property bool presed: false
- property bool selected: false
-
property real power: 1.0
property string toolTip: ""
- property color textColor: Material.color(Material.Grey)
+ property color textColor: Material.foreground
- property color background: colorPicker.pick(source)
- property color selectedColor: "#5de2ff"
- property color borderColor: "#00000000"
- property color hoverColor: "#00000000"
-
- signal clicked(var mouse);
+ property color backgroundColor: Material.background
+ property color selectedColor: Material.accent
+ property color hoverColor: Material.accent
Connections {
target: sourceImg
function onStatusChanged(status) {
if (status === Image.Ready) {
- root.background = colorPicker.pick(source);
+ root.backgroundColor = colorPicker.pick(source);
}
}
}
- Item {
+ hoverEnabled: true
+
+ opacity: {
+ if (enabled) {
+ return 1
+ }
+
+ return 0.5
+ }
+
+ contentItem: Control {
id: privateData
property int rootMinSize: Math.min(root.height, root.width)
- anchors.margins: (root.hover && !presed)? rootMinSize * 0.01: rootMinSize * 0.1
-
+ bottomPadding : 8
property real rx : 0
property real ry : 0
property real rz : 0
@@ -53,20 +62,41 @@ Item {
}
}
- anchors.fill: parent
- Rectangle {
- id: background
- color: root.background
- border.color: (root.hover)? root.hoverColor: root.selected? root.selectedColor: "#00000000"
- border.width: 4
- anchors.fill: parent
- radius: border.width * 2
-
- Behavior on border.color {
- ColorAnimation {
- duration: 250
- }
+ Behavior on rx {
+ NumberAnimation {
+ easing.type: Easing.OutExpo
+ duration: 550
}
+ }
+
+ Behavior on ry {
+ NumberAnimation {
+ easing.type: Easing.OutExpo
+ duration: 550
+ }
+ }
+
+ Behavior on rz {
+ NumberAnimation {
+ easing.type: Easing.OutExpo
+ duration: 550
+ }
+ }
+
+ background: Rectangle {
+ color: {
+
+ if (root.hovered) {
+ return root.hoverColor
+ }
+
+ if (root.checked) {
+ return root.selectedColor
+ }
+
+ return root.backgroundColor
+ }
+ radius: 16
Behavior on color {
ColorAnimation {
@@ -75,34 +105,56 @@ Item {
}
}
- ColumnLayout {
- Image {
- id: sourceImg
- source: root.source
+ contentItem: ColumnLayout {
+ spacing: 8
- clip: true
- fillMode: Image.PreserveAspectCrop
- Layout.fillHeight: true
+
+ MultiEffect {
+ id: imgEffect
Layout.fillWidth: true
- Layout.margins: 5
+ Layout.fillHeight: true
+ source: Image {
+ id: sourceImg
+ source: root.source
+ clip: true
+ fillMode: Image.PreserveAspectCrop
+ width: imgEffect.width
+ height: imgEffect.height
+ }
+
+ maskEnabled: true
+ maskSource: ShaderEffectSource {
+ sourceItem: Rectangle {
+ radius: 16
+ width: imgEffect.width
+ height: imgEffect.height
+ color: "Black"
+
+ Rectangle {
+ color: "Black"
+
+ anchors.bottom: parent.bottom
+ height: 20
+ width: parent.width
+ }
+ }
+ }
}
+
Label {
text: root.text
visible: text.length
- Layout.preferredHeight: root.height * 0.1
Layout.fillWidth: true
- color: textColor
- font.pixelSize: root.height * 0.09
- font.bold: true
+ color: root.textColor
+ font: root.font
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
- anchors.fill: parent
}
transform: [
@@ -126,7 +178,7 @@ Item {
ToolTip {
parent: root
- visible: root.hover && text.length
+ visible: root.hovered && text.length
text: root.toolTip
delay: 500
@@ -134,38 +186,23 @@ Item {
MouseArea {
-
+ acceptedButtons: Qt.NoButton
hoverEnabled: true;
- onEntered: {
- hover = true
- }
-
onExited: {
- hover = false;
privateData.ry = 0
privateData.rx = 0
}
onPositionChanged: (mouse) => {
- let fromCenter = root.width / 2
- privateData.ry = -((mouse.x - fromCenter) / (fromCenter * 0.05)) * power
+ let fromCenter = root.width / 2
+ privateData.ry = -((mouse.x - fromCenter) / (fromCenter * 0.05)) * root.power
- fromCenter = root.height / 2
- privateData.rx = ((mouse.y - fromCenter) / (fromCenter * 0.05)) * power
+ fromCenter = root.height / 2
+ privateData.rx = ((mouse.y - fromCenter) / (fromCenter * 0.05)) * root.power
- }
-
- onPressed: {
- presed = true;
- }
-
- onReleased: (mouse) => {
- presed = false;
-
- root.clicked(mouse)
- }
+ }
anchors.fill: parent
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..9f7cdd8
--- /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..1d69ea7
--- /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..2f8cbd6
--- /dev/null
+++ b/ViewSolutions/src/iguitokensmodel.cpp
@@ -0,0 +1,27 @@
+//#
+//# 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 {
+ return addTransporentImpl(input, alpha);
+}
+
+QColor &iGUITokensModel::addTransporentImpl(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..98f67e5
--- /dev/null
+++ b/ViewSolutions/src/iguitokensmodel.h
@@ -0,0 +1,145 @@
+//#
+//# 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 READ color_devider CONSTANT FINAL)
+ Q_PROPERTY(QColor color_background READ color_background 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() const = 0;
+ virtual QColor color_background() 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;
+
+ Q_INVOKABLE QColor addTransporent(QColor input, float alpha) 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& addTransporentImpl(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..dd28f23 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 VIEWSOLUTION_EXPORT init(QQmlApplicationEngine *engine);
}
#endif // VIEWSOLUTIONS_H