diff --git a/src/mainwindow/mainwindow-async.cpp b/src/mainwindow/mainwindow-async.cpp index bbddc7c3e..777c30eb1 100644 --- a/src/mainwindow/mainwindow-async.cpp +++ b/src/mainwindow/mainwindow-async.cpp @@ -263,10 +263,13 @@ struct NODISCARD MainWindow::AsyncBase { public: const std::shared_ptr progressCounter; + const CancelDispositionEnum cancelDisposition = CancelDispositionEnum::Allow; public: - explicit AsyncBase(std::shared_ptr pc) + explicit AsyncBase(std::shared_ptr pc, + const CancelDispositionEnum cancelDisposition_) : progressCounter{std::move(pc)} + , cancelDisposition{cancelDisposition_} { if (!progressCounter) { throw std::invalid_argument("pc"); @@ -285,12 +288,16 @@ struct NODISCARD MainWindow::AsyncBase NODISCARD PollResultEnum poll() { return poll(std::chrono::milliseconds{0}); } void request_cancel(); NODISCARD bool requested_cancel() const; + NODISCARD bool is_allowed_to_cancel() const; }; MainWindow::AsyncBase::~AsyncBase() = default; void MainWindow::AsyncBase::request_cancel() { + if (!is_allowed_to_cancel()) { + return; + } progressCounter->requestCancel(); virt_request_cancel(); } @@ -300,6 +307,11 @@ bool MainWindow::AsyncBase::requested_cancel() const return progressCounter->requestedCancel(); } +bool MainWindow::AsyncBase::is_allowed_to_cancel() const +{ + return cancelDisposition == CancelDispositionEnum::Allow; +} + MainWindow::AsyncTask::AsyncTask(QObject *parent) : QObject(parent) {} @@ -337,7 +349,7 @@ void MainWindow::AsyncTask::tick() return; } - if (m_task->poll() != PollResultEnum::Finished) { + if (deref(m_task).poll() != PollResultEnum::Finished) { return; } @@ -347,7 +359,12 @@ void MainWindow::AsyncTask::tick() void MainWindow::AsyncTask::request_cancel() { - m_task->request_cancel(); + deref(m_task).request_cancel(); +} + +bool MainWindow::AsyncTask::is_allowed_to_cancel() const +{ + return deref(m_task).is_allowed_to_cancel(); } void MainWindow::AsyncTask::reset() @@ -403,7 +420,7 @@ struct NODISCARD MainWindow::AsyncHelper : public AsyncBase UniqueStorage ps, const QString &dialogText, const CancelDispositionEnum allow_cancel) - : AsyncBase{std::move(pc)} + : AsyncBase{std::move(pc), allow_cancel} , mainWindow{mw} , fileName{name} , pDevice(std::move(pd)) diff --git a/src/mainwindow/mainwindow.cpp b/src/mainwindow/mainwindow.cpp index 5340baaa5..af5d0f3f9 100644 --- a/src/mainwindow/mainwindow.cpp +++ b/src/mainwindow/mainwindow.cpp @@ -1556,8 +1556,16 @@ bool MainWindow::eventFilter(QObject *const obj, QEvent *const event) void MainWindow::closeEvent(QCloseEvent *const event) { - // REVISIT: wait and see if we're actually exiting first? - writeSettings(); + qInfo() << MM_SOURCE_LOCATION().function_name(); + + if (m_asyncTask) { + // first check avoids prompting to save while saving. + if (!m_asyncTask.is_allowed_to_cancel()) { + qInfo() << "Note: Ignoring close request because the current async task cannot be canceled."; + event->ignore(); + return; + } + } if (!maybeSave()) { event->ignore(); @@ -1565,9 +1573,24 @@ void MainWindow::closeEvent(QCloseEvent *const event) } if (m_asyncTask) { - qInfo() << "Attempting to async task for faster shutdown"; - m_progressDlg->reject(); + // second check is in case we just scheduled a save. + if (!m_asyncTask.is_allowed_to_cancel()) { + qInfo() << "Note: Ignoring close request because the scheduled async task cannot be canceled."; + event->ignore(); + return; + } + if (m_asyncTask.isWorking()) { + qInfo() << "Attempting to cancel async task for faster shutdown"; + m_asyncTask.request_cancel(); + } + if (auto dlg = m_progressDlg.get()) { + qInfo() << "Attempting to reject the progress dialog for faster shutdown"; + dlg->reject(); + } } + + writeSettings(); + event->accept(); } diff --git a/src/mainwindow/mainwindow.h b/src/mainwindow/mainwindow.h index 86622774d..ea03c1ecc 100644 --- a/src/mainwindow/mainwindow.h +++ b/src/mainwindow/mainwindow.h @@ -271,6 +271,7 @@ class NODISCARD_QOBJECT MainWindow final : public QMainWindow void begin(std::unique_ptr task); void tick(); void request_cancel(); + NODISCARD bool is_allowed_to_cancel() const; private: void reset();