25#include <wx/textfile.h>
36#pragma warning( disable : 4786 )
80 auto pList =
mList.lock();
82 pList->SelectionEvent(*
this);
88 auto pList =
mList.lock();
97 auto result =
Clone();
100 const auto copyOne = [&](
const Track *pChannel){
101 pChannel->AttachedTrackObjects::ForEach([&](
auto &attachment){
103 attachment.CopyTo(**iter);
124 wxASSERT(
mList.lock() == NULL ||
this ==
mNode.first->get());
149 auto pList =
mList.lock();
150 if (pList && pList->mPendingUpdates && !pList->mPendingUpdates->empty()) {
151 auto orig = pList->FindById(
GetId() );
152 if (orig && orig !=
this) {
153 orig->SetLinkType(linkType);
161 pList->RecalcPositions(
mNode);
162 pList->ResizingEvent(
mNode);
170 if (
auto pLeader = *pList->Find(pTrack))
173 return pTrack->ChannelGroup::GetGroupData();
184 if (linkType == oldType)
193 partner->DestroyGroupData();
201 partner->DestroyGroupData();
210 assert(!partner->FindGroupData());
211 partner->ChannelGroup::Init(*
this);
233 if (!pList->isNull(
mNode)) {
236 if ( !pList->isNull( next ) )
237 return next.first->get();
241 auto prev = pList->getPrev(
mNode );
242 if ( !pList->isNull( prev ) ) {
243 auto track = prev.first->get();
244 if (track && track->HasLinkedTrack())
266 auto pList =
mList.lock();
280 if (newT1 > oldT1 && oldT1 > endTime)
283 auto cutChannels =
Cut(oldT1, endTime);
284 assert(
NChannels() == cutChannels->NChannels());
285 Paste(newT1, *cutChannels);
287 else if (newT1 < oldT1)
316 if (link->HasLinkedTrack()) {
320 L
"Left track %s had linked right track %s with extra right "
321 "track link.\n Removing extra link from right track.",
331 L
"Track %s had link to NULL track. Setting it to not be linked.",
374 return std::make_shared<TrackList>(pOwner);
391 ListOfTracks &a,
const std::weak_ptr< TrackList > &aSelf,
392 ListOfTracks &b,
const std::weak_ptr< TrackList > &bSelf )
395 for (
auto it = a.begin(), last = a.end(); it != last; ++it)
396 (*it)->SetOwner(aSelf, {it, &a});
397 for (
auto it = b.begin(), last = b.end(); it != last; ++it)
398 (*it)->SetOwner(bSelf, {it, &b});
401 const auto self = shared_from_this();
402 const auto otherSelf = that.shared_from_this();
403 SwapLOTs( *
this, self, that, otherSelf );
405 assert(!GetOwner() && !that.GetOwner());
407 assert(!this->mPendingUpdates);
408 assert(!that.mPendingUpdates);
410 mUpdaters.swap(that.mUpdaters);
422 auto name = wxString::Format(
"%s %d", baseTrackName, n++);
425 for(
const auto track : Tracks<const Track>()) {
426 if(track->GetName() ==
name) {
446 t = prev.first->get();
450 const auto theEnd =
End();
451 for (
auto n =
DoFind(node.first->get()); n != theEnd; ++n) {
462 if (
auto pThis = wThis.lock())
463 pThis->Publish(event);
475 const std::shared_ptr<Track> &pTrack,
bool allChannels,
int code)
477 auto doQueueEvent = [
this, code](
const std::shared_ptr<Track> &theTrack){
481 for (
auto channel :
Channels(pTrack.get()))
482 doQueueEvent(channel->shared_from_this());
484 doQueueEvent(pTrack);
488 const std::shared_ptr<Track> &pTrack,
bool modifyState )
491 const auto pLeader = *
Find(pTrack.get());
493 pLeader ? pLeader->SharedPointer() :
nullptr,
494 static_cast<int>(modifyState) });
530 if (!pTrack || pTrack->GetHolder() !=
this)
531 return EndIterator<Track>();
533 return MakeTrackIterator<Track>(pTrack->GetNode());
538 auto iter = DoFind(pTrack);
539 while( *iter && ! ( *iter )->IsLeader() )
551 auto pPartner = pOwner->GetNext(&track,
false);
558 pOwner->MoveUp(pPartner);
559 pPartner->AssignGroupData(move(pData));
565 assert(before ==
nullptr || (before->
IsLeader() &&
Find(before) != EndIterator<const Track>()));
567 if(before ==
nullptr)
569 Append(std::move(trackList));
573 std::vector<Track *> arr;
574 arr.reserve(
Size() + trackList.Size());
575 for (
const auto track : *
this) {
578 for(
const auto addedTrack : trackList)
579 arr.push_back(addedTrack);
581 arr.push_back(track);
583 Append(std::move(trackList));
589 std::vector<TrackNodePointer> permutation;
590 for (
const auto pTrack :
tracks)
591 for (
const auto pChannel :
Channels(pTrack))
592 permutation.push_back(pChannel->GetNode());
593 for (
const auto iter : permutation) {
594 ListOfTracks::value_type track = *iter.first;
596 Track *pTrack = track.get();
597 pTrack->
SetOwner(shared_from_this(),
610 [=](
const ListOfTracks::value_type &ptr){
return ptr->GetId() ==
id; } );
618 Track *pTrack = t.get();
619 push_front(ListOfTracks::value_type(t));
621 pTrack->
SetOwner(shared_from_this(), n);
625 return front().get();
630 if (!ListOfTracks::empty()) {
631 auto &pLast = *ListOfTracks::rbegin();
632 if (
auto pGroupData = pLast->FindGroupData()
638 t->DestroyGroupData();
646 t->SetOwner(shared_from_this(), n);
661 assert(nChannels >= (*with.begin())->NChannels());
665 auto iter = with.ListOfTracks::begin(),
666 end = with.ListOfTracks::end();
667 bool isLeader =
true;
668 std::vector<Track*> saveChannels;
670 saveChannels.push_back(pChannel);
673 std::optional<TrackNodePointer> lastNode;
675 for (
const auto pChannel : saveChannels) {
676 auto spChannel = pChannel->shared_from_this();
679 auto node = pChannel->GetNode();
680 pChannel->SetOwner({}, {});
681 result->Add(spChannel);
684 assert(isLeader == pChannel->IsLeader());
688 node.second->erase(node.first);
693 lastNode.emplace(node);
695 const auto pTrack = *iter;
696 *node.first = pTrack;
697 iter = with.erase(iter);
698 pTrack->SetOwner(shared_from_this(), node);
699 pTrack->SetId(pChannel->GetId());
710 auto list = track.
mList.lock();
711 if (list.get() ==
this)
714 for (
auto c : channels)
716 return { channels.begin(), channels.end() };
727 auto list = track.
mList.lock();
728 if (list.get() ==
this) {
729 if (*list->Find(&track) != &track)
732 auto first = list->DoFind(&track);
733 auto canLink = [&]() ->
bool {
734 int count = nChannels;
737 if ((*it)->HasLinkedTrack())
750 for(
auto it = std::next(first), last = std::next(first, nChannels);
754 (*it)->DestroyGroupData();
768 for (
size_t ii = 0; t !=
nullptr && ii < nChannels; ++ii, t = nextT) {
771 auto node = t->GetNode();
775 ListOfTracks::value_type holder = *node.first;
781 nextT = iter.first->get();
794 for (
auto pTrack: Tracks<Track>()) {
795 pTrack->SetOwner({}, {});
803 pTrack->SetOwner({}, {});
809 tempList.swap( *
this );
830 return node.first->get();
861 !(*node.first)->HasLinkedTrack() && (*node.first)->GetLinkedTrack() )
865 return node.first->get();
875 return GetPrev(t,
true) != NULL;
880 return GetNext(t,
true) != NULL;
894 s1 = ( *
Find( s1.first->get() ) )->GetNode();
895 s2 = ( *
Find( s2.first->get() ) )->GetNode();
902 if ((*s1.first)->GetIndex() >= (*s2.first)->GetIndex())
906 using Saved = std::vector< ListOfTracks::value_type >;
907 Saved saved1, saved2;
914 saved[nn] = *s.first, s.first = erase(s.first);
917 doSave( saved1, s1 );
919 const bool same = (s1 == s2);
920 doSave( saved2, s2 );
928 for (
auto & pointer : saved)
929 pTrack = pointer.get(),
932 pTrack->
SetOwner(shared_from_this(),
933 s = { insert(s.first, pointer),
this } );
936 doInsert( saved2, s1 );
939 doInsert( saved1, s2 );
991 const double &(*combine)(
const double&,
const double&))
998 return list.
Any().accumulate(
ident, combine, memfn);
1005 std::numeric_limits<double>::max(),
std::min);
1011 std::numeric_limits<double>::lowest(), std::max);
1028 for (
const auto pChannel : channels)
1032 const auto result = *
tracks->begin();
1034 auto iter =
tracks->ListOfTracks::begin(),
1036 while (iter !=
end) {
1037 auto pTrack = *iter;
1038 iter =
tracks->erase(iter);
1053 auto src =
FindById(pendingTrack->GetId());
1057 if (pendingTrack && src) {
1062 pendingTrack->DoSetLinkType(src->GetLinkType());
1071 pTrack->SetOwner( {}, {} );
1080 bool foundNode =
false;
1084 if (it->get()->GetId() ==
TrackId{}) {
1087 pAdded->push_back( *it );
1088 (*it)->SetOwner( {}, {} );
1092 while (it != stop && it->get()->GetId() ==
TrackId{});
1094 if (!foundNode && it != stop) {
1095 node = (*it)->GetNode();
1111 bool result =
false;
1125 std::vector< std::shared_ptr<Track> > reinstated;
1128 for (
auto pendingTrack :
static_cast<ListOfTracks &
>(*updates))
1129 pendingTrack->AttachedTrackObjects::ForEach([&](
auto &attachment){
1130 attachment.Reparent( pendingTrack );
1132 while (updates && !updates->empty()) {
1133 auto iter = updates->ListOfTracks::begin();
1134 auto pendingTrack = *iter;
1135 auto src =
FindById(pendingTrack->GetId());
1144 reinstated.push_back(pendingTrack);
1145 updates->ListOfTracks::erase(iter);
1150 for (
auto &pendingTrack : reinstated)
1152 this->
Add( pendingTrack ), result =
true;
1156 bool inserted =
false;
1157 ListOfTracks::iterator first;
1158 for (
auto &pendingTrack : additions) {
1161 std::advance( iter, pendingTrack->GetIndex() );
1162 iter = ListOfTracks::insert( iter, pendingTrack );
1163 pendingTrack->SetOwner( shared_from_this(), {iter,
this} );
1184 auto pList =
mList.lock();
1185 if (pList && pList->mPendingUpdates) {
1186 const auto id =
GetId();
1187 const auto end = pList->mPendingUpdates->ListOfTracks::end();
1188 auto it = std::find_if(
1189 pList->mPendingUpdates->ListOfTracks::begin(),
end,
1190 [=](
const ListOfTracks::value_type &ptr){ return ptr->GetId() == id; } );
1204 auto pList =
mList.lock();
1205 if (pList && pList->mPendingUpdates) {
1206 const auto id =
GetId();
1207 const auto pred = [=](
const ListOfTracks::value_type &ptr ) {
1208 return ptr->GetId() ==
id; };
1209 const auto end = pList->mPendingUpdates->ListOfTracks::end();
1211 std::find_if(pList->mPendingUpdates->ListOfTracks::begin(),
end, pred);
1214 const auto end2 = list2.end();
1215 const auto it2 = std::find_if( list2.begin(), end2, pred );
1226 {
"generic",
"generic",
XO(
"Generic Track") },
false };
1237 XMLWriter &xmlFile,
bool includeNameAndSelected)
const
1239 if (includeNameAndSelected) {
1247 attachment.WriteXMLAttributes( xmlFile );
1257 bool handled =
false;
1259 handled = handled || attachment.HandleXMLAttribute( attr, valueView );
1266 else if (attr ==
"name") {
1270 else if (attr ==
"isSelected" && valueView.
TryGet(nValue)) {
1279 auto pList =
mList.lock();
1281 pList->RecalcPositions(
mNode);
1282 pList->ResizingEvent(
mNode);
1326 assert(!pTrack || iChannel < pTrack->NChannels());
1329 const auto pAttachments =
1332 if (!pAttachments ||
iChannel >= pAttachments->mAttachments.size())
1352 pAttachment->CopyTo(track);
1359 pAttachment->Reparent(parent);
1366 pAttachment->WriteXMLAttributes(writer);
1373 [&](
auto &pAttachment) {
1374 return pAttachment && pAttachment->HandleXMLAttribute(attr, valueView);
1383 mProjectTempo = newTempo;
1395 : mpTracks{
TrackList::Create(nullptr) }
1398 if (pTrack->GetId() ==
TrackId{})
1401 mpTracks->
Append(std::move(*pTrack->Duplicate()));
1407 for (
auto pTrack : *mpTracks)
1408 dstTracks.Append(std::move(*pTrack->Duplicate()));
1418 return std::make_shared<TrackListRestorer>(
project);
1427 iter = std::find_if(
exts.begin(),
end, [](
auto &pExt){
1428 return dynamic_cast<TrackListRestorer*>(pExt.get());
1431 return static_cast<TrackListRestorer*
>(iter->get())->mpTracks.get();
1438 assert(left ==
nullptr || left->GetOwner() ==
nullptr);
1439 assert(right ==
nullptr || (left && right->GetOwner() ==
nullptr));
1441 auto tempList =
Create(pProject);
1443 tempList->Add(left);
1445 tempList->Add(right);
1446 tempList->MakeMultiChannelTrack(*left, 2);
1449 tempList->mAssignsIds =
false;
1454 const std::vector<Track::Holder> &channels)
1456 auto nChannels = channels.size();
1458 (nChannels > 0 ? channels[0] :
nullptr),
1459 (nChannels > 1 ? channels[1] :
nullptr));
1467 auto iter = list.ListOfTracks::begin(),
1468 end = list.ListOfTracks::end();
1469 while (iter !=
end) {
1470 auto pTrack = *iter;
1471 iter = list.erase(iter);
1478 for(
auto it = list.ListOfTracks::begin(); it != list.ListOfTracks::end();)
1482 it = list.erase(it);
1488 auto iter = list.ListOfTracks::begin(),
1489 end = list.ListOfTracks::end();
1492 auto pTrack = *iter;
1493 iter = list.erase(iter);
Toolkit-neutral facade for basic user interface services.
const TranslatableString name
MessageBoxException for violation of preconditions or assertions.
#define THROW_INCONSISTENCY_EXCEPTION
Throw InconsistencyException, using C++ preprocessor to identify the source code location.
static CommandHandlerObject & ident(AudacityProject &project)
static const AudacityProject::AttachedObjects::RegisteredFactory key
declares abstract base class Track, TrackList, and iterators over TrackList
std::pair< ListOfTracks::iterator, ListOfTracks * > TrackNodePointer
Pairs a std::list iterator and a pointer to a list, for comparison purposes.
std::list< std::shared_ptr< Track > > ListOfTracks
std::shared_ptr< TrackList > TrackListHolder
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Holds multiple objects as a single attachment to Track.
static TrackAttachment & Get(const AttachedTrackObjects::RegisteredFactory &key, Track &track, size_t iChannel)
std::vector< std::shared_ptr< TrackAttachment > > mAttachments
~ChannelAttachmentsBase() override
void WriteXMLAttributes(XMLWriter &writer) const override
Serialize persistent attributes.
void Reparent(const std::shared_ptr< Track > &parent) override
Object may be shared among tracks but hold a special back-pointer to one of them; reassign it.
static TrackAttachment * Find(const AttachedTrackObjects::RegisteredFactory &key, Track *pTrack, size_t iChannel)
bool HandleXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &valueView) override
Deserialize an attribute, returning true if recognized.
void CopyTo(Track &track) const override
Copy state, for undo/redo purposes.
std::function< std::shared_ptr< TrackAttachment >(Track &, size_t)> Factory
ChannelAttachmentsBase(Track &track, Factory factory)
double GetEndTime() const
Get the maximum of End() values of intervals, or 0 when none.
double GetStartTime() const
Get the minimum of Start() values of intervals, or 0 when none.
ChannelGroupData * FindGroupData()
Do not make attachment site on demand if absent.
LinkType
For two tracks describes the type of the linkage.
@ Aligned
Tracks are grouped and changes should be synchronized.
virtual size_t NChannels() const =0
Report the number of channels.
std::unique_ptr< ChannelGroupData > DetachGroupData()
Move attachments out.
void Init(const ChannelGroup &other)
Copy, including cloning of attached objects.
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Utility to register hooks into a host class that attach client data.
void ForEach(const Function &function)
Invoke function on each ClientData object that has been created in this.
Abstract base class for an object holding data associated with points on a time axis.
virtual TrackListHolder Clone() const =0
bool GetSelected() const
Selectedness is always the same for all channels of a group.
void EnsureVisible(bool modifyState=false)
virtual void Paste(double t, const Track &src)=0
Weak precondition allows overrides to replicate one channel into many.
virtual void SetSelected(bool s)
void Notify(bool allChannels, int code=-1)
virtual bool SupportsBasicEditing() const
Whether this track type implements cut-copy-paste; by default, true.
static const TypeInfo & ClassTypeInfo()
bool IsSelectedLeader() const
virtual void SyncLockAdjust(double oldT1, double newT1)
TrackNodePointer GetNode() const
Retrieve mNode with debug checks.
TrackList * GetHolder() const
std::shared_ptr< Track > SubstitutePendingChangedTrack()
virtual void DoOnProjectTempoChange(const std::optional< double > &oldTempo, double newTempo)=0
std::shared_ptr< const Track > SubstituteOriginalTrack() const
std::shared_ptr< TrackList > GetOwner() const
virtual bool LinkConsistencyFix(bool doFix=true)
Check consistency of channel groups, and maybe fix it.
void SetLinkType(LinkType linkType, bool completeList=true)
std::shared_ptr< Subclass > SharedPointer()
bool HasLinkedTrack() const noexcept
Returns true for leaders of multichannel groups.
virtual void Clear(double t0, double t1)=0
bool IsLeader() const override
std::shared_ptr< Track > Holder
void SetOwner(const std::weak_ptr< TrackList > &list, TrackNodePointer node)
Update mNode when Track is added to TrackList, or removed from it.
bool HandleCommonXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &valueView)
virtual TrackListHolder Duplicate() const
public nonvirtual duplication function that invokes Clone()
ChannelGroupData & GetGroupData()
const wxString & GetName() const
Name is always the same for all channels of a group.
void Init(const Track &orig)
void OnProjectTempoChange(double newTempo)
method to set project tempo on track
void WriteCommonXMLAttributes(XMLWriter &xmlFile, bool includeNameAndSelected=true) const
std::weak_ptr< TrackList > mList
TrackNodePointer mNode
Holds iterator to self, so that TrackList::Find can be constant-time.
virtual TrackListHolder Cut(double t0, double t1)=0
Create tracks and modify this track.
Track * GetLinkedTrack() const
LinkType GetLinkType() const noexcept
int mIndex
0-based position of this track in its TrackList
virtual std::optional< TranslatableString > GetErrorOpening() const
const std::optional< double > & GetProjectTempo() const
void DoSetLinkType(LinkType linkType, bool completeList=true)
bool LinkConsistencyCheck()
Do the non-mutating part of consistency fix only and return status.
void SetName(const wxString &n)
TrackId mId
Identifies the track only in-session, not persistently.
An in-session identifier of track objects across undo states. It does not persist between sessions.
Iterator over only members of a TrackList of the specified subtype, optionally filtered by a predicat...
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
void PermutationEvent(TrackNodePointer node)
static TrackListHolder Create(AudacityProject *pOwner)
std::function< void(Track &dest, const Track &src)> Updater
void RegisterPendingNewTracks(TrackList &&list)
bool CanMoveUp(Track *t) const
void AppendOne(TrackList &&list)
std::shared_ptr< TrackList > mPendingUpdates
static Track * SwapChannels(Track &track)
void Permute(const std::vector< Track * > &tracks)
void Append(TrackList &&list)
Remove all tracks from list and put them at the end of this
double GetEndTime() const
Return the greatest end time of the tracks, or 0 when no tracks.
bool CanMoveDown(Track *t) const
std::vector< Updater > mUpdaters
This is in correspondence with leader tracks in mPendingUpdates.
static TrackList * FindUndoTracks(const UndoStackElem &state)
void Insert(const Track *before, TrackList &&trackList)
Inserts tracks form trackList starting from position where before is located. If before is nullptr tr...
void ResizingEvent(TrackNodePointer node)
TrackNodePointer getBegin() const
TrackIter< Track > Find(Track *pTrack)
wxString MakeUniqueTrackName(const wxString &baseTrackName) const
Returns string that contains baseTrackName, but is guaranteed to be unique among other tracks in that...
TrackList & operator=(const TrackList &)=delete
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
double GetStartTime() const
Return the least start time of the tracks, or 0 when no tracks.
bool isNull(TrackNodePointer p) const
Track * RegisterPendingChangedTrack(Updater updater, Track *src)
TrackNodePointer getNext(TrackNodePointer p) const
Move an iterator to the next node, if any; else stay at end.
void Swap(TrackList &that)
void AdditionEvent(TrackNodePointer node)
void RecalcPositions(TrackNodePointer node)
bool MakeMultiChannelTrack(Track &first, int nChannels)
Converts channels to a multichannel track.
void Remove(Track &track)
Remove a channel group, given the leader.
auto Any() -> TrackIterRange< TrackType >
void SelectionEvent(Track &track)
TrackNodePointer getEnd() const
bool ApplyPendingTracks()
TrackListHolder ReplaceOne(Track &t, TrackList &&with)
TrackIterRange< Track > EmptyRange() const
void EnsureVisibleEvent(const std::shared_ptr< Track > &pTrack, bool modifyState)
static TrackList & Get(AudacityProject &project)
Track * DoAdd(const std::shared_ptr< Track > &t)
Track * GetNext(Track *t, bool linked=false) const
Return a track in the list that comes after Track t.
Track * GetPrev(Track *t, bool linked=false) const
void ClearPendingTracks(ListOfTracks *pAdded=nullptr)
void UpdatePendingTracks()
Track * DoAddToHead(const std::shared_ptr< Track > &t)
Track * FindById(TrackId id)
std::vector< Track * > UnlinkChannels(Track &track)
Removes linkage if track belongs to a group.
TrackIter< Track > DoFind(Track *pTrack)
void DataEvent(const std::shared_ptr< Track > &pTrack, bool allChannels, int code)
iterator Begin()
This private function still iterates channels not tracks.
iterator End()
This private function still iterates channels not tracks.
AudacityProject * GetOwner()
void QueueEvent(TrackListEvent event)
void SwapNodes(TrackNodePointer s1, TrackNodePointer s2)
TrackList(const TrackList &that)=delete
bool HasPendingTracks() const
void Clear(bool sendEvent=true)
Make the list empty.
void DeletionEvent(std::weak_ptr< Track > node, bool duringReplace)
TrackNodePointer getPrev(TrackNodePointer p) const
Move an iterator to the previous node, if any; else wrap to end.
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
static TrackListHolder Temporary(AudacityProject *pProject, const Track::Holder &left={}, const Track::Holder &right={})
Base class for extra information attached to undo/redo states.
A view into an attribute value. The class does not take the ownership of the data.
wxString ToWString() const
Convert the view value to wxString.
bool TryGet(bool &value) const noexcept
Try to get a boolean value from the view.
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
void WriteAttr(const wxString &name, const Identifier &value)
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
std::optional< LogWindowUpdater > pUpdater
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
double Accumulate(const TrackList &list, double(Track::*memfn)() const, double ident, const double &(*combine)(const double &, const double &))
UndoRedoExtensionRegistry::Entry sEntry
static RegisteredToolbarFactory factory
std::optional< double > mProjectTempo
Empty argument passed to some public constructors.
Range between two TrackIters, usable in range-for statements, and with Visit member functions.
Notification of changes in individual tracks of TrackList, or of TrackList's composition.
@ RESIZING
Posted when some track changed its height.
@ SELECTION_CHANGE
Posted when the set of selected tracks changes.
@ DELETION
Posted when a track has been deleted from a tracklist. Also posted when one track replaces another.
@ ADDITION
Posted when a track has been added to a tracklist. Also posted when one track replaces another.
@ PERMUTED
Posted when tracks are reordered but otherwise unchanged.
@ TRACK_REQUEST_VISIBLE
Posted when a track needs to be scrolled into view; leader track only.
@ TRACK_DATA_CHANGE
Posted when certain fields of a track change.
Typically statically constructed.
Holds one item with description and time range for the UndoManager.
void RestoreUndoRedoState(AudacityProject &project) override
Modify the project when undoing or redoing to some state in history.
const std::shared_ptr< TrackList > mpTracks
TrackListRestorer(AudacityProject &project)
bool CanUndoOrRedo(const AudacityProject &project) override
Whether undo or redo is now permitted; default returns true.