From e75defd86460514f0d3bcab2004ef0e04c810d7e Mon Sep 17 00:00:00 2001 From: Jyrki Gadinger Date: Wed, 19 Mar 2025 09:39:15 +0100 Subject: [PATCH] gui: add a "Yes to all" button when resolving multiple conflicts at once Fixes #7446 Signed-off-by: Jyrki Gadinger --- src/gui/conflictsolver.cpp | 68 +++++++++++++++++++++++++++++++--- src/gui/conflictsolver.h | 12 ++++++ src/gui/syncconflictsmodel.cpp | 8 +++- 3 files changed, 81 insertions(+), 7 deletions(-) diff --git a/src/gui/conflictsolver.cpp b/src/gui/conflictsolver.cpp index 2affc8e39e3c8..a0458a8332629 100644 --- a/src/gui/conflictsolver.cpp +++ b/src/gui/conflictsolver.cpp @@ -31,6 +31,16 @@ QString ConflictSolver::remoteVersionFilename() const return _remoteVersionFilename; } +bool ConflictSolver::isBulkSolution() const +{ + return _isBulkSolution; +} + +bool ConflictSolver::yesToAllRequested() const +{ + return _yesToAllRequested; +} + bool ConflictSolver::exec(ConflictSolver::Solution solution) { switch (solution) { @@ -65,6 +75,26 @@ void ConflictSolver::setRemoteVersionFilename(const QString &remoteVersionFilena emit remoteVersionFilenameChanged(); } +void ConflictSolver::setIsBulkSolution(bool isBulkSolution) +{ + if (_isBulkSolution == isBulkSolution) { + return; + } + + _isBulkSolution = isBulkSolution; + emit isBulkSolutionChanged(); +} + +void ConflictSolver::setYesToAllRequested(bool yesToAllRequested) +{ + if (_yesToAllRequested == yesToAllRequested) { + return; + } + + _yesToAllRequested = yesToAllRequested; + emit yesToAllRequestedChanged(); +} + bool ConflictSolver::deleteLocalVersion() { if (_localVersionFilename.isEmpty()) { @@ -75,13 +105,9 @@ bool ConflictSolver::deleteLocalVersion() return false; } - QFileInfo info(_localVersionFilename); - const auto message = FileSystem::isDir(_localVersionFilename) - ? tr("Do you want to delete the directory %1 and all its contents permanently?").arg(info.dir().dirName()) - : tr("Do you want to delete the file %1 permanently?").arg(info.fileName()); - const auto result = QMessageBox::question(_parentWidget, tr("Confirm deletion"), message, QMessageBox::Yes, QMessageBox::No); - if (result != QMessageBox::Yes) + if (!confirmDeletion()) { return false; + } if (FileSystem::isDir(_localVersionFilename)) { return FileSystem::removeRecursively(_localVersionFilename); @@ -152,4 +178,34 @@ bool ConflictSolver::overwriteRemoteVersion() } } +bool ConflictSolver::confirmDeletion() +{ + if (_yesToAllRequested) { + return true; + } + + QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::No; + if (_isBulkSolution) { + buttons |= QMessageBox::YesToAll; + } + + QFileInfo info(_localVersionFilename); + const auto message = FileSystem::isDir(_localVersionFilename) + ? tr("Do you want to delete the directory %1 and all its contents permanently?").arg(info.dir().dirName()) + : tr("Do you want to delete the file %1 permanently?").arg(info.fileName()); + const auto result = QMessageBox::question(_parentWidget, tr("Confirm deletion"), message, buttons); + switch (result) + { + case QMessageBox::YesToAll: + setYesToAllRequested(true); + return true; + case QMessageBox::Yes: + return true; + default: + // any other button pressed + return false; + } + return false; +} + } // namespace OCC diff --git a/src/gui/conflictsolver.h b/src/gui/conflictsolver.h index f6c1f5e8ca63b..2a5e53d5c2cda 100644 --- a/src/gui/conflictsolver.h +++ b/src/gui/conflictsolver.h @@ -17,6 +17,9 @@ class ConflictSolver : public QObject Q_OBJECT Q_PROPERTY(QString localVersionFilename READ localVersionFilename WRITE setLocalVersionFilename NOTIFY localVersionFilenameChanged) Q_PROPERTY(QString remoteVersionFilename READ remoteVersionFilename WRITE setRemoteVersionFilename NOTIFY remoteVersionFilenameChanged) + Q_PROPERTY(bool isBulkSolution READ isBulkSolution WRITE setIsBulkSolution NOTIFY isBulkSolutionChanged) + Q_PROPERTY(bool yesToAllRequested READ yesToAllRequested WRITE setYesToAllRequested NOTIFY yesToAllRequestedChanged) + public: enum Solution { KeepLocalVersion, @@ -29,25 +32,34 @@ class ConflictSolver : public QObject [[nodiscard]] QString localVersionFilename() const; [[nodiscard]] QString remoteVersionFilename() const; + [[nodiscard]] bool isBulkSolution() const; + [[nodiscard]] bool yesToAllRequested() const; bool exec(Solution solution); public slots: void setLocalVersionFilename(const QString &localVersionFilename); void setRemoteVersionFilename(const QString &remoteVersionFilename); + void setIsBulkSolution(bool isBulkSolution); + void setYesToAllRequested(bool yesToAllRequested); signals: void localVersionFilenameChanged(); void remoteVersionFilenameChanged(); + void isBulkSolutionChanged(); + void yesToAllRequestedChanged(); private: bool deleteLocalVersion(); bool renameLocalVersion(); bool overwriteRemoteVersion(); + bool confirmDeletion(); QWidget *_parentWidget; QString _localVersionFilename; QString _remoteVersionFilename; + bool _isBulkSolution = false; + bool _yesToAllRequested = false; }; } // namespace OCC diff --git a/src/gui/syncconflictsmodel.cpp b/src/gui/syncconflictsmodel.cpp index 388a2f71884f9..686e6b04f70b0 100644 --- a/src/gui/syncconflictsmodel.cpp +++ b/src/gui/syncconflictsmodel.cpp @@ -215,13 +215,19 @@ void SyncConflictsModel::selectAllConflicting(bool selected) void SyncConflictsModel::applySolution() { - for(const auto &syncConflict : std::as_const(_conflictData)) { + bool yesToAllRequested = false; + bool isBulkSolution = _conflictData.size() > 1; // no need to display the "Yes for all" button if only one file is affected + + for (const auto &syncConflict : std::as_const(_conflictData)) { if (syncConflict.isValid()) { qCInfo(lcSyncConflictsModel) << syncConflict.mExistingFilePath << syncConflict.mConflictingFilePath << syncConflict.solution(); ConflictSolver solver; + solver.setIsBulkSolution(isBulkSolution); + solver.setYesToAllRequested(yesToAllRequested); solver.setLocalVersionFilename(syncConflict.mConflictingFilePath); solver.setRemoteVersionFilename(syncConflict.mExistingFilePath); solver.exec(syncConflict.solution()); + yesToAllRequested = solver.yesToAllRequested(); } } }