connect(_engine.data(), SIGNAL(seenLockedFile(QString)), FolderMan::instance(), SLOT(slotSyncOnceFileUnlocks(QString)));
connect(_engine.data(), SIGNAL(aboutToPropagate(SyncFileItemVector &)),
SLOT(slotLogPropagationStart()));
+ connect(_engine.data(), SIGNAL(summaryError(QString)), SLOT(slotSyncError(QString)));
_scheduleSelfTimer.setSingleShot(true);
_scheduleSelfTimer.setInterval(SyncEngine::minimumFileAgeForUpload);
_engine->setNetworkLimits(uploadLimit, downloadLimit);
}
-
-void Folder::slotSyncError(const QString &err)
+void Folder::slotSyncError(const QString &message)
{
- _syncResult.appendErrorString(err);
+ _syncResult.appendErrorString(message);
+ emit ProgressDispatcher::instance()->syncError(alias(), message);
}
void Folder::slotSyncStarted()
private slots:
void slotSyncStarted();
- void slotSyncError(const QString &);
- void slotCsyncUnavailable();
void slotSyncFinished(bool);
+ /** Adds a error message that's not tied to a specific item.
+ */
+ void slotSyncError(const QString &message);
+
+ void slotCsyncUnavailable();
+
void slotFolderDiscovered(bool local, QString folderName);
+
void slotTransmissionProgress(const ProgressInfo &pi);
void slotItemCompleted(const SyncFileItemPtr &);
this, SLOT(slotProgressInfo(QString, ProgressInfo)));
connect(ProgressDispatcher::instance(), SIGNAL(itemCompleted(QString, SyncFileItemPtr)),
this, SLOT(slotItemCompleted(QString, SyncFileItemPtr)));
+ connect(ProgressDispatcher::instance(), SIGNAL(syncError(QString, QString)),
+ this, SLOT(addLine(QString, QString)));
connect(_ui->_treeWidget, SIGNAL(itemActivated(QTreeWidgetItem *, int)), SLOT(slotOpenFile(QTreeWidgetItem *, int)));
connect(_ui->copyIssuesButton, SIGNAL(clicked()), SIGNAL(copyToClipboard()));
emit(issueCountUpdated(_ui->_treeWidget->topLevelItemCount()));
}
+void IssuesWidget::addItem(QTreeWidgetItem *item)
+{
+ if (!item)
+ return;
+ _ui->_treeWidget->insertTopLevelItem(0, item);
+ item->setHidden(!shouldBeVisible(item, currentAccountFilter(), currentFolderFilter()));
+ emit issueCountUpdated(_ui->_treeWidget->topLevelItemCount());
+}
+
void IssuesWidget::slotOpenFile(QTreeWidgetItem *item, int)
{
QString folderName = item->data(2, Qt::UserRole).toString();
QTreeWidgetItem *line = ProtocolWidget::createCompletedTreewidgetItem(folder, *item);
if (!line)
return;
-
- _ui->_treeWidget->insertTopLevelItem(0, line);
- line->setHidden(!shouldBeVisible(line, currentAccountFilter(), currentFolderFilter()));
- emit issueCountUpdated(_ui->_treeWidget->topLevelItemCount());
+ addItem(line);
}
void IssuesWidget::slotRefreshIssues()
_ui->showIgnores->setChecked(false);
_ui->showWarnings->setChecked(false);
}
+
+void IssuesWidget::addLine(const QString &folderAlias, const QString &message)
+{
+ SyncFileItem::Status status = SyncFileItem::NormalError;
+
+ auto folder = FolderMan::instance()->folder(folderAlias);
+ if (!folder)
+ return;
+
+ QStringList columns;
+ QDateTime timestamp = QDateTime::currentDateTime();
+ const QString timeStr = ProtocolWidget::timeString(timestamp);
+ const QString longTimeStr = ProtocolWidget::timeString(timestamp, QLocale::LongFormat);
+
+ columns << timeStr;
+ columns << tr("<global error>");
+ columns << folder->shortGuiLocalPath();
+ columns << message;
+
+ QIcon icon;
+ if (status == SyncFileItem::NormalError
+ || status == SyncFileItem::FatalError) {
+ icon = Theme::instance()->syncStateIcon(SyncResult::Error);
+ } else if (Progress::isWarningKind(status)) {
+ icon = Theme::instance()->syncStateIcon(SyncResult::Problem);
+ }
+
+ QTreeWidgetItem *twitem = new QTreeWidgetItem(columns);
+ twitem->setData(0, Qt::SizeHintRole, QSize(0, ActivityItemDelegate::rowHeight()));
+ twitem->setIcon(0, icon);
+ twitem->setToolTip(0, longTimeStr);
+ twitem->setToolTip(3, message);
+ twitem->setData(0, Qt::UserRole, status);
+ twitem->setData(2, Qt::UserRole, folderAlias);
+
+ addItem(twitem);
+}
}
void showFolderErrors(const QString &folderAlias);
public slots:
+ void addLine(const QString &folderAlias, const QString &message);
void slotProgressInfo(const QString &folder, const ProgressInfo &progress);
void slotItemCompleted(const QString &folder, const SyncFileItemPtr &item);
void slotOpenFile(QTreeWidgetItem *item, int);
bool shouldBeVisible(QTreeWidgetItem *item, AccountState *filterAccount,
const QString &filterFolderAlias) const;
void cleanItems(const QString &folder);
+ void addItem(QTreeWidgetItem *item);
Ui::IssuesWidget *_ui;
};
_item->_status = SyncFileItem::SoftError;
}
+ // Blacklist handling
switch (_item->_status) {
case SyncFileItem::SoftError:
case SyncFileItem::FatalError:
*/
DiskSpaceResult diskSpaceCheck() const;
-
private slots:
/** Emit the finished signal and make sure it is only emitted once */
*/
void touchedFile(const QString &fileName);
+ void insufficientLocalStorage();
+
private:
AccountPtr _account;
QScopedPointer<PropagateDirectory> _rootJob;
*/
void itemCompleted(const QString &folder, const SyncFileItemPtr &item);
+ /**
+ * @brief A new folder-wide sync error was seen.
+ */
+ void syncError(const QString &folder, const QString &message);
+
protected:
void setProgressInfo(const QString &folder, const ProgressInfo &progress);
const auto diskSpaceResult = propagator()->diskSpaceCheck();
if (diskSpaceResult != OwncloudPropagator::DiskSpaceOk) {
if (diskSpaceResult == OwncloudPropagator::DiskSpaceFailure) {
- _item->_errorMayBeBlacklisted = true;
- done(SyncFileItem::NormalError,
- tr("The download would reduce free disk space below %1").arg(Utility::octetsToString(freeSpaceLimit())));
+ // Using BlacklistedError here will make the error not pop up in the account
+ // tab: instead we'll generate a general "disk space low" message and show
+ // these detail errors only in the error view.
+ done(SyncFileItem::BlacklistedError,
+ tr("The download would reduce free local disk space below the limit"));
+ emit propagator()->insufficientLocalStorage();
} else if (diskSpaceResult == OwncloudPropagator::DiskSpaceCritical) {
done(SyncFileItem::FatalError,
tr("Free space on disk is less than %1").arg(Utility::octetsToString(criticalFreeSpaceLimit())));
#include "csync_private.h"
#include "filesystem.h"
#include "propagateremotedelete.h"
+#include "propagatedownload.h"
#include "asserts.h"
#ifdef Q_OS_WIN
connect(_propagator.data(), SIGNAL(finished(bool)), this, SLOT(slotFinished(bool)), Qt::QueuedConnection);
connect(_propagator.data(), SIGNAL(seenLockedFile(QString)), SIGNAL(seenLockedFile(QString)));
connect(_propagator.data(), SIGNAL(touchedFile(QString)), SLOT(slotAddTouchedFile(QString)));
+ connect(_propagator.data(), SIGNAL(insufficientLocalStorage()), SLOT(slotInsufficientLocalStorage()));
// apply the network limits to the propagator
setNetworkLimits(_uploadLimit, _downloadLimit);
_seenFiles.clear();
_temporarilyUnavailablePaths.clear();
_renamedFolders.clear();
+ _uniqueErrors.clear();
_clearTouchedFilesTimer.start();
}
}
}
+void SyncEngine::slotSummaryError(const QString &message)
+{
+ if (_uniqueErrors.contains(message))
+ return;
+
+ _uniqueErrors.insert(message);
+ emit summaryError(message);
+}
+
+void SyncEngine::slotInsufficientLocalStorage()
+{
+ slotSummaryError(
+ tr("Disk space is low: Downloads that would reduce free space "
+ "below %1 were skipped.")
+ .arg(Utility::octetsToString(freeSpaceLimit())));
+}
+
} // namespace OCC
void transmissionProgress(const ProgressInfo &progress);
+ /// We've produced a new summary error.
+ void summaryError(const QString &message);
+
void finished(bool success);
void started();
/** Wipes the _touchedFiles hash */
void slotClearTouchedFiles();
+ /** Emit a summary error, unless it was seen before */
+ void slotSummaryError(const QString &message);
+
+ void slotInsufficientLocalStorage();
+
private:
void handleSyncError(CSYNC *ctx, const char *state);
/** For clearing the _touchedFiles variable after sync finished */
QTimer _clearTouchedFilesTimer;
+
+ /** List of unique errors that occurred in a sync run. */
+ QSet<QString> _uniqueErrors;
};
}