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 TrackList &l, const SelectedRegion &selectedRegion, const TranslatableString &longDescription, const TranslatableString &shortDescription, UndoPush flags=UndoPush::NONE)
 
void ModifyState (const TrackList &l, const SelectedRegion &selectedRegion)
 
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 ()
 
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

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 163 of file UndoManager.h.

Member Typedef Documentation

◆ Consumer

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

Definition at line 206 of file UndoManager.h.

Constructor & Destructor Documentation

◆ UndoManager() [1/2]

UndoManager::UndoManager ( AudacityProject project)
explicit

Definition at line 77 of file UndoManager.cpp.

78 : mProject{ project }
79{
80 current = -1;
81 saved = -1;
82}
AudacityProject & mProject
Definition: UndoManager.h:231

References current, and saved.

◆ ~UndoManager()

UndoManager::~UndoManager ( )

Definition at line 84 of file UndoManager.cpp.

85{
86 wxASSERT( stack.empty() );
87}
UndoStack stack
Definition: UndoManager.h:237

References stack.

◆ UndoManager() [2/2]

UndoManager::UndoManager ( const UndoManager )
delete

Member Function Documentation

◆ AbandonRedo()

void UndoManager::AbandonRedo ( )

Definition at line 268 of file UndoManager.cpp.

269{
270 if (saved > current) {
271 saved = -1;
272 }
273 RemoveStates( current + 1, stack.size() );
274}
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:

◆ ClearStates()

void UndoManager::ClearStates ( )

Definition at line 151 of file UndoManager.cpp.

152{
153 RemoveStates(0, stack.size());
154 current = -1;
155 saved = -1;
156}

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 118 of file UndoManager.cpp.

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

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 67 of file UndoManager.cpp.

68{
69 return project.AttachedObjects::Get< UndoManager >( key );
70}
static const AudacityProject::AttachedObjects::RegisteredFactory key
Definition: UndoManager.cpp:62
Maintain a non-persistent list of states of the project, to support undo and redo commands.
Definition: UndoManager.h:167

References key.

Referenced by MacroCommands::ApplyMacro(), ProjectFileManager::Compact(), ProjectFileManager::CompactProjectOnClose(), anonymous_namespace{ClipMenus.cpp}::DoClipLeftOrRight(), ProjectFileManager::DoSave(), EstimateRemovedBlocks(), ViewActions::Handler::Handler(), HistoryDialog::HistoryDialog(), ProjectHistory::InitialState(), LyricsPanel::LyricsPanel(), MenuManager::MenuManager(), ProjectHistory::ModifyState(), MenuManager::ModifyUndoMenuItems(), PluginActions::Handler::OnApplyMacroDirectlyByName(), ProjectManager::OnCloseWindow(), EditActions::Handler::OnRedo(), TrackActions::Handler::OnResample(), TransportActions::Handler::OnTimerRecord(), EditActions::Handler::OnUndo(), ProjectManager::OpenProject(), ProjectWindow::ProjectWindow(), ProjectHistory::PushState(), RealtimeEffectPanel::RealtimeEffectPanel(), ProjectHistory::RedoAvailable(), ProjectHistory::RollbackState(), ProjectHistory::SetStateTo(), SqliteSampleBlockFactory::SqliteSampleBlockFactory(), TrackPanel::TrackPanel(), ProjectHistory::UndoAvailable(), and UnsavedChangesFlag().

Here is the caller graph for this function:

◆ Get() [2/2]

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

Definition at line 72 of file UndoManager.cpp.

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

References BasicUI::Get().

Here is the call graph for this function:

◆ GetCurrentState()

unsigned int UndoManager::GetCurrentState ( )

Definition at line 163 of file UndoManager.cpp.

164{
165 return current;
166}

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 158 of file UndoManager.cpp.

159{
160 return stack.size();
161}

References stack.

◆ GetSavedState()

int UndoManager::GetSavedState ( ) const

Definition at line 368 of file UndoManager.cpp.

369{
370 return saved;
371}

References saved.

◆ GetShortDescription()

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

Definition at line 89 of file UndoManager.cpp.

90{
91 wxASSERT(n < stack.size());
92
93 *desc = stack[n]->shortDescription;
94}
const TranslatableString desc
Definition: ExportPCM.cpp:58

References desc, and stack.

◆ ModifyState()

void UndoManager::ModifyState ( const TrackList l,
const SelectedRegion selectedRegion 
)

Definition at line 178 of file UndoManager.cpp.

180{
181 if (current == wxNOT_FOUND) {
182 return;
183 }
184
185// SonifyBeginModifyState();
186 // Delete current -- not necessary, but let's reclaim space early
187 stack[current]->state.tracks.reset();
188
189 // Duplicate
190 auto tracksCopy = TrackList::Create( nullptr );
191 for (auto t : l) {
192 if ( t->GetId() == TrackId{} )
193 // Don't copy a pending added track
194 continue;
195 tracksCopy->Add(t->Duplicate());
196 }
197
198 // Replace
199 stack[current]->state.extensions = GetExtensions(mProject);
200 stack[current]->state.tracks = std::move(tracksCopy);
201
202 stack[current]->state.selectedRegion = selectedRegion;
203// SonifyEndModifyState();
204
206
207 if (saved == current)
208 saved = -1;
209}
An in-session identifier of track objects across undo states. It does not persist between sessions.
Definition: Track.h:151
static std::shared_ptr< TrackList > Create(AudacityProject *pOwner)
Definition: Track.cpp:502
void EnqueueMessage(UndoRedoMessage message)
UndoState::Extensions GetExtensions(AudacityProject &project)
Definition: UndoManager.cpp:45

References TrackList::Create(), current, EnqueueMessage(), anonymous_namespace{UndoManager.cpp}::GetExtensions(), UndoRedoMessage::Modified, mProject, saved, 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 TrackList l,
const SelectedRegion selectedRegion,
const TranslatableString longDescription,
const TranslatableString shortDescription,
UndoPush  flags = UndoPush::NONE 
)

Definition at line 224 of file UndoManager.cpp.

229{
230 if ( (flags & UndoPush::CONSOLIDATE) != UndoPush::NONE &&
231 // compare full translations not msgids!
232 lastAction.Translation() == longDescription.Translation() &&
234 ModifyState(l, selectedRegion);
235 // MB: If the "saved" state was modified by ModifyState, reset
236 // it so that UnsavedChanges returns true.
237 if (current == saved) {
238 saved = -1;
239 }
240 return;
241 }
242
243 auto tracksCopy = TrackList::Create( nullptr );
244 for (auto t : l) {
245 if ( t->GetId() == TrackId{} )
246 // Don't copy a pending added track
247 continue;
248 tracksCopy->Add(t->Duplicate());
249 }
250
251 mayConsolidate = true;
252
253 AbandonRedo();
254
255 stack.push_back(
256 std::make_unique<UndoStackElem>
257 (GetExtensions(mProject), std::move(tracksCopy),
258 longDescription, shortDescription, selectedRegion)
259 );
260
261 current++;
262
263 lastAction = longDescription;
264
266}
wxString Translation() const
void ModifyState(const TrackList &l, const SelectedRegion &selectedRegion)
bool mayConsolidate
Definition: UndoManager.h:240
void AbandonRedo()
TranslatableString lastAction
Definition: UndoManager.h:239

References AbandonRedo(), CONSOLIDATE, TrackList::Create(), 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 304 of file UndoManager.cpp.

305{
306 wxASSERT(RedoAvailable());
307
308 current++;
309
310 /*
311 if (!RedoAvailable()) {
312 *sel0 = stack[current]->sel0;
313 *sel1 = stack[current]->sel1;
314 }
315 else {
316 current++;
317 *sel0 = stack[current]->sel0;
318 *sel1 = stack[current]->sel1;
319 current--;
320 }
321 */
322
323 lastAction = {};
324 mayConsolidate = false;
325
326 consumer( *stack[current] );
327
329}
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 173 of file UndoManager.cpp.

174{
175 return (current < (int)stack.size() - 1);
176}

References current, and stack.

Referenced by Redo().

Here is the caller graph for this function:

◆ RemoveStateAt()

void UndoManager::RemoveStateAt ( int  n)
private

Definition at line 106 of file UndoManager.cpp.

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

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 126 of file UndoManager.cpp.

127{
129 auto cleanup =
130 finally([&]{ Publish({ UndoRedoMessage::EndPurge }); });
131
132 // Wrap the whole in a savepoint for better performance
133 TransactionScope trans{mProject, "DiscardingUndoStates"};
134
135 for (size_t ii = begin; ii < end; ++ii) {
137
138 if (current > begin)
139 --current;
140 if (saved > static_cast<int>(begin))
141 --saved;
142 }
143
144 // Success, commit the savepoint
145 trans.Commit();
146
147 if (begin != end)
149}
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)
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150
@ EndPurge
End elimination of old undo states.
Definition: UndoManager.h:79
@ Purge
Undo or redo states eliminated.
Definition: UndoManager.h:75
@ BeginPurge
Begin elimination of old undo states.
Definition: UndoManager.h:78

References PackedArray::begin(), UndoRedoMessage::BeginPurge, current, PackedArray::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 211 of file UndoManager.cpp.

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

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 96 of file UndoManager.cpp.

98{
99 n -= 1;
100
101 wxASSERT(n < stack.size());
102
103 stack[n]->description = desc;
104}

References desc, and stack.

◆ SetStateTo()

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

Definition at line 276 of file UndoManager.cpp.

277{
278 wxASSERT(n < stack.size());
279
280 current = n;
281
282 lastAction = {};
283 mayConsolidate = false;
284
285 consumer( *stack[current] );
286
288}

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

Here is the call graph for this function:

◆ StateSaved()

void UndoManager::StateSaved ( )

Definition at line 363 of file UndoManager.cpp.

364{
365 saved = current;
366}

References current, and saved.

Referenced by ProjectFileManager::DoSave().

Here is the caller graph for this function:

◆ StopConsolidating()

void UndoManager::StopConsolidating ( )
inline

Definition at line 198 of file UndoManager.h.

198{ mayConsolidate = false; }

◆ Undo()

void UndoManager::Undo ( const Consumer consumer)

Definition at line 290 of file UndoManager.cpp.

291{
292 wxASSERT(UndoAvailable());
293
294 current--;
295
296 lastAction = {};
297 mayConsolidate = false;
298
299 consumer( *stack[current] );
300
302}
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 168 of file UndoManager.cpp.

169{
170 return (current > 0);
171}

References current.

Referenced by Undo().

Here is the caller graph for this function:

◆ UnsavedChanges()

bool UndoManager::UnsavedChanges ( ) const

Definition at line 358 of file UndoManager.cpp.

359{
360 return (saved != current);
361}

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 331 of file UndoManager.cpp.

332{
333 auto fn = [&]( decltype(stack[0]) &ptr ){ consumer( *ptr ); };
334 if (newestFirst)
335 std::for_each(stack.rbegin(), stack.rend(), fn);
336 else
337 std::for_each(stack.begin(), stack.end(), fn);
338}
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 340 of file UndoManager.cpp.

342{
343 auto size = stack.size();
344 if (begin < end) {
345 end = std::min(end, size);
346 for (auto ii = begin; ii < end; ++ii)
347 consumer(*stack[ii]);
348 }
349 else {
350 if (size == 0)
351 return;
352 begin = std::min(begin, size - 1);
353 for (auto ii = begin; ii > end; --ii)
354 consumer(*stack[ii]);
355 }
356}
int min(int a, int b)

References PackedArray::begin(), PackedArray::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 239 of file UndoManager.h.

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

◆ mayConsolidate

bool UndoManager::mayConsolidate { false }
private

Definition at line 240 of file UndoManager.h.

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

◆ mProject

AudacityProject& UndoManager::mProject
private

Definition at line 231 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: