Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Common/LtsTimeline/track.cpp
T
2026-10-03 09:20:13 +02:00

658 lines
18 KiB
C++

#include "track.h"
#include <utility>
namespace LtsTimeline
{
const Track& Track::track(int id) const noexcept(false)
{
auto const it = std::find_if(m_childrenTracks.cbegin(), m_childrenTracks.cend(),
[id](const TrackPtr& trackPtr) { return (trackPtr.get()->id() == id); });
if (it != m_childrenTracks.cend())
return **it;
for (const TrackPtr& track : std::as_const(m_childrenTracks))
{
try
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // self-recursive lookup: recurses via the deprecated public Track API
return track->track(id);
#pragma GCC diagnostic pop
}
catch (...)
{
}
}
throw QStringLiteral("lookup failed!");
;
}
bool Track::hasTrack(int id, bool recursive) const
{
if (std::find_if(m_childrenTracks.cbegin(), m_childrenTracks.cend(), [id](const TrackPtr& trackPtr) {
return (trackPtr.get()->id() == id);
}) != m_childrenTracks.cend())
return true;
if (!recursive)
return false;
for (const TrackPtr& trackPtr : std::as_const(m_childrenTracks))
{
if (trackPtr->hasTrack(id, true))
return true;
}
return false;
}
void Track::addCopyItemIds(const QSet<int>& ids)
{
m_copyItemIds += ids;
}
void Track::addCopyItemId(int id)
{
m_copyItemIds += id;
}
const Track& Track::parentOf(int id) const noexcept(false)
{
for (const TrackPtr& trackPtr : std::as_const(m_childrenTracks))
{
if (trackPtr->hasTrack(id))
return *trackPtr;
if (trackPtr->hasTrack(id, true))
return trackPtr->parentOf(id);
}
throw("not found");
}
bool Track::isItemBetween(const Item& item, qint64 start, qint64 end, bool strict, bool complete,
qint64 minimumDuration)
{
if (end - start == -1)
{
if (item.duration() == -1)
{
if (!complete)
return true;
return strict ? item.startTime() > start : item.startTime() >= start;
}
if (strict)
{
return (complete && item.startTime() > start) || (!complete && item.startTime() + item.duration() > start);
}
else
{
return (complete && item.startTime() >= start) ||
(!complete && item.startTime() + item.duration() >= start);
}
}
if (item.duration() == -1)
{
if (complete)
return false;
return strict ? item.startTime() < end : item.startTime() <= end;
}
Q_ASSERT(end + 1 > start);
qint64 itemStart = item.startTime(),
itemEnd = item.startTime() + (std::max((qint64)item.duration(), minimumDuration));
if (strict)
return ((complete && (itemStart > start && itemEnd < end)) ||
(!complete && (itemEnd > start && itemStart < end)));
else
return ((complete && (itemStart >= start && itemEnd <= end)) ||
(!complete && (itemEnd >= start && itemStart <= end)));
}
void Track::removeCopyItem(int itemId) noexcept(false)
{
m_copyItemIds.remove(itemId);
for (TrackPtr& t : m_childrenTracks)
{
t->removeCopyItem(itemId);
}
}
const QVector<int> Track::copyItemIdsBetween(qint64 start, qint64 end, bool strict, bool complete, bool recursive,
bool sorted, qint64 minimumDuration) const
{
Q_UNUSED(minimumDuration);
auto itemPtrRefs = _copyItems();
if (recursive)
{
for (const TrackPtr& trackPtr : std::as_const(m_childrenTracks))
{
auto itemPtrRefs2 = trackPtr->_copyItems();
itemPtrRefs.insert(itemPtrRefs.end(), itemPtrRefs2.begin(), itemPtrRefs2.end());
}
}
itemPtrRefs.erase(std::remove_if(itemPtrRefs.begin(), itemPtrRefs.end(),
[this, start, end, strict, complete](const ItemPtr& itemPtr) {
return !isItemBetween(*itemPtr, start, end, strict, complete);
}),
itemPtrRefs.end());
if (sorted)
{
sort(itemPtrRefs);
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // internal call to the deprecated transformItemPtrsToIds helper
return transformItemPtrsToIds(itemPtrRefs);
#pragma GCC diagnostic pop
}
const QVector<int> Track::itemIdsBetween(qint64 start, qint64 end, bool strict, bool complete, bool recursive,
bool sorted, qint64 minimumDuration) const
{
if (sorted)
{
auto itemPtrRefs = _items(recursive);
itemPtrRefs.erase(std::remove_if(itemPtrRefs.begin(), itemPtrRefs.end(),
[this, start, end, strict, complete, minimumDuration](const ItemPtr& itemPtr) {
return !isItemBetween(*itemPtr, start, end, strict, complete,
minimumDuration);
}),
itemPtrRefs.end());
sort(itemPtrRefs);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // internal call to the deprecated transformItemPtrsToIds helper
return transformItemPtrsToIds(itemPtrRefs);
#pragma GCC diagnostic pop
}
QVector<int> itemIds;
itemIds.reserve(m_items.size());
for (const ItemPtr& itemPtr : std::as_const(m_items))
{
const Item& item = *itemPtr;
if (isItemBetween(item, start, end, strict, complete, minimumDuration))
itemIds += item.id();
}
if (!recursive)
{
itemIds.squeeze();
return itemIds;
}
for (const TrackPtr& trackPtr : std::as_const(m_childrenTracks))
itemIds += trackPtr->itemIdsBetween(start, end, strict, complete, true, minimumDuration);
return itemIds;
}
bool Track::isItemsBetween(qint64 start, qint64 end, const QVector<int>& ignoreIds, bool strict, bool complete,
bool recursive, qint64 minimumDuration) const
{
for (const ItemPtr& itemPtr : std::as_const(m_items))
{
const Item& i = *itemPtr;
if (!ignoreIds.contains(i.id()))
if (isItemBetween(i, start, end, strict, complete, minimumDuration))
return true;
}
for (const int itemId : std::as_const(m_copyItemIds))
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // internal lookup via the deprecated Track::item
const Item& i = item(itemId);
#pragma GCC diagnostic pop
if (!ignoreIds.contains(i.id()))
if (isItemBetween(i, start, end, strict, complete, minimumDuration))
return true;
}
if (!recursive)
return false;
for (const TrackPtr& trackPtr : std::as_const(m_childrenTracks))
if (trackPtr->isItemsBetween(start, end, ignoreIds, strict, complete, true, minimumDuration))
return true;
return false;
}
bool Track::isItemsBetween(qint64 start, qint64 end, int ignoreId, bool strict, bool complete, bool recursive,
qint64 minimumDuration) const
{
return isItemsBetween(start, end, QVector<int>({ignoreId}), strict, complete, recursive, minimumDuration);
}
ItemPtrRefs Track::_items(bool recursive) const
{
ItemPtrRefs x(m_items.cbegin(), m_items.cend());
if (!m_copyItemIds.isEmpty())
x.reserve(x.size() + m_copyItemIds.count());
for (const int itemId : std::as_const(m_copyItemIds))
{
try
{
x.push_back(std::cref(_item(itemId)));
}
catch (const QString& msg)
{
fprintf(stderr, "cannot add item ptr ref from copy item with copy item id %d: %s\n", itemId,
msg.toStdString().c_str());
}
}
if (!recursive)
return x;
for (const TrackPtr& t : std::as_const(m_childrenTracks))
{
const ItemPtrRefs x2(t->_items(true));
x.insert(x.end(), x2.begin(), x2.end());
}
return x;
}
ItemPtrRefs Track::_copyItems() const
{
ItemPtrRefs x;
for (int id : std::as_const(m_copyItemIds))
{
try
{
x.push_back(_item(id));
}
catch (...)
{
fprintf(stderr, "Track::_copyItems: cannot find item for item id %d\n", id);
continue;
}
}
return x;
}
ItemPtrNCVRefs Track::_itemsNCV(bool recursive)
{
ItemPtrNCVRefs x(m_items.begin(), m_items.end());
if (!recursive)
return x;
for (TrackPtr& t : m_childrenTracks)
{
ItemPtrNCVRefs x2(t->_itemsNCV(true));
x.insert(x.end(), x2.begin(), x2.end());
}
return x;
}
const QVector<int> Track::_itemIds(bool recursive) const
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // internal call to the deprecated transformItemPtrsToIds helper
QVector<int> itemIds(transformItemPtrsToIds(m_items));
#pragma GCC diagnostic pop
if (!recursive)
return itemIds;
for (const TrackPtr& trackPtr : std::as_const(m_childrenTracks))
itemIds += trackPtr->_itemIds(true);
return itemIds;
}
ItemPtrRef Track::_item(int id) const noexcept(false)
{
auto const it = std::find_if(m_items.cbegin(), m_items.cend(),
[id](const ItemPtr& itemPtr) { return (itemPtr.get()->id() == id); });
if (it != m_items.cend())
return *it;
for (const TrackPtr& track : std::as_const(m_childrenTracks))
{
try
{
return track->_item(id);
}
catch (...)
{
}
}
throw QStringLiteral("_item: item with id %1 not found!").arg(id);
}
void Track::printTrackIds(bool withItems, int level) const
{
fprintf(stderr, "%*c Track %16.16s ", level * 2, '>', text().toStdString().c_str());
if (withItems)
{
fprintf(stderr, " ( ");
for (const ItemPtr& itemPtr : std::as_const(m_items))
{
fprintf(stderr, "%d ", itemPtr->id());
}
fprintf(stderr, ")");
}
fprintf(stderr, "\n");
for (const TrackPtr& trackPtr : std::as_const(m_childrenTracks))
trackPtr->printTrackIds(level + 1);
}
QVector<int> Track::itemIds(bool recursive, bool sorted) const
{
if (sorted)
{
if (!recursive)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // internal call to the deprecated transformItemPtrsToIds helper
return transformItemPtrsToIds(m_items);
#pragma GCC diagnostic pop
ItemPtrRefs is(_items(true));
sort(is);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // internal call to the deprecated transformItemPtrsToIds helper
return transformItemPtrsToIds(is);
#pragma GCC diagnostic pop
}
QVector<int> itemIds;
itemIds.reserve(m_items.size());
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // internal call to the deprecated transformItemPtrsToIds helper
itemIds += transformItemPtrsToIds(m_items);
#pragma GCC diagnostic pop
if (!recursive)
return itemIds;
for (const TrackPtr& trackPtr : std::as_const(m_childrenTracks))
itemIds += trackPtr->_itemIds(true);
return itemIds;
}
void Track::addItemPtr(ItemPtr&& itemPtr)
{
m_items.insert(
std::upper_bound(m_items.begin(), m_items.end(), itemPtr->startTime(),
[](qint64 startTime, const ItemPtr& other) { return (other->startTime() > startTime); }),
std::move(itemPtr));
}
void Track::removeItem(int itemId) noexcept(false)
{
auto it = std::find_if(m_items.begin(), m_items.end(),
[itemId](const ItemPtr& itemPtr) { return (itemPtr->id() == itemId); });
if (it == m_items.end())
throw QStringLiteral("removeItem: item %1 not found").arg(itemId);
m_items.erase(it);
}
void Track::removeTrack(int trackId) noexcept(false)
{
auto it = std::find_if(m_childrenTracks.begin(), m_childrenTracks.end(),
[trackId](const TrackPtr& trackPtr) { return (trackPtr->id() == trackId); });
if (it == m_childrenTracks.end())
throw QStringLiteral("removeTrack: track %1 not found on track %2").arg(trackId, id());
m_childrenTracks.erase(it);
}
ItemPtr Track::takeItem(int itemId) noexcept(false)
{
auto it = std::find_if(m_items.begin(), m_items.end(),
[itemId](const ItemPtr& itemPtr) { return (itemPtr->id() == itemId); });
if (it == m_items.end())
throw QStringLiteral("Track::takeItem: item with id %1 not found").arg(itemId);
ItemPtr ptr = std::move(*it);
m_items.erase(it);
return ptr;
}
Track& Track::track(int id) noexcept(false)
{
auto it = std::find_if(m_childrenTracks.begin(), m_childrenTracks.end(),
[id](TrackPtr& trackPtr) { return (trackPtr.get()->id() == id); });
if (it != m_childrenTracks.end())
{
Track& t = **it;
return t;
}
for (TrackPtr& track : m_childrenTracks)
{
try
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // self-recursive lookup: recurses via the deprecated public Track API
return track->track(id);
#pragma GCC diagnostic pop
}
catch (...)
{
}
}
throw QStringLiteral("Track: track with id %1 not found").arg(id);
}
ItemPtrNCVRef Track::_itemNCV(int id) noexcept(false)
{
auto const it =
std::find_if(m_items.begin(), m_items.end(), [id](ItemPtr& itemPtr) { return (itemPtr.get()->id() == id); });
if (it != m_items.end())
return *it;
for (TrackPtr& track : m_childrenTracks)
{
try
{
return track->_itemNCV(id);
}
catch (...)
{
}
}
throw QStringLiteral("lookup failed!");
;
}
Item& Track::item(int id) noexcept(false)
{
auto const it =
std::find_if(m_items.begin(), m_items.end(), [id](ItemPtr& itemPtr) { return (itemPtr.get()->id() == id); });
if (it != m_items.end())
return **it;
for (TrackPtr& track : m_childrenTracks)
{
try
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // self-recursive lookup: recurses via the deprecated public Track API
return track->item(id);
#pragma GCC diagnostic pop
}
catch (...)
{
}
}
throw QStringLiteral("lookup failed!");
;
}
const Item& Track::item(int id) const noexcept(false)
{
auto const it = std::find_if(m_items.cbegin(), m_items.cend(),
[id](const ItemPtr& itemPtr) { return (itemPtr.get()->id() == id); });
if (it != m_items.cend())
return **it;
for (const TrackPtr& track : std::as_const(m_childrenTracks))
{
try
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // self-recursive lookup: recurses via the deprecated public Track API
return track->item(id);
#pragma GCC diagnostic pop
}
catch (...)
{
}
}
throw QStringLiteral("lookup failed!");
;
}
Item& Track::previous(int id) noexcept(false)
{
auto it =
std::find_if(m_items.begin(), m_items.end(), [id](ItemPtr& itemPtr) { return (itemPtr.get()->id() == id); });
if (it != m_items.end() && (*it) != m_items.front())
return **(--it);
throw QStringLiteral("Track::previous: previous item for id %1 not found").arg(id);
}
Item& Track::next(int id) noexcept(false)
{
auto it =
std::find_if(m_items.begin(), m_items.end(), [id](ItemPtr& itemPtr) { return (itemPtr.get()->id() == id); });
if (it != m_items.end() && (*it) != m_items.back())
return **(++it);
throw QStringLiteral("lookup failed!");
;
}
int Track::rowOfTrack(int id) const noexcept(false)
{
int row = 0;
for (const TrackPtr& trackPtr : std::as_const(m_childrenTracks))
{
if (trackPtr->id() == id)
return row;
row++;
}
throw("not found");
}
Track& Track::trackAt(int index) noexcept(false)
{
return *m_childrenTracks.at(index);
}
const Track& Track::trackAt(int index) const noexcept(false)
{
return *m_childrenTracks.at(index);
}
const Item& Track::copyItemAt(qint64 time) const noexcept(false)
{
auto const itemPtrRefs = _copyItems();
const ItemPtrRefs::const_iterator it =
std::find_if(itemPtrRefs.cbegin(), itemPtrRefs.cend(), [time](const ItemPtr& itemPtr) {
return itemPtr.get()->startTime() <= time && time <= itemPtr.get()->startTime() + itemPtr.get()->duration();
});
if (it != itemPtrRefs.cend())
return *it->get();
throw QStringLiteral("Track: can't find copy item at %1").arg(time);
}
Item& Track::itemAt(qint64 time) noexcept(false)
{
auto it = std::find_if(m_items.cbegin(), m_items.cend(), [time](const ItemPtr& itemPtr) {
return itemPtr.get()->startTime() <= time && time <= itemPtr.get()->startTime() + itemPtr.get()->duration();
});
if (it != m_items.cend())
return **it;
throw QStringLiteral("lookup failed!");
;
}
const Item& Track::itemAt(qint64 time) const noexcept(false)
{
auto const it = std::find_if(m_items.cbegin(), m_items.cend(), [time](const ItemPtr& itemPtr) {
return itemPtr.get()->startTime() <= time && time <= itemPtr.get()->startTime() + itemPtr.get()->duration();
});
if (it != m_items.cend())
return **it;
throw QStringLiteral("lookup failed!");
;
}
} // namespace LtsTimeline