From e7d76461516df14dcdb2f128d5cde6ef81f545d8 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 26 Jun 2015 15:40:34 +0200 Subject: [PATCH 1/7] 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/7] 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 516509b4ed5d9f23b491a7a0f8c02deeb7a0e697 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 26 Jun 2015 17:01:43 +0200 Subject: [PATCH 3/7] csync_statedb: fix leak Spotted by coverity (CID 98061) --- csync/src/csync_statedb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/csync/src/csync_statedb.c b/csync/src/csync_statedb.c index 49c098dc71..779bb34046 100644 --- a/csync/src/csync_statedb.c +++ b/csync/src/csync_statedb.c @@ -491,6 +491,7 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) { if (excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE || excluded == CSYNC_FILE_SILENTLY_EXCLUDED) { + SAFE_FREE(st); continue; } From 51c10de6721ab792e5144fa6911865fc50ad3e9f Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 26 Jun 2015 18:04:27 +0200 Subject: [PATCH 4/7] 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 5/7] 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 From 7a324ff25b7b6decb1e33450fe5b745299646182 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 29 Jun 2015 14:53:37 +0200 Subject: [PATCH 6/7] Utility: improve the function to conver a duration to string - Make it translatable - Make use of the %n so that it supports plurals (but this will only take effect if we have an english translation) - Only put two units. eg: "5 years 7 months" instead of "5 years 7 months 12 days 34 minutes 23 seconds" Even when it is "2 hours 23 minutes" the amount of second does not matter, especially since the estimation is likely to be boggus anyway Issues #2672 and #3097 --- src/gui/folderstatusmodel.cpp | 4 +-- src/gui/owncloudgui.cpp | 5 ++- src/libsync/utility.cpp | 68 +++++++++++++++++------------------ src/libsync/utility.h | 6 ++-- test/testutility.h | 28 +++++++++++++++ 5 files changed, 67 insertions(+), 44 deletions(-) diff --git a/src/gui/folderstatusmodel.cpp b/src/gui/folderstatusmodel.cpp index 92dcba5f26..8b654a1f69 100644 --- a/src/gui/folderstatusmodel.cpp +++ b/src/gui/folderstatusmodel.cpp @@ -645,7 +645,7 @@ void FolderStatusModel::slotSetProgress(const ProgressInfo &progress) //: Example text: "uploading foobar.png (1MB of 2MB) time left 2 minutes at a rate of 24Kb/s" fileProgressString = tr("%1 %2 (%3 of %4) %5 left at a rate of %6/s") .arg(kindString, itemFileName, s1, s2, - Utility::timeToDescriptiveString(progress.fileProgress(curItem).estimatedEta, 3, " ", true), + Utility::durationToDescriptiveString(progress.fileProgress(curItem).estimatedEta), Utility::octetsToString(estimatedBw) ); } else { //: Example text: "uploading foobar.png (2MB of 2MB)" @@ -672,7 +672,7 @@ void FolderStatusModel::slotSetProgress(const ProgressInfo &progress) overallSyncString = tr("%1 of %2, file %3 of %4\nTotal time left %5") .arg(s1, s2) .arg(currentFile).arg(totalFileCount) - .arg( Utility::timeToDescriptiveString(progress.totalProgress().estimatedEta, 3, " ", true) ); + .arg( Utility::durationToDescriptiveString(progress.totalProgress().estimatedEta) ); } else if (totalFileCount > 0) { // Don't attemt to estimate the time left if there is no kb to transfer. overallSyncString = tr("file %1 of %2") .arg(currentFile).arg(totalFileCount); diff --git a/src/gui/owncloudgui.cpp b/src/gui/owncloudgui.cpp index 39b6af7b09..bdf8dab033 100644 --- a/src/gui/owncloudgui.cpp +++ b/src/gui/owncloudgui.cpp @@ -476,12 +476,11 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo& quint64 totalFileCount = qMax(progress.totalFiles(), currentFile); _actionStatus->setText( tr("Syncing %1 of %2 (%3 left)") .arg( currentFile ).arg( totalFileCount ) - .arg( Utility::timeToDescriptiveString(progress.totalProgress().estimatedEta, 2, " ",true) ) ); + .arg( Utility::durationToDescriptiveString(progress.totalProgress().estimatedEta) ) ); } else { QString totalSizeStr = Utility::octetsToString( progress.totalSize() ); _actionStatus->setText( tr("Syncing %1 (%2 left)") - .arg( totalSizeStr ) - .arg( Utility::timeToDescriptiveString(progress.totalProgress().estimatedEta, 2, " ",true) ) ); + .arg( totalSizeStr, Utility::durationToDescriptiveString(progress.totalProgress().estimatedEta) ) ); } diff --git a/src/libsync/utility.cpp b/src/libsync/utility.cpp index a9cb284148..fa13c99d2e 100644 --- a/src/libsync/utility.cpp +++ b/src/libsync/utility.cpp @@ -304,45 +304,43 @@ static QList > timeMapping = QList QPair("%1h",3600) << QPair("%1m",60) << QPair("%1s",1); - - -QString Utility::timeToDescriptiveString(quint64 msecs, quint8 precision, QString separator, bool specific) -{ - return timeToDescriptiveString( timeMapping , msecs, precision, separator, specific); -} +QString Utility::durationToDescriptiveString(quint64 msecs) +{ + struct Period { const char *name; quint64 msec; }; + Q_DECL_CONSTEXPR const Period periods[] = { + { QT_TRANSLATE_NOOP("Utility", "%Ln year(s)") , 365*24*3600*1000L }, + { QT_TRANSLATE_NOOP("Utility", "%Ln month(s)") , 30*24*3600*1000L }, + { QT_TRANSLATE_NOOP("Utility", "%Ln day(s)") , 24*3600*1000L }, + { QT_TRANSLATE_NOOP("Utility", "%Ln hour(s)") , 3600*1000L }, + { QT_TRANSLATE_NOOP("Utility", "%Ln minute(s)") , 60*1000L }, + { QT_TRANSLATE_NOOP("Utility", "%Ln second(s)") , 1000L }, + { 0, 0 } + }; -QString Utility::timeToDescriptiveString(QList > &timeMapping, quint64 msecs, quint8 precision, QString separator, bool specific) -{ - quint64 secs = msecs / 1000; - QString retStr = QString(timeMapping.last().first).arg(0); // default value in case theres no actual time in msecs. - QList > values; - bool timeStartFound = false; - - for(QList >::Iterator itr = timeMapping.begin(); itr != timeMapping.end() && precision > 0; itr++) { - quint64 result = secs / itr->second; - if(!timeStartFound) { - if(result == 0 ) { - continue; - } - retStr = ""; - timeStartFound= true; - } - secs -= result * itr->second; - values.append(QPair(itr->first,result)); - precision--; + int p = 0; + while (periods[p].name && msecs < periods[p].msec) { + p++; } - - for(QList >::Iterator itr = values.begin(); itr < values.end(); itr++) { - retStr = retStr.append((specific || itr == values.end()-1) ? itr->first : "%1").arg(itr->second, (itr == values.begin() ? 1 :2 ), 10, QChar('0')); - if(itr < values.end()-1) { - retStr.append(separator); - } - - + + if (!periods[p].name) { + return QCoreApplication::translate("Utility", "0 seconds"); } - - return retStr; + + auto firstPart = QCoreApplication::translate("Utility", periods[p].name, 0, int(msecs / periods[p].msec)); + + if (!periods[p+1].name) { + return firstPart; + } + + quint64 secondPartNum = qRound( double(msecs % periods[p].msec) / periods[p+1].msec); + + if (secondPartNum == 0) { + return firstPart; + } + + return QCoreApplication::translate("Utility", "%1 %2").arg(firstPart, + QCoreApplication::translate("Utility", periods[p+1].name, 0, secondPartNum)); } bool Utility::hasDarkSystray() diff --git a/src/libsync/utility.h b/src/libsync/utility.h index 272dc89629..91c05b4fa0 100644 --- a/src/libsync/utility.h +++ b/src/libsync/utility.h @@ -61,13 +61,11 @@ namespace Utility OWNCLOUDSYNC_EXPORT qint64 qDateTimeToTime_t(const QDateTime &t); /** - * @brief Convert milliseconds to HMS string. + * @brief Convert milliseconds duration to human readable string. * @param quint64 msecs the milliseconds to convert to string. - * @param uint precision the amount of sub dviving scale to include in the result. * @return an HMS representation of the milliseconds value. */ - OWNCLOUDSYNC_EXPORT QString timeToDescriptiveString(QList > &timeMapping, quint64 msecs, quint8 precision, QString separator, bool specific); - OWNCLOUDSYNC_EXPORT QString timeToDescriptiveString(quint64 msecs, quint8 precision, QString separator, bool specific); + OWNCLOUDSYNC_EXPORT QString durationToDescriptiveString(quint64 msecs); /** * @brief hasDarkSystray - determines whether the systray is dark or light. diff --git a/test/testutility.h b/test/testutility.h index 95a4d467c2..8d29dad81b 100644 --- a/test/testutility.h +++ b/test/testutility.h @@ -75,6 +75,34 @@ private slots: QVERIFY(toCSyncScheme("https://example.com/owncloud/") == "ownclouds://example.com/owncloud/"); } + + void testDurationToDescriptiveString() + { + QLocale::setDefault(QLocale("C")); + //NOTE: in order for the plural to work we would need to load the english translation + + quint64 sec = 1000; + quint64 hour = 3600 * sec; + + QDateTime current = QDateTime::currentDateTime(); + + QCOMPARE(durationToDescriptiveString(0), QString("0 seconds") ); + QCOMPARE(durationToDescriptiveString(5), QString("0 seconds") ); + QCOMPARE(durationToDescriptiveString(1000), QString("1 second(s)") ); + QCOMPARE(durationToDescriptiveString(1005), QString("1 second(s)") ); + QCOMPARE(durationToDescriptiveString(56123), QString("56 second(s)") ); + QCOMPARE(durationToDescriptiveString(90*sec), QString("1 minute(s) 30 second(s)") ); + QCOMPARE(durationToDescriptiveString(3*hour), QString("3 hour(s)") ); + QCOMPARE(durationToDescriptiveString(3*hour + 20*sec), QString("3 hour(s)") ); + QCOMPARE(durationToDescriptiveString(3*hour + 70*sec), QString("3 hour(s) 1 minute(s)") ); + QCOMPARE(durationToDescriptiveString(3*hour + 100*sec), QString("3 hour(s) 2 minute(s)") ); + QCOMPARE(durationToDescriptiveString(current.msecsTo(current.addYears(4).addMonths(5).addDays(2).addSecs(23*60*60))), + QString("4 year(s) 5 month(s)") ); + QCOMPARE(durationToDescriptiveString(current.msecsTo(current.addDays(2).addSecs(23*60*60))), + QString("2 day(s) 23 hour(s)") ); + + + } }; #endif From ef1e6add4f0ded7d4890361ec63dcd2c4b14c288 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 29 Jun 2015 17:43:25 +0200 Subject: [PATCH 7/7] Settings: Auto download bandwidth limit #1485 --- src/gui/networksettings.cpp | 31 +++++++--- src/gui/networksettings.ui | 96 ++++++++++++++----------------- src/libsync/configfile.cpp | 8 +-- src/libsync/configfile.h | 4 +- src/libsync/propagatedownload.cpp | 2 +- 5 files changed, 73 insertions(+), 68 deletions(-) diff --git a/src/gui/networksettings.cpp b/src/gui/networksettings.cpp index f70cc30e28..8612b6d371 100644 --- a/src/gui/networksettings.cpp +++ b/src/gui/networksettings.cpp @@ -63,6 +63,7 @@ NetworkSettings::NetworkSettings(QWidget *parent) : connect(_ui->autoUploadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings())); connect(_ui->downloadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings())); connect(_ui->noDownloadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings())); + connect(_ui->autoDownloadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings())); connect(_ui->downloadSpinBox, SIGNAL(valueChanged(int)), SLOT(saveBWLimitSettings())); connect(_ui->uploadSpinBox, SIGNAL(valueChanged(int)), SLOT(saveBWLimitSettings())); } @@ -109,16 +110,25 @@ void NetworkSettings::loadProxySettings() void NetworkSettings::loadBWLimitSettings() { ConfigFile cfgFile; - _ui->downloadLimitRadioButton->setChecked(cfgFile.useDownloadLimit()); - int uploadLimit = cfgFile.useUploadLimit(); - if ( uploadLimit >= 1 ) { + + int useDownloadLimit = cfgFile.useDownloadLimit(); + if ( useDownloadLimit >= 1 ) { + _ui->downloadLimitRadioButton->setChecked(true); + } else if (useDownloadLimit == 0){ + _ui->noDownloadLimitRadioButton->setChecked(true); + } else { + _ui->autoDownloadLimitRadioButton->setChecked(true); + } + _ui->downloadSpinBox->setValue(cfgFile.downloadLimit()); + + int useUploadLimit = cfgFile.useUploadLimit(); + if ( useUploadLimit >= 1 ) { _ui->uploadLimitRadioButton->setChecked(true); - } else if (uploadLimit == 0){ + } else if (useUploadLimit == 0){ _ui->noUploadLimitRadioButton->setChecked(true); } else { _ui->autoUploadLimitRadioButton->setChecked(true); } - _ui->downloadSpinBox->setValue(cfgFile.downloadLimit()); _ui->uploadSpinBox->setValue(cfgFile.uploadLimit()); } @@ -151,7 +161,14 @@ void NetworkSettings::saveProxySettings() void NetworkSettings::saveBWLimitSettings() { ConfigFile cfgFile; - cfgFile.setUseDownloadLimit(_ui->downloadLimitRadioButton->isChecked()); + if (_ui->downloadLimitRadioButton->isChecked()) { + cfgFile.setUseDownloadLimit(1); + } else if (_ui->noDownloadLimitRadioButton->isChecked()) { + cfgFile.setUseDownloadLimit(0); + } else if (_ui->autoDownloadLimitRadioButton->isChecked()) { + cfgFile.setUseDownloadLimit(-1); + } + cfgFile.setDownloadLimit(_ui->downloadSpinBox->value()); if (_ui->uploadLimitRadioButton->isChecked()) { cfgFile.setUseUploadLimit(1); @@ -160,8 +177,6 @@ void NetworkSettings::saveBWLimitSettings() } else if (_ui->autoUploadLimitRadioButton->isChecked()) { cfgFile.setUseUploadLimit(-1); } - - cfgFile.setDownloadLimit(_ui->downloadSpinBox->value()); cfgFile.setUploadLimit(_ui->uploadSpinBox->value()); FolderMan::instance()->setDirtyNetworkLimits(); diff --git a/src/gui/networksettings.ui b/src/gui/networksettings.ui index cd0ba71e05..56eb1cacbf 100644 --- a/src/gui/networksettings.ui +++ b/src/gui/networksettings.ui @@ -6,8 +6,8 @@ 0 0 - 518 - 384 + 542 + 391 @@ -104,7 +104,7 @@ - true + false @@ -141,13 +141,22 @@ false - + + 0 + + + 0 + + + 0 + + 0 - true + false @@ -157,7 +166,7 @@ - true + false @@ -190,14 +199,37 @@ Download Bandwidth - + Limit to - + + + + No limit + + + true + + + + + + + Qt::Vertical + + + + 147 + 25 + + + + + @@ -221,42 +253,13 @@ - - + + - No limit - - - true + Limit automatically - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - 147 - 25 - - - - @@ -323,19 +326,6 @@ - - - - Qt::Horizontal - - - - 40 - 20 - - - - autoUploadLimitRadioButton uploadLimitRadioButton diff --git a/src/libsync/configfile.cpp b/src/libsync/configfile.cpp index d3c39c0c72..c5f0568b9a 100644 --- a/src/libsync/configfile.cpp +++ b/src/libsync/configfile.cpp @@ -514,9 +514,9 @@ int ConfigFile::useUploadLimit() const return getValue(useUploadLimitC, QString::null, 0).toInt(); } -bool ConfigFile::useDownloadLimit() const +int ConfigFile::useDownloadLimit() const { - return getValue(useDownloadLimitC, QString::null, false).toBool(); + return getValue(useDownloadLimitC, QString::null, 0).toInt(); } void ConfigFile::setUseUploadLimit(int val) @@ -524,9 +524,9 @@ void ConfigFile::setUseUploadLimit(int val) setValue(useUploadLimitC, val); } -void ConfigFile::setUseDownloadLimit(bool enable) +void ConfigFile::setUseDownloadLimit(int val) { - setValue(useDownloadLimitC, enable); + setValue(useDownloadLimitC, val); } int ConfigFile::uploadLimit() const diff --git a/src/libsync/configfile.h b/src/libsync/configfile.h index d1af84c552..55bde5d202 100644 --- a/src/libsync/configfile.h +++ b/src/libsync/configfile.h @@ -87,9 +87,9 @@ public: /** 0: no limit, 1: manual, >0: automatic */ int useUploadLimit() const; - bool useDownloadLimit() const; + int useDownloadLimit() const; void setUseUploadLimit(int); - void setUseDownloadLimit(bool); + void setUseDownloadLimit(int); /** in kbyte/s */ int uploadLimit() const; int downloadLimit() const; diff --git a/src/libsync/propagatedownload.cpp b/src/libsync/propagatedownload.cpp index a1dff6e0b3..936b4eff14 100644 --- a/src/libsync/propagatedownload.cpp +++ b/src/libsync/propagatedownload.cpp @@ -242,7 +242,7 @@ void GETFileJob::slotReadyRead() if (_bandwidthLimited) { toRead = qMin(qint64(bufferSize), _bandwidthQuota); if (toRead == 0) { - qDebug() << Q_FUNC_INFO << "Out of quota"; + //qDebug() << Q_FUNC_INFO << "Out of quota"; break; } _bandwidthQuota -= toRead;