diff --git a/.zenodo.json b/.zenodo.json index 679504442..8e70b4f5c 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -2,7 +2,7 @@ "description": "

Mergin Maps mobile app is a QGIS powered app for Android and iOS devices.

", "license": "GPLv3", "title": "Mergin Maps mobile app", - "version": "2024.5.0", + "version": "2024.4.1", "upload_type": "software", "publication_date": "2022-02-24", "creators": [ @@ -39,7 +39,7 @@ "related_identifiers": [ { "scheme": "url", - "identifier": "https://github.com/MerginMaps/mobile/tree/2024.5.0", + "identifier": "https://github.com/MerginMaps/mobile/tree/2024.4.1", "relation": "isSupplementTo" }, { diff --git a/CITATION.cff b/CITATION.cff index 8b1d6266b..b53b22977 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,4 +1,4 @@ -cff-version: 2024.5.0 +cff-version: 2024.4.1 message: "If you use this software, please cite it as below." authors: - family-names: "Martin" diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a883047c..a02d666a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,8 +6,8 @@ cmake_minimum_required(VERSION 3.22) # TODO automatically change with the scripts/update version script set(MM_VERSION_MAJOR "2024") -set(MM_VERSION_MINOR "5") -set(MM_VERSION_PATCH "0") +set(MM_VERSION_MINOR "4") +set(MM_VERSION_PATCH "1") set(QT_VERSION_DEFAULT "6.6.3") # Note: we cannot set this for non-android build, since CMake will start looking for diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 7d8400e9d..cf9201375 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -53,7 +53,6 @@ set(MM_SRCS compass.cpp featurelayerpair.cpp featuresmodel.cpp - featuresproxymodel.cpp fieldsmodel.cpp guidelinecontroller.cpp identifykit.cpp @@ -138,7 +137,6 @@ set(MM_HDRS enumhelper.h featurelayerpair.h featuresmodel.h - featuresproxymodel.h fieldsmodel.h guidelinecontroller.h identifykit.h diff --git a/app/android/src/uk/co/lutraconsulting/PositionTrackingBroadcastMiddleware.java b/app/android/src/uk/co/lutraconsulting/PositionTrackingBroadcastMiddleware.java index 1040bb519..5bf89a93a 100644 --- a/app/android/src/uk/co/lutraconsulting/PositionTrackingBroadcastMiddleware.java +++ b/app/android/src/uk/co/lutraconsulting/PositionTrackingBroadcastMiddleware.java @@ -10,6 +10,7 @@ package uk.co.lutraconsulting; import android.util.Log; +import android.os.Build; import android.content.Intent; import android.content.Context; @@ -46,7 +47,12 @@ public void registerBroadcastReceiver( Context context ) { intentFilter.addAction( TRACKING_ALIVE_STATUS_ACTION ); // Set this as the receiver of POSITION_UPDATE and STATUS_MESSAGE intent actions - context.registerReceiver( serviceMessageReceiver, intentFilter ); + if ( Build.VERSION.SDK_INT >= 34 ) { // Android 14 ( Upside Down Cake ) + context.registerReceiver( serviceMessageReceiver, intentFilter, Context.RECEIVER_EXPORTED ); + } + else { + context.registerReceiver( serviceMessageReceiver, intentFilter ); + } } public void unregisterBroadcastReceiver( Context context ) { diff --git a/app/android/src/uk/co/lutraconsulting/PositionTrackingService.java b/app/android/src/uk/co/lutraconsulting/PositionTrackingService.java index 3d384e0a4..dc38a3cb8 100644 --- a/app/android/src/uk/co/lutraconsulting/PositionTrackingService.java +++ b/app/android/src/uk/co/lutraconsulting/PositionTrackingService.java @@ -16,6 +16,7 @@ import android.content.Intent; import android.app.PendingIntent; import android.content.pm.PackageManager; +import android.content.pm.ServiceInfo; import android.app.Notification; import android.app.NotificationChannel; @@ -65,7 +66,7 @@ public void onCreate() { File file = new File( getFilesDir(), "tracking_updates.txt" ); sendStatusUpdateMessage( "Tracking file path:" + file.getAbsolutePath() ); - + try { // Open the FileOutputStream in append mode positionUpdatesStream = new FileOutputStream(file, true); @@ -166,7 +167,12 @@ public int onStartCommand( Intent intent, int flags, int startId ) { Notification notification = notificationBuilder.build(); - startForeground( SERVICE_ID, notification ); + if ( Build.VERSION.SDK_INT >= 34) { // Android 14 ( Upside Down Cake ) + startForeground( SERVICE_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION ); + } + else { + startForeground( SERVICE_ID, notification ); + } sendStatusUpdateMessage( "Position tracking: Started the foreground service!" ); diff --git a/app/featuresmodel.cpp b/app/featuresmodel.cpp index 07a70552b..7cc386424 100644 --- a/app/featuresmodel.cpp +++ b/app/featuresmodel.cpp @@ -141,7 +141,6 @@ QVariant FeaturesModel::data( const QModelIndex &index, int role ) const case LayerName: return pair.layer() ? pair.layer()->name() : QString(); case LayerIcon: return pair.layer() ? InputUtils::loadIconFromLayer( pair.layer() ) : QString(); case Qt::DisplayRole: return featureTitle( pair ); - case SortValue: return sortValue( pair ); } return QVariant(); @@ -178,15 +177,6 @@ QVariant FeaturesModel::featureTitle( const FeatureLayerPair &featurePair ) cons return title; } -QVariant FeaturesModel::sortValue( const FeatureLayerPair &featurePair ) const -{ - QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( featurePair.layer() ) ); - context.setFeature( featurePair.feature() ); - QgsExpression expr( mSortExpression ); - QVariant result = expr.evaluate( &context ); - return result; -} - QString FeaturesModel::searchResultPair( const FeatureLayerPair &pair ) const { if ( mSearchExpression.isEmpty() ) @@ -261,6 +251,20 @@ void FeaturesModel::setupFeatureRequest( QgsFeatureRequest &request ) request.setFilterExpression( buildSearchExpression() ); } + if ( mUseAttributeTableSortOrder && mLayer && !mLayer->attributeTableConfig().sortExpression().isEmpty() ) + { + // get a context with global, project and layer scopes + // QGIS docs are not very clear, but this context is also used for evaluation of the request's 'order by' expressions too + QgsExpressionContext context = mLayer->createExpressionContext(); + request.setExpressionContext( context ); + request.setOrderBy( QgsFeatureRequest::OrderBy( + { + QgsFeatureRequest::OrderByClause( + mLayer->attributeTableConfig().sortExpression(), + mLayer->attributeTableConfig().sortOrder() == Qt::AscendingOrder ) + } ) ); + } + request.setLimit( FEATURES_LIMIT ); } @@ -290,7 +294,6 @@ QHash FeaturesModel::roleNames() const roleNames[SearchResult] = QStringLiteral( "SearchResult" ).toLatin1(); roleNames[LayerName] = QStringLiteral( "LayerName" ).toLatin1(); roleNames[LayerIcon] = QStringLiteral( "LayerIcon" ).toLatin1(); - roleNames[SortValue] = QStringLiteral( "SortValue" ).toLatin1(); return roleNames; } @@ -363,7 +366,6 @@ void FeaturesModel::setLayer( QgsVectorLayer *newLayer ) } mLayer = newLayer; - setupSorting(); emit layerChanged( mLayer ); if ( mLayer ) @@ -384,19 +386,3 @@ QgsVectorLayer *FeaturesModel::layer() const { return mLayer; } - -void FeaturesModel::setupSorting() -{ - mSortExpression = mLayer ? mLayer->attributeTableConfig().sortExpression() : QString(); - mSortOrder = mLayer ? mLayer->attributeTableConfig().sortOrder() : Qt::AscendingOrder; -} - -bool FeaturesModel::sortingEnabled() const -{ - return !mSortExpression.isEmpty(); -} - -Qt::SortOrder FeaturesModel::sortOrder() const -{ - return mSortOrder; -} diff --git a/app/featuresmodel.h b/app/featuresmodel.h index 32af6cb56..1a7ddaad8 100644 --- a/app/featuresmodel.h +++ b/app/featuresmodel.h @@ -52,6 +52,9 @@ class FeaturesModel : public QAbstractListModel // Name of the property is intentionally `count` so that it matches ListModel's count property Q_PROPERTY( int count READ count NOTIFY countChanged ) + // Returns if the model should be sorted according to the layer's attribute table configuration sort order + Q_PROPERTY( bool useAttributeTableSortOrder MEMBER mUseAttributeTableSortOrder ) + public: enum ModelRoles @@ -64,7 +67,6 @@ class FeaturesModel : public QAbstractListModel SearchResult, // pair of attribute and its value by which the feature was found, empty if search expression is empty LayerName, LayerIcon, - SortValue, }; Q_ENUM( ModelRoles ); @@ -118,15 +120,6 @@ class FeaturesModel : public QAbstractListModel int layerFeaturesCount() const; - //! Populates the sort expression and sort order for the model - virtual void setupSorting(); - - //! Returns true if there is a sort expression set for the model - bool sortingEnabled() const; - - //! Returns the order in witch the model should be sorted - Qt::SortOrder sortOrder() const; - signals: void featuresLimitChanged( int featuresLimit ); @@ -149,9 +142,6 @@ class FeaturesModel : public QAbstractListModel virtual QVariant featureTitle( const FeatureLayerPair &featurePair ) const; - QString mSortExpression; - Qt::SortOrder mSortOrder = Qt::AscendingOrder; - private slots: void onFutureFinished(); @@ -164,9 +154,6 @@ class FeaturesModel : public QAbstractListModel //! Returns found attribute and its value from search expression for feature QString searchResultPair( const FeatureLayerPair &feat ) const; - //! Evaluates the sort expression and returns the value used for this feature when sorting the model - QVariant sortValue( const FeatureLayerPair &featurePair ) const; - const int FEATURES_LIMIT = 10000; //!< Number of maximum features loaded from layer FeatureLayerPairs mFeatures; @@ -176,6 +163,9 @@ class FeaturesModel : public QAbstractListModel QAtomicInt mNextSearchId = 0; QFutureWatcher mSearchResultWatcher; bool mFetchingResults = false; + bool mUseAttributeTableSortOrder = false; + + friend class TestModels; }; #endif // FEATURESMODEL_H diff --git a/app/featuresproxymodel.cpp b/app/featuresproxymodel.cpp deleted file mode 100644 index a91664e7a..000000000 --- a/app/featuresproxymodel.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************** - * * - * 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. * - * * - ***************************************************************************/ - -#include "featuresproxymodel.h" - -FeaturesProxyModel::FeaturesProxyModel( QObject *parent ) : QSortFilterProxyModel( parent ) -{ - setSortRole( FeaturesModel::SortValue ); - setSortCaseSensitivity( Qt::CaseInsensitive ); -} - -void FeaturesProxyModel::updateSorting() -{ - // don't sort if there is no sort expression for the layer - if ( mModel->sortingEnabled() ) - { - sort( 0, mModel->sortOrder() ); - } - else - { - invalidate(); - } -} - -FeaturesModel *FeaturesProxyModel::featuresSourceModel() const -{ - return mModel; -} - -void FeaturesProxyModel::setFeaturesSourceModel( FeaturesModel *sourceModel ) -{ - if ( mModel == sourceModel ) - return; - - if ( mModel ) - disconnect( mModel, nullptr, this, nullptr ); - - mModel = sourceModel; - setSourceModel( mModel ); - mModel->setupSorting(); - connect( mModel, &FeaturesModel::fetchingResultsChanged, this, [ = ]( bool pending ) { if ( !pending ) updateSorting(); } ); -} diff --git a/app/featuresproxymodel.h b/app/featuresproxymodel.h deleted file mode 100644 index 3f3d537ef..000000000 --- a/app/featuresproxymodel.h +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************** - * * - * 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. * - * * - ***************************************************************************/ - -#ifndef FEATURESPROXYMODEL_H -#define FEATURESPROXYMODEL_H - -#include -#include - -#include "featuresmodel.h" - -/** - * \brief The FeaturesProxyModel class used as a proxy sort model for the \see FeaturesModel class. - * - * FeaturesProxyModel is a QML type with required property of FeatureSourceModel. Without source model, this model does nothing (is not initialized). - * After setting source model, this model starts sorting if sortingEnabled() returns true for the source model. - */ -class FeaturesProxyModel : public QSortFilterProxyModel -{ - Q_OBJECT - - Q_PROPERTY( FeaturesModel *featuresSourceModel READ featuresSourceModel WRITE setFeaturesSourceModel ) - - public: - explicit FeaturesProxyModel( QObject *parent = nullptr ); - ~FeaturesProxyModel() override {}; - - FeaturesModel *featuresSourceModel() const; - - public slots: - void setFeaturesSourceModel( FeaturesModel *sourceModel ); - - private: - void updateSorting(); - - FeaturesModel *mModel = nullptr; // not owned by this, needs to be set in order to proxy model to work - - friend class TestModels; -}; - -#endif // FEATURESPROXYMODEL_H diff --git a/app/i18n/input_en.ts b/app/i18n/input_en.ts index d4fb5e6cb..4513cea6d 100644 --- a/app/i18n/input_en.ts +++ b/app/i18n/input_en.ts @@ -156,7 +156,7 @@ FeaturesModel - + Unknown title @@ -735,7 +735,7 @@ Won't be added to the project. MMFeaturesListPage - + Add feature @@ -2791,12 +2791,12 @@ only allows up to %1 downloaded projects. - + Report submitted. Please contact us on %1 - + Failed to submit report. Please check your internet connection. diff --git a/app/i18n/input_hu.qm b/app/i18n/input_hu.qm index bad31a884..e28299bfa 100644 Binary files a/app/i18n/input_hu.qm and b/app/i18n/input_hu.qm differ diff --git a/app/i18n/input_sl.qm b/app/i18n/input_sl.qm index eadfb766c..91f9f5a6a 100644 Binary files a/app/i18n/input_sl.qm and b/app/i18n/input_sl.qm differ diff --git a/app/i18n/input_sl.ts b/app/i18n/input_sl.ts index 980815380..6a7813f45 100644 --- a/app/i18n/input_sl.ts +++ b/app/i18n/input_sl.ts @@ -353,8 +353,8 @@ V projekt ne bo dodano. MMAboutPage - About Mergin Maps - O Mergin Maps + About + O programu @@ -389,8 +389,8 @@ V projekt ne bo dodano. - It is better to work together, join the workspace and explore Mergin Maps! - Bolje je delati skupaj, pridruži se delovnemu prostoru in začni raziskovati Mergin Maps! + Join the workspace and explore together! + Pridruži se delovnemu prostoru in raziščimo skupaj! @@ -422,8 +422,8 @@ V projekt ne bo dodano. - I accept the Mergin Maps %1Terms and Conditions%3 and %2Privacy Policy%3 - Sprejemam Mergin Maps %1Pogoje uporabe%3 in %2Politiko zasebnosti%3 + I accept the %1Terms and Conditions%3 and %2Privacy Policy%3 + Sprejemam %1pravila in pogoje%3 ter %2politiko zasebnosti%3 @@ -583,8 +583,8 @@ V projekt ne bo dodano. - This action will delete your Mergin Maps account. If you are a workspace owner, you need to transfer the ownership to somebody else or close the workspace. - To dejanje bo izbrisalo tvoj Mergin Maps račun . Če si lastnik delovnega prostora, moraš lastništvo prenesti na nekoga drugega ali zapreti delovni prostor. + This action will delete your account. If you are a workspace owner, you need to transfer the ownership to somebody else or close the workspace. + To dejanje bo izbrisalo tvoj račun . Če si lastnik delovnega prostora, moraš lastništvo prenesti na nekoga drugega ali zapreti delovni prostor. @@ -659,8 +659,8 @@ V projekt ne bo dodano. - Tip from Mergin Maps - Nasvet od Mergin Maps + A tip from us + Nasvet od nas @@ -1200,7 +1200,7 @@ V projekt ne bo dodano. (no-entries) - (no-entries) + (ni-zapisov) @@ -1286,7 +1286,7 @@ V projekt ne bo dodano. streaming - streaming + sledenje @@ -1427,8 +1427,8 @@ V projekt ne bo dodano. - You need to be signed in to your Mergin Maps account in order to synchronise the project. - Za sinhronizacijo projekta moraš biti prijavljen v svoj Mergin Maps račun. + You need to be signed in to your account in order to synchronise the project. + Za sinhronizacijo projekta moraš biti prijavljen v svoj račun. @@ -1524,8 +1524,8 @@ V projekt ne bo dodano. - This function is not available on iOS. Your hardware vendor may provide a custom app that connects to the receiver and sets position. Mergin Maps will still think it is the internal GPS of your phone/tablet. - Ta funkcija ni na voljo za iOS. Vaš prodajalec strojne opreme lahko zagotovi posebno aplikacijo, ki se poveže s sprejemnikom in nastavi lokacijo. Mergin Maps bo še vedno upošteval, da je to notranji GPS vašega telefona/tablice. + This function is not available on iOS. Your hardware vendor may provide a custom app that connects to the receiver and sets position. The app will still think it is the internal GPS of your phone/tablet. + Ta funkcija ni na voljo za iOS. Vaš prodajalec strojne opreme lahko zagotovi posebno aplikacijo, ki se poveže s sprejemnikom in nastavi lokacijo. Aplikacija bo še vedno upoštevala, da je to notranji GPS vašega telefona/tablice. @@ -1547,13 +1547,13 @@ V projekt ne bo dodano. - Mergin Maps can track your position on this project. - Mergin Maps lahko v tem projektu sledi tvojemu položaju. + Track your routes even with your screen off. Your records are stored in a separate layer. Finalised tracks are synced like any other feature. + Sledi tvojim potem tudi ob izklopljenem zaslonu. Poti so shranjene v ločenem sloju. Končane poti se sinhronizirajo enako kot drugi podatki. - Track your routes even with your screen off. Your records are stored in a separate layer. Finalised tracks are synced like any other feature. - Sledi tvojim potem tudi ob izklopljenem zaslonu. Poti so shranjene v ločenem sloju. Končane poti se sinhronizirajo enako kot drugi podatki. + The app can track your position on this project. + Aplikacija lahko v tem projektu sledi tvojemu položaju. @@ -1695,8 +1695,8 @@ V projekt ne bo dodano. - Click here to visit Mergin Maps dashboard - Klikni tukaj za Mergin Maps nadzorno ploščo + Click here to access the dashboard + Klikni tukaj za dostop do nadzorne plošče @@ -1769,8 +1769,8 @@ V projekt ne bo dodano. - Get started with Mergin Maps - Začni delo z Mergin Maps + Let's get started + Začnimo! @@ -2327,12 +2327,12 @@ V projekt ne bo dodano. Stop streaming mode - Stop streaming mode + Ustavi sledenje Start streaming mode - Start streaming mode + Začni sledenje @@ -2398,8 +2398,8 @@ V projekt ne bo dodano. - We've been busy making Mergin Maps even better! This update brings a fresh look and improved navigation, making it faster to find what you need. Take a look around! - We've been busy making Mergin Maps even better! This update brings a fresh look and improved navigation, making it faster to find what you need. Take a look around! + We've been busy making the app even better! This update brings a fresh look and improved navigation, making it faster to find what you need. Take a look around! + Zelo smo se potrudili, da bi aplikacijo še izboljšali! Ta posodobitev prinaša svež videz in izboljšano navigacijo, zaradi česar boš hitreje našeš, kar potrebuješ. Razišči naokrog! diff --git a/app/i18n/input_sl_SI.qm b/app/i18n/input_sl_SI.qm index 208f13724..b375e978f 100644 Binary files a/app/i18n/input_sl_SI.qm and b/app/i18n/input_sl_SI.qm differ diff --git a/app/i18n/input_sl_SI.ts b/app/i18n/input_sl_SI.ts index 855d2c0b2..835b58300 100644 --- a/app/i18n/input_sl_SI.ts +++ b/app/i18n/input_sl_SI.ts @@ -353,8 +353,8 @@ V projekt ne bo dodano. MMAboutPage - About Mergin Maps - O Mergin Maps + About + O programu @@ -389,8 +389,8 @@ V projekt ne bo dodano. - It is better to work together, join the workspace and explore Mergin Maps! - Bolje je delati skupaj, pridruži se delovnemu prostoru in začni raziskovati Mergin Maps! + Join the workspace and explore together! + Pridruži se delovnemu prostoru in raziščimo skupaj! @@ -422,8 +422,8 @@ V projekt ne bo dodano. - I accept the Mergin Maps %1Terms and Conditions%3 and %2Privacy Policy%3 - Sprejemam Mergin Maps %1Pogoje uporabe%3 in %2Politiko zasebnosti%3 + I accept the %1Terms and Conditions%3 and %2Privacy Policy%3 + Sprejemam %1pravila in pogoje%3 ter %2politiko zasebnosti%3 @@ -583,8 +583,8 @@ V projekt ne bo dodano. - This action will delete your Mergin Maps account. If you are a workspace owner, you need to transfer the ownership to somebody else or close the workspace. - To dejanje bo izbrisalo tvoj Mergin Maps račun . Če si lastnik delovnega prostora, moraš lastništvo prenesti na nekoga drugega ali zapreti delovni prostor. + This action will delete your account. If you are a workspace owner, you need to transfer the ownership to somebody else or close the workspace. + To dejanje bo izbrisalo tvoj račun . Če si lastnik delovnega prostora, moraš lastništvo prenesti na nekoga drugega ali zapreti delovni prostor. @@ -659,8 +659,8 @@ V projekt ne bo dodano. - Tip from Mergin Maps - Nasvet od Mergin Maps + A tip from us + Nasvet od nas @@ -1427,8 +1427,8 @@ V projekt ne bo dodano. - You need to be signed in to your Mergin Maps account in order to synchronise the project. - Za sinhronizacijo projekta moraš biti prijavljen v svoj Mergin Maps račun. + You need to be signed in to your account in order to synchronise the project. + Za sinhronizacijo projekta moraš biti prijavljen v svoj račun. @@ -1524,8 +1524,8 @@ V projekt ne bo dodano. - This function is not available on iOS. Your hardware vendor may provide a custom app that connects to the receiver and sets position. Mergin Maps will still think it is the internal GPS of your phone/tablet. - Ta funkcija ni na voljo za iOS. Vaš prodajalec strojne opreme lahko zagotovi posebno aplikacijo, ki se poveže s sprejemnikom in nastavi lokacijo. Mergin Maps bo še vedno upošteval, da je to notranji GPS vašega telefona/tablice. + This function is not available on iOS. Your hardware vendor may provide a custom app that connects to the receiver and sets position. The app will still think it is the internal GPS of your phone/tablet. + Ta funkcija ni na voljo za iOS. Vaš prodajalec strojne opreme lahko zagotovi posebno aplikacijo, ki se poveže s sprejemnikom in nastavi lokacijo. Aplikacija bo še vedno upoštevala, da je to notranji GPS vašega telefona/tablice. @@ -1547,13 +1547,13 @@ V projekt ne bo dodano. - Mergin Maps can track your position on this project. - Mergin Maps lahko v tem projektu sledi tvojemu položaju. + Track your routes even with your screen off. Your records are stored in a separate layer. Finalised tracks are synced like any other feature. + Snema tvoje poti tudi ob izklopljenem zaslonu. Posnete poti so shranjene v ločenem sloju. Končane poti se sinhronizirajo enako kot drugi podatki. - Track your routes even with your screen off. Your records are stored in a separate layer. Finalised tracks are synced like any other feature. - Snema tvoje poti tudi ob izklopljenem zaslonu. Posnete poti so shranjene v ločenem sloju. Končane poti se sinhronizirajo enako kot drugi podatki. + The app can track your position on this project. + Aplikacija lahko v tem projektu sledi tvojemu položaju. @@ -1695,8 +1695,8 @@ V projekt ne bo dodano. - Click here to visit Mergin Maps dashboard - Klikni tukaj za Mergin Maps nadzorno ploščo + Click here to access the dashboard + Klikni tukaj za dostop do nadzorne plošče @@ -1769,8 +1769,8 @@ V projekt ne bo dodano. - Get started with Mergin Maps - Začni delo z Mergin Maps + Let's get started + Začnimo! @@ -2398,8 +2398,8 @@ V projekt ne bo dodano. - We've been busy making Mergin Maps even better! This update brings a fresh look and improved navigation, making it faster to find what you need. Take a look around! - We've been busy making Mergin Maps even better! This update brings a fresh look and improved navigation, making it faster to find what you need. Take a look around! + We've been busy making the app even better! This update brings a fresh look and improved navigation, making it faster to find what you need. Take a look around! + Zelo smo se potrudili, da bi aplikacijo še izboljšali! Ta posodobitev prinaša svež videz in izboljšano navigacijo, zaradi česar boš hitreje našeš, kar potrebuješ. Razišči naokrog! diff --git a/app/main.cpp b/app/main.cpp index 148e00c6c..2ff044e83 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -91,7 +91,6 @@ #include "position/positionkit.h" #include "scalebarkit.h" #include "featuresmodel.h" -#include "featuresproxymodel.h" #include "relationfeaturesmodel.h" #include "relationreferencefeaturesmodel.h" #include "fieldvalidator.h" @@ -328,7 +327,6 @@ void initDeclarative() qmlRegisterType< MapThemesModel >( "mm", 1, 0, "MapThemesModel" ); qmlRegisterType< GuidelineController >( "mm", 1, 0, "GuidelineController" ); qmlRegisterType< FeaturesModel >( "mm", 1, 0, "FeaturesModel" ); - qmlRegisterType< FeaturesProxyModel >( "mm", 1, 0, "FeaturesProxyModel" ); qmlRegisterType< RelationFeaturesModel >( "mm", 1, 0, "RelationFeaturesModel" ); qmlRegisterType< ValueRelationFeaturesModel >( "mm", 1, 0, "ValueRelationFeaturesModel" ); qmlRegisterType< RelationReferenceFeaturesModel >( "mm", 1, 0, "RelationReferenceFeaturesModel" ); diff --git a/app/qml/form/editors/MMFormValueRelationEditor.qml b/app/qml/form/editors/MMFormValueRelationEditor.qml index 41c4b31a3..e98643ed2 100644 --- a/app/qml/form/editors/MMFormValueRelationEditor.qml +++ b/app/qml/form/editors/MMFormValueRelationEditor.qml @@ -76,15 +76,11 @@ MMFormComboboxBaseEditor { valueRole: "FeatureId" textRole: "FeatureTitle" - list.model: MM.FeaturesProxyModel { - id: vrDropdownProxyModel + list.model: MM.ValueRelationFeaturesModel { + id: vrDropdownModel - featuresSourceModel: MM.ValueRelationFeaturesModel { - id: vrDropdownModel - - config: root._fieldConfig - pair: root._fieldFeatureLayerPair - } + config: root._fieldConfig + pair: root._fieldFeatureLayerPair } onSearchTextChanged: ( searchText ) => vrDropdownModel.searchExpression = searchText diff --git a/app/qml/layers/MMFeaturesListPage.qml b/app/qml/layers/MMFeaturesListPage.qml index 41c5012c8..04b8bb256 100644 --- a/app/qml/layers/MMFeaturesListPage.qml +++ b/app/qml/layers/MMFeaturesListPage.qml @@ -21,6 +21,7 @@ MMComponents.MMPage { property var selectedLayer: null property bool hasToolbar: false + property bool layerIsReadOnly: selectedLayer?.readOnly ?? false signal featureClicked( var featurePair ) signal addFeatureClicked( var toLayer ) @@ -55,14 +56,11 @@ MMComponents.MMPage { topMargin: __style.spacing20 } - model: MM.FeaturesProxyModel { - id: featuresProxyModel + model: MM.FeaturesModel { + id: featuresModel - featuresSourceModel: MM.FeaturesModel { - id: featuresModel - - layer: root.selectedLayer - } + useAttributeTableSortOrder: true + layer: root.selectedLayer } clip: true @@ -91,7 +89,7 @@ MMComponents.MMPage { anchors.bottom: parent.bottom anchors.bottomMargin: root.hasToolbar ? __style.margin20 : ( __style.safeAreaBottom + __style.margin8 ) - visible: __inputUtils.isNoGeometryLayer( root.selectedLayer ) + visible: __inputUtils.isNoGeometryLayer( root.selectedLayer ) && !root.layerIsReadOnly text: qsTr("Add feature") diff --git a/app/test/testmodels.cpp b/app/test/testmodels.cpp index 844fd07ba..0d637bd90 100644 --- a/app/test/testmodels.cpp +++ b/app/test/testmodels.cpp @@ -10,7 +10,6 @@ #include "testmodels.h" #include "testutils.h" #include "featuresmodel.h" -#include "featuresproxymodel.h" #include "valuerelationfeaturesmodel.h" #include "projectsmodel.h" #include "projectsproxymodel.h" @@ -58,10 +57,9 @@ void TestModels::testFeaturesModel() QCOMPARE( title, QStringLiteral( "First" ) ); } -void TestModels::testFeaturesProxyModel() +void TestModels::testFeaturesModelSorted() { FeaturesModel model; - FeaturesProxyModel proxy; QSignalSpy spy( &model, &FeaturesModel::fetchingResultsChanged ); @@ -71,66 +69,62 @@ void TestModels::testFeaturesProxyModel() QVERIFY( layer && layer->isValid() ); // enable sorting + model.mUseAttributeTableSortOrder = true; QgsAttributeTableConfig conf = layer->attributeTableConfig(); conf.setSortExpression( QStringLiteral( "Name" ) ); layer->setAttributeTableConfig( conf ); - proxy.setFeaturesSourceModel( &model ); model.setLayer( layer ); model.reloadFeatures(); spy.wait(); - QCOMPARE( proxy.rowCount(), layer->dataProvider()->featureCount() ); - QCOMPARE( proxy.data( proxy.index( 0, 0 ), FeaturesModel::SortValue ), QLatin1String( "A1" ) ); - QCOMPARE( proxy.data( proxy.index( 1, 0 ), FeaturesModel::SortValue ), QLatin1String( "A2" ) ); - QCOMPARE( proxy.data( proxy.index( 2, 0 ), FeaturesModel::SortValue ), QLatin1String( "B1" ) ); - QCOMPARE( proxy.data( proxy.index( 3, 0 ), FeaturesModel::SortValue ), QLatin1String( "B2" ) ); - QCOMPARE( proxy.data( proxy.index( 4, 0 ), FeaturesModel::SortValue ), QLatin1String( "C1" ) ); - QCOMPARE( proxy.data( proxy.index( 5, 0 ), FeaturesModel::SortValue ), QLatin1String( "C2" ) ); - QCOMPARE( proxy.data( proxy.index( 6, 0 ), FeaturesModel::SortValue ), QLatin1String( "D1" ) ); - QCOMPARE( proxy.data( proxy.index( 7, 0 ), FeaturesModel::SortValue ), QLatin1String( "D2" ) ); - QCOMPARE( proxy.data( proxy.index( 8, 0 ), FeaturesModel::SortValue ), QLatin1String( "VERYBIG" ) ); - - // filter the fModel (this is not proxy model filtering) - // and reverse sort order + QCOMPARE( model.rowCount(), layer->dataProvider()->featureCount() ); + QCOMPARE( model.data( model.index( 0, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "A1" ) ); + QCOMPARE( model.data( model.index( 1, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "A2" ) ); + QCOMPARE( model.data( model.index( 2, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "B1" ) ); + QCOMPARE( model.data( model.index( 3, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "B2" ) ); + QCOMPARE( model.data( model.index( 4, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "C1" ) ); + QCOMPARE( model.data( model.index( 5, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "C2" ) ); + QCOMPARE( model.data( model.index( 6, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "D1" ) ); + QCOMPARE( model.data( model.index( 7, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "D2" ) ); + QCOMPARE( model.data( model.index( 8, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "VERYBIG" ) ); + + // filter the model and reverse sort order conf.setSortOrder( Qt::DescendingOrder ); layer->setAttributeTableConfig( conf ); - model.setupSorting(); model.setSearchExpression( QStringLiteral( "D" ) ); spy.wait(); - QCOMPARE( proxy.rowCount(), 2 ); - QCOMPARE( proxy.data( proxy.index( 0, 0 ), FeaturesModel::SortValue ), QLatin1String( "D2" ) ); - QCOMPARE( proxy.data( proxy.index( 1, 0 ), FeaturesModel::SortValue ), QLatin1String( "D1" ) ); + QCOMPARE( model.rowCount(), 2 ); + QCOMPARE( model.data( model.index( 0, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "D2" ) ); + QCOMPARE( model.data( model.index( 1, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "D1" ) ); // disable sorting and filtering // should get all items with default ordering - conf.setSortExpression( QString() ); - layer->setAttributeTableConfig( conf ); - model.setupSorting(); + model.mUseAttributeTableSortOrder = false; model.setSearchExpression( QString() ); spy.wait(); - QCOMPARE( proxy.rowCount(), layer->dataProvider()->featureCount() ); - QCOMPARE( proxy.data( proxy.index( 0, 0 ), FeaturesModel::FeatureId ), 1 ); - QCOMPARE( proxy.data( proxy.index( 1, 0 ), FeaturesModel::FeatureId ), 2 ); - QCOMPARE( proxy.data( proxy.index( 2, 0 ), FeaturesModel::FeatureId ), 3 ); - QCOMPARE( proxy.data( proxy.index( 3, 0 ), FeaturesModel::FeatureId ), 4 ); - QCOMPARE( proxy.data( proxy.index( 4, 0 ), FeaturesModel::FeatureId ), 5 ); - QCOMPARE( proxy.data( proxy.index( 5, 0 ), FeaturesModel::FeatureId ), 6 ); - QCOMPARE( proxy.data( proxy.index( 6, 0 ), FeaturesModel::FeatureId ), 7 ); - QCOMPARE( proxy.data( proxy.index( 7, 0 ), FeaturesModel::FeatureId ), 8 ); - QCOMPARE( proxy.data( proxy.index( 8, 0 ), FeaturesModel::FeatureId ), 100000000 ); + QCOMPARE( model.rowCount(), layer->dataProvider()->featureCount() ); + QCOMPARE( model.data( model.index( 0, 0 ), FeaturesModel::ModelRoles::FeatureId ), 1 ); + QCOMPARE( model.data( model.index( 1, 0 ), FeaturesModel::ModelRoles::FeatureId ), 2 ); + QCOMPARE( model.data( model.index( 2, 0 ), FeaturesModel::ModelRoles::FeatureId ), 3 ); + QCOMPARE( model.data( model.index( 3, 0 ), FeaturesModel::ModelRoles::FeatureId ), 4 ); + QCOMPARE( model.data( model.index( 4, 0 ), FeaturesModel::ModelRoles::FeatureId ), 5 ); + QCOMPARE( model.data( model.index( 5, 0 ), FeaturesModel::ModelRoles::FeatureId ), 6 ); + QCOMPARE( model.data( model.index( 6, 0 ), FeaturesModel::ModelRoles::FeatureId ), 7 ); + QCOMPARE( model.data( model.index( 7, 0 ), FeaturesModel::ModelRoles::FeatureId ), 8 ); + QCOMPARE( model.data( model.index( 8, 0 ), FeaturesModel::ModelRoles::FeatureId ), 100000000 ); } -void TestModels::testFeaturesProxyModelWithValueRelation() +void TestModels::testValueRelationFeaturesModel() { QString projectDir = TestUtils::testDataDir() + "/project_value_relations"; QString projectName = "proj.qgz"; @@ -151,8 +145,6 @@ void TestModels::testFeaturesProxyModelWithValueRelation() FeatureLayerPair pair( f, mainLayer ); ValueRelationFeaturesModel model; - FeaturesProxyModel proxy; - proxy.setFeaturesSourceModel( &model ); QSignalSpy spy( &model, &FeaturesModel::fetchingResultsChanged ); @@ -171,78 +163,86 @@ void TestModels::testFeaturesProxyModelWithValueRelation() QCOMPARE( model.rowCount(), 9 ); QCOMPARE( model.layer()->id(), subsubLayer->id() ); - QCOMPARE( proxy.rowCount(), 9 ); - QCOMPARE( proxy.data( proxy.index( 0, 0 ), FeaturesModel::FeatureId ), 1 ); - QCOMPARE( proxy.data( proxy.index( 1, 0 ), FeaturesModel::FeatureId ), 2 ); - QCOMPARE( proxy.data( proxy.index( 2, 0 ), FeaturesModel::FeatureId ), 3 ); - QCOMPARE( proxy.data( proxy.index( 3, 0 ), FeaturesModel::FeatureId ), 4 ); - QCOMPARE( proxy.data( proxy.index( 4, 0 ), FeaturesModel::FeatureId ), 5 ); - QCOMPARE( proxy.data( proxy.index( 5, 0 ), FeaturesModel::FeatureId ), 6 ); - QCOMPARE( proxy.data( proxy.index( 6, 0 ), FeaturesModel::FeatureId ), 7 ); - QCOMPARE( proxy.data( proxy.index( 7, 0 ), FeaturesModel::FeatureId ), 8 ); - QCOMPARE( proxy.data( proxy.index( 8, 0 ), FeaturesModel::FeatureId ), 100000000 ); + QCOMPARE( model.rowCount(), 9 ); + QCOMPARE( model.data( model.index( 0, 0 ), FeaturesModel::ModelRoles::FeatureId ), 1 ); + QCOMPARE( model.data( model.index( 1, 0 ), FeaturesModel::ModelRoles::FeatureId ), 2 ); + QCOMPARE( model.data( model.index( 2, 0 ), FeaturesModel::ModelRoles::FeatureId ), 3 ); + QCOMPARE( model.data( model.index( 3, 0 ), FeaturesModel::ModelRoles::FeatureId ), 4 ); + QCOMPARE( model.data( model.index( 4, 0 ), FeaturesModel::ModelRoles::FeatureId ), 5 ); + QCOMPARE( model.data( model.index( 5, 0 ), FeaturesModel::ModelRoles::FeatureId ), 6 ); + QCOMPARE( model.data( model.index( 6, 0 ), FeaturesModel::ModelRoles::FeatureId ), 7 ); + QCOMPARE( model.data( model.index( 7, 0 ), FeaturesModel::ModelRoles::FeatureId ), 8 ); + QCOMPARE( model.data( model.index( 8, 0 ), FeaturesModel::ModelRoles::FeatureId ), 100000000 ); // enable order by value for the value relation model.reset(); config[ QStringLiteral( "OrderByValue" ) ] = true; model.setConfig( config ); - model.setupSorting(); model.setPair( pair ); spy.wait(); - QCOMPARE( proxy.rowCount(), 9 ); - QCOMPARE( proxy.data( proxy.index( 0, 0 ), FeaturesModel::SortValue ), QLatin1String( "A1" ) ); - QCOMPARE( proxy.data( proxy.index( 1, 0 ), FeaturesModel::SortValue ), QLatin1String( "A2" ) ); - QCOMPARE( proxy.data( proxy.index( 2, 0 ), FeaturesModel::SortValue ), QLatin1String( "B1" ) ); - QCOMPARE( proxy.data( proxy.index( 3, 0 ), FeaturesModel::SortValue ), QLatin1String( "B2" ) ); - QCOMPARE( proxy.data( proxy.index( 4, 0 ), FeaturesModel::SortValue ), QLatin1String( "C1" ) ); - QCOMPARE( proxy.data( proxy.index( 5, 0 ), FeaturesModel::SortValue ), QLatin1String( "C2" ) ); - QCOMPARE( proxy.data( proxy.index( 6, 0 ), FeaturesModel::SortValue ), QLatin1String( "D1" ) ); - QCOMPARE( proxy.data( proxy.index( 7, 0 ), FeaturesModel::SortValue ), QLatin1String( "D2" ) ); - QCOMPARE( proxy.data( proxy.index( 8, 0 ), FeaturesModel::SortValue ), QLatin1String( "VERYBIG" ) ); - - // add a search expression to base model + QCOMPARE( model.rowCount(), 9 ); + QCOMPARE( model.data( model.index( 0, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "A1" ) ); + QCOMPARE( model.data( model.index( 1, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "A2" ) ); + QCOMPARE( model.data( model.index( 2, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "B1" ) ); + QCOMPARE( model.data( model.index( 3, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "B2" ) ); + QCOMPARE( model.data( model.index( 4, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "C1" ) ); + QCOMPARE( model.data( model.index( 5, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "C2" ) ); + QCOMPARE( model.data( model.index( 6, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "D1" ) ); + QCOMPARE( model.data( model.index( 7, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "D2" ) ); + QCOMPARE( model.data( model.index( 8, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "VERYBIG" ) ); + + // add a search expression to model model.setSearchExpression( QStringLiteral( "D" ) ); spy.wait(); QCOMPARE( model.rowCount(), 2 ); - QCOMPARE( proxy.rowCount(), 2 ); - QCOMPARE( proxy.data( proxy.index( 0, 0 ), FeaturesModel::SortValue ), QLatin1String( "D1" ) ); - QCOMPARE( proxy.data( proxy.index( 1, 0 ), FeaturesModel::SortValue ), QLatin1String( "D2" ) ); + QCOMPARE( model.rowCount(), 2 ); + QCOMPARE( model.data( model.index( 0, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "D1" ) ); + QCOMPARE( model.data( model.index( 1, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "D2" ) ); - // add a filter expression to the base model + // add a filter expression to the model config[ QStringLiteral( "FilterExpression" ) ] = "subFk = 1"; model.setConfig( config ); - model.setupSorting(); model.setSearchExpression( QString() ); spy.wait(); QCOMPARE( model.rowCount(), 2 ); - QCOMPARE( proxy.data( proxy.index( 0, 0 ), FeaturesModel::SortValue ), QLatin1String( "A1" ) ); - QCOMPARE( proxy.data( proxy.index( 1, 0 ), FeaturesModel::SortValue ), QLatin1String( "A2" ) ); + QCOMPARE( model.data( model.index( 0, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "A1" ) ); + QCOMPARE( model.data( model.index( 1, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "A2" ) ); - // remove filters and sorting + // remove sorting model.reset(); config.remove( QStringLiteral( "OrderByValue" ) ); + model.setConfig( config ); + model.setPair( pair ); + + spy.wait(); + + QCOMPARE( model.rowCount(), 2 ); + QCOMPARE( model.data( model.index( 0, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "A2" ) ); + QCOMPARE( model.data( model.index( 1, 0 ), FeaturesModel::ModelRoles::FeatureTitle ), QLatin1String( "A1" ) ); + + // remove filters + model.reset(); config.remove( QStringLiteral( "FilterExpression" ) ); model.setConfig( config ); - model.setupSorting(); model.setPair( pair ); spy.wait(); - QCOMPARE( proxy.rowCount(), 9 ); - QCOMPARE( proxy.data( proxy.index( 0, 0 ), FeaturesModel::FeatureId ), 1 ); - QCOMPARE( proxy.data( proxy.index( 1, 0 ), FeaturesModel::FeatureId ), 2 ); - QCOMPARE( proxy.data( proxy.index( 2, 0 ), FeaturesModel::FeatureId ), 3 ); - QCOMPARE( proxy.data( proxy.index( 3, 0 ), FeaturesModel::FeatureId ), 4 ); - QCOMPARE( proxy.data( proxy.index( 4, 0 ), FeaturesModel::FeatureId ), 5 ); - QCOMPARE( proxy.data( proxy.index( 5, 0 ), FeaturesModel::FeatureId ), 6 ); - QCOMPARE( proxy.data( proxy.index( 6, 0 ), FeaturesModel::FeatureId ), 7 ); - QCOMPARE( proxy.data( proxy.index( 7, 0 ), FeaturesModel::FeatureId ), 8 ); - QCOMPARE( proxy.data( proxy.index( 8, 0 ), FeaturesModel::FeatureId ), 100000000 ); + QCOMPARE( model.rowCount(), 9 ); + QCOMPARE( model.data( model.index( 0, 0 ), FeaturesModel::ModelRoles::FeatureId ), 1 ); + QCOMPARE( model.data( model.index( 1, 0 ), FeaturesModel::ModelRoles::FeatureId ), 2 ); + QCOMPARE( model.data( model.index( 2, 0 ), FeaturesModel::ModelRoles::FeatureId ), 3 ); + QCOMPARE( model.data( model.index( 3, 0 ), FeaturesModel::ModelRoles::FeatureId ), 4 ); + QCOMPARE( model.data( model.index( 4, 0 ), FeaturesModel::ModelRoles::FeatureId ), 5 ); + QCOMPARE( model.data( model.index( 5, 0 ), FeaturesModel::ModelRoles::FeatureId ), 6 ); + QCOMPARE( model.data( model.index( 6, 0 ), FeaturesModel::ModelRoles::FeatureId ), 7 ); + QCOMPARE( model.data( model.index( 7, 0 ), FeaturesModel::ModelRoles::FeatureId ), 8 ); + QCOMPARE( model.data( model.index( 8, 0 ), FeaturesModel::ModelRoles::FeatureId ), 100000000 ); } void TestModels::testProjectsModel() diff --git a/app/test/testmodels.h b/app/test/testmodels.h index d66b1ba37..4c3e41991 100644 --- a/app/test/testmodels.h +++ b/app/test/testmodels.h @@ -23,8 +23,8 @@ class TestModels : public QObject void cleanup(); // will be called after every testfunction. void testFeaturesModel(); - void testFeaturesProxyModel(); - void testFeaturesProxyModelWithValueRelation(); + void testFeaturesModelSorted(); + void testValueRelationFeaturesModel(); void testProjectsModel(); void testProjectsProxyModel(); diff --git a/app/valuerelationfeaturesmodel.cpp b/app/valuerelationfeaturesmodel.cpp index 2ed0638de..6ce4e65ae 100644 --- a/app/valuerelationfeaturesmodel.cpp +++ b/app/valuerelationfeaturesmodel.cpp @@ -40,6 +40,12 @@ void ValueRelationFeaturesModel::setupFeatureRequest( QgsFeatureRequest &request request.setExpressionContext( filterContext ); } } + + if ( mConfig.value( QStringLiteral( "OrderByValue" ) ).toBool() ) + { + // replace any existing order by clause with our value field + request.setOrderBy( QgsFeatureRequest::OrderBy( { QgsFeatureRequest::OrderByClause( mTitleField ) } ) ); + } } void ValueRelationFeaturesModel::setup() @@ -207,9 +213,3 @@ void ValueRelationFeaturesModel::setConfig( const QVariantMap &newConfig ) setup(); } - -void ValueRelationFeaturesModel::setupSorting() -{ - const bool orderByValue = mConfig.value( QStringLiteral( "OrderByValue" ) ).toBool(); - mSortExpression = orderByValue ? mTitleField : QString(); -} diff --git a/app/valuerelationfeaturesmodel.h b/app/valuerelationfeaturesmodel.h index 2c660efeb..7a1d178bd 100644 --- a/app/valuerelationfeaturesmodel.h +++ b/app/valuerelationfeaturesmodel.h @@ -37,7 +37,6 @@ class ValueRelationFeaturesModel : public FeaturesModel void reset() override; void setupFeatureRequest( QgsFeatureRequest &request ) override; QVariant featureTitle( const FeatureLayerPair &pair ) const override; - void setupSorting() override; Q_INVOKABLE QVariant convertToKey( const QVariant &id ); Q_INVOKABLE QVariant convertToQgisType( const QVariantList &featureIds ); // feature id -> key diff --git a/cmake_templates/AndroidManifest.xml.in b/cmake_templates/AndroidManifest.xml.in index 729a9c1b1..07fd864ee 100644 --- a/cmake_templates/AndroidManifest.xml.in +++ b/cmake_templates/AndroidManifest.xml.in @@ -17,6 +17,7 @@ +