Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/localprojectsmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ enum ProjectStatus
NoVersion, //!< the project is not available locally
UpToDate, //!< both server and local copy are in sync with no extra modifications
OutOfDate, //!< server has newer version than what is available locally (but the project is not modified locally)
Modified //!< there are some local modifications in the project that need to be pushed (note: also server may have newer version)
Modified, //!< there are some local modifications in the project that need to be pushed (note: also server may have newer version)
NonProjectItem //!< only for mock projects, acts like a hook to enable extra functionality for models working with projects .
};
Q_ENUMS( ProjectStatus )

Expand Down
2 changes: 1 addition & 1 deletion app/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ int main( int argc, char *argv[] )
QObject::connect( &app, &QGuiApplication::applicationStateChanged, &loader, &Loader::appStateChanged );
QObject::connect( &app, &QCoreApplication::aboutToQuit, &loader, &Loader::appAboutToQuit );
QObject::connect( ma.get(), &MerginApi::syncProjectFinished, &pm, &ProjectModel::syncedProjectFinished );
QObject::connect( ma.get(), &MerginApi::listProjectsFinished, &mpm, &MerginProjectModel::resetProjects );
QObject::connect( ma.get(), &MerginApi::listProjectsFinished, &mpm, &MerginProjectModel::updateModel );
QObject::connect( ma.get(), &MerginApi::syncProjectStatusChanged, &mpm, &MerginProjectModel::syncProjectStatusChanged );
QObject::connect( ma.get(), &MerginApi::reloadProject, &loader, &Loader::reloadProject );
QObject::connect( &mtm, &MapThemesModel::mapThemeChanged, &recordingLpm, &LayersProxyModel::onMapThemeChanged );
Expand Down
105 changes: 66 additions & 39 deletions app/merginapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,8 @@ MerginUserInfo *MerginApi::userInfo() const
return mUserInfo;
}

void MerginApi::listProjects( const QString &searchExpression,
const QString &flag, const QString &filterTag )
void MerginApi::listProjects( const QString &searchExpression, const QString &flag, const QString &filterTag, const int page )
{

bool authorize = !flag.isEmpty();
if ( ( authorize && !validateAuthAndContinute() ) || mApiVersionStatus != MerginApiStatus::OK )
{
Expand All @@ -84,13 +82,18 @@ void MerginApi::listProjects( const QString &searchExpression,
}
if ( !searchExpression.isEmpty() )
{
query.addQueryItem( "q", searchExpression );
query.addQueryItem( "name", searchExpression );
}
if ( !flag.isEmpty() )
{
query.addQueryItem( "flag", flag );
}
QUrl url( mApiRoot + QStringLiteral( "/v1/project" ) );
query.addQueryItem( "order_by", QStringLiteral( "name" ) );
// Required query parameters
query.addQueryItem( "page", QString::number( page ) );
query.addQueryItem( "per_page", QString::number( PROJECT_PER_PAGE ) );

QUrl url( mApiRoot + QStringLiteral( "/v1/project/paginated" ) );
url.setQuery( query );

// Even if the authorization is not required, it can be include to fetch more results
Expand All @@ -102,7 +105,6 @@ void MerginApi::listProjects( const QString &searchExpression,
connect( reply, &QNetworkReply::finished, this, &MerginApi::listProjectsReplyFinished );
}


void MerginApi::downloadNextItem( const QString &projectFullName )
{
Q_ASSERT( mTransactionalStatus.contains( projectFullName ) );
Expand Down Expand Up @@ -1165,10 +1167,27 @@ void MerginApi::listProjectsReplyFinished()
QNetworkReply *r = qobject_cast<QNetworkReply *>( sender() );
Q_ASSERT( r );

int projectCount = -1;
int requestedPage = 1;

if ( r->error() == QNetworkReply::NoError )
{
QUrlQuery query( r->request().url().query() );
requestedPage = query.queryItemValue( "page" ).toInt();

QByteArray data = r->readAll();
mRemoteProjects = parseListProjectsMetadata( data );
QJsonDocument doc = QJsonDocument::fromJson( data );
if ( doc.isObject() )
{
QJsonObject obj = doc.object();
QJsonArray rawProjects = obj.value( "projects" ).toArray();
projectCount = obj.value( "count" ).toInt();
mRemoteProjects = parseProjectJsonArray( rawProjects );
}
else
{
mRemoteProjects.clear();
}

// for any local projects we can update the latest server version
for ( MerginProjectListEntry project : mRemoteProjects )
Expand All @@ -1195,7 +1214,7 @@ void MerginApi::listProjectsReplyFinished()
}

r->deleteLater();
emit listProjectsFinished( mRemoteProjects, mTransactionalStatus );
emit listProjectsFinished( mRemoteProjects, mTransactionalStatus, projectCount, requestedPage );
}


Expand Down Expand Up @@ -2174,46 +2193,54 @@ ProjectDiff MerginApi::compareProjectFiles( const QList<MerginFile> &oldServerFi
}


MerginProjectList MerginApi::parseListProjectsMetadata( const QByteArray &data )
MerginProjectList MerginApi::parseProjectJsonArray( const QJsonArray &vArray )
{
MerginProjectList result;

QJsonDocument doc = QJsonDocument::fromJson( data );
if ( doc.isArray() )
MerginProjectList result;
for ( auto it = vArray.constBegin(); it != vArray.constEnd(); ++it )
{
QJsonArray vArray = doc.array();
QJsonObject projectMap = it->toObject();
MerginProjectListEntry project;

for ( auto it = vArray.constBegin(); it != vArray.constEnd(); ++it )
project.projectName = projectMap.value( QStringLiteral( "name" ) ).toString();
project.projectNamespace = projectMap.value( QStringLiteral( "namespace" ) ).toString();

QString versionStr = projectMap.value( QStringLiteral( "version" ) ).toString();
if ( versionStr.isEmpty() )
{
project.version = 0;
}
else if ( versionStr.startsWith( "v" ) ) // cut off 'v' part from v123
{
QJsonObject projectMap = it->toObject();
MerginProjectListEntry project;
versionStr = versionStr.mid( 1 );
project.version = versionStr.toInt();
}

project.projectName = projectMap.value( QStringLiteral( "name" ) ).toString();
project.projectNamespace = projectMap.value( QStringLiteral( "namespace" ) ).toString();
QDateTime updated = QDateTime::fromString( projectMap.value( QStringLiteral( "updated" ) ).toString(), Qt::ISODateWithMs ).toUTC();
if ( !updated.isValid() )
{
project.serverUpdated = QDateTime::fromString( projectMap.value( QStringLiteral( "created" ) ).toString(), Qt::ISODateWithMs ).toUTC();
}
else
{
project.serverUpdated = updated;
}

QString versionStr = projectMap.value( QStringLiteral( "version" ) ).toString();
if ( versionStr.isEmpty() )
{
project.version = 0;
}
else if ( versionStr.startsWith( "v" ) ) // cut off 'v' part from v123
{
versionStr = versionStr.mid( 1 );
project.version = versionStr.toInt();
}
result << project;
}
return result;
}

QDateTime updated = QDateTime::fromString( projectMap.value( QStringLiteral( "updated" ) ).toString(), Qt::ISODateWithMs ).toUTC();
if ( !updated.isValid() )
{
project.serverUpdated = QDateTime::fromString( projectMap.value( QStringLiteral( "created" ) ).toString(), Qt::ISODateWithMs ).toUTC();
}
else
{
project.serverUpdated = updated;
}
MerginProjectList MerginApi::parseListProjectsMetadata( const QByteArray &data )
{
MerginProjectList result;

result << project;
}
QJsonDocument doc = QJsonDocument::fromJson( data );
if ( doc.isArray() )
{
QJsonArray vArray = doc.array();

result = parseProjectJsonArray( vArray );
}
return result;
}
Expand Down
9 changes: 6 additions & 3 deletions app/merginapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,11 @@ class MerginApi: public QObject
* Eventually emits listProjectsFinished on which ProjectPanel (qml component) updates content.
* \param searchExpression Search filter on projects name.
* \param flag If defined, it is used to filter out projects tagged as 'created' or 'shared' with a authorized user
* \param withFilter If true, applies "input" tag in request.
* \param filterTag Name of tag that fetched projects have to have.
* \param page Requested page of projects.
*/
Q_INVOKABLE void listProjects( const QString &searchExpression = QStringLiteral(),
const QString &flag = QStringLiteral(), const QString &filterTag = QStringLiteral() );
const QString &flag = QStringLiteral(), const QString &filterTag = QStringLiteral(), const int page = 1 );

/**
* Sends non-blocking POST request to the server to download/update a project with a given name. On downloadProjectReplyFinished,
Expand Down Expand Up @@ -375,7 +376,7 @@ class MerginApi: public QObject
signals:
void apiSupportsSubscriptionsChanged();

void listProjectsFinished( const MerginProjectList &merginProjects, Transactions pendingProjects );
void listProjectsFinished( const MerginProjectList &merginProjects, Transactions pendingProjects, int projectCount, int page );
void listProjectsFailed();
void syncProjectFinished( const QString &projectDir, const QString &projectFullName, bool successfully = true );
/**
Expand Down Expand Up @@ -430,6 +431,7 @@ class MerginApi: public QObject

private:
MerginProjectList parseListProjectsMetadata( const QByteArray &data );
MerginProjectList parseProjectJsonArray( const QJsonArray &vArray );
static QStringList generateChunkIdsForSize( qint64 fileSize );
QJsonArray prepareUploadChangesJSON( const QList<MerginFile> &files );
static QString getApiKey( const QString &serverName );
Expand Down Expand Up @@ -556,6 +558,7 @@ class MerginApi: public QObject

static const int CHUNK_SIZE = 65536;
static const int UPLOAD_CHUNK_SIZE;
const int PROJECT_PER_PAGE = 50;
const QString TEMP_FOLDER = QStringLiteral( ".temp/" );

static QList<DownloadQueueItem> itemsForFileChunks( const MerginFile &file, int version );
Expand Down
31 changes: 29 additions & 2 deletions app/merginprojectmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ MerginProjectModel::MerginProjectModel( LocalProjectsManager &localProjects, QOb
QObject::connect( &mLocalProjects, &LocalProjectsManager::projectMetadataChanged, this, &MerginProjectModel::projectMetadataChanged );
QObject::connect( &mLocalProjects, &LocalProjectsManager::localProjectAdded, this, &MerginProjectModel::onLocalProjectAdded );
QObject::connect( &mLocalProjects, &LocalProjectsManager::localProjectRemoved, this, &MerginProjectModel::onLocalProjectRemoved );

mAdditionalItem->status = NonProjectItem;
}

QVariant MerginProjectModel::data( const QModelIndex &index, int role ) const
Expand Down Expand Up @@ -59,6 +61,8 @@ QVariant MerginProjectModel::data( const QModelIndex &index, int role ) const
return QVariant( QStringLiteral( "noVersion" ) );
case ProjectStatus::Modified:
return QVariant( QStringLiteral( "modified" ) );
case ProjectStatus::NonProjectItem:
return QVariant( QStringLiteral( "nonProjectItem" ) );
}
break;
}
Expand Down Expand Up @@ -96,10 +100,17 @@ int MerginProjectModel::rowCount( const QModelIndex &parent ) const
return mMerginProjects.count();
}

void MerginProjectModel::resetProjects( const MerginProjectList &merginProjects, QHash<QString, TransactionStatus> pendingProjects )
void MerginProjectModel::updateModel( const MerginProjectList &merginProjects, QHash<QString, TransactionStatus> pendingProjects, int expectedProjectCount, int page )
{
beginResetModel();
mMerginProjects.clear();
mMerginProjects.removeOne( mAdditionalItem );

if ( page == 1 )
{
mMerginProjects.clear();
}
setLastPage( page );


for ( MerginProjectListEntry entry : merginProjects )
{
Expand Down Expand Up @@ -129,6 +140,11 @@ void MerginProjectModel::resetProjects( const MerginProjectList &merginProjects,
mMerginProjects << project;
}

if ( mMerginProjects.count() < expectedProjectCount )
{
mMerginProjects << mAdditionalItem;
}

endResetModel();
}

Expand All @@ -144,6 +160,17 @@ int MerginProjectModel::findProjectIndex( const QString &projectFullName )
return -1;
}

void MerginProjectModel::setLastPage( int lastPage )
{
mLastPage = lastPage;
emit lastPageChanged();
}

int MerginProjectModel::lastPage() const
{
return mLastPage;
}

QString MerginProjectModel::searchExpression() const
{
return mSearchExpression;
Expand Down
20 changes: 18 additions & 2 deletions app/merginprojectmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class MerginProjectModel: public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY( QString searchExpression READ searchExpression WRITE setSearchExpression )
Q_PROPERTY( int lastPage READ lastPage NOTIFY lastPageChanged )

public:
enum Roles
Expand All @@ -68,8 +69,14 @@ class MerginProjectModel: public QAbstractListModel

int rowCount( const QModelIndex &parent = QModelIndex() ) const override;

//! Updates list of projects with synchronization progress if a project is pending
void resetProjects( const MerginProjectList &merginProjects, QHash<QString, TransactionStatus> pendingProjects );
/**
* Updates list of projects with synchronization progress if a project is pending.
* \param merginProjects List of mergin projects
* \param pendingProjects Projects in pending state
* \param expectedProjectCount Total number of projects
* \param page Int representing page.
*/
void updateModel( const MerginProjectList &merginProjects, QHash<QString, TransactionStatus> pendingProjects, int expectedProjectCount, int page );

int filterCreator() const;
void setFilterCreator( int filterCreator );
Expand All @@ -80,6 +87,12 @@ class MerginProjectModel: public QAbstractListModel
QString searchExpression() const;
void setSearchExpression( const QString &searchExpression );

int lastPage() const;
void setLastPage( int lastPage );

signals:
void lastPageChanged();

public slots:
void syncProjectStatusChanged( const QString &projectFullName, qreal progress );

Expand All @@ -96,6 +109,9 @@ class MerginProjectModel: public QAbstractListModel
ProjectList mMerginProjects;
LocalProjectsManager &mLocalProjects;
QString mSearchExpression;
int mLastPage;
//! Special item as a placeholder for custom component with extended funtionality
std::shared_ptr<MerginProject> mAdditionalItem = std::make_shared<MerginProject>();

};
#endif // MERGINPROJECTMODEL_H
1 change: 1 addition & 0 deletions app/qml/InputStyle.qml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ QtObject {
property real panelOpacity: 1
property real lowHighlightOpacity: 0.4
property real highHighlightOpacity: 0.8
property real cornerRadius: 8 * QgsQuick.Utils.dp

property real refWidth: 640
property real refHeight: 1136
Expand Down
Loading