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

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

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(), 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 365 of file UndoManager.cpp.

366{
367 return saved;
368}

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}
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, 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 221 of file UndoManager.cpp.

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

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

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

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

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

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

Here is the call graph for this function:

◆ StateSaved()

void UndoManager::StateSaved ( )

Definition at line 360 of file UndoManager.cpp.

361{
362 saved = current;
363}

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

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

356{
357 return (saved != current);
358}

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

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

339{
340 auto size = stack.size();
341 if (begin < end) {
342 end = std::min(end, size);
343 for (auto ii = begin; ii < end; ++ii)
344 consumer(*stack[ii]);
345 }
346 else {
347 if (size == 0)
348 return;
349 begin = std::min(begin, size - 1);
350 for (auto ii = begin; ii > end; --ii)
351 consumer(*stack[ii]);
352 }
353}
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: