From: Christian Kamm Date: Tue, 13 Oct 2015 12:10:52 +0000 (+0200) Subject: SelectiveSync: Show in-progress label #3524 X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~1557 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=05eee16959ab7cc485bee9c273392b84ba57eae8;p=nextcloud-desktop.git SelectiveSync: Show in-progress label #3524 We now show 'Fetching data...' after a second. This also increased the timeout to 60s, making the error condition much less likely. --- diff --git a/src/gui/folderstatusmodel.cpp b/src/gui/folderstatusmodel.cpp index bcbbdcd98..1e15e84a7 100644 --- a/src/gui/folderstatusmodel.cpp +++ b/src/gui/folderstatusmodel.cpp @@ -90,7 +90,7 @@ Qt::ItemFlags FolderStatusModel::flags ( const QModelIndex &index ) const } return Qt::ItemIsEnabled | ret; } - case ErrorLabel: + case FetchLabel: return Qt::ItemIsEnabled #if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) | Qt::ItemNeverHasChildren @@ -151,11 +151,20 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const } } return QVariant(); - case ErrorLabel: + case FetchLabel: + { + const auto x = static_cast(index.internalPointer()); switch(role) { - case Qt::DisplayRole: return tr("Error while loading the list of folders from the server."); + case Qt::DisplayRole: + if (x->_hasError) { + return tr("Error while loading the list of folders from the server."); + } else { + return tr("Fetching folder list from server..."); + } + break; default: return QVariant(); } + } case RootFolder: break; } @@ -302,7 +311,7 @@ int FolderStatusModel::rowCount(const QModelIndex& parent) const auto info = infoForIndex(parent); if (!info) return 0; - if (info->_hasError) + if (info->hasLabel()) return 1; return info->_subs.count(); } @@ -310,7 +319,11 @@ int FolderStatusModel::rowCount(const QModelIndex& parent) const FolderStatusModel::ItemType FolderStatusModel::classify(const QModelIndex& index) const { if (auto sub = static_cast(index.internalPointer())) { - return sub->_hasError ? ErrorLabel : SubFolder; + if (sub->hasLabel()) { + return FetchLabel; + } else { + return SubFolder; + } } if (index.row() < _folders.count()) { return RootFolder; @@ -323,8 +336,7 @@ FolderStatusModel::SubFolderInfo* FolderStatusModel::infoForIndex(const QModelIn if (!index.isValid()) return 0; if (auto parentInfo = static_cast(index.internalPointer())) { - if (parentInfo->_hasError) { - // Error label + if (parentInfo->hasLabel()) { return 0; } return &parentInfo->_subs[index.row()]; @@ -384,20 +396,21 @@ QModelIndex FolderStatusModel::index(int row, int column, const QModelIndex& par } switch(classify(parent)) { case AddButton: - case ErrorLabel: + case FetchLabel: return QModelIndex(); case RootFolder: if (_folders.count() <= parent.row()) return QModelIndex(); // should not happen return createIndex(row, column, const_cast(&_folders[parent.row()])); case SubFolder: { - auto info = static_cast(parent.internalPointer()); - if (info->_subs.count() <= parent.row()) + auto pinfo = static_cast(parent.internalPointer()); + if (pinfo->_subs.count() <= parent.row()) return QModelIndex(); // should not happen - if (!info->_subs.at(parent.row())._hasError - && info->_subs.at(parent.row())._subs.count() <= row) + auto & info = pinfo->_subs[parent.row()]; + if (!info.hasLabel() + && info._subs.count() <= row) return QModelIndex(); // should not happen - return createIndex(row, column, &info->_subs[parent.row()]); + return createIndex(row, column, &info); } } return QModelIndex(); @@ -413,7 +426,7 @@ QModelIndex FolderStatusModel::parent(const QModelIndex& child) const case AddButton: return QModelIndex(); case SubFolder: - case ErrorLabel: + case FetchLabel: break; } auto pathIdx = static_cast(child.internalPointer())->_pathIdx; @@ -467,7 +480,9 @@ void FolderStatusModel::fetchMore(const QModelIndex& parent) if (!info || info->_fetched || info->_fetching) return; + info->_hasError = false; info->_fetching = true; + info->_fetchingLabel = false; QString path = info->_folder->remotePath(); if (info->_path != QLatin1String("/")) { if (!path.endsWith(QLatin1Char('/'))) { @@ -477,13 +492,18 @@ void FolderStatusModel::fetchMore(const QModelIndex& parent) } LsColJob *job = new LsColJob(_accountState->account(), path, this); job->setProperties(QList() << "resourcetype" << "quota-used-bytes"); - job->setTimeout(5 * 1000); + job->setTimeout(60 * 1000); connect(job, SIGNAL(directoryListingSubfolders(QStringList)), SLOT(slotUpdateDirectories(QStringList))); connect(job, SIGNAL(finishedWithError(QNetworkReply*)), this, SLOT(slotLscolFinishedWithError(QNetworkReply*))); job->start(); - job->setProperty(propertyParentIndexC , QVariant::fromValue(parent)); + QPersistentModelIndex persistentIndex(parent); + job->setProperty(propertyParentIndexC , QVariant::fromValue(persistentIndex)); + + // Show 'fetching data...' hint after a while. + _fetchingItems[persistentIndex].start(); + QTimer::singleShot(1000, this, SLOT(slotShowFetchProgress())); } void FolderStatusModel::slotUpdateDirectories(const QStringList &list_) @@ -496,12 +516,16 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list_) return; } - if (parentInfo->_hasError) { + if (parentInfo->hasLabel()) { beginRemoveRows(idx, 0 ,0); parentInfo->_hasError = false; + parentInfo->_fetchingLabel = false; endRemoveRows(); } + parentInfo->_fetching = false; + parentInfo->_fetched = true; + auto list = list_; list.removeFirst(); // remove the parent item @@ -522,9 +546,6 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list_) beginInsertRows(idx, 0, list.count() - 1); - parentInfo->_fetched = true; - parentInfo->_fetching = false; - QStringList selectiveSyncBlackList; if (parentInfo->_checked == Qt::PartiallyChecked) { selectiveSyncBlackList = parentInfo->_folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList); @@ -589,14 +610,17 @@ void FolderStatusModel::slotLscolFinishedWithError(QNetworkReply* r) } auto parentInfo = infoForIndex(idx); if (parentInfo) { - parentInfo->_fetching = false; if (r->error() == QNetworkReply::ContentNotFoundError) { parentInfo->_fetched = true; - } else if (!parentInfo->_hasError) { - beginInsertRows(idx, 0, 0); + } else { + if (!parentInfo->hasLabel()) { + beginInsertRows(idx, 0, 0); + endInsertRows(); + } parentInfo->_hasError = true; - endInsertRows(); } + parentInfo->_fetching = false; + parentInfo->_fetchingLabel = false; } } @@ -900,13 +924,8 @@ void FolderStatusModel::slotFolderSyncStateChange(Folder *f) if (i->_isDirectory && (i->_instruction == CSYNC_INSTRUCTION_NEW || i->_instruction == CSYNC_INSTRUCTION_REMOVE)) { // There is a new or a removed folder. reset all data - _folders[folderIndex]._fetched = false; - _folders[folderIndex]._fetching = false; - if (!_folders.at(folderIndex)._subs.isEmpty()) { - beginRemoveRows(index(folderIndex), 0, _folders.at(folderIndex)._subs.count() - 1); - _folders[folderIndex]._subs.clear(); - endRemoveRows(); - } + auto & info = _folders[folderIndex]; + info.resetSubs(this, index(folderIndex)); return; } } @@ -942,17 +961,53 @@ void FolderStatusModel::slotNewBigFolder() } if (folderIndex < 0) { return; } - _folders[folderIndex]._fetched = false; - _folders[folderIndex]._fetching = false; - if (!_folders.at(folderIndex)._subs.isEmpty()) { - beginRemoveRows(index(folderIndex), 0, _folders.at(folderIndex)._subs.count() - 1); - _folders[folderIndex]._subs.clear(); - endRemoveRows(); - } + _folders[folderIndex].resetSubs(this, index(folderIndex)); emit suggestExpand(index(folderIndex)); emit dirtyChanged(); } +void FolderStatusModel::slotShowFetchProgress() +{ + QMutableMapIterator it(_fetchingItems); + while (it.hasNext()) { + it.next(); + if (it.value().elapsed() > 800) + { + auto idx = it.key(); + auto* info = infoForIndex(idx); + if (info && info->_fetching) { + if (!info->hasLabel()) { + beginInsertRows(idx, 0, 0); + endInsertRows(); + } + info->_fetchingLabel = true; + } + it.remove(); + } + } +} + +bool FolderStatusModel::SubFolderInfo::hasLabel() const +{ + return _hasError || _fetchingLabel; +} + +void FolderStatusModel::SubFolderInfo::resetSubs(FolderStatusModel* model, QModelIndex index) +{ + _fetched = false; + _fetching = false; + if (hasLabel()) { + model->beginRemoveRows(index, 0 ,0); + _fetchingLabel = false; + _hasError = false; + model->endRemoveRows(); + } else if (!_subs.isEmpty()) { + model->beginRemoveRows(index, 0, _subs.count() - 1); + _subs.clear(); + model->endRemoveRows(); + } +} + } // namespace OCC diff --git a/src/gui/folderstatusmodel.h b/src/gui/folderstatusmodel.h index 932408056..b5f3de15e 100644 --- a/src/gui/folderstatusmodel.h +++ b/src/gui/folderstatusmodel.h @@ -18,7 +18,7 @@ #include #include #include - +#include class QNetworkReply; namespace OCC { @@ -51,20 +51,30 @@ public: struct SubFolderInfo { SubFolderInfo() - : _folder(0), _size(0), _fetched(false), _fetching(false), _isUndecided(false), - _hasError(false), _checked(Qt::Checked) {} + : _folder(0), _size(0), _fetched(false), _fetching(false), + _hasError(false), _fetchingLabel(false), _isUndecided(false), _checked(Qt::Checked) {} Folder *_folder; QString _name; QString _path; QVector _pathIdx; QVector _subs; qint64 _size; + bool _fetched; // If we did the LSCOL for this folder already - bool _fetching; - bool _isUndecided; // undecided folders are the big folders that the user has not accepted yet + bool _fetching; // Whether a LSCOL job is currently running bool _hasError; // If the last fetching job ended in an error + bool _fetchingLabel; // Whether a 'fetching in progress' label is shown. + + bool _isUndecided; // undecided folders are the big folders that the user has not accepted yet + Qt::CheckState _checked; + // Whether this has a FetchLabel subrow + bool hasLabel() const; + + // Reset all subfolders and fetch status + void resetSubs(FolderStatusModel* model, QModelIndex index); + struct Progress { Progress() : _warningCount(0), _overallPercent(0) {} bool isNull() const @@ -79,7 +89,7 @@ public: QVector _folders; - enum ItemType { RootFolder, SubFolder, AddButton, ErrorLabel }; + enum ItemType { RootFolder, SubFolder, AddButton, FetchLabel }; ItemType classify(const QModelIndex &index) const; SubFolderInfo *infoForIndex(const QModelIndex &index) const; @@ -105,12 +115,25 @@ private slots: void slotFolderScheduleQueueChanged(); void slotNewBigFolder(); + /** + * "In progress" labels for fetching data from the server are only + * added after some time to avoid popping. + */ + void slotShowFetchProgress(); + private: QStringList createBlackList(OCC::FolderStatusModel::SubFolderInfo* root, const QStringList& oldBlackList) const; const AccountState* _accountState; bool _dirty; // If the selective sync checkboxes were changed + /** + * Keeps track of items that are fetching data from the server. + * + * See slotShowPendingFetchProgress() + */ + QMap _fetchingItems; + #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) //the roles argument was added in Qt5 void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles = QVector()) @@ -120,6 +143,8 @@ private: signals: void dirtyChanged(); void suggestExpand(const QModelIndex &); // Tell the view that this item should be expanded because it has an undecided item + + friend class SubFolderInfo; }; } // namespace OCC