#pragma once #include "item.h" #include #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 ©ItemAt(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 ©ItemIds() 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; }; }