From e7d76461516df14dcdb2f128d5cde6ef81f545d8 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 26 Jun 2015 15:40:34 +0200 Subject: [PATCH 1/4] QuotaInfo: only request the quota when the UI is visible --- src/gui/accountsettings.cpp | 14 +++++++++---- src/gui/accountsettings.h | 6 ++++-- src/gui/accountstate.cpp | 9 -------- src/gui/accountstate.h | 4 ---- src/gui/quotainfo.cpp | 41 ++++++++++++++++++++++--------------- src/gui/quotainfo.h | 33 +++++++++++++++++++++++------ 6 files changed, 66 insertions(+), 41 deletions(-) diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp index 640f1f87f8..8a3fa0a99f 100644 --- a/src/gui/accountsettings.cpp +++ b/src/gui/accountsettings.cpp @@ -62,7 +62,8 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent) : QWidget(parent), ui(new Ui::AccountSettings), _wasDisabledBefore(false), - _accountState(accountState) + _accountState(accountState), + _quotaInfo(accountState) { ui->setupUi(this); @@ -123,10 +124,8 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent) : connect(_accountState, SIGNAL(stateChanged(int)), SLOT(slotAccountStateChanged(int))); slotAccountStateChanged(_accountState->state()); - QuotaInfo *quotaInfo = _accountState->quotaInfo(); - connect( quotaInfo, SIGNAL(quotaUpdated(qint64,qint64)), + connect( &_quotaInfo, SIGNAL(quotaUpdated(qint64,qint64)), this, SLOT(slotUpdateQuota(qint64,qint64))); - slotUpdateQuota(quotaInfo->lastQuotaTotalBytes(), quotaInfo->lastQuotaUsedBytes()); connect(ui->deleteButton, SIGNAL(clicked()) , this, SLOT(slotDeleteAccount())); @@ -514,5 +513,12 @@ void AccountSettings::slotDeleteAccount() manager->save(); } +bool AccountSettings::event(QEvent* e) +{ + if (e->type() == QEvent::Hide || e->type() == QEvent::Show) { + _quotaInfo.setActive(isVisible()); + } + return QWidget::event(e); +} } // namespace OCC diff --git a/src/gui/accountsettings.h b/src/gui/accountsettings.h index dd6438de14..c7ca0f0a82 100644 --- a/src/gui/accountsettings.h +++ b/src/gui/accountsettings.h @@ -21,6 +21,7 @@ #include #include "folder.h" +#include "quotainfo.h" #include "progressdispatcher.h" class QModelIndex; @@ -76,9 +77,11 @@ protected slots: void slotDeleteAccount(); void refreshSelectiveSyncStatus(); void slotForceRemoteDiscoveryOnFolders(); + void slotCustomContextMenuRequested(const QPoint&); private: void showConnectionLabel( const QString& message, const QString& tooltip = QString() ); + bool event(QEvent*) Q_DECL_OVERRIDE; Ui::AccountSettings *ui; @@ -88,8 +91,7 @@ private: bool _wasDisabledBefore; AccountState *_accountState; QLabel *_quotaLabel; -private slots: - void slotCustomContextMenuRequested(const QPoint&); + QuotaInfo _quotaInfo; }; } // namespace OCC diff --git a/src/gui/accountstate.cpp b/src/gui/accountstate.cpp index e95ec9b387..c8d3ea90ab 100644 --- a/src/gui/accountstate.cpp +++ b/src/gui/accountstate.cpp @@ -12,7 +12,6 @@ */ #include "accountstate.h" -#include "quotainfo.h" #include "accountmanager.h" #include "account.h" #include "creds/abstractcredentials.h" @@ -25,15 +24,12 @@ namespace OCC { AccountState::AccountState(AccountPtr account) : QObject() , _account(account) - , _quotaInfo(0) , _state(AccountState::Disconnected) , _connectionStatus(ConnectionValidator::Undefined) , _waitingForNewCredentials(false) { qRegisterMetaType("AccountState*"); - _quotaInfo = new QuotaInfo(this); // Need to be initialized when 'this' is fully initialized - connect(account.data(), SIGNAL(invalidCredentials()), SLOT(slotInvalidCredentials())); connect(account.data(), SIGNAL(credentialsFetched(AbstractCredentials*)), @@ -134,11 +130,6 @@ bool AccountState::isConnectedOrTemporarilyUnavailable() const return isConnected() || _state == ServiceUnavailable; } -QuotaInfo *AccountState::quotaInfo() -{ - return _quotaInfo; -} - void AccountState::checkConnectivity() { if (isSignedOut() || _waitingForNewCredentials) { diff --git a/src/gui/accountstate.h b/src/gui/accountstate.h index a2c3c60e22..d3a72ce9a9 100644 --- a/src/gui/accountstate.h +++ b/src/gui/accountstate.h @@ -25,7 +25,6 @@ class QSettings; namespace OCC { -class QuotaInfo; class AccountState; class Account; class AbstractCredentials; @@ -82,8 +81,6 @@ public: bool isConnected() const; bool isConnectedOrTemporarilyUnavailable() const; - QuotaInfo *quotaInfo(); - /// Triggers a ping to the server to update state and /// connection status and errors. void checkConnectivity(); @@ -106,7 +103,6 @@ protected Q_SLOTS: private: AccountPtr _account; - QuotaInfo *_quotaInfo; State _state; ConnectionStatus _connectionStatus; QStringList _connectionErrors; diff --git a/src/gui/quotainfo.cpp b/src/gui/quotainfo.cpp index 54746326cb..8098245fe7 100644 --- a/src/gui/quotainfo.cpp +++ b/src/gui/quotainfo.cpp @@ -25,31 +25,39 @@ namespace OCC { namespace { static const int defaultIntervalT = 30*1000; static const int failIntervalT = 5*1000; -static const int initialTimeT = 1*1000; } -QuotaInfo::QuotaInfo(AccountState *accountState) - : QObject(accountState) +QuotaInfo::QuotaInfo(AccountState *accountState, QObject *parent) + : QObject(parent) , _accountState(accountState) , _lastQuotaTotalBytes(0) , _lastQuotaUsedBytes(0) - , _jobRestartTimer(new QTimer(this)) + , _active(false) { connect(accountState, SIGNAL(stateChanged(int)), - SLOT(slotAccountStateChanged(int))); - connect(_jobRestartTimer, SIGNAL(timeout()), SLOT(slotCheckQuota())); - _jobRestartTimer->setSingleShot(true); - if (canGetQuota()) { - _jobRestartTimer->start(initialTimeT); - } + SLOT(slotAccountStateChanged())); + connect(&_jobRestartTimer, SIGNAL(timeout()), SLOT(slotCheckQuota())); + _jobRestartTimer.setSingleShot(true); } -void QuotaInfo::slotAccountStateChanged(int /*state*/) +void QuotaInfo::setActive(bool active) +{ + _active = active; + slotAccountStateChanged(); +} + + +void QuotaInfo::slotAccountStateChanged() { if (canGetQuota()) { - _jobRestartTimer->start(initialTimeT); + if (_lastQuotaRecieved.isNull() + || _lastQuotaRecieved.msecsTo(QDateTime::currentDateTime()) > defaultIntervalT) { + slotCheckQuota(); + } else { + _jobRestartTimer.start(defaultIntervalT); + } } else { - _jobRestartTimer->stop(); + _jobRestartTimer.stop(); } } @@ -57,12 +65,12 @@ void QuotaInfo::slotRequestFailed() { _lastQuotaTotalBytes = 0; _lastQuotaUsedBytes = 0; - _jobRestartTimer->start(failIntervalT); + _jobRestartTimer.start(failIntervalT); } bool QuotaInfo::canGetQuota() const { - if (! _accountState) { + if (! _accountState || !_active) { return false; } AccountPtr account = _accountState->account(); @@ -93,7 +101,8 @@ void QuotaInfo::slotUpdateLastQuota(const QVariantMap &result) _lastQuotaUsedBytes = result["quota-used-bytes"].toDouble(); _lastQuotaTotalBytes = _lastQuotaUsedBytes + avail; emit quotaUpdated(_lastQuotaTotalBytes, _lastQuotaUsedBytes); - _jobRestartTimer->start(defaultIntervalT); + _jobRestartTimer.start(defaultIntervalT); + _lastQuotaRecieved = QDateTime::currentDateTime(); } } diff --git a/src/gui/quotainfo.h b/src/gui/quotainfo.h index 385da011d1..583d1ed04b 100644 --- a/src/gui/quotainfo.h +++ b/src/gui/quotainfo.h @@ -17,27 +17,46 @@ #include #include #include - -class QTimer; +#include +#include namespace OCC { - class AccountState; +/** + * This class handle the getting the quota to display in the UI + * It is typically owned by the AccountSetting page. + * + * The quota is requested if those 3 conditions are met: + * - This object is active via setActive() (typically if the settings page is visible.) + * - The account is connected. + * - Every 30 seconds (defaultIntervalT) or 5 seconds in case of failure (failIntervalT) + * + * We only request the quota when the UI is visible otherwise this might slow down the server with + * too many requests. But we still need to do it every 30 seconds otherwise user complains that the + * quota is not updated fast enough when changed on the server. + */ class QuotaInfo : public QObject { Q_OBJECT public: - QuotaInfo(AccountState *account); + explicit QuotaInfo(OCC::AccountState* accountState, QObject* parent = 0); qint64 lastQuotaTotalBytes() const { return _lastQuotaTotalBytes; } qint64 lastQuotaUsedBytes() const { return _lastQuotaUsedBytes; } + /** + * When the quotainfo is active, it requests the quota at regular interval. + * When setting it to active it will request the quota imediatly if the last time + * the quota was requested was more than the interval + */ + void setActive(bool active); + public Q_SLOTS: void slotCheckQuota(); private Q_SLOTS: void slotUpdateLastQuota(const QVariantMap &); - void slotAccountStateChanged(int state); + void slotAccountStateChanged(); void slotRequestFailed(); Q_SIGNALS: @@ -49,7 +68,9 @@ private: QPointer _accountState; qint64 _lastQuotaTotalBytes; qint64 _lastQuotaUsedBytes; - QTimer *_jobRestartTimer; + QTimer _jobRestartTimer; + QDateTime _lastQuotaRecieved; // the time at which de quota was recieved last + bool _active; // if we should check at regular interval (when the UI is visible) }; From 236951d9b33c4fe899e23b20cfee2b34ee8566aa Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 26 Jun 2015 16:58:34 +0200 Subject: [PATCH 2/4] QuotaInfo: allow only one job at the same time --- src/gui/quotainfo.cpp | 15 ++++++++++----- src/gui/quotainfo.h | 2 ++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/gui/quotainfo.cpp b/src/gui/quotainfo.cpp index 8098245fe7..0b2475f6c4 100644 --- a/src/gui/quotainfo.cpp +++ b/src/gui/quotainfo.cpp @@ -85,12 +85,17 @@ void QuotaInfo::slotCheckQuota() return; } + if (_job) { + // The previous job was not finished? Then we cancel it! + _job->deleteLater(); + } + AccountPtr account = _accountState->account(); - PropfindJob *job = new PropfindJob(account, "/", this); - job->setProperties(QList() << "quota-available-bytes" << "quota-used-bytes"); - connect(job, SIGNAL(result(QVariantMap)), SLOT(slotUpdateLastQuota(QVariantMap))); - connect(job, SIGNAL(networkError(QNetworkReply*)), SLOT(slotRequestFailed())); - job->start(); + _job = new PropfindJob(account, "/", this); + _job->setProperties(QList() << "quota-available-bytes" << "quota-used-bytes"); + connect(_job, SIGNAL(result(QVariantMap)), SLOT(slotUpdateLastQuota(QVariantMap))); + connect(_job, SIGNAL(networkError(QNetworkReply*)), SLOT(slotRequestFailed())); + _job->start(); } void QuotaInfo::slotUpdateLastQuota(const QVariantMap &result) diff --git a/src/gui/quotainfo.h b/src/gui/quotainfo.h index 583d1ed04b..cfd2b312c4 100644 --- a/src/gui/quotainfo.h +++ b/src/gui/quotainfo.h @@ -22,6 +22,7 @@ namespace OCC { class AccountState; +class PropfindJob; /** * This class handle the getting the quota to display in the UI @@ -71,6 +72,7 @@ private: QTimer _jobRestartTimer; QDateTime _lastQuotaRecieved; // the time at which de quota was recieved last bool _active; // if we should check at regular interval (when the UI is visible) + QPointer _job; // the currently running job }; From 51c10de6721ab792e5144fa6911865fc50ad3e9f Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 26 Jun 2015 18:04:27 +0200 Subject: [PATCH 3/4] QuotaInfo: make sure that we always check the quota every 30 seconds --- src/gui/quotainfo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/quotainfo.cpp b/src/gui/quotainfo.cpp index 0b2475f6c4..9035a1c9e6 100644 --- a/src/gui/quotainfo.cpp +++ b/src/gui/quotainfo.cpp @@ -50,11 +50,11 @@ void QuotaInfo::setActive(bool active) void QuotaInfo::slotAccountStateChanged() { if (canGetQuota()) { - if (_lastQuotaRecieved.isNull() - || _lastQuotaRecieved.msecsTo(QDateTime::currentDateTime()) > defaultIntervalT) { + auto elapsed = _lastQuotaRecieved.msecsTo(QDateTime::currentDateTime()); + if (_lastQuotaRecieved.isNull() || elapsed >= defaultIntervalT) { slotCheckQuota(); } else { - _jobRestartTimer.start(defaultIntervalT); + _jobRestartTimer.start(defaultIntervalT - elapsed); } } else { _jobRestartTimer.stop(); From 23ccaa28216711f0a4883689275335c9d0f1f2cc Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 29 Jun 2015 10:57:32 +0200 Subject: [PATCH 4/4] QuotaInfo: add a comment about long running job To document the change made two commits ago --- src/gui/quotainfo.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/quotainfo.h b/src/gui/quotainfo.h index cfd2b312c4..8b9377f943 100644 --- a/src/gui/quotainfo.h +++ b/src/gui/quotainfo.h @@ -36,6 +36,8 @@ class PropfindJob; * We only request the quota when the UI is visible otherwise this might slow down the server with * too many requests. But we still need to do it every 30 seconds otherwise user complains that the * quota is not updated fast enough when changed on the server. + * + * If the quota job is not finished within 30 seconds, it is cancelled and another one is started */ class QuotaInfo : public QObject { Q_OBJECT