From 8ddbff5a7adda64c67eb341da8569ce75a742d7a Mon Sep 17 00:00:00 2001 From: Gabriel Bolbotina Date: Wed, 1 Apr 2026 09:50:46 +0300 Subject: [PATCH 1/4] Removed filter controller from main (#4436) --- app/filtercontroller.cpp | 8 +++ app/filtercontroller.h | 7 +++ app/qml/CMakeLists.txt | 1 + app/qml/components/MMButton.qml | 33 ++++++++--- app/qml/components/private/MMBaseInput.qml | 33 +++++++++++ app/qml/filters/MMFiltersPanel.qml | 5 +- app/qml/filters/components/MMFilterBanner.qml | 59 +++++++++++++++++++ .../components/MMFeaturesListPageDrawer.qml | 16 +++++ app/qml/form/editors/MMFormGalleryEditor.qml | 4 ++ app/qml/form/editors/MMFormRelationEditor.qml | 4 ++ app/qml/layers/MMFeaturesListPage.qml | 38 ++++++------ app/qml/main.qml | 9 --- app/qml/map/MMMapController.qml | 9 +-- 13 files changed, 180 insertions(+), 46 deletions(-) create mode 100644 app/qml/filters/components/MMFilterBanner.qml diff --git a/app/filtercontroller.cpp b/app/filtercontroller.cpp index 81fe79fd7..e6207ad4d 100644 --- a/app/filtercontroller.cpp +++ b/app/filtercontroller.cpp @@ -868,3 +868,11 @@ QStringList FilterController::lookupValueRelationTexts( const QVariantMap &confi return texts; } + +bool FilterController::isReferencingLayerFiltered( const QgsRelation &relation ) const +{ + QgsVectorLayer *layer = qobject_cast( relation.referencingLayer() ); + if ( !layer ) + return false; + return !layer->subsetString().isEmpty(); +} diff --git a/app/filtercontroller.h b/app/filtercontroller.h index 3e7342ea1..26e4a11bc 100644 --- a/app/filtercontroller.h +++ b/app/filtercontroller.h @@ -13,6 +13,8 @@ #include #include +#include "qgsrelation.h" + class QgsVectorLayer; class QgsMapLayer; @@ -201,6 +203,11 @@ class FilterController : public QObject */ Q_INVOKABLE QVariantList getVectorLayers() const; + /** + * @brief Returns true if the referencing layer of the given relation has active filters applied + */ + Q_INVOKABLE bool isReferencingLayerFiltered( const QgsRelation &relation ) const; + /** * @brief Discards pending filter changes, reverting to the last applied state. * Call this when the user closes the filter drawer without pressing "Show results". 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..e5788503e 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,22 @@ 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: { + if ( root.type === MMButton.Types.Tertiary && root.size !== MMButton.Sizes.ExtraSmall ) + return buttonContent.height + else + return buttonContent.height + topPadding + bottomPadding + } + implicitWidth: { + if ( root.size === MMButton.Sizes.ExtraSmall ) return row.paintedChildrenWidth + 2 * __style.margin8 + return row.paintedChildrenWidth + 2 * ( root.size === MMButton.Sizes.Small ? __style.margin16 : __style.margin20 ) + } 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 +189,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 +214,10 @@ 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: { + if ( root.size === MMButton.Sizes.ExtraSmall ) return parent.width - 2 * __style.margin8 + return parent.width - 2 * ( root.size === MMButton.Sizes.Small ? __style.margin16 : __style.margin20 ) + } 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..793105f10 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 hintMsg: "" property alias inputContent: contentGroup.children @@ -165,6 +166,38 @@ Item { height: childrenRect.height } + Item { + // hint message + + width: parent.width + height: hintMessageGroup.implicitHeight + + visible: root.hintMsg !== "" + + RowLayout { + id: hintMessageGroup + + width: parent.width + + MMComponents.MMIcon { + source: __style.infoFilledIcon + size: __style.icon16 + color: __style.informativeColor + } + + MMComponents.MMText { + Layout.fillWidth: true + + text: root.hintMsg + color: __style.deepOceanColor + font: __style.t4 + + wrapMode: Text.Wrap + maximumLineCount: 10 + } + } + } + Item { // validation messages diff --git a/app/qml/filters/MMFiltersPanel.qml b/app/qml/filters/MMFiltersPanel.qml index 3532398e9..bcb81327d 100644 --- a/app/qml/filters/MMFiltersPanel.qml +++ b/app/qml/filters/MMFiltersPanel.qml @@ -79,8 +79,8 @@ MMComponents.MMDrawer { } onClicked: { - __activeProject.filterController.clearAllFilters() - filterController.applyFiltersToAllLayers() + __activeProject.filterController.clearAllFilters() + __activeProject.filterController.applyFiltersToAllLayers() root.filtersApplied = true // Refresh the UI to clear input fields internal.refreshLayers() @@ -131,7 +131,6 @@ MMComponents.MMDrawer { layerId: model.layerId layerName: model.layerName - filterController: __activeProject.filterController vectorLayer: model.layer } } diff --git a/app/qml/filters/components/MMFilterBanner.qml b/app/qml/filters/components/MMFilterBanner.qml new file mode 100644 index 000000000..36bc4e10a --- /dev/null +++ b/app/qml/filters/components/MMFilterBanner.qml @@ -0,0 +1,59 @@ +/*************************************************************************** + * * + * 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 "../../components" as MMComponents + +Rectangle { + id: root + + property string text + property string actionText: "" + + signal actionClicked() + + color: __style.informativeColor + radius: __style.radius8 + implicitHeight: bannerText.implicitHeight + 2 * __style.margin8 + + MMComponents.MMText { + id: bannerText + + anchors.left: parent.left + anchors.leftMargin: __style.margin12 + anchors.right: actionButton.visible ? actionButton.left : parent.right + anchors.rightMargin: actionButton.visible ? __style.spacing8 : __style.margin12 + anchors.verticalCenter: parent.verticalCenter + + text: root.text + font: __style.t4 + color: __style.deepOceanColor + wrapMode: Text.Wrap + elide: Text.ElideNone + } + + MMComponents.MMButton { + id: actionButton + + visible: root.actionText !== "" + + type: MMComponents.MMButton.Types.Tertiary + size: MMComponents.MMButton.Sizes.ExtraSmall + text: root.actionText + fontColor: __style.skyColor + bgndColor: __style.deepOceanColor + + anchors.right: parent.right + anchors.rightMargin: __style.margin8 + anchors.verticalCenter: parent.verticalCenter + + onClicked: root.actionClicked() + } +} diff --git a/app/qml/form/components/MMFeaturesListPageDrawer.qml b/app/qml/form/components/MMFeaturesListPageDrawer.qml index da8797332..3c1985a07 100644 --- a/app/qml/form/components/MMFeaturesListPageDrawer.qml +++ b/app/qml/form/components/MMFeaturesListPageDrawer.qml @@ -12,6 +12,7 @@ import QtQuick.Controls 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 @@ -75,11 +76,26 @@ Drawer { MMComponents.MMListSpacer { height: __style.spacing20 } + MMFilters.MMFilterBanner { + id: filterBanner + + visible: globalFilterController.hasActiveFilters + + width: parent.width + text: qsTr( "Some features may be hidden by active filters" ) + } + + MMComponents.MMListSpacer { + visible: filterBanner.visible + height: __style.spacing10 + } + MMComponents.MMListView { id: listView width: parent.width height: parent.height - 2 * __style.spacing20 - searchBar.height + - ( filterBanner.visible ? filterBanner.height + __style.spacing10 : 0 ) clip: true diff --git a/app/qml/form/editors/MMFormGalleryEditor.qml b/app/qml/form/editors/MMFormGalleryEditor.qml index bfa98db84..86d7c71c5 100644 --- a/app/qml/form/editors/MMFormGalleryEditor.qml +++ b/app/qml/form/editors/MMFormGalleryEditor.qml @@ -30,6 +30,10 @@ MMPrivateComponents.MMBaseInput { title: _fieldShouldShowTitle ? _fieldTitle : "" + hintMsg: root._fieldAssociatedRelation && globalFilterController.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..67386714e 100644 --- a/app/qml/form/editors/MMFormRelationEditor.qml +++ b/app/qml/form/editors/MMFormRelationEditor.qml @@ -42,6 +42,10 @@ MMPrivateComponents.MMBaseInput { title: _fieldShouldShowTitle ? _fieldTitle : "" + hintMsg: root._fieldAssociatedRelation && globalFilterController.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 e5232c7d7..cce253702 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,15 +34,24 @@ 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 + delayedSearch: true + onSearchTextChanged: featuresModel.searchExpression = searchBar.text + } + + MMFilterComponents.MMFilterBanner { + id: filterBanner + + anchors.top: searchBar.bottom + anchors.topMargin: __style.spacing20 + + width: parent.width visible: root.selectedLayer && globalFilterController.filteredLayerIds.indexOf(root.selectedLayer.id) >= 0 @@ -79,35 +89,23 @@ MMComponents.MMPage { anchors.verticalCenter: parent.verticalCenter onClicked: { - globalFilterController.clearAllFilters() - globalFilterController.applyFiltersToAllLayers() + __activeProject.filterController.clearAllFilters() + __activeProject.filterController.applyFiltersToAllLayers() featuresModel.reloadFeatures() } } } } - MMSearchInput { - id: searchBar - - anchors.top: filterNotification.visible ? filterNotification.bottom : parent.top - anchors.topMargin: __style.spacing20 - - width: parent.width - - delayedSearch: true - onSearchTextChanged: featuresModel.searchExpression = searchBar.text - } - MMComponents.MMListView { id: listView 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 { diff --git a/app/qml/main.qml b/app/qml/main.qml index 323bf4d75..b09da1575 100644 --- a/app/qml/main.qml +++ b/app/qml/main.qml @@ -32,11 +32,6 @@ import "./filters" ApplicationWindow { id: window - // Global filter controller for managing map filters - MM.FilterController { - id: globalFilterController - } - visible: true x: __appwindowx y: __appwindowy @@ -155,8 +150,6 @@ ApplicationWindow { height: window.height - mapToolbar.height width: window.width - filterController: globalFilterController - mapExtentOffset: { // offset depends on what panels are visible. // we need to subtract mapToolbar's height from any visible panel @@ -524,8 +517,6 @@ ApplicationWindow { active: false sourceComponent: MMFiltersPanel { - filterController: globalFilterController - onClosed: { filtersDrawerLoader.active = false stateManager.state = "map" diff --git a/app/qml/map/MMMapController.qml b/app/qml/map/MMMapController.qml index ef37784e5..e512bb7d2 100644 --- a/app/qml/map/MMMapController.qml +++ b/app/qml/map/MMMapController.qml @@ -46,9 +46,6 @@ Item { property MM.MapSketchingController sketchingController: sketchesLoader.item?.controller ?? null - // Filter controller for managing feature filters - property var filterController: null - signal featureIdentified( var pair ) signal featuresIdentified( var pairs ) signal nothingIdentified() @@ -595,9 +592,9 @@ Item { MMMapButton { id: filterIndicatorButton - visible: root.state === "view" && root.filterController && (root.filterController.hasActiveFilters || AppSettings.alwaysShowFilterButton) - iconSource: root.filterController && root.filterController.hasActiveFilters ? __style.filterFilledIcon : __style.filterIcon - bgndColor: root.filterController && root.filterController.hasActiveFilters ? __style.sandColor : __style.polarColor + visible: root.state === "view" && __activeProject.filterController && (__activeProject.filterController.hasActiveFilters || AppSettings.alwaysShowFilterButton) + iconSource: __activeProject.filterController && __activeProject.filterController.hasActiveFilters ? __style.filterFilledIcon : __style.filterIcon + bgndColor: __activeProject.filterController && __activeProject.filterController.hasActiveFilters ? __style.sandColor : __style.polarColor anchors { left: parent.left From 6e10b060e67350bf0f38ad47e32693db5c1f53f0 Mon Sep 17 00:00:00 2001 From: Gabriel Bolbotina Date: Wed, 1 Apr 2026 10:19:57 +0300 Subject: [PATCH 2/4] Added modifications after rebase --- .../components/MMFeaturesListPageDrawer.qml | 2 +- app/qml/form/editors/MMFormGalleryEditor.qml | 2 +- app/qml/form/editors/MMFormRelationEditor.qml | 2 +- app/qml/layers/MMFeaturesListPage.qml | 50 ++++--------------- 4 files changed, 12 insertions(+), 44 deletions(-) diff --git a/app/qml/form/components/MMFeaturesListPageDrawer.qml b/app/qml/form/components/MMFeaturesListPageDrawer.qml index 3c1985a07..8cd5f5877 100644 --- a/app/qml/form/components/MMFeaturesListPageDrawer.qml +++ b/app/qml/form/components/MMFeaturesListPageDrawer.qml @@ -79,7 +79,7 @@ Drawer { MMFilters.MMFilterBanner { id: filterBanner - visible: globalFilterController.hasActiveFilters + visible: __activeProject.filterController.hasActiveFilters width: parent.width text: qsTr( "Some features may be hidden by active filters" ) diff --git a/app/qml/form/editors/MMFormGalleryEditor.qml b/app/qml/form/editors/MMFormGalleryEditor.qml index 86d7c71c5..938dc9318 100644 --- a/app/qml/form/editors/MMFormGalleryEditor.qml +++ b/app/qml/form/editors/MMFormGalleryEditor.qml @@ -30,7 +30,7 @@ MMPrivateComponents.MMBaseInput { title: _fieldShouldShowTitle ? _fieldTitle : "" - hintMsg: root._fieldAssociatedRelation && globalFilterController.hasActiveFilters + hintMsg: root._fieldAssociatedRelation && __activeProject.filterController.hasActiveFilters ? qsTr( "Some features may be hidden by active filters" ) : "" diff --git a/app/qml/form/editors/MMFormRelationEditor.qml b/app/qml/form/editors/MMFormRelationEditor.qml index 67386714e..fc6ae7649 100644 --- a/app/qml/form/editors/MMFormRelationEditor.qml +++ b/app/qml/form/editors/MMFormRelationEditor.qml @@ -42,7 +42,7 @@ MMPrivateComponents.MMBaseInput { title: _fieldShouldShowTitle ? _fieldTitle : "" - hintMsg: root._fieldAssociatedRelation && globalFilterController.hasActiveFilters + hintMsg: root._fieldAssociatedRelation && __activeProject.filterController.hasActiveFilters ? qsTr( "Some features may be hidden by active filters" ) : "" diff --git a/app/qml/layers/MMFeaturesListPage.qml b/app/qml/layers/MMFeaturesListPage.qml index cce253702..eba4d374b 100644 --- a/app/qml/layers/MMFeaturesListPage.qml +++ b/app/qml/layers/MMFeaturesListPage.qml @@ -53,47 +53,15 @@ MMComponents.MMPage { width: parent.width - visible: root.selectedLayer && globalFilterController.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() - } - } + 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() } } From 4e22a4277a54c3baeb556361b974d39c764f3335 Mon Sep 17 00:00:00 2001 From: Gabriel Bolbotina Date: Wed, 1 Apr 2026 11:13:55 +0300 Subject: [PATCH 3/4] Implemented review findings --- app/qml/components/MMButton.qml | 20 +++--- app/qml/components/private/MMBaseInput.qml | 48 ++++---------- app/qml/filters/components/MMFilterBanner.qml | 65 ++++++++++--------- .../components/MMFeaturesListPageDrawer.qml | 18 ++--- app/qml/form/editors/MMFormGalleryEditor.qml | 2 +- app/qml/form/editors/MMFormRelationEditor.qml | 2 +- 6 files changed, 70 insertions(+), 85 deletions(-) diff --git a/app/qml/components/MMButton.qml b/app/qml/components/MMButton.qml index e5788503e..019c651d0 100644 --- a/app/qml/components/MMButton.qml +++ b/app/qml/components/MMButton.qml @@ -162,15 +162,13 @@ Button { state: "default" - implicitHeight: { - if ( root.type === MMButton.Types.Tertiary && root.size !== MMButton.Sizes.ExtraSmall ) - return buttonContent.height - else - return buttonContent.height + topPadding + bottomPadding - } + implicitHeight: buttonContent.height + topPadding + bottomPadding + implicitWidth: { - if ( root.size === MMButton.Sizes.ExtraSmall ) return row.paintedChildrenWidth + 2 * __style.margin8 - return row.paintedChildrenWidth + 2 * ( root.size === MMButton.Sizes.Small ? __style.margin16 : __style.margin20 ) + 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: { @@ -215,8 +213,10 @@ Button { property real paintedChildrenWidth: buttonIconLeft.paintedWidth + buttonContent.implicitWidth + buttonIconRight.paintedWidth + spacing property real maxWidth: { - if ( root.size === MMButton.Sizes.ExtraSmall ) return parent.width - 2 * __style.margin8 - return parent.width - 2 * ( root.size === MMButton.Sizes.Small ? __style.margin16 : __style.margin20 ) + 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 diff --git a/app/qml/components/private/MMBaseInput.qml b/app/qml/components/private/MMBaseInput.qml index 793105f10..4423d4ba7 100644 --- a/app/qml/components/private/MMBaseInput.qml +++ b/app/qml/components/private/MMBaseInput.qml @@ -32,7 +32,7 @@ Item { property string errorMsg: "" property string warningMsg: "" - property string hintMsg: "" + property string infoMsg: "" property alias inputContent: contentGroup.children @@ -66,7 +66,7 @@ Item { states: [ State { name: "valid" - when: !shouldShowValidation || ( !warningMsg && !errorMsg ) + when: !shouldShowValidation || ( !warningMsg && !errorMsg && !infoMsg ) }, State { name: "error" @@ -75,6 +75,10 @@ Item { State { name: "warning" when: warningMsg && !errorMsg + }, + State { + name: "information" + when: infoMsg } ] @@ -166,38 +170,6 @@ Item { height: childrenRect.height } - Item { - // hint message - - width: parent.width - height: hintMessageGroup.implicitHeight - - visible: root.hintMsg !== "" - - RowLayout { - id: hintMessageGroup - - width: parent.width - - MMComponents.MMIcon { - source: __style.infoFilledIcon - size: __style.icon16 - color: __style.informativeColor - } - - MMComponents.MMText { - Layout.fillWidth: true - - text: root.hintMsg - color: __style.deepOceanColor - font: __style.t4 - - wrapMode: Text.Wrap - maximumLineCount: 10 - } - } - } - Item { // validation messages @@ -212,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 } } @@ -227,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 index 36bc4e10a..c0ee2e4ba 100644 --- a/app/qml/filters/components/MMFilterBanner.qml +++ b/app/qml/filters/components/MMFilterBanner.qml @@ -8,6 +8,7 @@ ***************************************************************************/ import QtQuick +import QtQuick.Layouts import "../../components" as MMComponents @@ -21,39 +22,45 @@ Rectangle { color: __style.informativeColor radius: __style.radius8 - implicitHeight: bannerText.implicitHeight + 2 * __style.margin8 - - MMComponents.MMText { - id: bannerText - - anchors.left: parent.left - anchors.leftMargin: __style.margin12 - anchors.right: actionButton.visible ? actionButton.left : parent.right - anchors.rightMargin: actionButton.visible ? __style.spacing8 : __style.margin12 - anchors.verticalCenter: parent.verticalCenter - - text: root.text - font: __style.t4 - color: __style.deepOceanColor - wrapMode: Text.Wrap - elide: Text.ElideNone - } + 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 - MMComponents.MMButton { - id: actionButton + text: root.text + font: __style.t4 + color: __style.deepOceanColor + wrapMode: Text.Wrap + elide: Text.ElideNone + } - visible: root.actionText !== "" + MMComponents.MMButton { + id: actionButton - type: MMComponents.MMButton.Types.Tertiary - size: MMComponents.MMButton.Sizes.ExtraSmall - text: root.actionText - fontColor: __style.skyColor - bgndColor: __style.deepOceanColor + visible: root.actionText !== "" + Layout.alignment: Qt.AlignVCenter - anchors.right: parent.right - anchors.rightMargin: __style.margin8 - anchors.verticalCenter: parent.verticalCenter + type: MMComponents.MMButton.Types.Tertiary + size: MMComponents.MMButton.Sizes.ExtraSmall + text: root.actionText + fontColor: __style.skyColor + bgndColor: __style.deepOceanColor - onClicked: root.actionClicked() + onClicked: root.actionClicked() + } } } diff --git a/app/qml/form/components/MMFeaturesListPageDrawer.qml b/app/qml/form/components/MMFeaturesListPageDrawer.qml index 8cd5f5877..6ec59c707 100644 --- a/app/qml/form/components/MMFeaturesListPageDrawer.qml +++ b/app/qml/form/components/MMFeaturesListPageDrawer.qml @@ -9,6 +9,7 @@ import QtQuick import QtQuick.Controls +import QtQuick.Layouts import "../../inputs" as MMInputs import "../../components" as MMComponents @@ -52,7 +53,7 @@ Drawer { width: parent.width height: parent.height - Column { + ColumnLayout { id: contentColumn width: parent.width @@ -60,42 +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 - width: parent.width + Layout.fillWidth: true text: qsTr( "Some features may be hidden by active filters" ) } MMComponents.MMListSpacer { visible: filterBanner.visible - height: __style.spacing10 + Layout.preferredHeight: __style.spacing20 } MMComponents.MMListView { id: listView - width: parent.width - height: parent.height - 2 * __style.spacing20 - searchBar.height - - ( filterBanner.visible ? filterBanner.height + __style.spacing10 : 0 ) + 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 938dc9318..b739c2f4c 100644 --- a/app/qml/form/editors/MMFormGalleryEditor.qml +++ b/app/qml/form/editors/MMFormGalleryEditor.qml @@ -30,7 +30,7 @@ MMPrivateComponents.MMBaseInput { title: _fieldShouldShowTitle ? _fieldTitle : "" - hintMsg: root._fieldAssociatedRelation && __activeProject.filterController.hasActiveFilters + infoMsg: root._fieldAssociatedRelation && __activeProject.filterController.hasActiveFilters ? qsTr( "Some features may be hidden by active filters" ) : "" diff --git a/app/qml/form/editors/MMFormRelationEditor.qml b/app/qml/form/editors/MMFormRelationEditor.qml index fc6ae7649..f61d1aeed 100644 --- a/app/qml/form/editors/MMFormRelationEditor.qml +++ b/app/qml/form/editors/MMFormRelationEditor.qml @@ -42,7 +42,7 @@ MMPrivateComponents.MMBaseInput { title: _fieldShouldShowTitle ? _fieldTitle : "" - hintMsg: root._fieldAssociatedRelation && __activeProject.filterController.hasActiveFilters + infoMsg: root._fieldAssociatedRelation && __activeProject.filterController.hasActiveFilters ? qsTr( "Some features may be hidden by active filters" ) : "" From 2139f697a2fc3fa28f089ad2ee5e43faa031bc91 Mon Sep 17 00:00:00 2001 From: Gabriel Bolbotina Date: Wed, 1 Apr 2026 11:16:50 +0300 Subject: [PATCH 4/4] Removed unused method from filter controller --- app/filtercontroller.cpp | 10 +--------- app/filtercontroller.h | 7 ------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/app/filtercontroller.cpp b/app/filtercontroller.cpp index e6207ad4d..2cb7f2fae 100644 --- a/app/filtercontroller.cpp +++ b/app/filtercontroller.cpp @@ -867,12 +867,4 @@ QStringList FilterController::lookupValueRelationTexts( const QVariantMap &confi } return texts; -} - -bool FilterController::isReferencingLayerFiltered( const QgsRelation &relation ) const -{ - QgsVectorLayer *layer = qobject_cast( relation.referencingLayer() ); - if ( !layer ) - return false; - return !layer->subsetString().isEmpty(); -} +} \ No newline at end of file diff --git a/app/filtercontroller.h b/app/filtercontroller.h index 26e4a11bc..3e7342ea1 100644 --- a/app/filtercontroller.h +++ b/app/filtercontroller.h @@ -13,8 +13,6 @@ #include #include -#include "qgsrelation.h" - class QgsVectorLayer; class QgsMapLayer; @@ -203,11 +201,6 @@ class FilterController : public QObject */ Q_INVOKABLE QVariantList getVectorLayers() const; - /** - * @brief Returns true if the referencing layer of the given relation has active filters applied - */ - Q_INVOKABLE bool isReferencingLayerFiltered( const QgsRelation &relation ) const; - /** * @brief Discards pending filter changes, reverting to the last applied state. * Call this when the user closes the filter drawer without pressing "Show results".