Skip to content

Commit

Permalink
updating project role on opening a project from active project and ch…
Browse files Browse the repository at this point in the history
…anging Add button visibility for readers
  • Loading branch information
VitorVieiraZ committed Nov 27, 2024
1 parent b3ded65 commit 5da5eca
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 90 deletions.
68 changes: 68 additions & 0 deletions app/activeproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ ActiveProject::ActiveProject( AppSettings &appSettings
, ActiveLayer &activeLayer
, LayersProxyModel &recordingLayerPM
, LocalProjectsManager &localProjectsManager
, MerginApi *merginApi
, QObject *parent ) :

QObject( parent )
, mAppSettings( 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
Expand Down Expand Up @@ -95,6 +97,7 @@ QString ActiveProject::projectFullName() const

bool ActiveProject::load( const QString &filePath )
{
updateProjectMetadata();
return forceLoad( filePath, false );
}

Expand Down Expand Up @@ -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<QNetworkRequest::Attribute>( mMerginApi->AttrProjectFullName ), projectFullName() );

connect( reply, &QNetworkReply::finished, this, &ActiveProject::updateProjectMetadataReplyFinished );

return true;
}

void ActiveProject::updateProjectMetadataReplyFinished()
{
QNetworkReply *r = qobject_cast<QNetworkReply *>( sender() );
Q_ASSERT( r );

QString projectFullName = r->request().attribute( static_cast<QNetworkRequest::Attribute>( 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();
}
}
19 changes: 19 additions & 0 deletions app/activeproject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 )
Expand All @@ -43,6 +45,7 @@ class ActiveProject: public QObject
, ActiveLayer &activeLayer
, LayersProxyModel &recordingLayerPM
, LocalProjectsManager &localProjectsManager
, MerginApi *mMerginApi
, QObject *parent = nullptr );

virtual ~ActiveProject();
Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -182,10 +199,12 @@ class ActiveProject: public QObject
LayersProxyModel &mRecordingLayerPM;
LocalProjectsManager &mLocalProjectsManager;
InputMapSettings *mMapSettings = nullptr;
MerginApi *mMerginApi = nullptr;

std::unique_ptr<AutosyncController> mAutosyncController;

QString mProjectLoadingLog;
QString mProjectRole;

/**
* Reloads project.
Expand Down
11 changes: 0 additions & 11 deletions app/inpututils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
5 changes: 0 additions & 5 deletions app/inpututils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 );

Expand Down
2 changes: 1 addition & 1 deletion app/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<VariablesManager> vm( new VariablesManager( ma.get() ) );
vm->registerInputExpressionFunctions();

Expand Down
3 changes: 1 addition & 2 deletions app/qml/main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -388,7 +388,6 @@ ApplicationWindow {
}

onOpenProjectRequested: function( projectPath ) {
__merginApi.updateProjectMetadata( projectPath ) //HERE
__activeProject.load( projectPath )
}

Expand Down
6 changes: 3 additions & 3 deletions app/test/testactiveproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand All @@ -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 );

Expand All @@ -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/";
Expand Down
2 changes: 1 addition & 1 deletion app/test/testmerginapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );

Expand Down
49 changes: 0 additions & 49 deletions core/merginapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down Expand Up @@ -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;
}
}


35 changes: 17 additions & 18 deletions core/merginapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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 );

Expand Down Expand Up @@ -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<QString> sIgnoreExtensions;
static const QSet<QString> sIgnoreImageExtensions;
Expand Down

1 comment on commit 5da5eca

@inputapp-bot
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iOS - version 24.11.696311 just submitted!

Please sign in to comment.