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; } 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 6f6bb63962..0ce4e64253 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; @@ -80,9 +81,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; @@ -92,8 +95,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 ddc5c00c02..7efc905c7c 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; @@ -83,8 +82,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(); @@ -105,7 +102,6 @@ protected Q_SLOTS: private: AccountPtr _account; - QuotaInfo *_quotaInfo; State _state; ConnectionStatus _connectionStatus; QStringList _connectionErrors; 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/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/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/gui/quotainfo.cpp b/src/gui/quotainfo.cpp index 54746326cb..9035a1c9e6 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); + auto elapsed = _lastQuotaRecieved.msecsTo(QDateTime::currentDateTime()); + if (_lastQuotaRecieved.isNull() || elapsed >= defaultIntervalT) { + slotCheckQuota(); + } else { + _jobRestartTimer.start(defaultIntervalT - elapsed); + } } 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(); @@ -77,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) @@ -93,7 +106,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 bb1912857c..286bfca6ef 100644 --- a/src/gui/quotainfo.h +++ b/src/gui/quotainfo.h @@ -17,31 +17,52 @@ #include #include #include - -class QTimer; +#include +#include namespace OCC { - class AccountState; +class PropfindJob; /*! - * \brief The QuotaInfo class + * \brief handles 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. + * + * If the quota job is not finished within 30 seconds, it is cancelled and another one is started + * * \ingroup gui */ 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: @@ -53,7 +74,10 @@ 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) + QPointer _job; // the currently running job }; 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 cf9976af47..43524efaf2 100644 --- a/src/libsync/configfile.h +++ b/src/libsync/configfile.h @@ -91,9 +91,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; 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 7773f04b0d..957f5e2154 100644 --- a/src/libsync/utility.h +++ b/src/libsync/utility.h @@ -64,13 +64,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