mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-18 09:37:40 +02:00
Define TrackId to identify tracks across undo states
This commit is contained in:
parent
8b60e7f02d
commit
bd2c7e6abc
@ -3585,6 +3585,10 @@ XMLTagHandler *AudacityProject::HandleXMLChild(const wxChar *tag)
|
|||||||
return mTags.get();
|
return mTags.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note that TrackList::Add includes assignment of unique in-session TrackId
|
||||||
|
// to a reloaded track, though no promise that it equals the id it originally
|
||||||
|
// had
|
||||||
|
|
||||||
if (!wxStrcmp(tag, wxT("wavetrack"))) {
|
if (!wxStrcmp(tag, wxT("wavetrack"))) {
|
||||||
return mTracks->Add(mTrackFactory->NewWaveTrack());
|
return mTracks->Add(mTrackFactory->NewWaveTrack());
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,8 @@ Track::Track(const Track &orig)
|
|||||||
// Copy all the track properties except the actual contents
|
// Copy all the track properties except the actual contents
|
||||||
void Track::Init(const Track &orig)
|
void Track::Init(const Track &orig)
|
||||||
{
|
{
|
||||||
|
mId = orig.mId;
|
||||||
|
|
||||||
mDefaultName = orig.mDefaultName;
|
mDefaultName = orig.mDefaultName;
|
||||||
mName = orig.mName;
|
mName = orig.mName;
|
||||||
|
|
||||||
@ -739,6 +741,9 @@ DEFINE_EVENT_TYPE(EVT_TRACKLIST_PERMUTED);
|
|||||||
DEFINE_EVENT_TYPE(EVT_TRACKLIST_RESIZING);
|
DEFINE_EVENT_TYPE(EVT_TRACKLIST_RESIZING);
|
||||||
DEFINE_EVENT_TYPE(EVT_TRACKLIST_DELETION);
|
DEFINE_EVENT_TYPE(EVT_TRACKLIST_DELETION);
|
||||||
|
|
||||||
|
// same value as in the default constructed TrackId:
|
||||||
|
long TrackList::mCounter = -1;
|
||||||
|
|
||||||
TrackList::TrackList()
|
TrackList::TrackList()
|
||||||
: wxEvtHandler()
|
: wxEvtHandler()
|
||||||
{
|
{
|
||||||
@ -853,6 +858,17 @@ void TrackList::Permute(const std::vector<TrackNodePointer> &permutation)
|
|||||||
PermutationEvent();
|
PermutationEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Track *TrackList::FindById( TrackId id )
|
||||||
|
{
|
||||||
|
// Linear search. Tracks in a project are usually very few.
|
||||||
|
// Search only the non-pending tracks.
|
||||||
|
auto it = std::find_if( ListOfTracks::begin(), ListOfTracks::end(),
|
||||||
|
[=](const ListOfTracks::value_type &ptr){ return ptr->GetId() == id; } );
|
||||||
|
if (it == ListOfTracks::end())
|
||||||
|
return {};
|
||||||
|
return it->get();
|
||||||
|
}
|
||||||
|
|
||||||
template<typename TrackKind>
|
template<typename TrackKind>
|
||||||
Track *TrackList::Add(std::unique_ptr<TrackKind> &&t)
|
Track *TrackList::Add(std::unique_ptr<TrackKind> &&t)
|
||||||
{
|
{
|
||||||
@ -862,6 +878,7 @@ Track *TrackList::Add(std::unique_ptr<TrackKind> &&t)
|
|||||||
auto n = getPrev( getEnd() );
|
auto n = getPrev( getEnd() );
|
||||||
|
|
||||||
pTrack->SetOwner(mSelf, n);
|
pTrack->SetOwner(mSelf, n);
|
||||||
|
pTrack->SetId( TrackId{ ++mCounter } );
|
||||||
RecalcPositions(n);
|
RecalcPositions(n);
|
||||||
ResizingEvent(n);
|
ResizingEvent(n);
|
||||||
return back().get();
|
return back().get();
|
||||||
@ -883,6 +900,7 @@ Track *TrackList::AddToHead(std::unique_ptr<TrackKind> &&t)
|
|||||||
push_front(ListOfTracks::value_type(pTrack = t.release()));
|
push_front(ListOfTracks::value_type(pTrack = t.release()));
|
||||||
auto n = getBegin();
|
auto n = getBegin();
|
||||||
pTrack->SetOwner(mSelf, n);
|
pTrack->SetOwner(mSelf, n);
|
||||||
|
pTrack->SetId( TrackId{ ++mCounter } );
|
||||||
RecalcPositions(n);
|
RecalcPositions(n);
|
||||||
ResizingEvent(n);
|
ResizingEvent(n);
|
||||||
return front().get();
|
return front().get();
|
||||||
@ -899,6 +917,7 @@ Track *TrackList::Add(std::shared_ptr<TrackKind> &&t)
|
|||||||
auto n = getPrev( getEnd() );
|
auto n = getPrev( getEnd() );
|
||||||
|
|
||||||
t->SetOwner(mSelf, n);
|
t->SetOwner(mSelf, n);
|
||||||
|
t->SetId( TrackId{ ++mCounter } );
|
||||||
RecalcPositions(n);
|
RecalcPositions(n);
|
||||||
ResizingEvent(n);
|
ResizingEvent(n);
|
||||||
return back().get();
|
return back().get();
|
||||||
@ -921,6 +940,7 @@ auto TrackList::Replace(Track * t, ListOfTracks::value_type &&with) ->
|
|||||||
Track *pTrack = with.get();
|
Track *pTrack = with.get();
|
||||||
*node = std::move(with);
|
*node = std::move(with);
|
||||||
pTrack->SetOwner(mSelf, node);
|
pTrack->SetOwner(mSelf, node);
|
||||||
|
pTrack->SetId( t->GetId() );
|
||||||
RecalcPositions(node);
|
RecalcPositions(node);
|
||||||
|
|
||||||
DeletionEvent();
|
DeletionEvent();
|
||||||
|
47
src/Track.h
47
src/Track.h
@ -64,6 +64,32 @@ using TrackNodePointer = ListOfTracks::iterator;
|
|||||||
|
|
||||||
class ViewInfo;
|
class ViewInfo;
|
||||||
|
|
||||||
|
// This is an in-session identifier of track objects across undo states
|
||||||
|
// It does not persist between sessions
|
||||||
|
// Default constructed value is not equal to the id of any track that has ever
|
||||||
|
// been added to a TrackList, or (directly or transitively) copied from such
|
||||||
|
// TrackIds are assigned uniquely across projects
|
||||||
|
class TrackId
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TrackId() : mValue(-1) {}
|
||||||
|
explicit TrackId (long value) : mValue(value) {}
|
||||||
|
|
||||||
|
bool operator == (const TrackId &other) const
|
||||||
|
{ return mValue == other.mValue; }
|
||||||
|
|
||||||
|
bool operator != (const TrackId &other) const
|
||||||
|
{ return mValue != other.mValue; }
|
||||||
|
|
||||||
|
// Define this in case you want to key a std::map on TrackId
|
||||||
|
// The operator does not mean anything else
|
||||||
|
bool operator < (const TrackId &other) const
|
||||||
|
{ return mValue < other.mValue; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
long mValue;
|
||||||
|
};
|
||||||
|
|
||||||
class AUDACITY_DLL_API Track /* not final */
|
class AUDACITY_DLL_API Track /* not final */
|
||||||
: public CommonTrackPanelCell, public XMLTagHandler
|
: public CommonTrackPanelCell, public XMLTagHandler
|
||||||
{
|
{
|
||||||
@ -72,6 +98,9 @@ class AUDACITY_DLL_API Track /* not final */
|
|||||||
friend class SyncLockedTracksIterator;
|
friend class SyncLockedTracksIterator;
|
||||||
|
|
||||||
// To be TrackDisplay
|
// To be TrackDisplay
|
||||||
|
private:
|
||||||
|
TrackId mId;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::weak_ptr<TrackList> mList;
|
std::weak_ptr<TrackList> mList;
|
||||||
TrackNodePointer mNode{};
|
TrackNodePointer mNode{};
|
||||||
@ -86,6 +115,11 @@ class AUDACITY_DLL_API Track /* not final */
|
|||||||
bool mLinked;
|
bool mLinked;
|
||||||
bool mMinimized;
|
bool mMinimized;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TrackId GetId() const { return mId; }
|
||||||
|
private:
|
||||||
|
void SetId( TrackId id ) { mId = id; }
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Given a bare pointer, find a shared_ptr. But this is not possible for
|
// Given a bare pointer, find a shared_ptr. But this is not possible for
|
||||||
@ -617,16 +651,22 @@ class TrackList final : public wxEvtHandler, public ListOfTracks
|
|||||||
/// For use in sorting: assume each iterator points into this list, no duplications
|
/// For use in sorting: assume each iterator points into this list, no duplications
|
||||||
void Permute(const std::vector<TrackNodePointer> &permutation);
|
void Permute(const std::vector<TrackNodePointer> &permutation);
|
||||||
|
|
||||||
/// Add this Track or all children of this TrackList.
|
Track *FindById( TrackId id );
|
||||||
|
|
||||||
|
/// Add a Track, giving it a fresh id
|
||||||
template<typename TrackKind>
|
template<typename TrackKind>
|
||||||
Track *Add(std::unique_ptr<TrackKind> &&t);
|
Track *Add(std::unique_ptr<TrackKind> &&t);
|
||||||
|
|
||||||
|
/// Add a Track, giving it a fresh id
|
||||||
template<typename TrackKind>
|
template<typename TrackKind>
|
||||||
Track *AddToHead(std::unique_ptr<TrackKind> &&t);
|
Track *AddToHead(std::unique_ptr<TrackKind> &&t);
|
||||||
|
|
||||||
|
/// Add a Track, giving it a fresh id
|
||||||
template<typename TrackKind>
|
template<typename TrackKind>
|
||||||
Track *Add(std::shared_ptr<TrackKind> &&t);
|
Track *Add(std::shared_ptr<TrackKind> &&t);
|
||||||
|
|
||||||
/// Replace first track with second track, give back a holder
|
/// Replace first track with second track, give back a holder
|
||||||
|
/// Give the replacement the same id as the replaced
|
||||||
ListOfTracks::value_type Replace(Track * t, ListOfTracks::value_type &&with);
|
ListOfTracks::value_type Replace(Track * t, ListOfTracks::value_type &&with);
|
||||||
|
|
||||||
/// Remove this Track or all children of this TrackList.
|
/// Remove this Track or all children of this TrackList.
|
||||||
@ -743,6 +783,11 @@ private:
|
|||||||
void SwapNodes(TrackNodePointer s1, TrackNodePointer s2);
|
void SwapNodes(TrackNodePointer s1, TrackNodePointer s2);
|
||||||
|
|
||||||
std::weak_ptr<TrackList> mSelf;
|
std::weak_ptr<TrackList> mSelf;
|
||||||
|
|
||||||
|
// Nondecreasing during the session.
|
||||||
|
// Nonpersistent.
|
||||||
|
// Used to assign ids to added tracks.
|
||||||
|
static long mCounter;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AUDACITY_DLL_API TrackFactory
|
class AUDACITY_DLL_API TrackFactory
|
||||||
|
Loading…
x
Reference in New Issue
Block a user