From 36b2f39a5466c80dd03aaa3a4dfbb4f8fe450654 Mon Sep 17 00:00:00 2001 From: VitorVieiraZ Date: Mon, 18 Nov 2024 12:32:26 -0300 Subject: [PATCH 1/8] wip - reader and guests cant edit --- app/inpututils.cpp | 11 +++++++++++ app/inpututils.h | 5 +++++ app/qml/main.qml | 1 + core/merginprojectmetadata.cpp | 1 + core/merginprojectmetadata.h | 1 + 5 files changed, 19 insertions(+) diff --git a/app/inpututils.cpp b/app/inpututils.cpp index 218c024e1..9f6328953 100644 --- a/app/inpututils.cpp +++ b/app/inpututils.cpp @@ -2222,3 +2222,14 @@ double InputUtils::pixelDistanceBetween( const QPointF &p1, const QPointF &p2 ) { return std::hypot( p1.x() - p2.x(), p1.y() - p2.y() ); } + +bool InputUtils::userHasEditableRole( QgsProject *project ) +{ + const QString &projectDir = project->absolutePath(); + QString metadataFilePath = projectDir + "/" + MerginApi::sMetadataFile; + MerginProjectMetadata metadata = MerginProjectMetadata::fromCachedJson( metadataFilePath ); + QString role = metadata.role; + + bool hasEditableRole = role != "reader" && role != "guest"; + return hasEditableRole; +} diff --git a/app/inpututils.h b/app/inpututils.h index 83be81f39..2bfd4066c 100644 --- a/app/inpututils.h +++ b/app/inpututils.h @@ -589,6 +589,11 @@ class InputUtils: public QObject */ static double pixelDistanceBetween( const QPointF &p1, const QPointF &p2 ); + /** + * Checks if the user can edit the project + */ + Q_INVOKABLE static bool userHasEditableRole( QgsProject *project ); + public slots: void onQgsLogMessageReceived( const QString &message, const QString &tag, Qgis::MessageLevel level ); diff --git a/app/qml/main.qml b/app/qml/main.qml index d6b7ea116..0a662b077 100644 --- a/app/qml/main.qml +++ b/app/qml/main.qml @@ -276,6 +276,7 @@ ApplicationWindow { MMToolbarButton { text: qsTr("Add") iconSource: __style.addIcon + visible: __inputUtils.userHasEditableRole( __activeProject.qgsProject ) onClicked: { if ( __recordingLayersModel.rowCount() > 0 ) { stateManager.state = "map" diff --git a/core/merginprojectmetadata.cpp b/core/merginprojectmetadata.cpp index 9609087fa..2943cfd9f 100644 --- a/core/merginprojectmetadata.cpp +++ b/core/merginprojectmetadata.cpp @@ -99,6 +99,7 @@ MerginProjectMetadata MerginProjectMetadata::fromJson( const QByteArray &data ) project.name = docObj.value( QStringLiteral( "name" ) ).toString(); project.projectNamespace = docObj.value( QStringLiteral( "namespace" ) ).toString(); + project.role = docObj.value( QStringLiteral( "role" ) ).toString(); QJsonValue access = docObj.value( QStringLiteral( "access" ) ); if ( access.isObject() ) diff --git a/core/merginprojectmetadata.h b/core/merginprojectmetadata.h index b56edf89d..90383ad23 100644 --- a/core/merginprojectmetadata.h +++ b/core/merginprojectmetadata.h @@ -59,6 +59,7 @@ struct MerginProjectMetadata { QString name; QString projectNamespace; + QString role; QList writersnames; int version = -1; QList files; From 8ecf262dc9fa600147a755b80c323dab2ef049e5 Mon Sep 17 00:00:00 2001 From: VitorVieiraZ Date: Thu, 21 Nov 2024 17:50:12 -0300 Subject: [PATCH 2/8] in progress --- app/qml/main.qml | 1 + core/merginapi.cpp | 18 ++++++++++++++++++ core/merginapi.h | 2 ++ core/merginprojectmetadata.cpp | 2 +- 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/app/qml/main.qml b/app/qml/main.qml index 0a662b077..6aca0ff70 100644 --- a/app/qml/main.qml +++ b/app/qml/main.qml @@ -388,6 +388,7 @@ ApplicationWindow { } onOpenProjectRequested: function( projectPath ) { + __merginApi.updateProjectMetadata( projectPath ) //HERE __activeProject.load( projectPath ) } diff --git a/core/merginapi.cpp b/core/merginapi.cpp index ab5e4a618..1b0400721 100644 --- a/core/merginapi.cpp +++ b/core/merginapi.cpp @@ -3945,3 +3945,21 @@ DownloadQueueItem::DownloadQueueItem( const QString &fp, qint64 s, int v, qint64 tempFileName = CoreUtils::uuidWithoutBraces( QUuid::createUuid() ); } +bool MerginApi::updateProjectMetadata( const QString &filePath ) +{ + + QNetworkReply *r = getProjectInfo( filePath ); + Q_ASSERT( r ); + + if ( r->error() == QNetworkReply::NoError ) + { + QByteArray data = r->readAll(); + MerginProjectMetadata serverProject = MerginProjectMetadata::fromJson( data ); + return true; + } + else + { + return false; + } +} + diff --git a/core/merginapi.h b/core/merginapi.h index 0e5380bb2..4f21ffccc 100644 --- a/core/merginapi.h +++ b/core/merginapi.h @@ -789,6 +789,8 @@ class MerginApi: public QObject bool projectFileHasBeenUpdated( const ProjectDiff &diff ); + bool updateProjectMetadata( const QString &filePath ); + QNetworkAccessManager mManager; QString mApiRoot; LocalProjectsManager &mLocalProjects; diff --git a/core/merginprojectmetadata.cpp b/core/merginprojectmetadata.cpp index 2943cfd9f..79d8f93db 100644 --- a/core/merginprojectmetadata.cpp +++ b/core/merginprojectmetadata.cpp @@ -100,7 +100,7 @@ MerginProjectMetadata MerginProjectMetadata::fromJson( const QByteArray &data ) project.name = docObj.value( QStringLiteral( "name" ) ).toString(); project.projectNamespace = docObj.value( QStringLiteral( "namespace" ) ).toString(); project.role = docObj.value( QStringLiteral( "role" ) ).toString(); - + qDebug() << "MerginProjectMetadata MerginProjectMetadata::fromJson( const QByteArray &data ) called, getting role: " << project.role; QJsonValue access = docObj.value( QStringLiteral( "access" ) ); if ( access.isObject() ) { From b3ded65756cc2602378a190c2d099419ed3fea9f Mon Sep 17 00:00:00 2001 From: VitorVieiraZ Date: Fri, 22 Nov 2024 10:26:41 -0300 Subject: [PATCH 3/8] in progress --- core/merginapi.cpp | 42 +++++++++++++++++++++++++++++++++++++----- core/merginapi.h | 4 ++-- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/core/merginapi.cpp b/core/merginapi.cpp index 1b0400721..eac8749e4 100644 --- a/core/merginapi.cpp +++ b/core/merginapi.cpp @@ -720,6 +720,7 @@ bool MerginApi::pullProject( const QString &projectNamespace, const QString &pro CoreUtils::log( "pull " + projectFullName, "### Starting ###" ); + qDebug() << "HERE projectNamespace AND projectName : " << projectNamespace << " " << projectName; QNetworkReply *reply = getProjectInfo( projectFullName, withAuth ); if ( reply ) { @@ -1403,6 +1404,7 @@ void MerginApi::onPlanProductIdChanged() QNetworkReply *MerginApi::getProjectInfo( const QString &projectFullName, bool withAuth ) { + qDebug() << "HERE getProjectInfo 1: " << projectFullName; if ( withAuth && !validateAuth() ) { emit missingAuthorizationError( projectFullName ); @@ -3945,21 +3947,51 @@ DownloadQueueItem::DownloadQueueItem( const QString &fp, qint64 s, int v, qint64 tempFileName = CoreUtils::uuidWithoutBraces( QUuid::createUuid() ); } -bool MerginApi::updateProjectMetadata( const QString &filePath ) +bool MerginApi::updateProjectMetadata(const QString &filePath) { + qDebug() << "Entering updateProjectMetadata with filePath:" << filePath; - QNetworkReply *r = getProjectInfo( filePath ); - Q_ASSERT( r ); + // Extract the project directory from the file path + QFileInfo fileInfo(filePath); + QString projectDir = fileInfo.absolutePath(); + qDebug() << "Extracted projectDir:" << projectDir; - if ( r->error() == QNetworkReply::NoError ) + // Try to find the project from local projects using directory + LocalProject projectInfo = mLocalProjects.projectFromDirectory(projectDir); + if (!projectInfo.isValid()) + { + qDebug() << "Could not find local project for path:" << filePath; + CoreUtils::log("update metadata", "Could not find local project for path: " + filePath); + return false; + } + qDebug() << "Found local project. Namespace:" << projectInfo.projectNamespace + << "Name:" << projectInfo.projectName; + + // Get the full project name from the local project info + QString projectFullName = getFullProjectName(projectInfo.projectNamespace, projectInfo.projectName); + qDebug() << "Full project name:" << projectFullName; + + QNetworkReply *r = getProjectInfo(projectFullName, true); + if (!r) + { + qDebug() << "Network reply is null for project name:" << projectFullName; + return false; + } + + qDebug() << "Network reply received. Checking for errors..."; + if (r->error() == QNetworkReply::NoError) { QByteArray data = r->readAll(); - MerginProjectMetadata serverProject = MerginProjectMetadata::fromJson( data ); + qDebug() << "Received data:" << data; + MerginProjectMetadata serverProject = MerginProjectMetadata::fromJson(data); + qDebug() << "Parsed server project metadata successfully."; return true; } else { + qDebug() << "Network reply error:" << r->errorString(); return false; } } + diff --git a/core/merginapi.h b/core/merginapi.h index 4f21ffccc..b198a5a00 100644 --- a/core/merginapi.h +++ b/core/merginapi.h @@ -573,6 +573,8 @@ class MerginApi: public QObject */ bool apiSupportsWorkspaces(); + Q_INVOKABLE bool updateProjectMetadata( const QString &filePath ); + signals: void apiSupportsSubscriptionsChanged(); void supportsSelectiveSyncChanged(); @@ -789,8 +791,6 @@ class MerginApi: public QObject bool projectFileHasBeenUpdated( const ProjectDiff &diff ); - bool updateProjectMetadata( const QString &filePath ); - QNetworkAccessManager mManager; QString mApiRoot; LocalProjectsManager &mLocalProjects; From 5da5eca910c72bef2d66e74c7ea5c605a71f5bfb Mon Sep 17 00:00:00 2001 From: VitorVieiraZ Date: Wed, 27 Nov 2024 17:36:52 -0300 Subject: [PATCH 4/8] updating project role on opening a project from active project and changing Add button visibility for readers --- app/activeproject.cpp | 68 ++++++++++++++++++++++++++++++++++ app/activeproject.h | 19 ++++++++++ app/inpututils.cpp | 11 ------ app/inpututils.h | 5 --- app/main.cpp | 2 +- app/qml/main.qml | 3 +- app/test/testactiveproject.cpp | 6 +-- app/test/testmerginapi.cpp | 2 +- core/merginapi.cpp | 49 ------------------------ core/merginapi.h | 35 +++++++++-------- 10 files changed, 110 insertions(+), 90 deletions(-) diff --git a/app/activeproject.cpp b/app/activeproject.cpp index acfb53093..39d855cb3 100644 --- a/app/activeproject.cpp +++ b/app/activeproject.cpp @@ -31,6 +31,7 @@ ActiveProject::ActiveProject( AppSettings &appSettings , ActiveLayer &activeLayer , LayersProxyModel &recordingLayerPM , LocalProjectsManager &localProjectsManager + , MerginApi *merginApi , QObject *parent ) : QObject( parent ) @@ -38,6 +39,7 @@ ActiveProject::ActiveProject( AppSettings &appSettings , mActiveLayer( activeLayer ) , mRecordingLayerPM( recordingLayerPM ) , mLocalProjectsManager( localProjectsManager ) + , mMerginApi( merginApi ) , mProjectLoadingLog( "" ) { // we used to have our own QgsProject instance, but unfortunately few pieces of qgis_core @@ -95,6 +97,7 @@ QString ActiveProject::projectFullName() const bool ActiveProject::load( const QString &filePath ) { + updateProjectMetadata(); return forceLoad( filePath, false ); } @@ -553,3 +556,68 @@ bool ActiveProject::positionTrackingSupported() const return mQgsProject->readBoolEntry( QStringLiteral( "Mergin" ), QStringLiteral( "PositionTracking/Enabled" ), false ); } + +bool ActiveProject::updateProjectMetadata() +{ + if ( !mMerginApi ) + { + return false; + } + + QNetworkReply *reply = mMerginApi->getProjectInfo( projectFullName() ); + if ( !reply ) + { + return false; + } + + reply->request().setAttribute( static_cast( mMerginApi->AttrProjectFullName ), projectFullName() ); + + connect( reply, &QNetworkReply::finished, this, &ActiveProject::updateProjectMetadataReplyFinished ); + + return true; +} + +void ActiveProject::updateProjectMetadataReplyFinished() +{ + QNetworkReply *r = qobject_cast( sender() ); + Q_ASSERT( r ); + + QString projectFullName = r->request().attribute( static_cast( mMerginApi->AttrProjectFullName ) ).toString(); + + if ( r->error() == QNetworkReply::NoError ) + { + QByteArray data = r->readAll(); + + MerginProjectMetadata serverProject = MerginProjectMetadata::fromJson( data ); + + QString role = serverProject.role; + setProjectRole( role ); + } + else + { + QString serverMsg = mMerginApi->extractServerErrorMsg( r->readAll() ); + + QString projectDir = mQgsProject->absolutePath(); + MerginProjectMetadata cachedProjectMetadata = MerginProjectMetadata::fromCachedJson( mLocalProject.projectDir + "/" + mMerginApi->sMetadataFile ); + + QString role = cachedProjectMetadata.role; + setProjectRole( role ); + } + + r->deleteLater(); +} + +QString ActiveProject::projectRole() const +{ + return mProjectRole; +} + +void ActiveProject::setProjectRole( const QString &role ) +{ + if ( mProjectRole != role ) + { + mProjectRole = role; + + emit projectRoleChanged(); + } +} diff --git a/app/activeproject.h b/app/activeproject.h index b775303f6..54b2de4e5 100644 --- a/app/activeproject.h +++ b/app/activeproject.h @@ -22,6 +22,7 @@ #include "localprojectsmanager.h" #include "autosynccontroller.h" #include "inputmapsettings.h" +#include "../core/merginapi.h" /** * \brief The ActiveProject class can load a QGIS project and holds its data. @@ -33,6 +34,7 @@ class ActiveProject: public QObject Q_PROPERTY( QgsProject *qgsProject READ qgsProject NOTIFY qgsProjectChanged ) // QgsProject instance of active project, never changes Q_PROPERTY( AutosyncController *autosyncController READ autosyncController NOTIFY autosyncControllerChanged ) Q_PROPERTY( InputMapSettings *mapSettings READ mapSettings WRITE setMapSettings NOTIFY mapSettingsChanged ) + Q_PROPERTY( QString projectRole READ projectRole WRITE setProjectRole NOTIFY projectRoleChanged ) Q_PROPERTY( QString mapTheme READ mapTheme WRITE setMapTheme NOTIFY mapThemeChanged ) Q_PROPERTY( bool positionTrackingSupported READ positionTrackingSupported NOTIFY positionTrackingSupportedChanged ) @@ -43,6 +45,7 @@ class ActiveProject: public QObject , ActiveLayer &activeLayer , LayersProxyModel &recordingLayerPM , LocalProjectsManager &localProjectsManager + , MerginApi *mMerginApi , QObject *parent = nullptr ); virtual ~ActiveProject(); @@ -118,6 +121,18 @@ class ActiveProject: public QObject bool positionTrackingSupported() const; + /** + * Returns role/permission level of current user for this project + */ + Q_INVOKABLE QString projectRole() const; + void setProjectRole( const QString &role ); + + /** + * Creates a network request to fetch latest project information and define user role in this project + */ + Q_INVOKABLE bool updateProjectMetadata(); + void updateProjectMetadataReplyFinished(); + signals: void qgsProjectChanged(); void localProjectChanged( LocalProject project ); @@ -145,6 +160,8 @@ class ActiveProject: public QObject // Emited when the app (UI) should show tracking because there is a running tracking service void startPositionTracking(); + void projectRoleChanged(); + public slots: // Reloads project if current project path matches given path (its the same project) bool reloadProject( QString projectDir ); @@ -182,10 +199,12 @@ class ActiveProject: public QObject LayersProxyModel &mRecordingLayerPM; LocalProjectsManager &mLocalProjectsManager; InputMapSettings *mMapSettings = nullptr; + MerginApi *mMerginApi = nullptr; std::unique_ptr mAutosyncController; QString mProjectLoadingLog; + QString mProjectRole; /** * Reloads project. diff --git a/app/inpututils.cpp b/app/inpututils.cpp index 9f6328953..218c024e1 100644 --- a/app/inpututils.cpp +++ b/app/inpututils.cpp @@ -2222,14 +2222,3 @@ double InputUtils::pixelDistanceBetween( const QPointF &p1, const QPointF &p2 ) { return std::hypot( p1.x() - p2.x(), p1.y() - p2.y() ); } - -bool InputUtils::userHasEditableRole( QgsProject *project ) -{ - const QString &projectDir = project->absolutePath(); - QString metadataFilePath = projectDir + "/" + MerginApi::sMetadataFile; - MerginProjectMetadata metadata = MerginProjectMetadata::fromCachedJson( metadataFilePath ); - QString role = metadata.role; - - bool hasEditableRole = role != "reader" && role != "guest"; - return hasEditableRole; -} diff --git a/app/inpututils.h b/app/inpututils.h index 2bfd4066c..83be81f39 100644 --- a/app/inpututils.h +++ b/app/inpututils.h @@ -589,11 +589,6 @@ class InputUtils: public QObject */ static double pixelDistanceBetween( const QPointF &p1, const QPointF &p2 ); - /** - * Checks if the user can edit the project - */ - Q_INVOKABLE static bool userHasEditableRole( QgsProject *project ); - public slots: void onQgsLogMessageReceived( const QString &message, const QString &tag, Qgis::MessageLevel level ); diff --git a/app/main.cpp b/app/main.cpp index 2ff044e83..7e87609b0 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -494,7 +494,7 @@ int main( int argc, char *argv[] ) LayersProxyModel recordingLpm( &lm, LayerModelTypes::ActiveLayerSelection ); ActiveLayer al; - ActiveProject activeProject( as, al, recordingLpm, localProjectsManager ); + ActiveProject activeProject( as, al, recordingLpm, localProjectsManager, ma.get() ); std::unique_ptr vm( new VariablesManager( ma.get() ) ); vm->registerInputExpressionFunctions(); diff --git a/app/qml/main.qml b/app/qml/main.qml index 6aca0ff70..4cb127ddb 100644 --- a/app/qml/main.qml +++ b/app/qml/main.qml @@ -276,7 +276,7 @@ ApplicationWindow { MMToolbarButton { text: qsTr("Add") iconSource: __style.addIcon - visible: __inputUtils.userHasEditableRole( __activeProject.qgsProject ) + visible: __activeProject.projectRole !== "reader" onClicked: { if ( __recordingLayersModel.rowCount() > 0 ) { stateManager.state = "map" @@ -388,7 +388,6 @@ ApplicationWindow { } onOpenProjectRequested: function( projectPath ) { - __merginApi.updateProjectMetadata( projectPath ) //HERE __activeProject.load( projectPath ) } diff --git a/app/test/testactiveproject.cpp b/app/test/testactiveproject.cpp index 8b14abd24..4e6edf70c 100644 --- a/app/test/testactiveproject.cpp +++ b/app/test/testactiveproject.cpp @@ -39,7 +39,7 @@ void TestActiveProject::testProjectValidations() ActiveLayer al; LayersModel lm; LayersProxyModel lpm( &lm, LayerModelTypes::ActiveLayerSelection ); - ActiveProject activeProject( as, al, lpm, mApi->localProjectsManager() ); + ActiveProject activeProject( as, al, lpm, mApi->localProjectsManager(), mApi ); QSignalSpy spyReportIssues( &activeProject, &ActiveProject::reportIssue ); QSignalSpy spyErrorsFound( &activeProject, &ActiveProject::loadingErrorFound ); @@ -66,7 +66,7 @@ void TestActiveProject::testProjectLoadFailure() ActiveLayer al; LayersModel lm; LayersProxyModel lpm( &lm, LayerModelTypes::ActiveLayerSelection ); - ActiveProject activeProject( as, al, lpm, mApi->localProjectsManager() ); + ActiveProject activeProject( as, al, lpm, mApi->localProjectsManager(), mApi ); mApi->localProjectsManager().addLocalProject( projectdir, projectname ); @@ -88,7 +88,7 @@ void TestActiveProject::testPositionTrackingFlag() ActiveLayer al; LayersModel lm; LayersProxyModel lpm( &lm, LayerModelTypes::ActiveLayerSelection ); - ActiveProject activeProject( as, al, lpm, mApi->localProjectsManager() ); + ActiveProject activeProject( as, al, lpm, mApi->localProjectsManager(), mApi ); // project "planes" - tracking not enabled QString projectDir = TestUtils::testDataDir() + "/planes/"; diff --git a/app/test/testmerginapi.cpp b/app/test/testmerginapi.cpp index 815563bef..5ec9f37a0 100644 --- a/app/test/testmerginapi.cpp +++ b/app/test/testmerginapi.cpp @@ -2369,7 +2369,7 @@ void TestMerginApi::testAutosync() MapThemesModel mtm; AppSettings as; ActiveLayer al; LayersModel lm; LayersProxyModel lpm( &lm, LayerModelTypes::ActiveLayerSelection ); - ActiveProject activeProject( as, al, lpm, mApi->localProjectsManager() ); + ActiveProject activeProject( as, al, lpm, mApi->localProjectsManager(), mApi ); mApi->localProjectsManager().addLocalProject( projectdir, projectname ); diff --git a/core/merginapi.cpp b/core/merginapi.cpp index eac8749e4..c2f40bd23 100644 --- a/core/merginapi.cpp +++ b/core/merginapi.cpp @@ -1404,7 +1404,6 @@ void MerginApi::onPlanProductIdChanged() QNetworkReply *MerginApi::getProjectInfo( const QString &projectFullName, bool withAuth ) { - qDebug() << "HERE getProjectInfo 1: " << projectFullName; if ( withAuth && !validateAuth() ) { emit missingAuthorizationError( projectFullName ); @@ -3947,51 +3946,3 @@ DownloadQueueItem::DownloadQueueItem( const QString &fp, qint64 s, int v, qint64 tempFileName = CoreUtils::uuidWithoutBraces( QUuid::createUuid() ); } -bool MerginApi::updateProjectMetadata(const QString &filePath) -{ - qDebug() << "Entering updateProjectMetadata with filePath:" << filePath; - - // Extract the project directory from the file path - QFileInfo fileInfo(filePath); - QString projectDir = fileInfo.absolutePath(); - qDebug() << "Extracted projectDir:" << projectDir; - - // Try to find the project from local projects using directory - LocalProject projectInfo = mLocalProjects.projectFromDirectory(projectDir); - if (!projectInfo.isValid()) - { - qDebug() << "Could not find local project for path:" << filePath; - CoreUtils::log("update metadata", "Could not find local project for path: " + filePath); - return false; - } - qDebug() << "Found local project. Namespace:" << projectInfo.projectNamespace - << "Name:" << projectInfo.projectName; - - // Get the full project name from the local project info - QString projectFullName = getFullProjectName(projectInfo.projectNamespace, projectInfo.projectName); - qDebug() << "Full project name:" << projectFullName; - - QNetworkReply *r = getProjectInfo(projectFullName, true); - if (!r) - { - qDebug() << "Network reply is null for project name:" << projectFullName; - return false; - } - - qDebug() << "Network reply received. Checking for errors..."; - if (r->error() == QNetworkReply::NoError) - { - QByteArray data = r->readAll(); - qDebug() << "Received data:" << data; - MerginProjectMetadata serverProject = MerginProjectMetadata::fromJson(data); - qDebug() << "Parsed server project metadata successfully."; - return true; - } - else - { - qDebug() << "Network reply error:" << r->errorString(); - return false; - } -} - - diff --git a/core/merginapi.h b/core/merginapi.h index b198a5a00..9fc47ac64 100644 --- a/core/merginapi.h +++ b/core/merginapi.h @@ -573,7 +573,23 @@ class MerginApi: public QObject */ bool apiSupportsWorkspaces(); - Q_INVOKABLE bool updateProjectMetadata( const QString &filePath ); + /** Creates a request to get project details (list of project files). + */ + QNetworkReply *getProjectInfo( const QString &projectFullName, bool withAuth = true ); + + enum CustomAttribute + { + AttrProjectFullName = QNetworkRequest::User, + AttrTempFileName = QNetworkRequest::User + 1, + AttrWorkspaceName = QNetworkRequest::User + 2, + AttrAcceptFlag = QNetworkRequest::User + 3, + }; + + /** + * Extracts detail (message) of an error json. If its not json or detail cannot be parsed, the whole data are return; + * \param data Data received from mergin server on a request failed. + */ + QString extractServerErrorMsg( const QByteArray &data ); signals: void apiSupportsSubscriptionsChanged(); @@ -746,20 +762,11 @@ class MerginApi: public QObject */ QVariant extractServerErrorValue( const QByteArray &data, const QString &key ); /** - * Extracts detail (message) of an error json. If its not json or detail cannot be parsed, the whole data are return; - * \param data Data received from mergin server on a request failed. - */ - QString extractServerErrorMsg( const QByteArray &data ); - /** * Returns a temporary project path. * \param projectFullName */ QString getTempProjectDir( const QString &projectFullName ); - /** Creates a request to get project details (list of project files). - */ - QNetworkReply *getProjectInfo( const QString &projectFullName, bool withAuth = true ); - //! Called when pull of project data has finished to finalize things and emit sync finished signal void finalizeProjectPull( const QString &projectFullName ); @@ -801,14 +808,6 @@ class MerginApi: public QObject MerginSubscriptionInfo *mSubscriptionInfo; //owned by this (qml grouped-properties) MerginUserAuth *mUserAuth; //owned by this (qml grouped-properties) - enum CustomAttribute - { - AttrProjectFullName = QNetworkRequest::User, - AttrTempFileName = QNetworkRequest::User + 1, - AttrWorkspaceName = QNetworkRequest::User + 2, - AttrAcceptFlag = QNetworkRequest::User + 3, - }; - Transactions mTransactionalStatus; //projectFullname -> transactionStatus static const QSet sIgnoreExtensions; static const QSet sIgnoreImageExtensions; From 7a01cc669eb3b9fed9ab8a3c42203e3fd7d00a7b Mon Sep 17 00:00:00 2001 From: VitorVieiraZ Date: Thu, 28 Nov 2024 08:50:32 -0300 Subject: [PATCH 5/8] updating role every time we open a project + visibility condition on editing buttons --- app/activeproject.cpp | 21 +++++++++++-------- app/activeproject.h | 6 ++++++ app/qml/form/MMFormPage.qml | 4 ++-- app/qml/form/MMPreviewDrawer.qml | 2 +- .../components/MMFeaturesListPageDrawer.qml | 1 + app/qml/layers/MMFeaturesListPage.qml | 2 +- app/qml/project/MMProjectController.qml | 2 ++ core/merginapi.cpp | 1 - core/merginprojectmetadata.cpp | 2 +- 9 files changed, 26 insertions(+), 15 deletions(-) diff --git a/app/activeproject.cpp b/app/activeproject.cpp index 39d855cb3..d51e64174 100644 --- a/app/activeproject.cpp +++ b/app/activeproject.cpp @@ -97,12 +97,14 @@ QString ActiveProject::projectFullName() const bool ActiveProject::load( const QString &filePath ) { - updateProjectMetadata(); return forceLoad( filePath, false ); } bool ActiveProject::forceLoad( const QString &filePath, bool force ) { + // update user's role each time a project is opened, following #3174 + updateProjectMetadata(); + CoreUtils::log( QStringLiteral( "Project loading" ), filePath + " " + ( force ? "true" : "false" ) ); // clear autosync @@ -567,6 +569,7 @@ bool ActiveProject::updateProjectMetadata() QNetworkReply *reply = mMerginApi->getProjectInfo( projectFullName() ); if ( !reply ) { + restoreCachedRole(); return false; } @@ -589,24 +592,24 @@ void ActiveProject::updateProjectMetadataReplyFinished() QByteArray data = r->readAll(); MerginProjectMetadata serverProject = MerginProjectMetadata::fromJson( data ); - QString role = serverProject.role; setProjectRole( role ); } else { - QString serverMsg = mMerginApi->extractServerErrorMsg( r->readAll() ); - - QString projectDir = mQgsProject->absolutePath(); - MerginProjectMetadata cachedProjectMetadata = MerginProjectMetadata::fromCachedJson( mLocalProject.projectDir + "/" + mMerginApi->sMetadataFile ); - - QString role = cachedProjectMetadata.role; - setProjectRole( role ); + restoreCachedRole(); } r->deleteLater(); } +void ActiveProject::restoreCachedRole() +{ + MerginProjectMetadata cachedProjectMetadata = MerginProjectMetadata::fromCachedJson( mLocalProject.projectDir + "/" + mMerginApi->sMetadataFile ); + QString role = cachedProjectMetadata.role; + setProjectRole( role ); +} + QString ActiveProject::projectRole() const { return mProjectRole; diff --git a/app/activeproject.h b/app/activeproject.h index 54b2de4e5..bec9a8b4f 100644 --- a/app/activeproject.h +++ b/app/activeproject.h @@ -125,8 +125,14 @@ class ActiveProject: public QObject * Returns role/permission level of current user for this project */ Q_INVOKABLE QString projectRole() const; + void setProjectRole( const QString &role ); + /** + * Restores cached project role in metadata + */ + void restoreCachedRole(); + /** * Creates a network request to fetch latest project information and define user role in this project */ diff --git a/app/qml/form/MMFormPage.qml b/app/qml/form/MMFormPage.qml index f12a9647f..1168a06d0 100644 --- a/app/qml/form/MMFormPage.qml +++ b/app/qml/form/MMFormPage.qml @@ -201,7 +201,7 @@ Page { footer: MMComponents.MMToolbar { - visible: !root.layerIsReadOnly + visible: !root.layerIsReadOnly && __activeProject.projectRole !== "reader" ObjectModel { id: readStateButtons @@ -231,7 +231,7 @@ Page { id: editGeometry text: qsTr( "Edit geometry" ) iconSource: __style.editIcon - visible: root.layerIsSpatial + visible: root.layerIsSpatial && __activeProject.projectRole !== "reader" onClicked: root.editGeometryRequested( root.controller.featureLayerPair ) } } diff --git a/app/qml/form/MMPreviewDrawer.qml b/app/qml/form/MMPreviewDrawer.qml index ca6753fc0..328d55ebb 100644 --- a/app/qml/form/MMPreviewDrawer.qml +++ b/app/qml/form/MMPreviewDrawer.qml @@ -295,7 +295,7 @@ Item { property bool isHTMLType: root.controller.type === MM.AttributePreviewController.HTML property bool isEmptyType: root.controller.type === MM.AttributePreviewController.Empty - property bool showEditButton: !root.layerIsReadOnly + property bool showEditButton: !root.layerIsReadOnly && __activeProject.projectRole !== "reader" property bool showStakeoutButton: __inputUtils.isPointLayerFeature( controller.featureLayerPair ) property bool showButtons: showEditButton || showStakeoutButton diff --git a/app/qml/form/components/MMFeaturesListPageDrawer.qml b/app/qml/form/components/MMFeaturesListPageDrawer.qml index c6f3a266a..ce9c22933 100644 --- a/app/qml/form/components/MMFeaturesListPageDrawer.qml +++ b/app/qml/form/components/MMFeaturesListPageDrawer.qml @@ -103,6 +103,7 @@ Drawer { } text: qsTr( "Add feature" ) + visible: __activeProject.projectRole !== "reader" onClicked: root.buttonClicked() } diff --git a/app/qml/layers/MMFeaturesListPage.qml b/app/qml/layers/MMFeaturesListPage.qml index 04b8bb256..5bf9c3f9f 100644 --- a/app/qml/layers/MMFeaturesListPage.qml +++ b/app/qml/layers/MMFeaturesListPage.qml @@ -89,7 +89,7 @@ MMComponents.MMPage { anchors.bottom: parent.bottom anchors.bottomMargin: root.hasToolbar ? __style.margin20 : ( __style.safeAreaBottom + __style.margin8 ) - visible: __inputUtils.isNoGeometryLayer( root.selectedLayer ) && !root.layerIsReadOnly + visible: __inputUtils.isNoGeometryLayer( root.selectedLayer ) && !root.layerIsReadOnly && __activeProject.projectRole !== "reader" text: qsTr("Add feature") diff --git a/app/qml/project/MMProjectController.qml b/app/qml/project/MMProjectController.qml index 04f52008d..47d34033d 100644 --- a/app/qml/project/MMProjectController.qml +++ b/app/qml/project/MMProjectController.qml @@ -50,6 +50,8 @@ Item { { // just hide the panel - project already loaded hidePanel() + // update user's role in project ( in case user has changed ) + __activeProject.updateProjectMetadata() } else { diff --git a/core/merginapi.cpp b/core/merginapi.cpp index c2f40bd23..ab5e4a618 100644 --- a/core/merginapi.cpp +++ b/core/merginapi.cpp @@ -720,7 +720,6 @@ bool MerginApi::pullProject( const QString &projectNamespace, const QString &pro CoreUtils::log( "pull " + projectFullName, "### Starting ###" ); - qDebug() << "HERE projectNamespace AND projectName : " << projectNamespace << " " << projectName; QNetworkReply *reply = getProjectInfo( projectFullName, withAuth ); if ( reply ) { diff --git a/core/merginprojectmetadata.cpp b/core/merginprojectmetadata.cpp index 79d8f93db..2943cfd9f 100644 --- a/core/merginprojectmetadata.cpp +++ b/core/merginprojectmetadata.cpp @@ -100,7 +100,7 @@ MerginProjectMetadata MerginProjectMetadata::fromJson( const QByteArray &data ) project.name = docObj.value( QStringLiteral( "name" ) ).toString(); project.projectNamespace = docObj.value( QStringLiteral( "namespace" ) ).toString(); project.role = docObj.value( QStringLiteral( "role" ) ).toString(); - qDebug() << "MerginProjectMetadata MerginProjectMetadata::fromJson( const QByteArray &data ) called, getting role: " << project.role; + QJsonValue access = docObj.value( QStringLiteral( "access" ) ); if ( access.isObject() ) { From eabfc850684c6ea26a61b5af2f01043652391d1b Mon Sep 17 00:00:00 2001 From: VitorVieiraZ Date: Mon, 9 Dec 2024 09:27:32 -0300 Subject: [PATCH 6/8] in progress --- app/activeproject.cpp | 66 ++++------------- app/activeproject.h | 13 +--- app/qml/project/MMProjectController.qml | 2 +- core/merginapi.cpp | 95 +++++++++++++++++++++++++ core/merginapi.h | 42 ++++++----- 5 files changed, 138 insertions(+), 80 deletions(-) diff --git a/app/activeproject.cpp b/app/activeproject.cpp index d51e64174..ba65999fc 100644 --- a/app/activeproject.cpp +++ b/app/activeproject.cpp @@ -76,6 +76,17 @@ ActiveProject::ActiveProject( AppSettings &appSettings setAutosyncEnabled( mAppSettings.autosyncAllowed() ); QObject::connect( &mAppSettings, &AppSettings::autosyncAllowedChanged, this, &ActiveProject::setAutosyncEnabled ); + + QObject::connect( + mMerginApi, + &MerginApi::projectMetadataRoleUpdated, + this, [this]( const QString & projectFullName, const QString & role ) + { + if ( projectFullName == this->projectFullName() ) + { + setProjectRole( role ); + } + } ); } ActiveProject::~ActiveProject() = default; @@ -103,7 +114,7 @@ bool ActiveProject::load( const QString &filePath ) bool ActiveProject::forceLoad( const QString &filePath, bool force ) { // update user's role each time a project is opened, following #3174 - updateProjectMetadata(); + mMerginApi->updateProjectMetadataRole( projectFullName() ); CoreUtils::log( QStringLiteral( "Project loading" ), filePath + " " + ( force ? "true" : "false" ) ); @@ -559,56 +570,9 @@ bool ActiveProject::positionTrackingSupported() const return mQgsProject->readBoolEntry( QStringLiteral( "Mergin" ), QStringLiteral( "PositionTracking/Enabled" ), false ); } -bool ActiveProject::updateProjectMetadata() -{ - if ( !mMerginApi ) - { - return false; - } - - QNetworkReply *reply = mMerginApi->getProjectInfo( projectFullName() ); - if ( !reply ) - { - restoreCachedRole(); - return false; - } - - reply->request().setAttribute( static_cast( mMerginApi->AttrProjectFullName ), projectFullName() ); - - connect( reply, &QNetworkReply::finished, this, &ActiveProject::updateProjectMetadataReplyFinished ); - - return true; -} - -void ActiveProject::updateProjectMetadataReplyFinished() -{ - QNetworkReply *r = qobject_cast( sender() ); - Q_ASSERT( r ); - - QString projectFullName = r->request().attribute( static_cast( mMerginApi->AttrProjectFullName ) ).toString(); - - if ( r->error() == QNetworkReply::NoError ) - { - QByteArray data = r->readAll(); - - MerginProjectMetadata serverProject = MerginProjectMetadata::fromJson( data ); - QString role = serverProject.role; - setProjectRole( role ); - } - else - { - restoreCachedRole(); - } - - r->deleteLater(); -} - -void ActiveProject::restoreCachedRole() -{ - MerginProjectMetadata cachedProjectMetadata = MerginProjectMetadata::fromCachedJson( mLocalProject.projectDir + "/" + mMerginApi->sMetadataFile ); - QString role = cachedProjectMetadata.role; - setProjectRole( role ); -} +// read cached role from metadata -> get reply -> update if changed +// metadataRoleFetchFinishedSignal -> (data) +// store role in app settings or update only role in cached json or nothing :) QString ActiveProject::projectRole() const { diff --git a/app/activeproject.h b/app/activeproject.h index bec9a8b4f..d7ff185eb 100644 --- a/app/activeproject.h +++ b/app/activeproject.h @@ -22,7 +22,7 @@ #include "localprojectsmanager.h" #include "autosynccontroller.h" #include "inputmapsettings.h" -#include "../core/merginapi.h" +#include "merginapi.h" /** * \brief The ActiveProject class can load a QGIS project and holds its data. @@ -128,17 +128,6 @@ class ActiveProject: public QObject void setProjectRole( const QString &role ); - /** - * Restores cached project role in metadata - */ - void restoreCachedRole(); - - /** - * Creates a network request to fetch latest project information and define user role in this project - */ - Q_INVOKABLE bool updateProjectMetadata(); - void updateProjectMetadataReplyFinished(); - signals: void qgsProjectChanged(); void localProjectChanged( LocalProject project ); diff --git a/app/qml/project/MMProjectController.qml b/app/qml/project/MMProjectController.qml index 47d34033d..a0b8283bb 100644 --- a/app/qml/project/MMProjectController.qml +++ b/app/qml/project/MMProjectController.qml @@ -51,7 +51,7 @@ Item { // just hide the panel - project already loaded hidePanel() // update user's role in project ( in case user has changed ) - __activeProject.updateProjectMetadata() + __merginApi.updateProjectMetadataRole( __activeProject.projectFullName() ) } else { diff --git a/core/merginapi.cpp b/core/merginapi.cpp index ab5e4a618..801f511e1 100644 --- a/core/merginapi.cpp +++ b/core/merginapi.cpp @@ -3449,6 +3449,45 @@ bool MerginApi::writeData( const QByteArray &data, const QString &path ) return true; } +bool MerginApi::updateCachedProjectRole( const QString &projectFullName, const QString &newRole ) +{ + LocalProject project = mLocalProjects.projectFromMerginName( projectFullName ); + if ( !project.isValid() ) + { + return false; + } + + QString metadataPath = project.projectDir + "/" + sMetadataFile; + + QFile file( metadataPath ); + if ( !file.open( QIODevice::ReadOnly ) ) + { + return false; + } + + QByteArray data = file.readAll(); + file.close(); + + QJsonDocument doc = QJsonDocument::fromJson( data ); + if ( !doc.isObject() ) + { + return false; + } + + QJsonObject obj = doc.object(); + obj["role"] = newRole; + doc.setObject( obj ); + + if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) ) + { + return false; + } + + bool success = ( file.write( doc.toJson() ) != -1 ); + file.close(); + + return success; +} void MerginApi::createPathIfNotExists( const QString &filePath ) { @@ -3945,3 +3984,59 @@ DownloadQueueItem::DownloadQueueItem( const QString &fp, qint64 s, int v, qint64 tempFileName = CoreUtils::uuidWithoutBraces( QUuid::createUuid() ); } +void MerginApi::updateProjectMetadataRole( const QString &projectFullName ) +{ + if ( projectFullName.isEmpty() ) + { + return; + } + + QString projectDir = mLocalProjects.projectFromMerginName( projectFullName ).projectDir; + MerginProjectMetadata cachedProjectMetadata = MerginProjectMetadata::fromCachedJson( projectDir + "/" + sMetadataFile ); + QString cachedRole = cachedProjectMetadata.role; + + QNetworkReply *reply = getProjectInfo( projectFullName ); + if ( !reply ) + { + emit projectMetadataRoleUpdated( projectFullName, cachedRole ); + return; + } + + reply->request().setAttribute( static_cast( AttrProjectFullName ), projectFullName ); + reply->request().setAttribute( static_cast( AttrCachedRole ), cachedRole ); + connect( reply, &QNetworkReply::finished, this, &MerginApi::updateProjectMetadataRoleReplyFinished ); +} + +void MerginApi::updateProjectMetadataRoleReplyFinished() +{ + QNetworkReply *r = qobject_cast( sender() ); + Q_ASSERT( r ); + + QString projectFullName = r->request().attribute( static_cast( AttrProjectFullName ) ).toString(); + QString cachedRole = r->request().attribute( static_cast( AttrCachedRole ) ).toString(); + + if ( r->error() == QNetworkReply::NoError ) + { + QByteArray data = r->readAll(); + MerginProjectMetadata serverProject = MerginProjectMetadata::fromJson( data ); + QString role = serverProject.role; + + if ( role != cachedRole ) + { + if ( updateCachedProjectRole( projectFullName, role ) ) + { + emit projectMetadataRoleUpdated( projectFullName, role ); + } + else + { + CoreUtils::log( "metadata", QString( "Failed to update cached role for project %1" ).arg( projectFullName ) ); + } + } + } + else + { + emit projectMetadataRoleUpdated( projectFullName, cachedRole ); + } + + r->deleteLater(); +} diff --git a/core/merginapi.h b/core/merginapi.h index 9fc47ac64..baa229e49 100644 --- a/core/merginapi.h +++ b/core/merginapi.h @@ -573,23 +573,10 @@ class MerginApi: public QObject */ bool apiSupportsWorkspaces(); - /** Creates a request to get project details (list of project files). - */ - QNetworkReply *getProjectInfo( const QString &projectFullName, bool withAuth = true ); - - enum CustomAttribute - { - AttrProjectFullName = QNetworkRequest::User, - AttrTempFileName = QNetworkRequest::User + 1, - AttrWorkspaceName = QNetworkRequest::User + 2, - AttrAcceptFlag = QNetworkRequest::User + 3, - }; - /** - * Extracts detail (message) of an error json. If its not json or detail cannot be parsed, the whole data are return; - * \param data Data received from mergin server on a request failed. - */ - QString extractServerErrorMsg( const QByteArray &data ); + * Updates project metadata role by fetching latest information from server. + */ + Q_INVOKABLE void updateProjectMetadataRole( const QString &projectFullName ); signals: void apiSupportsSubscriptionsChanged(); @@ -668,6 +655,7 @@ class MerginApi: public QObject void apiSupportsWorkspacesChanged(); void serverWasUpgraded(); + void projectMetadataRoleUpdated( const QString &projectFullName, const QString &role ); private slots: void listProjectsReplyFinished( QString requestId ); @@ -762,11 +750,20 @@ class MerginApi: public QObject */ QVariant extractServerErrorValue( const QByteArray &data, const QString &key ); /** + * Extracts detail (message) of an error json. If its not json or detail cannot be parsed, the whole data are return; + * \param data Data received from mergin server on a request failed. + */ + QString extractServerErrorMsg( const QByteArray &data ); + /** * Returns a temporary project path. * \param projectFullName */ QString getTempProjectDir( const QString &projectFullName ); + /** Creates a request to get project details (list of project files). + */ + QNetworkReply *getProjectInfo( const QString &projectFullName, bool withAuth = true ); + //! Called when pull of project data has finished to finalize things and emit sync finished signal void finalizeProjectPull( const QString &projectFullName ); @@ -798,6 +795,10 @@ class MerginApi: public QObject bool projectFileHasBeenUpdated( const ProjectDiff &diff ); + void updateProjectMetadataRoleReplyFinished(); + + bool updateCachedProjectRole( const QString &projectFullName, const QString &newRole ); + QNetworkAccessManager mManager; QString mApiRoot; LocalProjectsManager &mLocalProjects; @@ -808,6 +809,15 @@ class MerginApi: public QObject MerginSubscriptionInfo *mSubscriptionInfo; //owned by this (qml grouped-properties) MerginUserAuth *mUserAuth; //owned by this (qml grouped-properties) + enum CustomAttribute + { + AttrProjectFullName = QNetworkRequest::User, + AttrTempFileName = QNetworkRequest::User + 1, + AttrWorkspaceName = QNetworkRequest::User + 2, + AttrAcceptFlag = QNetworkRequest::User + 3, + AttrCachedRole = QNetworkRequest::User + 4 + }; + Transactions mTransactionalStatus; //projectFullname -> transactionStatus static const QSet sIgnoreExtensions; static const QSet sIgnoreImageExtensions; From 6596705ed7b7b33cb5cd8182159fb5d4e5234c5d Mon Sep 17 00:00:00 2001 From: VitorVieiraZ Date: Tue, 10 Dec 2024 08:55:14 -0300 Subject: [PATCH 7/8] ensuring user role is cached/updated each time we open a project --- app/activeproject.cpp | 10 +++++++--- app/activeproject.h | 5 +++++ app/qml/project/MMProjectController.qml | 4 ++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/app/activeproject.cpp b/app/activeproject.cpp index ba65999fc..5ba30e925 100644 --- a/app/activeproject.cpp +++ b/app/activeproject.cpp @@ -113,9 +113,6 @@ bool ActiveProject::load( const QString &filePath ) bool ActiveProject::forceLoad( const QString &filePath, bool force ) { - // update user's role each time a project is opened, following #3174 - mMerginApi->updateProjectMetadataRole( projectFullName() ); - CoreUtils::log( QStringLiteral( "Project loading" ), filePath + " " + ( force ? "true" : "false" ) ); // clear autosync @@ -204,6 +201,7 @@ bool ActiveProject::forceLoad( const QString &filePath, bool force ) updateRecordingLayers(); updateActiveLayer(); updateMapSettingsLayers(); + updateUserRoleInActiveProject(); emit localProjectChanged( mLocalProject ); emit projectReloaded( mQgsProject ); @@ -588,3 +586,9 @@ void ActiveProject::setProjectRole( const QString &role ) emit projectRoleChanged(); } } + +void ActiveProject::updateUserRoleInActiveProject() +{ + // update user's role each time a project is opened, following #3174 + mMerginApi->updateProjectMetadataRole( projectFullName() ); +} diff --git a/app/activeproject.h b/app/activeproject.h index d7ff185eb..faa166e60 100644 --- a/app/activeproject.h +++ b/app/activeproject.h @@ -128,6 +128,11 @@ class ActiveProject: public QObject void setProjectRole( const QString &role ); + /** + * Calls Mergin API to update current project’s role + */ + void updateUserRoleInActiveProject(); + signals: void qgsProjectChanged(); void localProjectChanged( LocalProject project ); diff --git a/app/qml/project/MMProjectController.qml b/app/qml/project/MMProjectController.qml index a0b8283bb..7ba3698af 100644 --- a/app/qml/project/MMProjectController.qml +++ b/app/qml/project/MMProjectController.qml @@ -48,10 +48,10 @@ Item { function setupProjectOpen( projectPath ) { if ( projectPath === __activeProject.localProject.qgisProjectFilePath ) { + // update user's role in project ( in case user has changed ) + __activeProject.updateUserRoleInActiveProject() // just hide the panel - project already loaded hidePanel() - // update user's role in project ( in case user has changed ) - __merginApi.updateProjectMetadataRole( __activeProject.projectFullName() ) } else { From 8a92bfffd42090369e1c20d634c3838cfcc6786b Mon Sep 17 00:00:00 2001 From: VitorVieiraZ Date: Tue, 10 Dec 2024 08:59:21 -0300 Subject: [PATCH 8/8] cleaning code --- app/activeproject.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/activeproject.cpp b/app/activeproject.cpp index 5ba30e925..b0a875674 100644 --- a/app/activeproject.cpp +++ b/app/activeproject.cpp @@ -568,10 +568,6 @@ bool ActiveProject::positionTrackingSupported() const return mQgsProject->readBoolEntry( QStringLiteral( "Mergin" ), QStringLiteral( "PositionTracking/Enabled" ), false ); } -// read cached role from metadata -> get reply -> update if changed -// metadataRoleFetchFinishedSignal -> (data) -// store role in app settings or update only role in cached json or nothing :) - QString ActiveProject::projectRole() const { return mProjectRole;