| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 |
- /*
- * Copyright (C) by Felix Weilbach <felix.weilbach@nextcloud.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
- #include "syncstatussummary.h"
- #include "accountfwd.h"
- #include "folderman.h"
- #include "navigationpanehelper.h"
- #include "networkjobs.h"
- #include "syncresult.h"
- #include "tray/usermodel.h"
- #include <theme.h>
- namespace {
- OCC::SyncResult::Status determineSyncStatus(const OCC::SyncResult &syncResult)
- {
- const auto status = syncResult.status();
- if (status == OCC::SyncResult::Success || status == OCC::SyncResult::Problem) {
- if (syncResult.hasUnresolvedConflicts()) {
- return OCC::SyncResult::Problem;
- }
- return OCC::SyncResult::Success;
- } else if (status == OCC::SyncResult::SyncPrepare || status == OCC::SyncResult::Undefined) {
- return OCC::SyncResult::SyncRunning;
- }
- return status;
- }
- }
- namespace OCC {
- Q_LOGGING_CATEGORY(lcSyncStatusModel, "nextcloud.gui.syncstatusmodel", QtInfoMsg)
- SyncStatusSummary::SyncStatusSummary(QObject *parent)
- : QObject(parent)
- {
- const auto folderMan = FolderMan::instance();
- connect(folderMan, &FolderMan::folderListChanged, this, &SyncStatusSummary::onFolderListChanged);
- connect(folderMan, &FolderMan::folderSyncStateChange, this, &SyncStatusSummary::onFolderSyncStateChanged);
- }
- bool SyncStatusSummary::reloadNeeded(AccountState *accountState) const
- {
- if (_accountState.data() == accountState) {
- return false;
- }
- return true;
- }
- void SyncStatusSummary::load()
- {
- const auto currentUser = UserModel::instance()->currentUser();
- if (!currentUser) {
- return;
- }
- setAccountState(currentUser->accountState());
- clearFolderErrors();
- connectToFoldersProgress(FolderMan::instance()->map());
- initSyncState();
- }
- double SyncStatusSummary::syncProgress() const
- {
- return _progress;
- }
- QUrl SyncStatusSummary::syncIcon() const
- {
- return _syncIcon;
- }
- bool SyncStatusSummary::syncing() const
- {
- return _isSyncing;
- }
- void SyncStatusSummary::onFolderListChanged(const OCC::Folder::Map &folderMap)
- {
- connectToFoldersProgress(folderMap);
- }
- void SyncStatusSummary::markFolderAsError(const Folder *folder)
- {
- _foldersWithErrors.insert(folder->alias());
- }
- void SyncStatusSummary::markFolderAsSuccess(const Folder *folder)
- {
- _foldersWithErrors.erase(folder->alias());
- }
- bool SyncStatusSummary::folderErrors() const
- {
- return _foldersWithErrors.size() != 0;
- }
- bool SyncStatusSummary::folderError(const Folder *folder) const
- {
- return _foldersWithErrors.find(folder->alias()) != _foldersWithErrors.end();
- }
- void SyncStatusSummary::clearFolderErrors()
- {
- _foldersWithErrors.clear();
- }
- void SyncStatusSummary::setSyncStateForFolder(const Folder *folder)
- {
- if (_accountState && !_accountState->isConnected()) {
- setSyncing(false);
- setSyncStatusString(tr("Offline"));
- setSyncStatusDetailString("");
- setSyncIcon(Theme::instance()->folderOffline());
- return;
- }
- const auto state = determineSyncStatus(folder->syncResult());
- switch (state) {
- case SyncResult::Success:
- case SyncResult::SyncPrepare:
- // Success should only be shown if all folders were fine
- if (!folderErrors() || folderError(folder)) {
- setSyncing(false);
- setSyncStatusString(tr("All synced!"));
- setSyncStatusDetailString("");
- setSyncIcon(Theme::instance()->syncStatusOk());
- markFolderAsSuccess(folder);
- }
- break;
- case SyncResult::Error:
- case SyncResult::SetupError:
- setSyncing(false);
- setSyncStatusString(tr("Some files couldn't be synced!"));
- setSyncStatusDetailString(tr("See below for errors"));
- setSyncIcon(Theme::instance()->syncStatusError());
- markFolderAsError(folder);
- break;
- case SyncResult::SyncRunning:
- case SyncResult::NotYetStarted:
- setSyncing(true);
- setSyncStatusString(tr("Syncing"));
- setSyncStatusDetailString("");
- setSyncIcon(Theme::instance()->syncStatusRunning());
- break;
- case SyncResult::Paused:
- case SyncResult::SyncAbortRequested:
- setSyncing(false);
- setSyncStatusString(tr("Sync paused"));
- setSyncStatusDetailString("");
- setSyncIcon(Theme::instance()->syncStatusPause());
- break;
- case SyncResult::Problem:
- case SyncResult::Undefined:
- setSyncing(false);
- setSyncStatusString(tr("Some files could not be synced!"));
- setSyncStatusDetailString(tr("See below for warnings"));
- setSyncIcon(Theme::instance()->syncStatusWarning());
- markFolderAsError(folder);
- break;
- }
- }
- void SyncStatusSummary::onFolderSyncStateChanged(const Folder *folder)
- {
- if (!folder) {
- return;
- }
- if (!_accountState || folder->accountState() != _accountState.data()) {
- return;
- }
- setSyncStateForFolder(folder);
- }
- constexpr double calculateOverallPercent(
- qint64 totalFileCount, qint64 completedFile, qint64 totalSize, qint64 completedSize)
- {
- int overallPercent = 0;
- if (totalFileCount > 0) {
- // Add one 'byte' for each file so the percentage is moving when deleting or renaming files
- overallPercent = qRound(double(completedSize + completedFile) / double(totalSize + totalFileCount) * 100.0);
- }
- overallPercent = qBound(0, overallPercent, 100);
- return overallPercent / 100.0;
- }
- void SyncStatusSummary::onFolderProgressInfo(const ProgressInfo &progress)
- {
- const qint64 completedSize = progress.completedSize();
- const qint64 currentFile = progress.currentFile();
- const qint64 completedFile = progress.completedFiles();
- const qint64 totalSize = qMax(completedSize, progress.totalSize());
- const qint64 totalFileCount = qMax(currentFile, progress.totalFiles());
- setSyncProgress(calculateOverallPercent(totalFileCount, completedFile, totalSize, completedSize));
- if (totalSize > 0) {
- const auto completedSizeString = Utility::octetsToString(completedSize);
- const auto totalSizeString = Utility::octetsToString(totalSize);
- if (progress.trustEta()) {
- setSyncStatusDetailString(
- tr("%1 of %2 · %3 left")
- .arg(completedSizeString, totalSizeString)
- .arg(Utility::durationToDescriptiveString1(progress.totalProgress().estimatedEta)));
- } else {
- setSyncStatusDetailString(tr("%1 of %2").arg(completedSizeString, totalSizeString));
- }
- }
- if (totalFileCount > 0) {
- setSyncStatusString(tr("Syncing file %1 of %2").arg(currentFile).arg(totalFileCount));
- }
- }
- void SyncStatusSummary::setSyncing(bool value)
- {
- if (value == _isSyncing) {
- return;
- }
- _isSyncing = value;
- emit syncingChanged();
- }
- void SyncStatusSummary::setSyncProgress(double value)
- {
- if (_progress == value) {
- return;
- }
- _progress = value;
- emit syncProgressChanged();
- }
- void SyncStatusSummary::setSyncStatusString(const QString &value)
- {
- if (_syncStatusString == value) {
- return;
- }
- _syncStatusString = value;
- emit syncStatusStringChanged();
- }
- QString SyncStatusSummary::syncStatusString() const
- {
- return _syncStatusString;
- }
- QString SyncStatusSummary::syncStatusDetailString() const
- {
- return _syncStatusDetailString;
- }
- void SyncStatusSummary::setSyncIcon(const QUrl &value)
- {
- if (_syncIcon == value) {
- return;
- }
- _syncIcon = value;
- emit syncIconChanged();
- }
- void SyncStatusSummary::setSyncStatusDetailString(const QString &value)
- {
- if (_syncStatusDetailString == value) {
- return;
- }
- _syncStatusDetailString = value;
- emit syncStatusDetailStringChanged();
- }
- void SyncStatusSummary::connectToFoldersProgress(const Folder::Map &folderMap)
- {
- for (const auto &folder : folderMap) {
- if (folder->accountState() == _accountState.data()) {
- connect(
- folder, &Folder::progressInfo, this, &SyncStatusSummary::onFolderProgressInfo, Qt::UniqueConnection);
- } else {
- disconnect(folder, &Folder::progressInfo, this, &SyncStatusSummary::onFolderProgressInfo);
- }
- }
- }
- void SyncStatusSummary::onIsConnectedChanged()
- {
- setSyncStateToConnectedState();
- }
- void SyncStatusSummary::setSyncStateToConnectedState()
- {
- setSyncing(false);
- setSyncStatusDetailString("");
- if (_accountState && !_accountState->isConnected()) {
- setSyncStatusString(tr("Offline"));
- setSyncIcon(Theme::instance()->folderOffline());
- } else {
- setSyncStatusString(tr("All synced!"));
- setSyncIcon(Theme::instance()->syncStatusOk());
- }
- }
- void SyncStatusSummary::setAccountState(AccountStatePtr accountState)
- {
- if (!reloadNeeded(accountState.data())) {
- return;
- }
- if (_accountState) {
- disconnect(
- _accountState.data(), &AccountState::isConnectedChanged, this, &SyncStatusSummary::onIsConnectedChanged);
- }
- _accountState = accountState;
- connect(_accountState.data(), &AccountState::isConnectedChanged, this, &SyncStatusSummary::onIsConnectedChanged);
- }
- void SyncStatusSummary::initSyncState()
- {
- auto syncStateFallbackNeeded = true;
- for (const auto &folder : FolderMan::instance()->map()) {
- onFolderSyncStateChanged(folder);
- syncStateFallbackNeeded = false;
- }
- if (syncStateFallbackNeeded) {
- setSyncStateToConnectedState();
- }
- }
- }
|