From 7e933237ab0c95bf5db1c197d612529adbdc1c8f Mon Sep 17 00:00:00 2001 From: Simon Briere Date: Wed, 10 Apr 2024 14:21:35 -0400 Subject: [PATCH] Refs #2. Updated Session Viewer Widget and general presentation. --- Frontend/DashboardsViewer/content/App.qml | 76 ++- .../content/dataSources/BaseDataSource.qml | 5 +- .../content/delegates/DashboardDelegate.qml | 6 +- .../delegates/SessionEventDelegate.qml | 4 + .../content/screens/Dashboard.qml | 9 +- .../content/screens/DashboardSelector.qml | 10 +- .../content/ui/BasicDialog.qml | 25 +- .../content/widgets/ButtonWidget.qml | 3 + .../content/widgets/ListViewWidget.qml | 10 + .../content/widgets/SessionViewerWidget.qml | 537 +++++++++++------- .../config_parser/src/ConfigParser.cpp | 2 +- .../resources/json/TestDashboardv2.json | 44 +- 12 files changed, 464 insertions(+), 267 deletions(-) diff --git a/Frontend/DashboardsViewer/content/App.qml b/Frontend/DashboardsViewer/content/App.qml index 9588a9a..bc4a2d9 100644 --- a/Frontend/DashboardsViewer/content/App.qml +++ b/Frontend/DashboardsViewer/content/App.qml @@ -1,6 +1,6 @@ import QtQuick 6.2 -import QtQuick.VirtualKeyboard 6.2 import QtQuick.Controls 6.2 +import QtQuick.Layouts import DashboardsViewer import "screens" @@ -16,6 +16,9 @@ Window { visible: true title: "DashboardsViewer" id: mainWindow + + property string contextText: "" + Rectangle{ id: background anchors.fill: parent @@ -41,28 +44,57 @@ Window { GradientStop { position: 1.0; color: Constants.backgroundColor } } - //Login username - Text { - id: username - text: "username" - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - color: "white" - } + RowLayout{ + anchors.fill: parent + //Back button + BasicButton { + id: btnBack + text: qsTr("Back") + /*color: "darkred" + hoverColor: "red"*/ + + visible: stackview.depth > 2 + + //height: parent.height + onClicked: function () { + stackview.pop() + } + } + Text { + id: txtContext + Layout.leftMargin: 10 + text: contextText + visible: stackview.depth > 2 && contextText + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + color: Constants.textAltColor + } + + Item{ + Layout.fillWidth: true + } + + //Login username + Text { + id: username + Layout.rightMargin: 10 + text: "username" + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignVCenter + color: "white" + } + + //Logout button + BasicButton { + id: logoutButton + text: qsTr("Logout") + color: "darkred" + hoverColor: "red" + - //Logout button - BasicButton { - id: logoutButton - text: "Logout" - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - color: "darkred" - hoverColor: "red" - width: 100 - //height: parent.height - onClicked: { - UserClient.disconnect(); + onClicked: { + UserClient.disconnect(); + } } } } diff --git a/Frontend/DashboardsViewer/content/dataSources/BaseDataSource.qml b/Frontend/DashboardsViewer/content/dataSources/BaseDataSource.qml index 6a205f2..40003ae 100644 --- a/Frontend/DashboardsViewer/content/dataSources/BaseDataSource.qml +++ b/Frontend/DashboardsViewer/content/dataSources/BaseDataSource.qml @@ -82,8 +82,9 @@ Item { else { //Insert response directly - response.dataSource = baseDataSource; - myModel.append(response); + //response.dataSource = baseDataSource; + //myModel.append(response); + myModel.clear(); } modelChanged(); }); diff --git a/Frontend/DashboardsViewer/content/delegates/DashboardDelegate.qml b/Frontend/DashboardsViewer/content/delegates/DashboardDelegate.qml index ec81124..9ed0d1b 100644 --- a/Frontend/DashboardsViewer/content/delegates/DashboardDelegate.qml +++ b/Frontend/DashboardsViewer/content/delegates/DashboardDelegate.qml @@ -9,9 +9,9 @@ Item { width: GridView.view.cellWidth - 10 height: mainLayout.implicitHeight + 10 //GridView.view.cellHeight - 10 - signal itemClicked(var id, var definition) + signal itemClicked(var id, var name, var definition) enabled: model.enabled - opacity: enabled ? 1.0 : 0.5 + opacity: enabled ? 1.0 : 0.2 states: [ State { @@ -32,7 +32,7 @@ Item { cursorShape: Qt.PointingHandCursor onClicked: function(){ //console.log("Click! " + model.id + " - " + model.definition); - itemClicked(model.id, model.definition); + itemClicked(model.id, model.name, model.definition); } } Rectangle{ diff --git a/Frontend/DashboardsViewer/content/delegates/SessionEventDelegate.qml b/Frontend/DashboardsViewer/content/delegates/SessionEventDelegate.qml index d1ef9ee..f6124d1 100644 --- a/Frontend/DashboardsViewer/content/delegates/SessionEventDelegate.qml +++ b/Frontend/DashboardsViewer/content/delegates/SessionEventDelegate.qml @@ -10,6 +10,8 @@ BaseDelegate { width: parent ? (parent.interactive ? parent.width - 20 : parent.width) : 0 function getEventIcon(){ + if (model.id_session_event_type === undefined) + return "../images/icons/error.png"; switch(id_session_event_type){ case 0: // Error return "../images/icons/error.png"; @@ -45,6 +47,8 @@ BaseDelegate { } function getEventName(){ + if (model.id_session_event_type === undefined) + return qsTr("Error"); switch(id_session_event_type){ case 0: // Error return qsTr("Error"); diff --git a/Frontend/DashboardsViewer/content/screens/Dashboard.qml b/Frontend/DashboardsViewer/content/screens/Dashboard.qml index a090cc1..81818d5 100644 --- a/Frontend/DashboardsViewer/content/screens/Dashboard.qml +++ b/Frontend/DashboardsViewer/content/screens/Dashboard.qml @@ -53,7 +53,7 @@ Item { } } - Text { + /*Text { id: dashboardText anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top @@ -73,13 +73,14 @@ Item { onClicked: function () { stackview.pop() } - } + }*/ StackView { id: dashboardStackView - anchors.top: dashboardText.bottom + anchors.fill: parent + /*anchors.top: dashboardText.bottom anchors.bottom: parent.bottom anchors.left: parent.left - anchors.right: parent.right + anchors.right: parent.right*/ } } diff --git a/Frontend/DashboardsViewer/content/screens/DashboardSelector.qml b/Frontend/DashboardsViewer/content/screens/DashboardSelector.qml index ba044e5..ee8007a 100644 --- a/Frontend/DashboardsViewer/content/screens/DashboardSelector.qml +++ b/Frontend/DashboardsViewer/content/screens/DashboardSelector.qml @@ -306,7 +306,8 @@ Item { delegate: DashboardDelegate { id: siteProjectDelegateSite - onItemClicked: function (id, definition) { + onItemClicked: function (id, name, definition) { + mainWindow.contextText = name; stackview.push("Dashboard.qml") // Get the current pushed element (the Dashboard) @@ -339,8 +340,9 @@ Item { delegate: DashboardDelegate { id: siteProjectDelegateProject - onItemClicked: function (id, definition) { - stackview.push("Dashboard.qml") + onItemClicked: function (id, name, definition) { + mainWindow.contextText = name; + stackview.push("Dashboard.qml"); // Get the current pushed element (the Dashboard) var currentElement = stackview.currentItem @@ -357,6 +359,8 @@ Item { text: qsTr("Test Mode") onClicked: function(){ let filename = ":/dashboards/DashboardsViewer/resources/json/TestDashboardv2.json"; + + mainWindow.contextText = qsTr("TestMode"); stackview.push("Dashboard.qml") // get current pushed element diff --git a/Frontend/DashboardsViewer/content/ui/BasicDialog.qml b/Frontend/DashboardsViewer/content/ui/BasicDialog.qml index 33d72a7..ce81b04 100644 --- a/Frontend/DashboardsViewer/content/ui/BasicDialog.qml +++ b/Frontend/DashboardsViewer/content/ui/BasicDialog.qml @@ -12,7 +12,9 @@ Item { id: baseItem property string title: "" - property bool showCloseButton: true + property bool showCloseButton: false + + property Item stackView: null default property alias contentItem: mainItem.data property int contentItemHeight: mainItem.implicitHeight @@ -95,7 +97,7 @@ Item { height: 40 color: "#7da4cf" - ColumnLayout{ + RowLayout{ anchors.fill: parent Text{ id: txtTitle @@ -108,6 +110,25 @@ Item { color: Constants.textColor font.pixelSize: Constants.largeFontSize } + Image{ + id: imgClose + visible: showCloseButton + source: "../images/icons/x.png" + height: 32 + width: height + sourceSize.height: height + sourceSize.width: width + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + MouseArea{ + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + if (stackView) { + stackView.pop(); + } + } + } + } } } diff --git a/Frontend/DashboardsViewer/content/widgets/ButtonWidget.qml b/Frontend/DashboardsViewer/content/widgets/ButtonWidget.qml index 421c9fc..97bd19c 100644 --- a/Frontend/DashboardsViewer/content/widgets/ButtonWidget.qml +++ b/Frontend/DashboardsViewer/content/widgets/ButtonWidget.qml @@ -11,6 +11,9 @@ BaseWidget { property color hoverColor: "#047eff" + implicitHeight: control.implicitHeight + implicitWidth: control.implicitWidth + 10 + Button { id: control diff --git a/Frontend/DashboardsViewer/content/widgets/ListViewWidget.qml b/Frontend/DashboardsViewer/content/widgets/ListViewWidget.qml index 038aa6a..5cecd76 100644 --- a/Frontend/DashboardsViewer/content/widgets/ListViewWidget.qml +++ b/Frontend/DashboardsViewer/content/widgets/ListViewWidget.qml @@ -13,6 +13,16 @@ BaseWidget { property alias delegate: myListView.delegate property var dataSource: null + readonly property bool itemSelected: myListView.currentIndex >= 0 + + Connections{ + ignoreUnknownSignals: true + target: dataSource + onModelChanged: function() { + myListView.currentIndex = -1; + } + } + Rectangle{ anchors.fill: parent color: "#88000000" diff --git a/Frontend/DashboardsViewer/content/widgets/SessionViewerWidget.qml b/Frontend/DashboardsViewer/content/widgets/SessionViewerWidget.qml index 3d74c5a..37d9751 100644 --- a/Frontend/DashboardsViewer/content/widgets/SessionViewerWidget.qml +++ b/Frontend/DashboardsViewer/content/widgets/SessionViewerWidget.qml @@ -7,261 +7,358 @@ import QtCore import "../ui" import "../dataSources" - -BaseWidget { - id:mySessionViewerWidget +Item { + id: rootItem property var session: null - Rectangle { - id: background - anchors.fill: parent - color: Constants.backgroundColor + BasicDialog { + id:mySessionViewerWidget + + showCloseButton: true + stackView: dashboardStackView ? dashboardStackView : null - ColumnLayout { - id: sessionLayout - spacing: 10 + width: 0.9 * parent.width + height: 0.9 * parent.height + anchors.centerIn: parent + + Rectangle { + id: background anchors.fill: parent - anchors.margins: 10 - Button { - id: button - Layout.fillWidth: false - Layout.fillHeight: false - Layout.alignment: Qt.AlignRight - implicitWidth: 200 - implicitHeight: 50 - text: "Click me to close." - onClicked: { - console.log("Button clicked") - if (stackView.currentItem === mySessionViewerWidget) { - stackView.pop(); + color: Constants.backgroundColor + + ColumnLayout { + id: sessionLayout + spacing: 10 + anchors.fill: parent + anchors.margins: 10 + RowLayout{ + Layout.fillWidth: true + Badge{ + visible: session.session_type_name + text: session.session_type_name + color: session.session_type_color ? session.session_type_color : "white" + font.pixelSize: Constants.baseFontSize + padding: 0 + textColor: "black" + } + Badge{ + visible: session.session_status === 2 + text: qsTr("Completed") + color: "darkgreen" + font.pixelSize: Constants.baseFontSize + padding: 0 + } + Badge{ + visible: session.session_status === 3 + text: qsTr("Cancelled") + color: "darkred" + font.pixelSize: Constants.baseFontSize + padding: 0 + } + Badge{ + visible: session.session_status === 4 + text: qsTr("Terminated") + color: "red" + font.pixelSize: Constants.baseFontSize + padding: 0 + } + Badge{ + visible: session.session_status === 1 + text: qsTr("In progress") + color: "darkgrey" + font.pixelSize: Constants.baseFontSize + padding: 0 + } + Badge{ + visible: session.session_status === 0 + text: qsTr("Planned") + color: "white" + font.pixelSize: Constants.baseFontSize + padding: 0 + textColor: "black" } } - } - Rectangle { - id: sessionName - Layout.fillWidth: true - Layout.fillHeight: false - implicitHeight: 30 - color: "lightblue" - Text { - id: sessionNameText - text: session.session_name + " [" + session.session_uuid + "]" - font.bold: true - font.pointSize: 20 - anchors.centerIn: parent - } - } - Rectangle { - id: sessionComments - Layout.fillWidth: true - Layout.fillHeight: false - implicitHeight: 30 - color: "lightyellow" - Text { - id: sessionCommentsText - text: session.session_comments - font.pointSize: 16 - anchors.fill: parent - wrapMode: Text.Wrap + /*Rectangle { + id: sessionName + Layout.fillWidth: true + Layout.fillHeight: false + implicitHeight: 30 + color: "lightblue" + Text { + id: sessionNameText + text: session.session_name + " [" + session.session_uuid + "]" + font.bold: true + font.pointSize: 20 + anchors.centerIn: parent + } + }*/ + Rectangle{ + Layout.fillWidth: true + implicitHeight: layoutHeader.implicitHeight + layoutHeader.anchors.margins*2 + color: Constants.lightBackgroundColor + radius: 10 + ColumnLayout{ + id: layoutHeader + anchors.fill: parent + anchors.margins: 10 + Text{ + id: txtDate + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + property date sessionDate: new Date(session.session_start_datetime) + text: sessionDate.toLocaleDateString() +" - " + sessionDate.toLocaleTimeString() + font.pixelSize: Constants.baseFontSize + style: Text.Outline + font.bold: true + color: Constants.textAltColor + wrapMode: Text.WordWrap + Layout.fillWidth: true + } + Text{ + id: txtName + Layout.fillWidth: true + text: session.session_name + font.pixelSize: Constants.baseFontSize * 1.2 + wrapMode: Text.WordWrap + style: Text.Outline + color: Constants.textColor + } + } } - } - // Participants - Rectangle { - id: participants - Layout.fillWidth: true - Layout.fillHeight: false - implicitHeight: 30 - color: "lightgreen" - Text { - id: participantsText - text: "Participants:" - font.bold: true - font.pointSize: 20 - anchors.centerIn: parent - } - Component.onCompleted: function() { - //Fill text with participant information - //for (var i = 0; i < mySessionViewerWidget.session.session_participants.length; i++) { - // participantsText.text += mySessionViewerWidget.session.session_participants[i] + ", "; - //} - } - } + Rectangle { + id: sessionComments + Layout.fillWidth: true + implicitHeight: layoutComments.implicitHeight + color: Constants.highlightColor + radius: 5 + visible: session.session_comments + ColumnLayout{ + id: layoutComments + anchors.fill: parent + Text { + id: sessionCommentsText + text: session.session_comments + color: "white" + Layout.fillWidth: true + wrapMode: Text.Wrap + } + } - // Assets - Rectangle { - id: assets - Layout.fillWidth: true - Layout.fillHeight: true - color: "lightgrey" - Text { - id: assetsText - text: "Assets:" - height: 40 - font.bold: true - font.pointSize: 20 - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - } - ListView { - id: assetsList - model: assetsDataSource.model - anchors.top: assetsText.bottom - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - delegate: Item { - id: assetItemDelegate - width: assetsList.width - height: 40 - - function delegateModel() { - return model - } + } - BasicButton { - id: singleAssetDownloadButton - anchors.fill: parent - text: delegateModel().asset_name + " [" + delegateModel().asset_uuid + "]" - onClicked: { - console.log("Download button clicked for asset: " + delegateModel().asset_name + " [" + delegateModel().asset_uuid + "]"); - - if (dashboardViewerApp.isWebAssembly()) { - console.log("WebAssembly is supported...") - //This will use the browser download function. Download UI is provided by browser. - fileDownloadDataSource.filename = delegateModel().asset_name - - //DownloadFile returnes a null object in WebASM - fileDownloadDataSource.downloadFile(); - } else { - console.log('WebAssembly is not supported'); - saveFileDialog.open(); - } + // Participants + /*Rectangle { + id: participants + Layout.fillWidth: true + Layout.fillHeight: false + implicitHeight: 30 + color: "lightgreen" + Text { + id: participantsText + text: "Participants:" + font.bold: true + font.pointSize: 20 + anchors.centerIn: parent + } - } - } + Component.onCompleted: function() { + //Fill text with participant information + //for (var i = 0; i < mySessionViewerWidget.session.session_participants.length; i++) { + // participantsText.text += mySessionViewerWidget.session.session_participants[i] + ", "; + //} + } + }*/ + + // Assets + Rectangle { + id: recAssets + Layout.fillWidth: true + Layout.fillHeight: true + color: "lightgrey" + radius: 5 + ColumnLayout{ + id: assetsLayout + anchors.fill: parent + anchors.margins: 5 Text { - id: singleAssetInfoText - anchors.right: singleAssetDownloadButton.right - anchors.top: singleAssetDownloadButton.top - anchors.bottom: singleAssetDownloadButton.bottom - text: "Hello World!" + id: assetsText + Layout.alignment: Qt.alignLeft | Qt.AlignTop + text: qsTr("Assets") + font.bold: true + font.pointSize: Constants.baseFontSize } - FileDownloadDataSource { - id: fileDownloadDataSource - url: "/file/api/assets" - filename: delegateModel().asset_name - params: {"asset_uuid": delegateModel().asset_uuid, "access_token": delegateModel().access_token} + Text{ + id: txtNoAssets + visible: !lstAssets.visible + text: qsTr("No assets") + verticalAlignment: Text.AlignTop + color: "darkred" + font.bold: true + font.pointSize: Constants.baseFontSize + Layout.alignment: Qt.alignLeft | Qt.AlignVCenter + Layout.fillHeight: true } - BaseDataSource { - id: assetInfoDataSource - url: "/file/api/assets/infos" - params: {"asset_uuid": delegateModel().asset_uuid, "access_token": delegateModel().access_token} - autoFetch: true - - //Be careful, we are using model from BaseDataSource not the delegate item - model.onCountChanged: function() { - console.log("infos count changed"); - var assetInfo = model.get(0); - singleAssetInfoText.text = "Size: " + (assetInfo.asset_file_size / (1024.0 * 1024.0)).toString() + " MB" - } - } - - //Download progress dialog - Dialog { - id: downloadProgressDialog - title: "Downloading " + delegateModel().asset_name - standardButtons: Dialog.Close - anchors.centerIn: assetItemDelegate - width: assetsList.width / 2 - height: assetsList.height / 2 - enabled: false - - ProgressBar { - id: progressBar - from: 0 - to: 100 - value: 0 - anchors.fill: parent - } + ListView { + id: lstAssets + model: assetsDataSource.model + Layout.fillHeight: true + Layout.fillWidth: true + Layout.leftMargin: 10 + Layout.rightMargin: 10 + clip: true + visible: count > 0 + + interactive: contentHeight < height + spacing: 2 + + delegate: Item { + id: assetItemDelegate + width: lstAssets.width + height: 40 + + function delegateModel() { + return model + } - Connections - { - target: fileDownloadDataSource - onDownloadProgress: function(bytesReceived, bytesTotal){ - console.log("DownloadProgressDialog progress: ", bytesReceived, bytesTotal); - progressBar.value = bytesReceived / bytesTotal * 100; + BasicButton { + id: singleAssetDownloadButton + anchors.fill: parent + text: delegateModel().asset_name + " [" + delegateModel().asset_uuid + "]" + onClicked: { + //console.log("Download button clicked for asset: " + delegateModel().asset_name + " [" + delegateModel().asset_uuid + "]"); + + if (dashboardViewerApp.isWebAssembly()) { + //console.log("WebAssembly is supported...") + //This will use the browser download function. Download UI is provided by browser. + fileDownloadDataSource.filename = delegateModel().asset_name + + //DownloadFile returnes a null object in WebASM + fileDownloadDataSource.downloadFile(); + } else { + //console.log('WebAssembly is not supported'); + saveFileDialog.open(); + } + + } } - onDownloadFinished: function() { - console.log("DownloadProgressDialog finished"); - downloadProgressDialog.enabled = true; + Text { + id: singleAssetInfoText + anchors.right: singleAssetDownloadButton.right + anchors.top: singleAssetDownloadButton.top + anchors.bottom: singleAssetDownloadButton.bottom + //text: "Hello World!" } - } - - onAccepted: { - console.log("DownloadProgressDialog accepted"); - saveFileDialog.open(); - } - } - FileDialog { - id: saveFileDialog - nameFilters: ["All files (*)"] - fileMode: FileDialog.SaveFile - //URL - currentFolder: StandardPaths.writableLocation(StandardPaths.DownloadLocation) - currentFile: delegateModel().asset_name - onAccepted: function() { - console.log("SaveFileDialog accepted"); - fileDownloadDataSource.filename = saveFileDialog.currentFile; - downloadProgressDialog.open(); - fileDownloadDataSource.downloadFile(); - } - } - } // Item (delegate) - - BaseDataSource { - id: assetsDataSource - url: "/api/user/assets" - params: {"id_session": session.id_session, "with_urls": true, "full": true} - autoFetch: true - } + FileDownloadDataSource { + id: fileDownloadDataSource + url: "/file/api/assets" + filename: delegateModel().asset_name + params: {"asset_uuid": delegateModel().asset_uuid, "access_token": delegateModel().access_token} + } + BaseDataSource { + id: assetInfoDataSource + url: "/file/api/assets/infos" + params: {"asset_uuid": delegateModel().asset_uuid, "access_token": delegateModel().access_token} + autoFetch: true + + //Be careful, we are using model from BaseDataSource not the delegate item + model.onCountChanged: function() { + //console.log("infos count changed"); + var assetInfo = model.get(0); + singleAssetInfoText.text = "Size: " + (assetInfo.asset_file_size / (1024.0 * 1024.0)).toString() + " MB" + } + } - }//ListView + //Download progress dialog + Dialog { + id: downloadProgressDialog + title: "Downloading " + delegateModel().asset_name + standardButtons: Dialog.Close + anchors.centerIn: assetItemDelegate + width: lstAssets.width / 2 + height: lstAssets.height / 2 + enabled: false + + ProgressBar { + id: progressBar + from: 0 + to: 100 + value: 0 + anchors.fill: parent + } + + Connections + { + target: fileDownloadDataSource + onDownloadProgress: function(bytesReceived, bytesTotal){ + console.log("DownloadProgressDialog progress: ", bytesReceived, bytesTotal); + progressBar.value = bytesReceived / bytesTotal * 100; + } + onDownloadFinished: function() { + console.log("DownloadProgressDialog finished"); + downloadProgressDialog.enabled = true; + } + } + + onAccepted: { + console.log("DownloadProgressDialog accepted"); + saveFileDialog.open(); + } + } + FileDialog { + id: saveFileDialog + nameFilters: ["All files (*)"] + fileMode: FileDialog.SaveFile + //URL + currentFolder: StandardPaths.writableLocation(StandardPaths.DownloadLocation) + currentFile: delegateModel().asset_name + onAccepted: function() { + console.log("SaveFileDialog accepted"); + fileDownloadDataSource.filename = saveFileDialog.currentFile; + downloadProgressDialog.open(); + fileDownloadDataSource.downloadFile(); + } + } + } // Item (delegate) + + BaseDataSource { + id: assetsDataSource + url: "/api/user/assets" + params: {"id_session": session.id_session, "with_urls": true, "full": true} + autoFetch: true + } - } + }//ListView + } + } - // Download Assets button - BasicButton { - id: downloadAssetsButton - Layout.fillWidth: false - Layout.fillHeight: false - Layout.alignment: Qt.AlignLeft - implicitWidth: 200 - implicitHeight: 50 - text: "Download Assets" - onClicked: { - console.log("Download Assets button clicked") + // Download Assets button + BasicButton { + id: downloadAssetsButton + Layout.fillWidth: false + Layout.fillHeight: false + Layout.alignment: Qt.AlignLeft + implicitWidth: 200 + implicitHeight: 50 + text: "Download Assets" + onClicked: { + console.log("Download Assets button clicked") + } } - } + } } - } - - Component.onCompleted: { - console.log("Item completed") } } diff --git a/Frontend/DashboardsViewer/qml_cpp_modules/config_parser/src/ConfigParser.cpp b/Frontend/DashboardsViewer/qml_cpp_modules/config_parser/src/ConfigParser.cpp index c0fe48e..ae7324b 100644 --- a/Frontend/DashboardsViewer/qml_cpp_modules/config_parser/src/ConfigParser.cpp +++ b/Frontend/DashboardsViewer/qml_cpp_modules/config_parser/src/ConfigParser.cpp @@ -25,7 +25,7 @@ ConfigParser::~ConfigParser() bool ConfigParser::isValidString(const QString &input) { - QRegularExpression regex("^[a-zA-Z0-9. //|]+$"); + QRegularExpression regex("^[a-zA-Z0-9. //|&]+$"); return regex.match(input).hasMatch(); } diff --git a/Frontend/DashboardsViewer/resources/json/TestDashboardv2.json b/Frontend/DashboardsViewer/resources/json/TestDashboardv2.json index d665ace..feedb2e 100644 --- a/Frontend/DashboardsViewer/resources/json/TestDashboardv2.json +++ b/Frontend/DashboardsViewer/resources/json/TestDashboardv2.json @@ -46,16 +46,40 @@ "layouts": [{ "type": "CenteredRowLayout", "id": "rightBottomLayout", - "widgets": [ + "properties":{ + "Layout.fillWidth": {"type": "bool", "value": "true"}, + "Layout.fillHeight": {"type": "bool", "value": "true"} + }, + "layouts": [ { - "type": "ListViewWidget", - "id": "participantSessionList", - "properties": { - "dataSource": {"type": "raw", "value": "participantSessionListData"}, - "delegate": {"type": "delegate", "value": "SessionDelegate"}, - "Layout.fillWidth": {"type": "bool", "value": "true"}, - "Layout.fillHeight": {"type": "bool", "value": "true"} - } + "type": "CenteredColumnLayout", + "id": "leftBottomLayout", + "widgets":[ + { + "type": "ListViewWidget", + "id": "participantSessionList", + "properties": { + "dataSource": {"type": "raw", "value": "participantSessionListData"}, + "delegate": {"type": "delegate", "value": "SessionDelegate"}, + "Layout.fillWidth": {"type": "bool", "value": "true"}, + "Layout.fillHeight": {"type": "bool", "value": "true"} + } + }, + { + "type": "ButtonWidget", + "id": "btnDownloadAssets", + "properties": { + "text": {"type": "string", "value": "Download assets"}, + "visible": {"type": "raw", "value": "participantSessionList.dataSource.model.count"} + } + } + ], + "properties":{ + "Layout.fillWidth": {"type": "bool", "value": "true"}, + "Layout.fillHeight": {"type": "bool", "value": "true"}, + "spacing": {"type": "int", "value": 10} + } + }, { "type": "ListViewWidget", @@ -66,7 +90,7 @@ "delegate": {"type": "delegate", "value": "SessionEventDelegate"}, "Layout.fillWidth": {"type": "bool", "value": "true"}, "Layout.fillHeight": {"type": "bool", "value": "true"}, - "visible": {"type": "raw", "value": "dataSource.model.count"} + "visible": {"type": "raw", "value": "participantSessionList.itemSelected && dataSource.model.count"} } } ]