#pragma once #include "item.h" #include "ltstimeline_export.h" #include #include #include #include namespace LtsTimeline { class Track; class TimelineModel; typedef std::unique_ptr TrackPtr; typedef std::vector Tracks; typedef std::reference_wrapper TrackPtrRef; typedef std::vector TrackPtrRefs; class LTSTIMELINE_EXPORT Track { public: Track(const QString& text = {}) : m_text(text) {} Track(const QString& text, int specialTrackType) : m_text(text), m_userData(specialTrackType) {} Track(const Track&) = delete; Track& operator=(const Track&) = delete; Track(Track&& t) noexcept = default; virtual ~Track() = default; [[deprecated("Use model's track(int) instead.")]] const Track& track(int id) const noexcept(false); [[deprecated("Use model's track(int) instead.")]] Track& track(int id) noexcept(false); [[deprecated("Use model's item(int) instead.")]] Item& item(int id) noexcept(false); [[deprecated("Use model's item(int) instead.")]] const Item& item(int id) const noexcept(false); Item& previous(int id) noexcept(false); Item& next(int id) noexcept(false); const Item& copyItemAt(qint64 time) const noexcept(false); Item& itemAt(qint64 time) noexcept(false); const Item& itemAt(qint64 time) const noexcept(false); Track& trackAt(int index) noexcept(false); const Track& trackAt(int index) const noexcept(false); bool hasTrack(int id, bool recursive = false) const; bool hasTracks() const { return !m_childrenTracks.empty(); } int rowOfTrack(int id) const noexcept(false); const Track& parentOf(int id) const noexcept(false); const QSet& copyItemIds() const { return m_copyItemIds; } void clearCopyItemIds() { m_copyItemIds.clear(); } void addCopyItemIds(const QSet& ids); void addCopyItemId(int id); bool hasItems() const { return !m_items.empty(); } bool hasCopyItems() const { return !m_copyItemIds.empty(); } int itemCount() const { return m_items.size(); } Items& items() { return m_items; } const Items& items() const { return m_items; } int trackCount() const { return m_childrenTracks.size(); } Tracks& tracks() { return m_childrenTracks; } const Tracks& tracks() const { return m_childrenTracks; } QVector itemIds(bool recursive = false, bool sorted = false) const; const QVector itemIdsBetween(qint64 start, qint64 end, bool strict = false, bool complete = false, bool recursive = false, bool sorted = false, qint64 minimumDuration = 0) const; [[deprecated]] const QVector copyItemIdsBetween(qint64 start, qint64 end, bool strict = false, bool complete = false, bool recursive = false, bool sorted = false, qint64 minimumDuration = 0) const; bool isItemsBetween(qint64 start, qint64 end, const QVector& ignoreIds, bool strict = false, bool complete = false, bool recursive = false, qint64 minimumDuration = 0) const; bool isItemsBetween(qint64 start, qint64 end, int ignoreId, bool strict = false, bool complete = false, bool recursive = false, qint64 minimumDuration = 0) const; int id() const { return m_id; } virtual const QString text() const { return m_text; } int parent() const { return m_parentId; } int parentId() const { return m_parentId; } void printTrackIds(bool withItems = false, int level = 0) const; void removeCopyItem(int itemId) noexcept(false); void removeItem(int itemId) noexcept(false); ItemPtr takeItem(int itemId) noexcept(false); QVariant userData() const { return m_userData; } void setUserData(const QVariant& data) { m_userData = data; } inline static void sort(Items& items) { std::sort(items.begin(), items.end(), [](const ItemPtr& itemA, const ItemPtr& itemB) { return itemA->startTime() < itemB->startTime(); }); } inline static void sort(ItemPtrNCVRefs& items) { std::sort(items.begin(), items.end(), [](const ItemPtrNCVRef& itemA, const ItemPtrNCVRef& itemB) { return itemA.get()->startTime() < itemB.get()->startTime(); }); } inline static void sort(ItemPtrRefs& items) { std::sort(items.begin(), items.end(), [](const ItemPtrRef& itemA, const ItemPtrRef& itemB) { return itemA.get()->startTime() < itemB.get()->startTime(); }); } bool hasInsertButton() const { return m_hasInsertButton; } void setInsertButton(bool hasButton) { m_hasInsertButton = hasButton; } bool hasRemoveButton() const { return m_hasRemoveButton; } void setRemoveButton(bool hasButton) { m_hasRemoveButton = hasButton; } protected: QString m_text; QVariant m_userData; private: void removeTrack(int trackId) noexcept(false); void addItemPtr(ItemPtr&& itemPtr); static bool isItemBetween(const Item& item, qint64 start, qint64 end, bool strict, bool complete, qint64 minimumDuration = 0); ItemPtrRefs _copyItems() const; ItemPtrRefs _items(bool recursive) const; ItemPtrNCVRefs _itemsNCV(bool recursive); ItemPtrNCVRef _itemNCV(int id) noexcept(false); ItemPtrRef _item(int id) const noexcept(false); const QVector _itemIds(bool recursive) const; public: void clearItems() { m_items.clear(); } private: friend class TimelineModel; void sort() { sort(m_items); } template Track* addTrack(TrackClass&& trackClass) { TrackClass _trackClass = std::move(trackClass); m_childrenTracks.push_back(std::move(std::move(std::make_unique(std::move(_trackClass))))); return m_childrenTracks.back().get(); } template [[deprecated("Use model's track(...) and call addTrack(TrackClass) directly on that track.")]] Track* addTrack(int parentTrackId, TrackClass&& trackClass) noexcept(false) { if (m_id == parentTrackId) return addTrack(std::move(trackClass)); return track(parentTrackId).addTrack(std::move(trackClass)); } template Item* addItem(ItemClass&& itemClass) { ItemClass _itemClass(std::move(itemClass)); auto it = m_items.insert( std::upper_bound(m_items.begin(), m_items.end(), _itemClass.startTime(), [](qint64 startTime, const ItemPtr& other) { return (other->startTime() > startTime); }), std::move(std::make_unique(std::move(_itemClass)))); return it->get(); } Item* addItem(ItemPtr&& itemPtr) { auto it = 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)); return it->get(); } template [[deprecated]] QVector transformItemPtrsToIds(const ItemContainer& itemContainer) const { QVector ids; std::transform(itemContainer.cbegin(), itemContainer.cend(), std::back_inserter(ids), [](const ItemPtr& itemPtr) -> int { return itemPtr->id(); }); return ids; } int m_id{-1}; Tracks m_childrenTracks; Items m_items; int m_parentId{-1}; bool m_hasInsertButton{false}; bool m_hasRemoveButton{false}; QSet m_copyItemIds; }; } // namespace LtsTimeline