Skip to content

Commit

Permalink
Handle undoable operations in a correct way. Low-level algorithm shou…
Browse files Browse the repository at this point in the history
…ldn't start undoable operations on their own, this is the responsibility of calling code. This fixes the crash occurring in ff33068.

Creating another undoable operation when a previous one is already opened will lead to an assertion now.
  • Loading branch information
codereader committed Mar 9, 2020
1 parent 686fae6 commit e43b36f
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 27 deletions.
1 change: 1 addition & 0 deletions radiant/selection/algorithm/Group.cpp
Expand Up @@ -549,6 +549,7 @@ void deleteAllSelectionGroupsCmd(const cmd::ArgumentList& args)
return;
}

UndoableCommand cmd("DeleteAllSelectionGroups");
getMapSelectionGroupManager().deleteAllSelectionGroups();
}

Expand Down
12 changes: 1 addition & 11 deletions radiant/selection/group/SelectionGroupManager.cpp
Expand Up @@ -9,7 +9,6 @@
#include "iselection.h"
#include "ieventmanager.h"
#include "imainframe.h"
#include "iundo.h"
#include "iorthocontextmenu.h"
#include "modulesystem/StaticModule.h"
#include "selection/algorithm/Group.h"
Expand Down Expand Up @@ -68,13 +67,6 @@ void SelectionGroupManager::setGroupSelected(std::size_t id, bool selected)
}

void SelectionGroupManager::deleteSelectionGroup(std::size_t id)
{
UndoableCommand cmd("DeleteSelectionGroup");

doDeleteSelectionGroup(id);
}

void SelectionGroupManager::doDeleteSelectionGroup(std::size_t id)
{
SelectionGroupMap::iterator found = _groups.find(id);

Expand All @@ -91,11 +83,9 @@ void SelectionGroupManager::doDeleteSelectionGroup(std::size_t id)

void SelectionGroupManager::deleteAllSelectionGroups()
{
UndoableCommand cmd("DeleteAllSelectionGroups");

for (SelectionGroupMap::iterator g = _groups.begin(); g != _groups.end(); )
{
doDeleteSelectionGroup((g++)->first);
deleteSelectionGroup((g++)->first);
}

assert(_groups.empty());
Expand Down
2 changes: 0 additions & 2 deletions radiant/selection/group/SelectionGroupManager.h
Expand Up @@ -35,8 +35,6 @@ class SelectionGroupManager :
private:
std::size_t generateGroupId();
void resetNextGroupId();

void doDeleteSelectionGroup(std::size_t id);
};

}
33 changes: 19 additions & 14 deletions radiant/undo/Stack.h
Expand Up @@ -27,7 +27,8 @@ class UndoStack
// The list of Operations that can be undone
Operations _stack;

// The pending undo operation (a working variable, so to say)
// The pending undo operation (will be committed as soon as the first
// undoable saves its data to the stack)
OperationPtr _pending;

public:
Expand Down Expand Up @@ -70,35 +71,39 @@ class UndoStack
// Allocate a new Operation to work with
void start(const std::string& command)
{
if (_pending)
{
_pending.reset();
}
// When starting an operation, we create one and declare it as pending
// It will not be added to the stack, it still might end up empty
// We will also replace any previously pending operation with the new one
// even though it should not happen by design
ASSERT_MESSAGE(!_pending, "undo operation already started");

_pending.reset(new Operation(command));
_pending = std::make_shared<Operation>(command);
}

// Finish the current undo operation
bool finish(const std::string& command)
{
if (_pending)
{
// The started operation has not been filled with any data
// so just discard it without doing anything
_pending.reset();
return false;
}
else
{
// Rename the last undo operation (it was "unnamed" till now)
ASSERT_MESSAGE(!_stack.empty(), "undo stack empty");
_stack.back()->setName(command);
return true;
}

// Reaching this point we don't have a *pending* operation
// but we need to make sure we have *any* operation at all
ASSERT_MESSAGE(!_stack.empty(), "undo stack empty");

// Rename the last undo operation (it may be "unnamed" till now)
_stack.back()->setName(command);
return true;
}

// Store an Undoable into the last snapshot
void save(IUndoable& undoable)
{
// Check, if there is still a pending undo command around
// Check, if there is still a pending undo operation waiting to be added to the stack
if (_pending)
{
// Save the pending undo command
Expand Down

0 comments on commit e43b36f

Please sign in to comment.