diff --git a/app/filtercontroller.cpp b/app/filtercontroller.cpp index 81fe79fd7..2cb7f2fae 100644 --- a/app/filtercontroller.cpp +++ b/app/filtercontroller.cpp @@ -867,4 +867,4 @@ QStringList FilterController::lookupValueRelationTexts( const QVariantMap &confi } return texts; -} +} \ No newline at end of file diff --git a/app/qml/CMakeLists.txt b/app/qml/CMakeLists.txt index ad6db84a0..ec241473e 100644 --- a/app/qml/CMakeLists.txt +++ b/app/qml/CMakeLists.txt @@ -62,6 +62,7 @@ set(MM_QML filters/MMFilterChip.qml filters/MMFilterLayerSection.qml filters/MMFiltersPanel.qml + filters/components/MMFilterBanner.qml dialogs/MMCloseAccountDialog.qml dialogs/MMDownloadProjectDialog.qml dialogs/MMMigrateToMerginDialog.qml diff --git a/app/qml/components/MMButton.qml b/app/qml/components/MMButton.qml index 0c91ef0d9..019c651d0 100644 --- a/app/qml/components/MMButton.qml +++ b/app/qml/components/MMButton.qml @@ -15,7 +15,7 @@ Button { id: root enum Types { Primary, Secondary, Tertiary } - enum Sizes { Small, Regular } + enum Sizes { Small, Regular, ExtraSmall } property int type: MMButton.Types.Primary property int size: MMButton.Sizes.Regular @@ -162,11 +162,20 @@ Button { state: "default" - implicitHeight: root.type === MMButton.Types.Tertiary ? buttonContent.height : buttonContent.height + topPadding + bottomPadding - implicitWidth: row.paintedChildrenWidth + 2 * ( root.size === MMButton.Sizes.Small ? __style.margin16 : __style.margin20 ) + implicitHeight: buttonContent.height + topPadding + bottomPadding + + implicitWidth: { + let margin = __style.margin20 + if ( root.size === MMButton.Sizes.ExtraSmall ) margin = __style.margin8 + else if ( root.size === MMButton.Sizes.Small ) margin = __style.margin16 + return row.paintedChildrenWidth + 2 * margin + } topPadding: { - if ( root.type === MMButton.Types.Tertiary ) { + if ( root.size === MMButton.Sizes.ExtraSmall ) { + return __style.margin2; + } + else if ( root.type === MMButton.Types.Tertiary ) { return 0; } else if ( root.size === MMButton.Sizes.Small ) { @@ -178,7 +187,10 @@ Button { } bottomPadding: { - if ( root.type === MMButton.Types.Tertiary ) { + if ( root.size === MMButton.Sizes.ExtraSmall ) { + return __style.margin2; + } + else if ( root.type === MMButton.Types.Tertiary ) { return 0; } else if ( root.size === MMButton.Sizes.Small ) { @@ -200,7 +212,12 @@ Button { id: row property real paintedChildrenWidth: buttonIconLeft.paintedWidth + buttonContent.implicitWidth + buttonIconRight.paintedWidth + spacing - property real maxWidth: parent.width - 2 * ( root.size === MMButton.Sizes.Small ? __style.margin16 : __style.margin20 ) + property real maxWidth: { + let margin = __style.margin20 + if ( root.size === MMButton.Sizes.ExtraSmall ) margin = __style.margin8 + else if ( root.size === MMButton.Sizes.Small ) margin = __style.margin16 + return parent.width - 2 * margin + } x: ( parent.width - width ) / 2 @@ -232,7 +249,7 @@ Button { width: parent.width - buttonIconLeft.paintedWidth - buttonIconRight.paintedWidth - font: __style.t3 + font: root.size === MMButton.Sizes.ExtraSmall ? __style.t5 : __style.t3 text: root.text } @@ -266,7 +283,7 @@ Button { background: Rectangle { id: buttonBackground - radius: __style.radius30 + radius: root.size === MMButton.Sizes.ExtraSmall ? __style.radius40 : __style.radius30 border.width: 2 * __dp } diff --git a/app/qml/components/private/MMBaseInput.qml b/app/qml/components/private/MMBaseInput.qml index 0044acf53..4423d4ba7 100644 --- a/app/qml/components/private/MMBaseInput.qml +++ b/app/qml/components/private/MMBaseInput.qml @@ -32,6 +32,7 @@ Item { property string errorMsg: "" property string warningMsg: "" + property string infoMsg: "" property alias inputContent: contentGroup.children @@ -65,7 +66,7 @@ Item { states: [ State { name: "valid" - when: !shouldShowValidation || ( !warningMsg && !errorMsg ) + when: !shouldShowValidation || ( !warningMsg && !errorMsg && !infoMsg ) }, State { name: "error" @@ -74,6 +75,10 @@ Item { State { name: "warning" when: warningMsg && !errorMsg + }, + State { + name: "information" + when: infoMsg } ] @@ -179,11 +184,15 @@ Item { width: parent.width MMComponents.MMIcon { - source: __style.errorCircleIcon + source: { + if ( root.validationState === "information" ) return __style.infoFilledIcon + return __style.errorCircleIcon + } size: __style.icon16 color: { if ( root.validationState === "error" ) return __style.negativeColor if ( root.validationState === "warning" ) return __style.warningColor + if ( root.validationState === "information" ) return __style.informativeColor return __style.forestColor } } @@ -194,11 +203,13 @@ Item { text: { if ( root.validationState === "error" ) return root.errorMsg if ( root.validationState === "warning" ) return root.warningMsg + if ( root.validationState === "information" ) return root.infoMsg return "" } color: { if ( root.validationState === "error" ) return __style.grapeColor if ( root.validationState === "warning" ) return __style.earthColor + if ( root.validationState === "information" ) return __style.deepOceanColor return __style.forestColor } diff --git a/app/qml/filters/components/MMFilterBanner.qml b/app/qml/filters/components/MMFilterBanner.qml new file mode 100644 index 000000000..c0ee2e4ba --- /dev/null +++ b/app/qml/filters/components/MMFilterBanner.qml @@ -0,0 +1,66 @@ +/*************************************************************************** + * * + * 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.Layouts + +import "../../components" as MMComponents + +Rectangle { + id: root + + property string text + property string actionText: "" + + signal actionClicked() + + color: __style.informativeColor + radius: __style.radius8 + implicitHeight: row.implicitHeight + 2 * __style.margin8 + + RowLayout { + id: row + + anchors { + left: parent.left + right: parent.right + leftMargin: __style.margin12 + rightMargin: __style.margin8 + verticalCenter: parent.verticalCenter + } + + spacing: __style.spacing8 + + MMComponents.MMText { + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + + text: root.text + font: __style.t4 + color: __style.deepOceanColor + wrapMode: Text.Wrap + elide: Text.ElideNone + } + + MMComponents.MMButton { + id: actionButton + + visible: root.actionText !== "" + Layout.alignment: Qt.AlignVCenter + + type: MMComponents.MMButton.Types.Tertiary + size: MMComponents.MMButton.Sizes.ExtraSmall + text: root.actionText + fontColor: __style.skyColor + bgndColor: __style.deepOceanColor + + onClicked: root.actionClicked() + } + } +} diff --git a/app/qml/form/components/MMFeaturesListPageDrawer.qml b/app/qml/form/components/MMFeaturesListPageDrawer.qml index da8797332..6ec59c707 100644 --- a/app/qml/form/components/MMFeaturesListPageDrawer.qml +++ b/app/qml/form/components/MMFeaturesListPageDrawer.qml @@ -9,9 +9,11 @@ import QtQuick import QtQuick.Controls +import QtQuick.Layouts import "../../inputs" as MMInputs import "../../components" as MMComponents +import "../../filters/components" as MMFilters // // Special type of drawer/page -> looks like page, but it is actually Drawer @@ -51,7 +53,7 @@ Drawer { width: parent.width height: parent.height - Column { + ColumnLayout { id: contentColumn width: parent.width @@ -59,27 +61,41 @@ Drawer { spacing: 0 - MMComponents.MMListSpacer { height: __style.spacing20 } + MMComponents.MMListSpacer { Layout.preferredHeight: __style.spacing20 } MMInputs.MMSearchInput { id: searchBar delayedSearch: true - width: parent.width + Layout.fillWidth: true placeholderText: qsTr("Search for features...") onSearchTextChanged: root.searchTextChanged( searchBar.searchText ) } - MMComponents.MMListSpacer { height: __style.spacing20 } + MMComponents.MMListSpacer { Layout.preferredHeight: __style.spacing20 } + + MMFilters.MMFilterBanner { + id: filterBanner + + visible: __activeProject.filterController.hasActiveFilters + + Layout.fillWidth: true + text: qsTr( "Some features may be hidden by active filters" ) + } + + MMComponents.MMListSpacer { + visible: filterBanner.visible + Layout.preferredHeight: __style.spacing20 + } MMComponents.MMListView { id: listView - width: parent.width - height: parent.height - 2 * __style.spacing20 - searchBar.height + Layout.fillWidth: true + Layout.fillHeight: true clip: true diff --git a/app/qml/form/editors/MMFormGalleryEditor.qml b/app/qml/form/editors/MMFormGalleryEditor.qml index bfa98db84..b739c2f4c 100644 --- a/app/qml/form/editors/MMFormGalleryEditor.qml +++ b/app/qml/form/editors/MMFormGalleryEditor.qml @@ -30,6 +30,10 @@ MMPrivateComponents.MMBaseInput { title: _fieldShouldShowTitle ? _fieldTitle : "" + infoMsg: root._fieldAssociatedRelation && __activeProject.filterController.hasActiveFilters + ? qsTr( "Some features may be hidden by active filters" ) + : "" + inputContent: MMComponents.MMListView { id: rowView diff --git a/app/qml/form/editors/MMFormRelationEditor.qml b/app/qml/form/editors/MMFormRelationEditor.qml index c2206f970..f61d1aeed 100644 --- a/app/qml/form/editors/MMFormRelationEditor.qml +++ b/app/qml/form/editors/MMFormRelationEditor.qml @@ -42,6 +42,10 @@ MMPrivateComponents.MMBaseInput { title: _fieldShouldShowTitle ? _fieldTitle : "" + infoMsg: root._fieldAssociatedRelation && __activeProject.filterController.hasActiveFilters + ? qsTr( "Some features may be hidden by active filters" ) + : "" + inputContent: Rectangle { width: parent.width height: privates.itemHeight * privates.rows + 2 * flow.spacing + 2 * __style.margin12 diff --git a/app/qml/layers/MMFeaturesListPage.qml b/app/qml/layers/MMFeaturesListPage.qml index 5a13ce34a..eba4d374b 100644 --- a/app/qml/layers/MMFeaturesListPage.qml +++ b/app/qml/layers/MMFeaturesListPage.qml @@ -15,6 +15,7 @@ import mm 1.0 as MM import "../inputs" import "../components" as MMComponents +import "../filters/components" as MMFilterComponents MMComponents.MMPage { id: root @@ -33,70 +34,35 @@ MMComponents.MMPage { width: parent.width height: parent.height - Rectangle { - id: filterNotification + MMSearchInput { + id: searchBar anchors.top: parent.top anchors.topMargin: __style.spacing20 width: parent.width - height: filterRow.implicitHeight + 2 * __style.margin8 - radius: __style.radius12 - - visible: root.selectedLayer && __activeProject.filterController.filteredLayerIds.indexOf(root.selectedLayer.id) >= 0 - - color: __style.sandColor - border.width: 1 * __dp - border.color: __style.sunsetColor - - Row { - id: filterRow - - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.right: parent.right - anchors.leftMargin: __style.margin12 - anchors.rightMargin: __style.margin12 - - spacing: __style.margin4 - - MMComponents.MMText { - width: parent.width - resetButton.width - parent.spacing - text: qsTr("Some features are hidden by a filter.") - font: __style.p6 - color: __style.nightColor - anchors.verticalCenter: parent.verticalCenter - wrapMode: Text.Wrap - } - - MMComponents.MMButton { - id: resetButton - - type: MMButton.Types.Tertiary - text: qsTr("Reset") - fontColor: __style.earthColor - size: MMButton.Sizes.Small - anchors.verticalCenter: parent.verticalCenter - - onClicked: { - __activeProject.filterController.clearAllFilters() - __activeProject.filterController.applyFiltersToAllLayers() - featuresModel.reloadFeatures() - } - } - } + delayedSearch: true + onSearchTextChanged: featuresModel.searchExpression = searchBar.text } - MMSearchInput { - id: searchBar + MMFilterComponents.MMFilterBanner { + id: filterBanner - anchors.top: filterNotification.visible ? filterNotification.bottom : parent.top + anchors.top: searchBar.bottom anchors.topMargin: __style.spacing20 width: parent.width - delayedSearch: true - onSearchTextChanged: featuresModel.searchExpression = searchBar.text + visible: root.selectedLayer && __activeProject.filterController.filteredLayerIds.indexOf(root.selectedLayer.id) >= 0 + + text: qsTr("Active filters applied") + actionText: qsTr("Reset") + + onActionClicked: { + __activeProject.filterController.clearAllFilters() + __activeProject.filterController.applyFiltersToAllLayers() + featuresModel.reloadFeatures() + } } MMComponents.MMListView { @@ -105,9 +71,9 @@ MMComponents.MMPage { width: parent.width anchors { - top: searchBar.bottom + top: filterBanner.visible ? filterBanner.bottom : searchBar.bottom bottom: parent.bottom - topMargin: __style.spacing20 + topMargin: filterBanner.visible ? __style.spacing10 : __style.spacing20 } model: MM.LayerFeaturesModel {