From 6fa2542a10926d6e6cde33b29a6ef524a5395f27 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Wed, 21 Sep 2022 19:13:54 +0200 Subject: [PATCH 1/2] Categorise file name clash sync file issues as separate FileNameClash enum treated as warning Signed-off-by: Claudio Cambra --- src/gui/tray/activitylistmodel.cpp | 3 ++- src/libsync/bulkpropagatorjob.cpp | 1 + src/libsync/owncloudpropagator.cpp | 1 + src/libsync/progressdispatcher.cpp | 3 ++- src/libsync/propagatedownload.cpp | 8 ++++---- src/libsync/syncfileitem.h | 6 ++++++ src/libsync/syncresult.cpp | 2 +- 7 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/gui/tray/activitylistmodel.cpp b/src/gui/tray/activitylistmodel.cpp index b94d5bfd80..a840143a68 100644 --- a/src/gui/tray/activitylistmodel.cpp +++ b/src/gui/tray/activitylistmodel.cpp @@ -232,7 +232,8 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const || a._status == SyncFileItem::Conflict || a._status == SyncFileItem::Restoration || a._status == SyncFileItem::FileLocked - || a._status == SyncFileItem::FileNameInvalid) { + || a._status == SyncFileItem::FileNameInvalid + || a._status == SyncFileItem::FileNameClash) { colorIconPath.append("state-warning.svg"); return colorIconPath; } else if (a._status == SyncFileItem::FileIgnored) { diff --git a/src/libsync/bulkpropagatorjob.cpp b/src/libsync/bulkpropagatorjob.cpp index 6d4074168b..228180711d 100644 --- a/src/libsync/bulkpropagatorjob.cpp +++ b/src/libsync/bulkpropagatorjob.cpp @@ -711,6 +711,7 @@ void BulkPropagatorJob::handleJobDoneErrors(SyncFileItemPtr item, case SyncFileItem::FileIgnored: case SyncFileItem::FileLocked: case SyncFileItem::FileNameInvalid: + case SyncFileItem::FileNameClash: case SyncFileItem::NoStatus: case SyncFileItem::NormalError: case SyncFileItem::Restoration: diff --git a/src/libsync/owncloudpropagator.cpp b/src/libsync/owncloudpropagator.cpp index aba3f437f3..428d82d908 100644 --- a/src/libsync/owncloudpropagator.cpp +++ b/src/libsync/owncloudpropagator.cpp @@ -273,6 +273,7 @@ void PropagateItemJob::done(SyncFileItem::Status statusArg, const QString &error case SyncFileItem::BlacklistedError: case SyncFileItem::FileLocked: case SyncFileItem::FileNameInvalid: + case SyncFileItem::FileNameClash: // nothing break; } diff --git a/src/libsync/progressdispatcher.cpp b/src/libsync/progressdispatcher.cpp index 45c5beac4f..8daf74b46f 100644 --- a/src/libsync/progressdispatcher.cpp +++ b/src/libsync/progressdispatcher.cpp @@ -97,7 +97,8 @@ bool Progress::isWarningKind(SyncFileItem::Status kind) || kind == SyncFileItem::FatalError || kind == SyncFileItem::FileIgnored || kind == SyncFileItem::Conflict || kind == SyncFileItem::Restoration || kind == SyncFileItem::DetailError || kind == SyncFileItem::BlacklistedError - || kind == SyncFileItem::FileLocked; + || kind == SyncFileItem::FileLocked || kind == SyncFileItem::FileNameInvalid + || kind == SyncFileItem::FileNameClash; } bool Progress::isIgnoredKind(SyncFileItem::Status kind) diff --git a/src/libsync/propagatedownload.cpp b/src/libsync/propagatedownload.cpp index 088ce72895..0bb179b816 100644 --- a/src/libsync/propagatedownload.cpp +++ b/src/libsync/propagatedownload.cpp @@ -528,14 +528,14 @@ void PropagateDownloadFile::startAfterIsEncryptedIsChecked() } if (_item->_type == ItemTypeVirtualFile) { if (propagator()->localFileNameClash(_item->_file)) { - done(SyncFileItem::NormalError, tr("File %1 cannot be downloaded because of a local file name clash!").arg(QDir::toNativeSeparators(_item->_file))); + done(SyncFileItem::FileNameClash, tr("File %1 cannot be downloaded because of a local file name clash!").arg(QDir::toNativeSeparators(_item->_file))); return; } qCDebug(lcPropagateDownload) << "creating virtual file" << _item->_file; // do a klaas' case clash check. if (propagator()->localFileNameClash(_item->_file)) { - done(SyncFileItem::NormalError, tr("File %1 can not be downloaded because of a local file name clash!").arg(QDir::toNativeSeparators(_item->_file))); + done(SyncFileItem::FileNameClash, tr("File %1 can not be downloaded because of a local file name clash!").arg(QDir::toNativeSeparators(_item->_file))); return; } auto r = vfs->createPlaceholder(*_item); @@ -633,7 +633,7 @@ void PropagateDownloadFile::startDownload() // do a klaas' case clash check. if (propagator()->localFileNameClash(_item->_file)) { - done(SyncFileItem::NormalError, tr("File %1 cannot be downloaded because of a local file name clash!").arg(QDir::toNativeSeparators(_item->_file))); + done(SyncFileItem::FileNameClash, tr("File %1 cannot be downloaded because of a local file name clash!").arg(QDir::toNativeSeparators(_item->_file))); return; } @@ -1126,7 +1126,7 @@ void PropagateDownloadFile::downloadFinished() // In case of file name clash, report an error // This can happen if another parallel download saved a clashing file. if (propagator()->localFileNameClash(_item->_file)) { - done(SyncFileItem::NormalError, tr("File %1 cannot be saved because of a local file name clash!").arg(QDir::toNativeSeparators(_item->_file))); + done(SyncFileItem::FileNameClash, tr("File %1 cannot be saved because of a local file name clash!").arg(QDir::toNativeSeparators(_item->_file))); return; } diff --git a/src/libsync/syncfileitem.h b/src/libsync/syncfileitem.h index 9dc6fa4f52..9668e3ff6e 100644 --- a/src/libsync/syncfileitem.h +++ b/src/libsync/syncfileitem.h @@ -71,6 +71,12 @@ public: */ FileNameInvalid, + /** + * There is a file name clash (e.g. attempting to download test.txt when TEST.TXT already exists + * on a platform where the filesystem is case-insensitive + */ + FileNameClash, + /** For errors that should only appear in the error view. * * Some errors also produce a summary message. Usually displaying that message is diff --git a/src/libsync/syncresult.cpp b/src/libsync/syncresult.cpp index e7aa3ab548..3dede86613 100644 --- a/src/libsync/syncresult.cpp +++ b/src/libsync/syncresult.cpp @@ -141,7 +141,7 @@ void SyncResult::processCompletedItem(const SyncFileItemPtr &item) if (!_firstItemError) { _firstItemError = item; } - } else if (item->_status == SyncFileItem::Conflict || item->_status == SyncFileItem::FileNameInvalid) { + } else if (item->_status == SyncFileItem::Conflict || item->_status == SyncFileItem::FileNameInvalid || item->_status == SyncFileItem::FileNameClash) { if (item->_instruction == CSYNC_INSTRUCTION_CONFLICT) { _numNewConflictItems++; if (!_firstNewConflictItem) { From 664a80cbb5c9327dd956f2aa74703277cee7659f Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Wed, 21 Sep 2022 19:15:35 +0200 Subject: [PATCH 2/2] Clicking on file name clash activities now opens file in web UI were the clash can be resolved Signed-off-by: Claudio Cambra --- src/gui/tray/activitylistmodel.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/gui/tray/activitylistmodel.cpp b/src/gui/tray/activitylistmodel.cpp index a840143a68..131a3dbc86 100644 --- a/src/gui/tray/activitylistmodel.cpp +++ b/src/gui/tray/activitylistmodel.cpp @@ -811,6 +811,22 @@ void ActivityListModel::slotTriggerDefaultAction(const int activityIndex) _currentInvalidFilenameDialog->open(); ownCloudGui::raiseDialog(_currentInvalidFilenameDialog); return; + } else if (activity._status == SyncFileItem::FileNameClash) { + const auto folder = FolderMan::instance()->folder(activity._folder); + const auto relPath = activity._fileAction == QStringLiteral("file_renamed") ? activity._renamedFile : activity._file; + SyncJournalFileRecord record; + + if (!folder || !folder->journalDb()->getFileRecord(relPath, &record)) { + return; + } + + fetchPrivateLinkUrl(folder->accountState()->account(), + relPath, + record.numericFileId(), + this, + [](const QString &link) { Utility::openBrowser(link); } + ); + return; } if (!path.isEmpty()) {