Skip to content
Open
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
74 changes: 74 additions & 0 deletions src/core/qfieldcloud/qfieldcloudconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,78 @@ QFieldCloudConnection::QFieldCloudConnection()
mTokenConfigId.clear();
QSettings().remove( "/QFieldCloud/tokenConfigId" );
}

QNetworkInformation::loadBackendByFeatures( QNetworkInformation::Feature::Reachability );
mNetworkInfo = QNetworkInformation::instance();

if ( mNetworkInfo )
{
connect( mNetworkInfo, &QNetworkInformation::reachabilityChanged, this,
[this]( QNetworkInformation::Reachability ) {
emit reachabilityToCloudChanged();
tryFlushQueuedProjectPushes();
} );
}
}


void QFieldCloudConnection::queueProjectPush( const QString &projectId, const bool shouldDownloadUpdates )
{
if ( projectId.isEmpty() )
return;

// merge flag so "true" wins
mQueuedProjectPushes[projectId] = mQueuedProjectPushes.value( projectId, false ) || shouldDownloadUpdates;

tryFlushQueuedProjectPushes();
}

void QFieldCloudConnection::tryFlushQueuedProjectPushes()
{
if ( mIsFlushingQueuedProjectPushes )
return;

if ( mQueuedProjectPushes.isEmpty() )
return;

if ( status() != ConnectionStatus::LoggedIn )
return;

if ( !isReachableToCloud() )
return;

mIsFlushingQueuedProjectPushes = true;

const auto queued = mQueuedProjectPushes;
mQueuedProjectPushes.clear();

for ( auto it = queued.cbegin(); it != queued.cend(); ++it )
emit queuedProjectPush( it.key(), it.value() );

mIsFlushingQueuedProjectPushes = false;
}

bool QFieldCloudConnection::isReachableToCloud() const
{
if ( !mNetworkInfo || !mNetworkInfo->supports( QNetworkInformation::Feature::Reachability ) )
{
// No backend or no reachability support, dont change behaviour
return true;
}

switch ( mNetworkInfo->reachability() )
{
case QNetworkInformation::Reachability::Online:
case QNetworkInformation::Reachability::Unknown:
return true;

case QNetworkInformation::Reachability::Disconnected:
case QNetworkInformation::Reachability::Local:
case QNetworkInformation::Reachability::Site:
return false;
}

return true;
}

QMap<QString, QString> QFieldCloudConnection::sErrors = QMap<QString, QString>(
Expand Down Expand Up @@ -155,6 +227,7 @@ void QFieldCloudConnection::setUsername( const QString &username )
if ( mUsername == username )
return;

mQueuedProjectPushes.clear();
mUsername = username;

if ( mStatus != ConnectionStatus::Disconnected )
Expand Down Expand Up @@ -603,6 +676,7 @@ void QFieldCloudConnection::setToken( const QByteArray &token )

void QFieldCloudConnection::invalidateToken()
{
mQueuedProjectPushes.clear();
if ( mToken.isNull() )
return;

Expand Down
14 changes: 14 additions & 0 deletions src/core/qfieldcloud/qfieldcloudconnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
#include "networkreply.h"
#include "qfieldcloudutils.h"

#include <QHash>
#include <QJsonDocument>
#include <QNetworkInformation>
#include <QObject>
#include <QVariantMap>

Expand Down Expand Up @@ -218,6 +220,10 @@ class QFieldCloudConnection : public QObject
*/
qsizetype uploadPendingAttachments();

bool isReachableToCloud() const;
void queueProjectPush( const QString &projectId, const bool shouldDownloadUpdates );
void tryFlushQueuedProjectPushes();

signals:
void providerChanged();
void usernameChanged();
Expand All @@ -240,6 +246,9 @@ class QFieldCloudConnection : public QObject
void availableProvidersChanged();
void isFetchingAvailableProvidersChanged();

void reachabilityToCloudChanged();
void queuedProjectPush( const QString &projectId, const bool shouldDownloadUpdates );

private:
void setStatus( ConnectionStatus status );
void setState( ConnectionState state );
Expand Down Expand Up @@ -271,6 +280,11 @@ class QFieldCloudConnection : public QObject
qsizetype mUploadFailingCount = 0;

void setClientHeaders( QNetworkRequest &request );

QHash<QString, bool> mQueuedProjectPushes;
bool mIsFlushingQueuedProjectPushes = false;

const QNetworkInformation *mNetworkInfo = nullptr;
};

#endif // QFIELDCLOUDCONNECTION_H
26 changes: 24 additions & 2 deletions src/core/qfieldcloud/qfieldcloudprojectsmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,16 @@
QFieldCloudProjectsModel::QFieldCloudProjectsModel()
{
// TODO all of these connects are a bit too much, and I guess not very precise, should be refactored!

connect( this, &QFieldCloudProjectsModel::dataChanged, this, [this]( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles ) {
Q_UNUSED( bottomRight )
Q_UNUSED( roles )

if ( roles.isEmpty() || roles.contains( StatusRole ) )
{
emit busyProjectIdsChanged();

if ( mCloudConnection )
mCloudConnection->tryFlushQueuedProjectPushes();
}
} );
}
Expand All @@ -67,6 +69,7 @@ void QFieldCloudProjectsModel::setCloudConnection( QFieldCloudConnection *cloudC
disconnect( mCloudConnection, &QFieldCloudConnection::statusChanged, this, &QFieldCloudProjectsModel::connectionStatusChanged );
disconnect( mCloudConnection, &QFieldCloudConnection::usernameChanged, this, &QFieldCloudProjectsModel::usernameChanged );
disconnect( mCloudConnection, &QFieldCloudConnection::urlChanged, this, &QFieldCloudProjectsModel::urlChanged );
disconnect( mCloudConnection, &QFieldCloudConnection::queuedProjectPush, this, &QFieldCloudProjectsModel::projectPush );
}

mCloudConnection = cloudConnection;
Expand All @@ -76,10 +79,12 @@ void QFieldCloudProjectsModel::setCloudConnection( QFieldCloudConnection *cloudC
connect( mCloudConnection, &QFieldCloudConnection::statusChanged, this, &QFieldCloudProjectsModel::connectionStatusChanged );
connect( mCloudConnection, &QFieldCloudConnection::usernameChanged, this, &QFieldCloudProjectsModel::usernameChanged );
connect( mCloudConnection, &QFieldCloudConnection::urlChanged, this, &QFieldCloudProjectsModel::urlChanged );
connect( mCloudConnection, &QFieldCloudConnection::queuedProjectPush, this, &QFieldCloudProjectsModel::projectPush );

mUsername = mCloudConnection->username();
mUrl = mCloudConnection->url();
resetProjects();
mCloudConnection->tryFlushQueuedProjectPushes();
}

emit cloudConnectionChanged();
Expand Down Expand Up @@ -323,9 +328,26 @@ void QFieldCloudProjectsModel::projectPush( const QString &projectId, const bool
return;

QFieldCloudProject *project = mProjects[projectIndex.row()];
if ( !project )
return;

// If the network is not active, queue the push and warn the user.
if ( !mCloudConnection || !mCloudConnection->isReachableToCloud() )
{
if ( mCloudConnection )
mCloudConnection->queueProjectPush( projectId, shouldDownloadUpdates );

if ( !( project->status() == QFieldCloudProject::ProjectStatus::Idle ) )
emit warning( tr( "Network is not currently active. "
"We will push the changes automatically once you are back online." ) );
return;
}

if ( project->status() != QFieldCloudProject::ProjectStatus::Idle )
{
// if user requested push while busy, schedule it
mCloudConnection->queueProjectPush( projectId, shouldDownloadUpdates );
return;
}

project->push( shouldDownloadUpdates );
}
Expand Down
1 change: 1 addition & 0 deletions src/core/qfieldcloud/qfieldcloudprojectsmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "qgsgpkgflusher.h"

#include <QAbstractListModel>
#include <QHash>
#include <QJsonArray>
#include <QNetworkReply>
#include <QPointer>
Expand Down
Loading