From ab51f02711eb30dc6fd5e8eb5ed4902e111c3d90 Mon Sep 17 00:00:00 2001 From: David Capello Date: Wed, 22 Nov 2017 11:11:31 -0300 Subject: [PATCH] Fix crash applying a filter w/all layers locked (fix #1610) The m_transaction field of FilterManagerImpl::commitTransaction() was nullptr because FilterManagerImpl::applyToTarget() was returning without creating the m_transaction. --- src/app/commands/filters/filter_manager_impl.cpp | 15 ++++++++++++--- src/app/commands/filters/filter_manager_impl.h | 1 + src/app/commands/filters/filter_worker.cpp | 7 ++++++- src/app/document_undo.cpp | 1 + 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/app/commands/filters/filter_manager_impl.cpp b/src/app/commands/filters/filter_manager_impl.cpp index fd9ec6f66..a156b25c7 100644 --- a/src/app/commands/filters/filter_manager_impl.cpp +++ b/src/app/commands/filters/filter_manager_impl.cpp @@ -234,8 +234,11 @@ void FilterManagerImpl::applyToTarget() m_site.frame(), (m_target & TARGET_ALL_FRAMES) == TARGET_ALL_FRAMES, true); // we will write in each image - if (images.empty() && !paletteChange) + if (images.empty() && !paletteChange) { + // We don't have images/palette changes to do (there will not be a + // transaction). return; + } // Initialize writting operation ContextReader reader(m_context); @@ -280,10 +283,16 @@ void FilterManagerImpl::applyToTarget() m_oldPalette.reset(nullptr); } +bool FilterManagerImpl::isTransaction() const +{ + return m_transaction != nullptr; +} + +// This must be executed in the main UI thread. +// Check Transaction::commit() comments. void FilterManagerImpl::commitTransaction() { - // This must be executed in the main UI thread. - // Check Transaction::commit() comments. + ASSERT(m_transaction); m_transaction->commit(); } diff --git a/src/app/commands/filters/filter_manager_impl.h b/src/app/commands/filters/filter_manager_impl.h index 6ad5c0c00..e7225ab16 100644 --- a/src/app/commands/filters/filter_manager_impl.h +++ b/src/app/commands/filters/filter_manager_impl.h @@ -83,6 +83,7 @@ namespace app { void end(); bool applyStep(); void applyToTarget(); + bool isTransaction() const; void commitTransaction(); app::Document* document(); diff --git a/src/app/commands/filters/filter_worker.cpp b/src/app/commands/filters/filter_worker.cpp index ba67cbb02..c1e60b0e8 100644 --- a/src/app/commands/filters/filter_worker.cpp +++ b/src/app/commands/filters/filter_worker.cpp @@ -16,6 +16,7 @@ #include "app/modules/editors.h" #include "app/modules/gui.h" #include "app/ui/editor/editor.h" +#include "app/ui/status_bar.h" #include "base/mutex.h" #include "base/scoped_lock.h" #include "base/thread.h" @@ -104,7 +105,7 @@ void FilterWorker::run() { scoped_lock lock(m_mutex); - if (m_done) + if (m_done && m_filterMgr->isTransaction()) m_filterMgr->commitTransaction(); else m_cancelled = true; @@ -117,6 +118,10 @@ void FilterWorker::run() Console console; console.printf("A problem has occurred.\n\nDetails:\n%s", m_error.c_str()); } + else if (m_cancelled && !m_filterMgr->isTransaction()) { + StatusBar::instance() + ->showTip(2500, "No unlocked layers to apply filter"); + } } // Called by FilterManagerImpl to informate the progress of the filter. diff --git a/src/app/document_undo.cpp b/src/app/document_undo.cpp index 973361ec3..288e3bb22 100644 --- a/src/app/document_undo.cpp +++ b/src/app/document_undo.cpp @@ -228,6 +228,7 @@ const undo::UndoState* DocumentUndo::nextRedo() const void DocumentUndo::onDeleteUndoState(undo::UndoState* state) { + ASSERT(state); Cmd* cmd = STATE_CMD(state); UNDO_TRACE("UNDO: Deleting undo state <%s> of %s from %s\n",