From 8feab04fcd1e472abf9992f81284b962a22e708e Mon Sep 17 00:00:00 2001 From: Lubos Date: Thu, 7 Dec 2023 23:28:10 +0100 Subject: [PATCH] Added Drawer with selected items; and animation --- app/icons/Download.svg | 5 + app/icons/Info.svg | 5 + app/icons/Sync.svg | 6 + app/icons/icons.qrc | 3 + app/mmstyle.h | 6 + app/qml/components/MMListDrawer.qml | 107 +++++ app/qml/components/MMListDrawerItem.qml | 58 +++ app/qml/components/MMProjectItem.qml | 551 ++++++++---------------- gallery/qml.qrc | 2 + gallery/qml/pages/ProjectItemsPage.qml | 99 ++++- 10 files changed, 461 insertions(+), 381 deletions(-) create mode 100644 app/icons/Download.svg create mode 100644 app/icons/Info.svg create mode 100644 app/icons/Sync.svg create mode 100644 app/qml/components/MMListDrawer.qml create mode 100644 app/qml/components/MMListDrawerItem.qml diff --git a/app/icons/Download.svg b/app/icons/Download.svg new file mode 100644 index 000000000..b97db411c --- /dev/null +++ b/app/icons/Download.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/icons/Info.svg b/app/icons/Info.svg new file mode 100644 index 000000000..ecf9df01d --- /dev/null +++ b/app/icons/Info.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/icons/Sync.svg b/app/icons/Sync.svg new file mode 100644 index 000000000..9fa37fa99 --- /dev/null +++ b/app/icons/Sync.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/icons/icons.qrc b/app/icons/icons.qrc index ec511e779..f932c10ec 100644 --- a/app/icons/icons.qrc +++ b/app/icons/icons.qrc @@ -22,5 +22,8 @@ More.svg ProjectButtonMore.svg Stop.svg + Download.svg + Info.svg + Sync.svg diff --git a/app/mmstyle.h b/app/mmstyle.h index ca43e1e81..319ff6c48 100644 --- a/app/mmstyle.h +++ b/app/mmstyle.h @@ -95,6 +95,9 @@ class MMStyle: public QObject Q_PROPERTY( QUrl moreIcon READ moreIcon CONSTANT ) Q_PROPERTY( QUrl projectButtonMoreIcon READ projectButtonMoreIcon CONSTANT ) Q_PROPERTY( QUrl stopIcon READ stopIcon CONSTANT ) + Q_PROPERTY( QUrl syncIcon READ syncIcon CONSTANT ) + Q_PROPERTY( QUrl infoIcon READ infoIcon CONSTANT ) + Q_PROPERTY( QUrl downloadIcon READ downloadIcon CONSTANT ) // Images Q_PROPERTY( QUrl uploadImage READ uploadImage CONSTANT ) @@ -177,6 +180,9 @@ class MMStyle: public QObject QUrl moreIcon() {return QUrl( "qrc:/More.svg" );} QUrl projectButtonMoreIcon() {return QUrl( "qrc:/ProjectButtonMore.svg" );} QUrl stopIcon() {return QUrl( "qrc:/Stop.svg" );} + QUrl syncIcon() {return QUrl( "qrc:/Sync.svg" );} + QUrl infoIcon() {return QUrl( "qrc:/Info.svg" );} + QUrl downloadIcon() {return QUrl( "qrc:/Download.svg" );} QUrl uploadImage() {return QUrl( "qrc:/UploadImage.svg" );} QUrl reachedDataLimitImage() {return QUrl( "qrc:/ReachedDataLimitImage.svg" );} diff --git a/app/qml/components/MMListDrawer.qml b/app/qml/components/MMListDrawer.qml new file mode 100644 index 000000000..2ac2bbf1c --- /dev/null +++ b/app/qml/components/MMListDrawer.qml @@ -0,0 +1,107 @@ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic + +Drawer { + id: control + + property alias title: title.text + property alias model: listView.model + + padding: 20 * __dp + + signal clicked(type: string) + + width: window.width + height: mainColumn.height + edge: Qt.BottomEdge + + Rectangle { + color: roundedRect.color + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + height: 2 * radius + anchors.topMargin: -radius + radius: 20 * __dp + } + + Rectangle { + id: roundedRect + + anchors.fill: parent + color: __style.whiteColor + + Column { + id: mainColumn + + width: parent.width + spacing: 20 * __dp + leftPadding: control.padding + rightPadding: control.padding + bottomPadding: control.padding + + Row { + width: parent.width - 2 * control.padding + anchors.horizontalCenter: parent.horizontalCenter + + Item { width: closeButton.width; height: 1 } + + Text { + id: title + + anchors.verticalCenter: parent.verticalCenter + font: __style.t2 + width: parent.width - closeButton.width * 2 + color: __style.forestColor + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + + Image { + id: closeButton + + source: __style.closeButtonIcon + + MouseArea { + anchors.fill: parent + onClicked: control.visible = false + } + } + } + + ListView { + id: listView + + width: parent.width - 2 * control.padding + height: control.model ? control.model.count * __style.menuDrawerHeight : 0 + interactive: false + + delegate: Item { + width: listView.width + height: __style.menuDrawerHeight + + MMListDrawerItem { + width: listView.width + + type: model.type + text: model.name + iconSource: model.iconSource + + onClicked: function(type) { control.clicked(type); control.visible = false } + } + } + } + } + } +} diff --git a/app/qml/components/MMListDrawerItem.qml b/app/qml/components/MMListDrawerItem.qml new file mode 100644 index 000000000..1e4b1b7fd --- /dev/null +++ b/app/qml/components/MMListDrawerItem.qml @@ -0,0 +1,58 @@ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic + +Item { + id: control + + signal clicked(type: string) + + required property string type + required property string text + required property var iconSource + + width: control.width + height: __style.menuDrawerHeight + + Rectangle { + anchors.top: parent.top + width: parent.width + height: 1 * __dp + color: __style.grayColor + } + + Row { + height: parent.height + width: parent.width + spacing: 10 * __dp + + MMIcon { + height: parent.height + width: 20 * __dp + color: __style.forestColor + source: control.iconSource ?? "" + } + + Text { + height: parent.height + verticalAlignment: Text.AlignVCenter + text: control.text + color: __style.nightColor + font: __style.t3 + } + } + + MouseArea { + anchors.fill: parent + onClicked: control.clicked(control.type) + } +} diff --git a/app/qml/components/MMProjectItem.qml b/app/qml/components/MMProjectItem.qml index 98571c3f0..389e4a100 100644 --- a/app/qml/components/MMProjectItem.qml +++ b/app/qml/components/MMProjectItem.qml @@ -9,38 +9,21 @@ import QtQuick import QtQuick.Controls -import QtQuick.Layouts -import Qt5Compat.GraphicalEffects -import QtQml.Models -import ".." +import "../components" Rectangle { id: root - // Required properties - property string projectDisplayName: "TITLE" - property string projectId: "ID" - property string projectDescription: "DESC" - property int projectStatus: 0 - property bool projectIsValid: true + required property string projectDisplayName + required property string projectId + required property string projectDescription + required property int projectStatus + required property bool projectIsValid + required property bool projectIsLocal + required property bool projectIsMergin property bool projectIsPending: false - property real projectSyncProgress: 10 - property bool projectIsLocal: true - property bool projectIsMergin: true - property string projectRemoteError: "ERROR" - - property color primaryColor: "red" //InputStyle.clrPanelMain - property color secondaryColor: "green"// InputStyle.fontColor - property real itemMargin: 20 //InputStyle.panelMargin - - property color iconColor: "yellow" // root.highlight ? root.primaryColor : InputStyle.actionColor - property real iconSize: height * 0.3 - property real borderWidth: 1 * __dp - property real menuItemHeight: height * 0.8 - - property real viewContentY: 0 - property real viewHeight: 0 + property real projectSyncProgress: 0.0 property bool highlight: false signal openRequested() @@ -50,11 +33,16 @@ Rectangle { signal stopSyncRequested() signal showChangesRequested() - color: root.highlight ? __style.forestColor : __style.whiteColor radius: 12 * __dp height: mainColumn.height + MouseArea { + anchors.fill: parent + enabled: root.projectIsValid + onClicked: openRequested() + } + Column { id: mainColumn @@ -64,383 +52,208 @@ Rectangle { Row { id: row + spacing: 6 * __dp Column { id: column + spacing: 6 * __dp Text { + width: mainColumn.width - 2 * mainColumn.padding - icon.width - row.spacing + text: root.projectDisplayName font: __style.t3 color: root.highlight ? __style.whiteColor : __style.nightColor elide: Text.ElideRight - width: mainColumn.width - 2 * mainColumn.padding - icon.width - row.spacing + opacity: root.projectIsValid ? 1.0 : 0.4 } - Text { - text: root.projectDescription - font: __style.p6 - color: root.highlight ? __style.whiteColor : __style.nightColor - elide: Text.ElideRight + Row { width: mainColumn.width - 2 * mainColumn.padding - icon.width - row.spacing + spacing: 4 * __dp + + MMIcon { + id: errorIcon + + source: visible ? __style.errorIcon : "" + color: __style.negativeColor + visible: !root.projectIsValid + } + + Text { + width: parent.width - errorIcon.width + + text: root.projectDescription + font: __style.p6 + elide: Text.ElideRight + color: { + if(root.projectIsValid) { + if(root.highlight) { + return __style.whiteColor + } + return __style.nightColor + } + return __style.grapeColor + } + } } } Image { id: icon - source: __style.projectButtonMoreIcon height: column.height + width: height + + source: __style.projectButtonMoreIcon fillMode: Image.PreserveAspectFit - } - } - MMProgressBar { - position: 0.5 - width: mainColumn.width - 2 * mainColumn.padding + MouseArea { + anchors.fill: parent + onClicked: { + root.fillMoreMenu() + listDrawer.visible = true + } + } + } } - Row { - id: syncRow - spacing: 6 * __dp + Item { + height: root.projectIsPending ? syncColumn.height : 0 + width: parent.width + clip: true - Text { - text: qsTr("Synchronising...") - font: __style.p6 - color: root.highlight ? __style.whiteColor : __style.nightColor - elide: Text.ElideRight - width: mainColumn.width - 2 * mainColumn.padding - stopIcon.width - syncRow.spacing * 2 - stopText.width - verticalAlignment: Text.AlignVCenter - anchors.verticalCenter: parent.verticalCenter + Behavior on height { + NumberAnimation { duration: 250 } } - MMIcon { - id: stopIcon - source: __style.stopIcon - anchors.verticalCenter: parent.verticalCenter - color: root.highlight ? __style.whiteColor : __style.forestColor + Column { + id: syncColumn - MouseArea { - anchors.fill: parent - onClicked: root.stopSyncRequested() + spacing: mainColumn.spacing + + MMProgressBar { + position: root.projectSyncProgress + width: mainColumn.width - 2 * mainColumn.padding } - } - Text { - id: stopText - text: qsTr("Stop") - font: __style.t4 - color: root.highlight ? __style.whiteColor : __style.nightColor - verticalAlignment: Text.AlignVCenter - anchors.verticalCenter: parent.verticalCenter + Row { + id: syncRow - MouseArea { - anchors.fill: parent - onClicked: root.stopSyncRequested() + spacing: 6 * __dp + + Text { + width: mainColumn.width - 2 * mainColumn.padding - stopIcon.width - syncRow.spacing * 2 - stopText.width + anchors.verticalCenter: parent.verticalCenter + + text: qsTr("Synchronising...") + font: __style.p6 + color: root.highlight ? __style.whiteColor : __style.nightColor + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } + + MMIcon { + id: stopIcon + + anchors.verticalCenter: parent.verticalCenter + + source: __style.stopIcon + color: root.highlight ? __style.whiteColor : __style.forestColor + + MouseArea { + anchors.fill: parent + onClicked: root.stopSyncRequested() + } + } + + Text { + id: stopText + + anchors.verticalCenter: parent.verticalCenter + + text: qsTr("Stop") + font: __style.t4 + color: root.highlight ? __style.whiteColor : __style.nightColor + verticalAlignment: Text.AlignVCenter + + MouseArea { + anchors.fill: parent + onClicked: root.stopSyncRequested() + } + } } } } } - ///* - // function getStatusIcon() { - // if ( projectIsPending ) - // return InputStyle.stopIcon - - // if ( projectIsLocal && projectIsMergin ) { - // // downloaded mergin projects - // if ( projectStatus === ProjectStatus.NeedsSync ) { - // return InputStyle.syncIcon - // } - // return "" // no icon if this project does not have changes - // } - - // if ( projectIsMergin && projectStatus === ProjectStatus.NoVersion ) - // return InputStyle.downloadIcon - - // if ( projectIsLocal && projectStatus === ProjectStatus.NoVersion ) - // return InputStyle.uploadIcon - - // return "" - // } - - // function getMoreMenuItems() { - // if ( projectIsMergin && projectIsLocal ) - // { - // if ( ( projectStatus === ProjectStatus.NeedsSync ) ) - // return "sync,changes,remove" - - // return "changes,remove" - // } - // else if ( !projectIsMergin && projectIsLocal ) - // return "upload,remove" - // else - // return "download" - // } - - // function fillMoreMenu() { - // // fill more menu with corresponding items - // let itemsMap = { - // "sync": { - // "name": qsTr("Synchronize project"), - // "iconSource": InputStyle.syncIcon, - // "callback": function() { root.syncRequested() } - // }, - // "changes": { - // "name": qsTr("Local changes"), - // "iconSource": InputStyle.infoIcon, - // "callback": function() { root.showChangesRequested() } - // }, - // "remove": { - // "name": qsTr("Remove from device"), - // "iconSource": InputStyle.removeIcon, - // "callback": function() { root.removeRequested() } - // }, - // "upload": { - // "name": qsTr("Upload to Mergin"), - // "iconSource": InputStyle.uploadIcon, - // "callback": function() { root.migrateRequested() } - // }, - // "download": { - // "name": qsTr("Download from Mergin"), - // "iconSource": InputStyle.downloadIcon, - // "callback": function() { root.syncRequested() } - // } - // } - - // let items = getMoreMenuItems() - // items = items.split(',') - - // // clear previous items - // while( contextMenu.count > 0 ) - // contextMenu.takeItem( 0 ); - - // items.forEach( function(item) { contextMenu.addItem( - // menuItemComponent.createObject( contextMenu, itemsMap[item] ) ) - // }) - // contextMenu.height = items.length * root.menuItemHeight - // } - //*/ - // color: "cyan" //root.highlight ? InputStyle.panelItemHighlight : root.primaryColor - - // MouseArea { - // anchors.fill: parent - // enabled: projectIsValid - // onClicked: openRequested() - // } - - // RowLayout { - // id: row - - // anchors.fill: parent - // anchors.leftMargin: root.itemMargin - // spacing: 0 - - // Item { - // id: textContainer - - // height: root.height - // Layout.fillWidth: true - - // Text { - // id: mainText - - // text: "Ahoj" //__inputUtils.formatProjectName( projectDisplayName ) - // height: textContainer.height/2 - // width: textContainer.width - // font.pixelSize: 20 //InputStyle.fontPixelSizeNormal - // color: "grey" /*if (root.highlight) root.primaryColor - // else if (!projectIsValid) InputStyle.panelBackgroundDark - // else root.secondaryColor*/ - // horizontalAlignment: Text.AlignLeft - // verticalAlignment: Text.AlignBottom - // elide: Text.ElideLeft - // } - - // Text { - // id: secondaryText - - // visible: !projectIsPending - // height: textContainer.height/2 - // text: projectDescription - // anchors.right: parent.right - // anchors.bottom: parent.bottom - // anchors.left: parent.left - // anchors.top: mainText.bottom - // font.pixelSize: 20 //InputStyle.fontPixelSizeSmall - // color: "orange" // root.highlight ? root.primaryColor : InputStyle.panelBackgroundDark - // horizontalAlignment: Text.AlignLeft - // verticalAlignment: Text.AlignTop - // elide: Text.ElideRight - // } - - //// ProgressBar { - //// id: progressBar - - //// property real itemHeight: 10 //InputStyle.rowHeightSmall - - //// anchors.top: mainText.bottom - //// height: itemHeight - //// width: secondaryText.width - //// value: projectSyncProgress - //// visible: projectIsPending - - //// background: Rectangle { - //// implicitWidth: parent.width - //// implicitHeight: progressBar.itemHeight - //// color: "blue" //InputStyle.panelBackgroundLight - //// } - - //// contentItem: Item { - //// implicitWidth: parent.width - //// implicitHeight: progressBar.itemHeight - - //// Rectangle { - //// width: progressBar.visualPosition * parent.width - //// height: parent.height - //// color: "brown" //InputStyle.fontColor - //// } - //// } - //// } - // } - - // Item { - // id: statusIconContainer - - // //property string iconSource: getStatusIcon() - - // //visible: iconSource !== "" - // Layout.preferredWidth: root.height - // height: root.height - - // Image { - // id: statusIcon - - // anchors.centerIn: parent - // //source: statusIconContainer.iconSource - // height: root.iconSize - // width: height - // sourceSize.width: width - // sourceSize.height: height - // fillMode: Image.PreserveAspectFit - // } - - // ColorOverlay { - // anchors.fill: statusIcon - // source: statusIcon - // color: root.iconColor - // } - - // MouseArea { - // anchors.fill: parent - // onClicked: { - // if ( projectRemoteError ) { - // __inputUtils.showNotification( qsTr( "Could not synchronize project, please make sure you are logged in and have sufficient rights." ) ) - // return - // } - // if ( projectIsPending ) - // stopSyncRequested() - // else if ( !projectIsMergin ) - // migrateRequested() - // else - // syncRequested() - // } - // } - // } - - // Item { - // id: moreMenuContainer - - // Layout.preferredWidth: root.height - // height: root.height - - // Image { - // id: moreMenuIcon - - // anchors.centerIn: parent - // //source: InputStyle.moreMenuIcon - // height: root.iconSize - // width: height - // sourceSize.width: width - // sourceSize.height: height - // fillMode: Image.PreserveAspectFit - // } - - // ColorOverlay { - // anchors.fill: moreMenuIcon - // source: moreMenuIcon - // color: root.iconColor - // } - - // MouseArea { - // anchors.fill: parent - // onClicked: { - // fillMoreMenu() - // contextMenu.open() - // } - // } - // } - // } - - // Rectangle { // border line - // color: "white" //InputStyle.panelBackground2 - // width: root.width - // height: root.borderWidth - // anchors.bottom: parent.bottom - // } - ///* - // // More Menu - // Menu { - // id: contextMenu - - // width: Math.min( root.width, 300 * __dp ) - // leftMargin: Math.max( root.width - width, 0 ) - // z: 100 - - // enter: Transition { - // ParallelAnimation { - // NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 100 } - // } - // } - // exit: Transition { - // ParallelAnimation { - // NumberAnimation { property: "opacity"; from: 1.0; to: 0; duration: 100 } - // } - // } - - // //! sets y-offset either above or below related item according relative position to end of the list - // onAboutToShow: { - // let itemRelativeY = parent.y - root.viewContentY - // if ( itemRelativeY + contextMenu.height >= root.viewHeight ) - // contextMenu.y = -contextMenu.height + parent.height / 3 - // else - // contextMenu.y = ( parent.height * 2 ) / 3 - // } - // } - - // Component { - // id: menuItemComponent - - // MenuItem { - // id: menuItem - - // property string name: "" - // property var callback: function cb() {} // default callback - // property string iconSource: "" - - // height: root.menuItemHeight - - // ExtendedMenuItem { - // height: parent.height - // rowHeight: parent.height * 0.8 - // width: parent.width - // contentText: menuItem.name - // imageSource: menuItem.iconSource - // overlayImage: true - // } - - // onClicked: callback() - // } - // }*/ + MMListDrawer { + id: listDrawer + + title: qsTr("More options") + model: ListModel { + id: menuModel + } + + onClicked: function(type) { + console.log(type) + switch(type) { + case "download": root.syncRequested(); break + case "sync": root.syncRequested(); break + case "changes": root.showChangesRequested(); break + case "remove": root.removeRequested(); break + case "upload": root.migrateRequested(); break + } + } + } + + function getMoreMenuItems() { + if ( projectIsMergin && projectIsLocal ) + { + if ( ( projectStatus === 2 /*ProjectStatus.NeedsSync*/ ) ) { // uncomment when using this component + return "sync,changes,remove" + } + return "changes,remove" + } + else if ( !projectIsMergin && projectIsLocal ) { + return "upload,remove" + } + return "download" + } + + function fillMoreMenu() { + // fill more menu with corresponding items + let itemsMap = { + "download": { + "name": qsTr("Download from Mergin"), + "iconSource": __style.downloadIcon + }, + "sync": { + "name": qsTr("Synchronize project"), + "iconSource": __style.syncIcon + }, + "changes": { + "name": qsTr("Local changes"), + "iconSource": __style.infoIcon + }, + "remove": { + "name": qsTr("Remove from device"), + "iconSource": __style.deleteIcon + }, + "upload": { + "name": qsTr("Upload to Mergin"), + "iconSource": __style.uploadIcon + } + } + + let items = getMoreMenuItems().split(',') + menuModel.clear() + items.forEach( function(item) { + var json = itemsMap[item] + json.type = item + menuModel.append( json ) + } ) + } } diff --git a/gallery/qml.qrc b/gallery/qml.qrc index e34f15175..921bcb69e 100644 --- a/gallery/qml.qrc +++ b/gallery/qml.qrc @@ -39,5 +39,7 @@ ../app/qml/components/MMToolbarMenuButton.qml ../app/qml/components/MMToolbarLongButton.qml qml/pages/ProjectItemsPage.qml + ../app/qml/components/MMListDrawer.qml + ../app/qml/components/MMListDrawerItem.qml diff --git a/gallery/qml/pages/ProjectItemsPage.qml b/gallery/qml/pages/ProjectItemsPage.qml index 0725b991d..f7fa27708 100644 --- a/gallery/qml/pages/ProjectItemsPage.qml +++ b/gallery/qml/pages/ProjectItemsPage.qml @@ -9,24 +9,99 @@ import QtQuick import QtQuick.Controls -import "../../app/qmlV2/component" +import "../../app/qml/components" Page { id: pane - MMProjectItem { - width: 300 - anchors.horizontalCenter: parent.horizontalCenter + Column { + width: parent.width anchors.top: parent.top anchors.topMargin: 20 - highlight: true - } + anchors.left: parent.left + anchors.leftMargin: 20 + spacing: 20 + + MMProjectItem { + width: 350 + + highlight: true + projectId: "1" + projectStatus: 2 + projectDisplayName: "Mergin local project" + projectDescription: "Highlighted" + projectIsValid: true + projectIsLocal: true + projectIsMergin: true + projectIsPending: true + + onOpenRequested: console.log("onOpenRequested") + onStopSyncRequested: projectIsPending = false + onShowChangesRequested: console.log("onShowChangesRequested") + onSyncRequested: projectIsPending = true + onRemoveRequested: console.log("onRemoveRequested") + onMigrateRequested: console.log("onMigrateRequested") + } + + MMProjectItem { + width: 350 + + highlight: false + projectId: "1" + projectStatus: 2 + projectDisplayName: "Mergin local project" + projectDescription: "Highlighted" + projectIsValid: true + projectIsLocal: true + projectIsMergin: true + + onOpenRequested: console.log("onOpenRequested") + onStopSyncRequested: projectIsPending = false + onShowChangesRequested: console.log("onShowChangesRequested") + onSyncRequested: projectIsPending = true + onRemoveRequested: console.log("onRemoveRequested") + onMigrateRequested: console.log("onMigrateRequested") + } + + MMProjectItem { + width: 350 + + highlight: false + projectId: "1" + projectStatus: 2 + projectDisplayName: "Mergin local project Long Long Long Long Long Long Long" + projectDescription: "Description Description Description Description Description" + projectIsValid: true + projectIsLocal: true + projectIsMergin: true + + onOpenRequested: console.log("onOpenRequested") + onStopSyncRequested: projectIsPending = false + onShowChangesRequested: console.log("onShowChangesRequested") + onSyncRequested: projectIsPending = true + onRemoveRequested: console.log("onRemoveRequested") + onMigrateRequested: console.log("onMigrateRequested") + } + + MMProjectItem { + width: 350 + + highlight: false + projectId: "2" + projectStatus: 0 + projectDisplayName: "Invalid project" + projectDescription: "A project error. A project error. A project error." + projectIsValid: false + projectIsLocal: false + projectIsMergin: false + + onOpenRequested: console.log("onOpenRequested") + onStopSyncRequested: console.log("onStopSyncRequested") + onShowChangesRequested: console.log("onShowChangesRequested") + onSyncRequested: { console.log("onSyncRequested"); projectIsPending = true } + onRemoveRequested: console.log("onRemoveRequested") + onMigrateRequested: console.log("onMigrateRequested") + } - MMProjectItem { - width: 300 - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - anchors.topMargin: 200 - highlight: false } }