Audacity 3.2.0
Public Types | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | List of all members
UndoManager Class Referencefinal

Maintain a non-persistent list of states of the project, to support undo and redo commands. More...

#include <UndoManager.h>

Inheritance diagram for UndoManager:
[legend]
Collaboration diagram for UndoManager:
[legend]

Public Types

using Consumer = std::function< void(const UndoStackElem &) >
 
- Public Types inherited from Observer::Publisher< UndoRedoMessage >
using message_type = UndoRedoMessage
 
using CallbackReturn = std::conditional_t< true, void, bool >
 
using Callback = std::function< CallbackReturn(const UndoRedoMessage &) >
 Type of functions that can be connected to the Publisher. More...
 

Public Member Functions

 UndoManager (AudacityProject &project)
 
 ~UndoManager ()
 
 UndoManager (const UndoManager &)=delete
 
UndoManageroperator= (const UndoManager &)=delete
 
void PushState (const TranslatableString &longDescription, const TranslatableString &shortDescription, UndoPush flags=UndoPush::NONE)
 
void ModifyState ()
 
void RenameState (int state, const TranslatableString &longDescription, const TranslatableString &shortDescription)
 
void AbandonRedo ()
 
void ClearStates ()
 
void RemoveStates (size_t begin, size_t end)
 
unsigned int GetNumStates ()
 
unsigned int GetCurrentState ()
 
void StopConsolidating ()
 
void GetShortDescription (unsigned int n, TranslatableString *desc)
 
void SetLongDescription (unsigned int n, const TranslatableString &desc)
 
void SetStateTo (unsigned int n, const Consumer &consumer)
 
void Undo (const Consumer &consumer)
 
void Redo (const Consumer &consumer)
 
void VisitStates (const Consumer &consumer, bool newestFirst)
 Give read-only access to all states. More...
 
void VisitStates (const Consumer &consumer, size_t begin, size_t end)
 Visit a specified range of states. More...
 
bool UndoAvailable ()
 
bool RedoAvailable ()
 
void MarkUnsaved ()
 
bool UnsavedChanges () const
 
int GetSavedState () const
 
void StateSaved ()
 
- Public Member Functions inherited from ClientData::Base
virtual ~Base ()
 
- Public Member Functions inherited from Observer::Publisher< UndoRedoMessage >
 Publisher (ExceptionPolicy *pPolicy=nullptr, Alloc a={})
 Constructor supporting type-erased custom allocation/deletion. More...
 
 Publisher (Publisher &&)=default
 
Publisheroperator= (Publisher &&)=default
 
Subscription Subscribe (Callback callback)
 Connect a callback to the Publisher; later-connected are called earlier. More...
 
Subscription Subscribe (Object &obj, Return(Object::*callback)(Args...))
 Overload of Subscribe takes an object and pointer-to-member-function. More...
 

Static Public Member Functions

static UndoManagerGet (AudacityProject &project)
 
static const UndoManagerGet (const AudacityProject &project)
 

Private Member Functions

bool CheckAvailable (int index)
 
void EnqueueMessage (UndoRedoMessage message)
 
void RemoveStateAt (int n)
 

Private Attributes

AudacityProjectmProject
 
int current
 
int saved
 
UndoStack stack
 
TranslatableString lastAction
 
bool mayConsolidate { false }
 

Additional Inherited Members

- Static Public Attributes inherited from Observer::Publisher< UndoRedoMessage >
static constexpr bool notifies_all
 
- Protected Member Functions inherited from Observer::Publisher< UndoRedoMessage >
CallbackReturn Publish (const UndoRedoMessage &message)
 Send a message to connected callbacks. More...
 

Detailed Description

Maintain a non-persistent list of states of the project, to support undo and redo commands.

Works with HistoryDialog to provide the Undo functionality.

The history should be cleared before destruction

Definition at line 151 of file UndoManager.h.

Member Typedef Documentation

◆ Consumer

using UndoManager::Consumer = std::function< void( const UndoStackElem & ) >

Definition at line 191 of file UndoManager.h.

Constructor & Destructor Documentation

◆ UndoManager() [1/2]

UndoManager::UndoManager ( AudacityProject project)
explicit

Definition at line 81 of file UndoManager.cpp.

82 : mProject{ project }
83{
84 current = -1;
85 saved = -1;
86}
const auto project
AudacityProject & mProject
Definition: UndoManager.h:219

References current, and saved.

◆ ~UndoManager()

UndoManager::~UndoManager ( )

Definition at line 88 of file UndoManager.cpp.

89{
90 wxASSERT( stack.empty() );
91}
UndoStack stack
Definition: UndoManager.h:224

References stack.

◆ UndoManager() [2/2]

UndoManager::UndoManager ( const UndoManager )
delete

Member Function Documentation

◆ AbandonRedo()

void UndoManager::AbandonRedo ( )

Definition at line 255 of file UndoManager.cpp.

256{
257 if (saved > current) {
258 saved = -1;
259 }
260 RemoveStates( current + 1, stack.size() );
261}
void RemoveStates(size_t begin, size_t end)

References current, RemoveStates(), saved, and stack.

Referenced by PushState().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CheckAvailable()

bool UndoManager::CheckAvailable ( int  index)
private

Definition at line 182 of file UndoManager.cpp.

183{
184 if (index < 0 || index >= (int)stack.size())
185 return false;
186 auto &extensions = stack[index]->state.extensions;
187 return std::all_of(extensions.begin(), extensions.end(), [&](auto &ext){
188 return !ext || ext->CanUndoOrRedo(mProject);
189 });
190}

References stack.

Referenced by RedoAvailable(), and UndoAvailable().

Here is the caller graph for this function:

◆ ClearStates()

void UndoManager::ClearStates ( )

Definition at line 155 of file UndoManager.cpp.

156{
157 RemoveStates(0, stack.size());
158 current = -1;
159 saved = -1;
160}

References current, RemoveStates(), saved, and stack.

Referenced by ProjectManager::OnCloseWindow().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ EnqueueMessage()

void UndoManager::EnqueueMessage ( UndoRedoMessage  message)
private

Definition at line 122 of file UndoManager.cpp.

123{
124 BasicUI::CallAfter([wThis = weak_from_this(), message]{
125 if (auto pThis = wThis.lock())
126 pThis->Publish(message);
127 });
128}
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
Definition: BasicUI.cpp:213

References BasicUI::CallAfter().

Referenced by ModifyState(), PushState(), Redo(), RemoveStates(), RenameState(), SetStateTo(), and Undo().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Get() [1/2]

UndoManager & UndoManager::Get ( AudacityProject project)
static

Definition at line 71 of file UndoManager.cpp.

72{
73 return project.AttachedObjects::Get< UndoManager >( key );
74}
static const AudacityProject::AttachedObjects::RegisteredFactory key
Definition: UndoManager.cpp:66
Maintain a non-persistent list of states of the project, to support undo and redo commands.
Definition: UndoManager.h:155

References key, and project.

Referenced by MacroCommands::ApplyMacro(), ProjectFileManager::Compact(), ProjectFileManager::CompactProjectOnClose(), anonymous_namespace{RealtimeEffectPanel.cpp}::RealtimeEffectControl::Create(), anonymous_namespace{ClipMenus.cpp}::DoClipLeftOrRight(), ProjectFileManager::DoSave(), EstimateRemovedBlocks(), HistoryDialog::HistoryDialog(), ProjectHistory::InitialState(), ProjectHistory::ModifyState(), CommandManager::ModifyUndoMenuItems(), anonymous_namespace{BatchProcessDialog.cpp}::OnApplyMacroDirectlyByName(), ProjectManager::OnCloseWindow(), EffectUIHost::OnEnable(), anonymous_namespace{EditMenus.cpp}::OnRedo(), anonymous_namespace{TrackMenus.cpp}::OnResample(), anonymous_namespace{TimerRecordDialog.cpp}::OnTimerRecord(), anonymous_namespace{EditMenus.cpp}::OnUndo(), ProjectManager::OpenProject(), ProjectHistory::PushState(), RealtimeEffectPanel::RealtimeEffectPanel(), ProjectHistory::RedoAvailable(), ProjectHistory::RollbackState(), ProjectHistory::SetStateTo(), RealtimeEffectStateUI::Show(), SqliteSampleBlockFactory::SqliteSampleBlockFactory(), TrackPanel::TrackPanel(), and ProjectHistory::UndoAvailable().

Here is the caller graph for this function:

◆ Get() [2/2]

const UndoManager & UndoManager::Get ( const AudacityProject project)
static

Definition at line 76 of file UndoManager.cpp.

77{
78 return Get( const_cast< AudacityProject & >( project ) );
79}
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
static UndoManager & Get(AudacityProject &project)
Definition: UndoManager.cpp:71

References BasicUI::Get(), and project.

Here is the call graph for this function:

◆ GetCurrentState()

unsigned int UndoManager::GetCurrentState ( )

Definition at line 167 of file UndoManager.cpp.

168{
169 return current;
170}

References current.

Referenced by HistoryDialog::DoUpdate(), and HistoryDialog::Populate().

Here is the caller graph for this function:

◆ GetNumStates()

unsigned int UndoManager::GetNumStates ( )

Definition at line 162 of file UndoManager.cpp.

163{
164 return stack.size();
165}

References stack.

◆ GetSavedState()

int UndoManager::GetSavedState ( ) const

Definition at line 360 of file UndoManager.cpp.

361{
362 return saved;
363}

References saved.

◆ GetShortDescription()

void UndoManager::GetShortDescription ( unsigned int  n,
TranslatableString desc 
)

Definition at line 93 of file UndoManager.cpp.

94{
95 wxASSERT(n < stack.size());
96
97 *desc = stack[n]->shortDescription;
98}
const TranslatableString desc
Definition: ExportPCM.cpp:51

References anonymous_namespace{ExportPCM.cpp}::desc, and stack.

◆ MarkUnsaved()

void UndoManager::MarkUnsaved ( )

Definition at line 345 of file UndoManager.cpp.

346{
347 saved = -1;
348}

References saved.

Referenced by anonymous_namespace{RealtimeEffectPanel.cpp}::RealtimeEffectControl::Create(), EffectUIHost::OnEnable(), RealtimeEffectPanel::RealtimeEffectPanel(), and RealtimeEffectStateUI::Show().

Here is the caller graph for this function:

◆ ModifyState()

void UndoManager::ModifyState ( )

Definition at line 192 of file UndoManager.cpp.

193{
194 if (current == wxNOT_FOUND) {
195 return;
196 }
197
198// SonifyBeginModifyState();
199 auto &state = stack[current]->state;
200
201 // Re-create all captured project state
202 state.extensions = GetExtensions(mProject);
203
204// SonifyEndModifyState();
205
207}
void EnqueueMessage(UndoRedoMessage message)
UndoState::Extensions GetExtensions(AudacityProject &project)
Definition: UndoManager.cpp:49

References current, EnqueueMessage(), anonymous_namespace{UndoManager.cpp}::GetExtensions(), UndoRedoMessage::Modified, mProject, and stack.

Referenced by PushState().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator=()

UndoManager & UndoManager::operator= ( const UndoManager )
delete

◆ PushState()

void UndoManager::PushState ( const TranslatableString longDescription,
const TranslatableString shortDescription,
UndoPush  flags = UndoPush::NONE 
)

Definition at line 222 of file UndoManager.cpp.

225{
226 if ( (flags & UndoPush::CONSOLIDATE) != UndoPush::NONE &&
227 // compare full translations not msgids!
228 lastAction.Translation() == longDescription.Translation() &&
230 ModifyState();
231 // MB: If the "saved" state was modified by ModifyState, reset
232 // it so that UnsavedChanges returns true.
233 if (current == saved) {
234 saved = -1;
235 }
236 return;
237 }
238
239 mayConsolidate = true;
240
241 AbandonRedo();
242
243 stack.push_back(
244 std::make_unique<UndoStackElem>
245 (GetExtensions(mProject), longDescription, shortDescription)
246 );
247
248 current++;
249
250 lastAction = longDescription;
251
253}
wxString Translation() const
bool mayConsolidate
Definition: UndoManager.h:227
void AbandonRedo()
TranslatableString lastAction
Definition: UndoManager.h:226
void ModifyState()

References AbandonRedo(), CONSOLIDATE, current, EnqueueMessage(), anonymous_namespace{UndoManager.cpp}::GetExtensions(), lastAction, mayConsolidate, ModifyState(), mProject, NONE, UndoRedoMessage::Pushed, saved, stack, and TranslatableString::Translation().

Here is the call graph for this function:

◆ Redo()

void UndoManager::Redo ( const Consumer consumer)

Definition at line 291 of file UndoManager.cpp.

292{
293 wxASSERT(RedoAvailable());
294
295 current++;
296
297 /*
298 if (!RedoAvailable()) {
299 *sel0 = stack[current]->sel0;
300 *sel1 = stack[current]->sel1;
301 }
302 else {
303 current++;
304 *sel0 = stack[current]->sel0;
305 *sel1 = stack[current]->sel1;
306 current--;
307 }
308 */
309
310 lastAction = {};
311 mayConsolidate = false;
312
313 consumer( *stack[current] );
314
316}
bool RedoAvailable()

References current, EnqueueMessage(), lastAction, mayConsolidate, RedoAvailable(), stack, and UndoRedoMessage::UndoOrRedo.

Here is the call graph for this function:

◆ RedoAvailable()

bool UndoManager::RedoAvailable ( )

Definition at line 177 of file UndoManager.cpp.

178{
179 return CheckAvailable(current + 1);
180}
bool CheckAvailable(int index)

References CheckAvailable(), and current.

Referenced by Redo().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ RemoveStateAt()

void UndoManager::RemoveStateAt ( int  n)
private

Definition at line 110 of file UndoManager.cpp.

111{
112 // Remove the state from the array first, and destroy it at function exit.
113 // Because in case of callbacks from destruction of Sample blocks, there
114 // might be a yield to GUI and other events might inspect the undo stack
115 // (such as history window update). Don't expose an inconsistent stack
116 // state.
117 auto iter = stack.begin() + n;
118 auto state = std::move(*iter);
119 stack.erase(iter);
120}

References stack.

Referenced by RemoveStates().

Here is the caller graph for this function:

◆ RemoveStates()

void UndoManager::RemoveStates ( size_t  begin,
size_t  end 
)
Parameters
begininclusive start of range
endexclusive end of range

Definition at line 130 of file UndoManager.cpp.

131{
133 auto cleanup =
134 finally([&]{ Publish({ UndoRedoMessage::EndPurge }); });
135
136 // Wrap the whole in a savepoint for better performance
137 TransactionScope trans{mProject, "DiscardingUndoStates"};
138
139 for (size_t ii = begin; ii < end; ++ii) {
141
142 if (current > begin)
143 --current;
144 if (saved > static_cast<int>(begin))
145 --saved;
146 }
147
148 // Success, commit the savepoint
149 trans.Commit();
150
151 if (begin != end)
153}
CallbackReturn Publish(const UndoRedoMessage &message)
Send a message to connected callbacks.
Definition: Observer.h:207
RAII for a database transaction, possibly nested.
void RemoveStateAt(int n)
const char * end(const char *str) noexcept
Definition: StringUtils.h:106
const char * begin(const char *str) noexcept
Definition: StringUtils.h:101
@ EndPurge
End elimination of old undo states.
Definition: UndoManager.h:73
@ Purge
Undo or redo states eliminated.
Definition: UndoManager.h:69
@ BeginPurge
Begin elimination of old undo states.
Definition: UndoManager.h:72

References details::begin(), UndoRedoMessage::BeginPurge, current, details::end(), UndoRedoMessage::EndPurge, EnqueueMessage(), mProject, Observer::Publisher< UndoRedoMessage >::Publish(), UndoRedoMessage::Purge, RemoveStateAt(), and saved.

Referenced by AbandonRedo(), ClearStates(), and HistoryDialog::OnDiscard().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ RenameState()

void UndoManager::RenameState ( int  state,
const TranslatableString longDescription,
const TranslatableString shortDescription 
)

Definition at line 209 of file UndoManager.cpp.

212{
213 if (state >= 0 && state < stack.size() ) {
214 auto &theState = *stack[state];
215 theState.description = longDescription;
216 theState.shortDescription = shortDescription;
217
219 }
220}

References EnqueueMessage(), UndoRedoMessage::Renamed, and stack.

Here is the call graph for this function:

◆ SetLongDescription()

void UndoManager::SetLongDescription ( unsigned int  n,
const TranslatableString desc 
)

Definition at line 100 of file UndoManager.cpp.

102{
103 n -= 1;
104
105 wxASSERT(n < stack.size());
106
107 stack[n]->description = desc;
108}

References anonymous_namespace{ExportPCM.cpp}::desc, and stack.

◆ SetStateTo()

void UndoManager::SetStateTo ( unsigned int  n,
const Consumer consumer 
)

Definition at line 263 of file UndoManager.cpp.

264{
265 wxASSERT(n < stack.size());
266
267 current = n;
268
269 lastAction = {};
270 mayConsolidate = false;
271
272 consumer( *stack[current] );
273
275}

References current, EnqueueMessage(), lastAction, mayConsolidate, UndoRedoMessage::Reset, and stack.

Here is the call graph for this function:

◆ StateSaved()

void UndoManager::StateSaved ( )

Definition at line 355 of file UndoManager.cpp.

356{
357 saved = current;
358}

References current, and saved.

Referenced by ProjectFileManager::DoSave().

Here is the caller graph for this function:

◆ StopConsolidating()

void UndoManager::StopConsolidating ( )
inline

Definition at line 183 of file UndoManager.h.

183{ mayConsolidate = false; }

◆ Undo()

void UndoManager::Undo ( const Consumer consumer)

Definition at line 277 of file UndoManager.cpp.

278{
279 wxASSERT(UndoAvailable());
280
281 current--;
282
283 lastAction = {};
284 mayConsolidate = false;
285
286 consumer( *stack[current] );
287
289}
bool UndoAvailable()

References current, EnqueueMessage(), lastAction, mayConsolidate, stack, UndoAvailable(), and UndoRedoMessage::UndoOrRedo.

Here is the call graph for this function:

◆ UndoAvailable()

bool UndoManager::UndoAvailable ( )

Definition at line 172 of file UndoManager.cpp.

173{
174 return CheckAvailable(current - 1);
175}

References CheckAvailable(), and current.

Referenced by Undo().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ UnsavedChanges()

bool UndoManager::UnsavedChanges ( ) const

Definition at line 350 of file UndoManager.cpp.

351{
352 return (saved != current);
353}

References current, and saved.

Referenced by ProjectFileManager::CompactProjectOnClose().

Here is the caller graph for this function:

◆ VisitStates() [1/2]

void UndoManager::VisitStates ( const Consumer consumer,
bool  newestFirst 
)

Give read-only access to all states.

Definition at line 318 of file UndoManager.cpp.

319{
320 auto fn = [&]( decltype(stack[0]) &ptr ){ consumer( *ptr ); };
321 if (newestFirst)
322 std::for_each(stack.rbegin(), stack.rend(), fn);
323 else
324 std::for_each(stack.begin(), stack.end(), fn);
325}
static const auto fn

References fn, and stack.

Referenced by HistoryDialog::DoUpdate().

Here is the caller graph for this function:

◆ VisitStates() [2/2]

void UndoManager::VisitStates ( const Consumer consumer,
size_t  begin,
size_t  end 
)

Visit a specified range of states.

end is exclusive; visit newer states first if end < begin

Definition at line 327 of file UndoManager.cpp.

329{
330 auto size = stack.size();
331 if (begin < end) {
332 end = std::min(end, size);
333 for (auto ii = begin; ii < end; ++ii)
334 consumer(*stack[ii]);
335 }
336 else {
337 if (size == 0)
338 return;
339 begin = std::min(begin, size - 1);
340 for (auto ii = begin; ii > end; --ii)
341 consumer(*stack[ii]);
342 }
343}
int min(int a, int b)

References details::begin(), details::end(), min(), size, and stack.

Here is the call graph for this function:

Member Data Documentation

◆ current

int UndoManager::current
private

◆ lastAction

TranslatableString UndoManager::lastAction
private

Definition at line 226 of file UndoManager.h.

Referenced by PushState(), Redo(), SetStateTo(), and Undo().

◆ mayConsolidate

bool UndoManager::mayConsolidate { false }
private

Definition at line 227 of file UndoManager.h.

Referenced by PushState(), Redo(), SetStateTo(), and Undo().

◆ mProject

AudacityProject& UndoManager::mProject
private

Definition at line 219 of file UndoManager.h.

Referenced by ModifyState(), PushState(), and RemoveStates().

◆ saved

int UndoManager::saved
private

◆ stack

UndoStack UndoManager::stack
private

The documentation for this class was generated from the following files: