Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+451
@@ -0,0 +1,451 @@
|
||||
#pragma once
|
||||
|
||||
#include "tln_abstract_event_factory.h"
|
||||
#include "tln_participant_track.h"
|
||||
#include "tln_party_track.h"
|
||||
#include "tln_timeline_delegate.h"
|
||||
#include "EventTypes/Block/tln_block_item.h"
|
||||
|
||||
#include <LtsTimeline/item.h>
|
||||
#include <LtsTimeline/timeline_model.h>
|
||||
#include <LtsTimeline/timeline_utils.h>
|
||||
#include <LtsTimeline/timeline_view.h>
|
||||
#include <LtsWidgets/lts_column_filter_proxy_model.h>
|
||||
#include <ParticipantManagement/ppm.hpp>
|
||||
#include <Plugins/AudioVideoManagement/avm_data_plugin_interface.h>
|
||||
#include <Plugins/AudioVideoManagement/avm_menu_edit_gui_plugin_interface.h>
|
||||
#include <AudioVideoManagement/Shared/stream_list_result.h>
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonParseError>
|
||||
#include <QMutex>
|
||||
#include <QPainter>
|
||||
#include <QSqlDatabase>
|
||||
#include <QStyleOptionViewItem>
|
||||
#include <QUuid>
|
||||
|
||||
#include <memory> // unique ptr
|
||||
#include <functional>
|
||||
#include <type_traits> // std::enable_if => type
|
||||
|
||||
|
||||
namespace LtsSession { class LtsSession; }
|
||||
namespace ParticipantManagement { namespace Interface { class Dtc; } }
|
||||
namespace MarkerManagement
|
||||
{
|
||||
namespace Interface { class Dtc; }
|
||||
class Marker;
|
||||
}
|
||||
namespace InfrastructureManagement { namespace Interface { class Dtc; } }
|
||||
namespace LtsTimeline { class TimelineView; }
|
||||
namespace TimeLineManagement { class ForeignDataInterface; }
|
||||
namespace ExerciseEventManagement { class Event; }
|
||||
|
||||
using Ticks = LtsTimeline::Ticks;
|
||||
using namespace LtsTimeline;
|
||||
|
||||
typedef QVector<QVariantMap> Rows;
|
||||
typedef QVariantMap Row;
|
||||
|
||||
|
||||
namespace Timeline
|
||||
{
|
||||
class TimelineDialog;
|
||||
class TimelineModelUpdate;
|
||||
class TimelineProxyModel;
|
||||
class BuildingHitsTrack;
|
||||
class TimelineModel;
|
||||
|
||||
|
||||
/*
|
||||
class GetOfflineVideosProcess : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GetOfflineVideosProcess(const QMap<QString, QString> &streams, TimelineModel *model, QObject *parent);
|
||||
|
||||
private slots:
|
||||
void next();
|
||||
|
||||
signals:
|
||||
void signalDone();
|
||||
|
||||
private:
|
||||
QMap<QString, QString> m_streams;
|
||||
TimelineModel *m_model;
|
||||
QMap<QString, QString>::const_iterator m_streamsIt;
|
||||
int m_open { 0 };
|
||||
};
|
||||
*/
|
||||
class TimelineTableInfos
|
||||
{
|
||||
public:
|
||||
static TimelineTableInfos *getInstance();
|
||||
|
||||
void insertTable(const QString &tableName)
|
||||
{
|
||||
m_tableNames += tableName;
|
||||
}
|
||||
|
||||
void removeTable(const QString &tableName)
|
||||
{
|
||||
m_tableNames.removeAll(tableName);
|
||||
}
|
||||
|
||||
const QStringList &tableNames() const { return m_tableNames; }
|
||||
|
||||
private:
|
||||
friend struct TimelineTableInfosHandler;
|
||||
|
||||
QStringList m_tableNames;
|
||||
};
|
||||
|
||||
class TimelineModel : public LtsTimeline::TimelineModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class TimelineModelUpdate;
|
||||
friend class TimelineSelectHandler;
|
||||
// friend class GetOfflineVideosProcess;
|
||||
|
||||
public:
|
||||
static QString s_eemEventColumns;
|
||||
static const int s_maxRows{1000};
|
||||
|
||||
static int getInt(const Row &row, const QString &column) noexcept(false);
|
||||
static qint64 getLongLong(const Row &row, const QString &column) noexcept(false);
|
||||
static QJsonObject getJsonObject(const Row &row, const QString &column, bool ignoreError = false) noexcept(false);
|
||||
static double getJsonDouble(const Row &row, const QString &column) noexcept(false);
|
||||
|
||||
static const EventItem &getEventItem(const ItemPtrNCVRef &itemPtr) { return static_cast<const EventItem &>(*itemPtr.get()); }
|
||||
static const EventItem &getEventItem(const EventItemPtr &eventItemPtr) { return *eventItemPtr; }
|
||||
|
||||
explicit TimelineModel(LtsSession::LtsSession *session, TimelineDialog *dialog, qint64 exerciseStart, qint64 exerciseEnd, QObject *parent = nullptr) noexcept(false);
|
||||
~TimelineModel();
|
||||
|
||||
void initEventFactories(qint64 exerciseStart, qint64 exerciseEnd);
|
||||
void clearUnusedTempTables();
|
||||
|
||||
bool canDropItem(const LtsTimeline::Item &item, int trackId, qint64 start) const override;
|
||||
bool canMoveItem(const LtsTimeline::Item &item, qint64 start) const override;
|
||||
bool canResizeItem(const LtsTimeline::Item &item, qint64 start, int duration) const override;
|
||||
|
||||
TrackType trackType(const LtsTimeline::Track &t) const;
|
||||
TrackType trackType(int trackId) const;
|
||||
|
||||
bool isBlockItem(int itemId) const;
|
||||
bool hasBlockItems(const QVector<int> &itemIds) const;
|
||||
|
||||
EventItemPtr createItem(int id, qint64 sampleTime, QJsonObject properties /* TODO: copy elision? */,
|
||||
int eventTypeId, int participantId, int partyId, int eqId, double posX, double posY, double posZ) noexcept(false);
|
||||
EventItemPtr createItemFromRow(const Row &row);
|
||||
std::vector<EventItemPtr> createItemsFromRows(const Rows &rows);
|
||||
std::vector<EventItemPtr> getMarkerItems(const Filters &filters, bool rangeOnly = false, int limit = s_maxRows) noexcept(false);
|
||||
int findTrack(const AbstractEventItem &_eventItem);
|
||||
int handleCopyCollision(const Track &t, const int copyItemId, const int itemId, const qint64 start, const qint64 duration) noexcept(false);
|
||||
int handleCollision(Track &t, ItemPtr &&itemPtr, const int itemId, const qint64 start, const qint64 duration) noexcept(false);
|
||||
void insertCopyItem(Track &t, const int copyItemId) noexcept(false);
|
||||
void insertItem(Track &t, ItemPtr &&itemPtr) noexcept(false);
|
||||
void insertItem(ItemPtr &&itemPtr);
|
||||
void insertItems(EventItemPtrs &eventItemPtrs);
|
||||
QString cnrStream(int id) const { return m_cnrStreams.value(id); }
|
||||
QMap<int, QString> cnrStreams() { return m_cnrStreams;}
|
||||
QString tvcStream(int id) const { return m_tvcStreams.value(id); }
|
||||
QMap<int, QString> tvcStreams() { return m_tvcStreams;}
|
||||
|
||||
|
||||
/**
|
||||
* @brief getEventsByFilter NOTE: ignores filter's active state!
|
||||
* @param filters
|
||||
* @return
|
||||
*/
|
||||
std::vector<EventItemPtr> getEventsByFilter(const QVector<AbstractEventFilter *> &filters) noexcept(false);
|
||||
|
||||
// // :'(
|
||||
// std::vector<EventItemPtr> getEventsBehindBlockItemBuildings(int tickId, const QVector<AbstractEventFilter *> &filters) noexcept(false); // HitBuilding only (for *Root*-Buildings-Track only!!!)
|
||||
// std::vector<EventItemPtr> getEventsBehindBlockItemBuilding(int tickId, int mountingPointId, const QString &streamName, const QVector<AbstractEventFilter *> &filters) noexcept(false); // HitBuilding only (for specific Building's Track!!!)
|
||||
|
||||
// std::vector<EventItemPtr> getEventsBehindBlockItemTVC(int tickId, const QVector<AbstractEventFilter *> &filters) noexcept(false); // ROOT
|
||||
// std::vector<EventItemPtr> getEventsBehindBlockItemTVC(int tickId, const QString &streamName, const QVector<AbstractEventFilter *> &filters) noexcept(false); // SPECIFIC
|
||||
|
||||
// std::vector<EventItemPtr> getEventsBehindBlockItemCNR(int tickId, const QVector<AbstractEventFilter *> &filters) noexcept(false); // ROOT
|
||||
// std::vector<EventItemPtr> getEventsBehindBlockItemCNR(int tickId, const QString &streamName, const QVector<AbstractEventFilter *> &filters) noexcept(false); // SPECIFIC
|
||||
|
||||
// std::vector<EventItemPtr> getEventsBehindBlockItemBuildingsVideo(int tickId, const QVector<AbstractEventFilter *> &filters) noexcept(false); // the "Video" track
|
||||
// std::vector<EventItemPtr> getEventsBehindBlockItemBuildingVideo(int tickId, int msei, const QVector<AbstractEventFilter *> &filters) noexcept(false); // the Building track
|
||||
// std::vector<EventItemPtr> getEventsBehindBlockItemCameraVideo(int tickId, int mountingPointId, const QString &streamName, const QVector<AbstractEventFilter *> &filters) noexcept(false); // the Stream track
|
||||
|
||||
// std::vector<EventItemPtr> getEventsBehindBlockItemHitBuildingsRoot(int tickId, const QVector<AbstractEventFilter *> &filters) noexcept(false); // the "Buildings" track
|
||||
// std::vector<EventItemPtr> getEventsBehindBlockItemHitBuilding(int tickId, int msei, const QVector<AbstractEventFilter *> &filters) noexcept(false); // the Building track
|
||||
|
||||
// std::vector<EventItemPtr> getEventsBehindBlockItemDefaultParty(int tickId, int partyId, const QVector<AbstractEventFilter *> &filters) noexcept(false); // the rest ... ROOT
|
||||
// std::vector<EventItemPtr> getEventsBehindBlockItemDefault(int tickId, int participantId, const QVector<AbstractEventFilter *> &filters) noexcept(false); // the rest ... PARTICIPANT
|
||||
// // </ :'( >
|
||||
|
||||
// std::vector<EventItemPtr> getEventsBehindBlockItem(int itemId) noexcept(false);
|
||||
|
||||
qint64 currentEventWidthTime() const { return m_zeroDurationItemWidthTime; }
|
||||
|
||||
void test_getEventsByFilter();
|
||||
|
||||
void clearAlmostAllItems();
|
||||
|
||||
QHash<EventType, AbstractEventFactory *> &eventFactories() { return m_eventFactories; }
|
||||
AbstractEventFactory *eventFactory(EventType eventType) { return m_eventFactories.value(eventType, nullptr); }
|
||||
|
||||
QHash<EventType, AbstractEventFilter *> &filters() { return m_filter; }
|
||||
AbstractEventFilter *filter(EventType eventType) { return m_filter.value(eventType, nullptr); }
|
||||
AbstractEventFilter *tempFilter(EventType eventType) { return m_tempFilter.value(eventType, nullptr); }
|
||||
|
||||
void update(bool fake = false);
|
||||
const QVector<qint64> markerLines() const { return m_modelState.markerTimes; }
|
||||
bool knownRange(qint64 &startOut, qint64 &endOut) const;
|
||||
bool isCurrentlyUpdating() const { return m_isCurrentlyUpdating; }
|
||||
void queueUpdate();
|
||||
void setLive(bool live) { m_isLive = live; if (!live) m_forceRebuildFilter = true; }
|
||||
bool isLive() const { return m_isLive; }
|
||||
|
||||
public slots:
|
||||
void onRangeChanged(qint64 start, qint64 end);
|
||||
void onCurrentTimeChanged(qint64 time);
|
||||
void onZoomChanged(LtsTimeline::ZoomFactor zoom);
|
||||
void onUpdate() { update(); }
|
||||
void onFilterChanged();
|
||||
|
||||
signals:
|
||||
void updateStatusChanged(bool running);
|
||||
void errorCountExceeded();
|
||||
void thingy(int i, bool result);
|
||||
void initializationFinished(); // NOTE: emit queued, you will have enough time to connect to this signal
|
||||
|
||||
//#warning // TODO: private
|
||||
/*private*/ public slots:
|
||||
void onMarkerChanged(const MarkerManagement::Marker &marker, DataModification mod);
|
||||
void onLiveEvent(const ExerciseEventManagement::Event &eemEvent);
|
||||
private slots:
|
||||
void onStreamListReceived(const QMap<QString, QString> &streamList);
|
||||
private:
|
||||
struct Party
|
||||
{
|
||||
int id;
|
||||
int trackId;
|
||||
Party(int id, int trackId) : id(id), trackId(trackId) {}
|
||||
};
|
||||
|
||||
struct Participant
|
||||
{
|
||||
int participantId { 0 };
|
||||
int trackId { 0 };
|
||||
int superiorId { 0 };
|
||||
int equipmentNumber { 0 };
|
||||
int partyId { 0 };
|
||||
QString text;
|
||||
QVector<int> inferiorIds;
|
||||
Participant() = default;
|
||||
Participant(int participantId, int equipmentNumber, int partyId, const QString &text, int trackId = 0, int superiorId = 0, const QVector<int> &inferiorIds = {})
|
||||
: participantId(participantId)
|
||||
, trackId(trackId)
|
||||
, superiorId(superiorId)
|
||||
, equipmentNumber(equipmentNumber)
|
||||
, partyId(partyId)
|
||||
, text(text)
|
||||
, inferiorIds(inferiorIds)
|
||||
{}
|
||||
};
|
||||
|
||||
struct Range
|
||||
{
|
||||
qint64 start { 0 };
|
||||
qint64 end { 0 };
|
||||
};
|
||||
|
||||
struct ModelState
|
||||
{
|
||||
QString publicTableName;
|
||||
|
||||
//#warning // TODO: ! publish to singleton thingy
|
||||
QString dbUuid = QUuid::createUuid().toString(QUuid::Id128);
|
||||
|
||||
// the event view is a temporary database table holding filtered EEM-Event data
|
||||
qint64 tempRangeStart { 0 };
|
||||
qint64 tempRangeEnd { 0 };
|
||||
|
||||
// start and end correspond to what time interval can currently be seen on the timeline
|
||||
qint64 start { 0 };
|
||||
qint64 end { 0 };
|
||||
|
||||
// knownStart and knownEnd is the time interval for which data is inside the model
|
||||
//QVector<Range> knownRanges;
|
||||
qint64 knownStart { 0 };
|
||||
qint64 knownEnd { 0 };
|
||||
|
||||
int markerTrackId { -1 }; // TODO: move me and others into a "ModelState" class, so I can be reset with only a recreation of the class !!
|
||||
QVector<qint64> markerTimes;
|
||||
QHash<int/*participantId*/, int/*trackId*/> participantTracks;
|
||||
QMap<int/*participantId*/, Participant> participants;
|
||||
QMap<int/*partyId*/, Party> partys;
|
||||
int hitBuildingsRootTrackId { -1 };
|
||||
|
||||
|
||||
|
||||
|
||||
int buildingRootTrackId { -1 };
|
||||
QMap<int /* buildingId (MSEI) */, int /* trackId */> buildingTrackIds;
|
||||
//QMap<QPair<int /* buildingId (MSEI) */, QString /* internal stream name */>, int /* trackId */> buildingStreamsTrackIds;
|
||||
|
||||
|
||||
|
||||
|
||||
// QMap<QPair<int /* buildingId */, QString /* internalStreamName */>, int /* trackId */> buildingStreamTracks;
|
||||
// int cnrRootTrackId { -1 };
|
||||
// QMap<QString /* internalStreamName */, int /* trackId */> cnrTrackIds;
|
||||
// int tvcRootTrackId { -1 };
|
||||
// QMap<QString /* internalStreamName */, int /* trackId */> tvcTrackIds;
|
||||
};
|
||||
|
||||
void updateFilterTable();
|
||||
void addParticipantTrack(Participant &participant, int superiorTrackId);
|
||||
void getParticipantTracks();
|
||||
//void getBuildingTracks();
|
||||
void getRadioTracks();
|
||||
|
||||
QVector<QVariantMap> /* aka. Rows */ executeQuery(const QString &query, bool ignoreError = false) const noexcept(false);
|
||||
QVector<QVariantMap> /* aka. Rows */ executeQuery(const QString &query, const QSqlDatabase &db, bool ignoreError = false) const noexcept(false);
|
||||
|
||||
bool isCollision(qint64 startTime, qint64 previousStartTime, qint64 previousDuration);
|
||||
void tryUpdate();
|
||||
|
||||
QJsonObject eventPropertiesFromMarker(const MarkerManagement::Marker &marker);
|
||||
|
||||
void reChannelSumEvents(int trackId, int onlyThisTick) noexcept(false);
|
||||
void backwardsChannelSumEvents(const Track &t);
|
||||
void channelSumEvents();
|
||||
void sumEvents(Track &track);
|
||||
|
||||
//int megaParent(int trackId) noexcept(false);
|
||||
//QModelIndex megaParentModelIndex(int trackId) noexcept(false);
|
||||
QVector<int> findItemIdsForDbId(int dbId) noexcept(false);
|
||||
EventItem &itemWithMarkerDbId(int dbId) noexcept(false);
|
||||
|
||||
// because bad deduction by compiler
|
||||
template <typename ItemClass>/*, typename = typename std::enable_if<std::is_base_of<LtsTimelineItem, ItemClass>::value, ItemClass>::type>*/
|
||||
int addItem(int parentTrackId, ItemClass &&item) noexcept(false)
|
||||
{
|
||||
return LtsTimeline::TimelineModel::addItem(parentTrackId, std::move(item));
|
||||
}
|
||||
|
||||
void getMarkers() noexcept(false);
|
||||
void getOfflineVideoTracks() ; //Same than the other but give back list of added streams
|
||||
// void getOfflineVideos() noexcept(false);
|
||||
// void addOfflineVideosToTimeline();
|
||||
BuildingHitsTrack createBuildingHitsTrack();
|
||||
void getBuildings();
|
||||
void getBuildingVideoStreams();
|
||||
|
||||
QVector<int /* msei */> m_mainStructureElements;
|
||||
QMap<int /* mpi */, int /* msei */> m_mountingPointsToMainStructureElementMapping;
|
||||
QVector<int /* mpi */> m_buildingVideoStreams;
|
||||
QMap<QPair<int /* buildingId (MSEI) */, QString /* internal stream name */>, int /* trackId */> m_buildingStreamsTracks;
|
||||
// offline videos
|
||||
QMap<QString, QString> m_offlineVideoDisplayNames;
|
||||
QMap<QString /* internal stream name */, int> m_offlineVideoTracks;
|
||||
// Outdoor Cameras
|
||||
int m_outdoorCameraRootTrackId { -1 };
|
||||
QMap<int/*mounting point id*/, QString/*human name*/> m_outdoorCameraStreams;
|
||||
QMap<QString/*internal stream name*/, int/*track id*/> m_outdoorCameraTracks;
|
||||
|
||||
int m_videosRootTrackId { -1 };
|
||||
QMap<QString /* stream name */, int /* track id */> m_videoTracks;
|
||||
|
||||
// CNR
|
||||
int m_cnrRootTrackId { -1 };
|
||||
QMap<QString /* __display__ stream name */, int /* trackId */> m_cnrTrackIds; // yea, avs saves the display name to db, not the internal name ... :)
|
||||
QMap<int /* channel id */, QString /* display name */> m_cnrChannelDisplayNames;
|
||||
//QMap<QString /* display name */, int /* channel id */> m_cnrChannelDisplayNamesLookup;
|
||||
|
||||
// TVC
|
||||
int m_tvcRootTrackId { -1 };
|
||||
QMap<QString /* internalStreamName */, int /* trackId */> m_tvcTrackIds;
|
||||
QMap<int /* channel id */, QString /* display name */> m_tvcChannelDisplayNames;
|
||||
|
||||
|
||||
template <typename First, typename Second>
|
||||
static QString keyToString(const QPair<First, Second> &key)
|
||||
{
|
||||
return QStringLiteral("%1/%2").arg(key.first).arg(key.second);
|
||||
}
|
||||
|
||||
template <typename Key>
|
||||
static QString keyToString(const Key &key)
|
||||
{
|
||||
return QStringLiteral("%1").arg(key);
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename Container, typename Key>
|
||||
static ReturnType constFinder(const Container &container, const Key &key) noexcept(false)
|
||||
{
|
||||
auto it = container.constFind(key);
|
||||
|
||||
if (it == container.constEnd())
|
||||
throw QStringLiteral("constFinder: cannot find '%1' in container").arg(keyToString(key));
|
||||
|
||||
return it.value();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
LtsSession::LtsSession *m_session { nullptr };
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc { nullptr };
|
||||
std::shared_ptr<MarkerManagement::Interface::Dtc> m_mrkDtc { nullptr };
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc { nullptr };
|
||||
std::shared_ptr<TimeLineManagement::ForeignDataInterface> m_eemForeign { nullptr };
|
||||
std::shared_ptr<AudioVideoManagement::Interface::Dtc> m_avmDtc { nullptr };
|
||||
std::shared_ptr<AudioVideoManagement::ForeignMenuEditGuiInterface> m_avmIfc { nullptr };
|
||||
|
||||
QHash<EventType, AbstractEventFactory *> m_eventFactories;
|
||||
QHash<EventType, AbstractEventFilter *> m_filter;
|
||||
public:
|
||||
QHash<EventType, AbstractEventFilter *> m_tempFilter;
|
||||
QMutex m_mutex;
|
||||
private:
|
||||
QMultiMap<QString, QPair<qint64, qint64>> m_multiMapClipsForStream;
|
||||
QMap<QString, qint64> m_lastStartTimePerStream;
|
||||
QString m_filterString;
|
||||
|
||||
QSqlDatabase m_db;
|
||||
|
||||
ModelState m_modelState;
|
||||
QTimer *m_updateTimer { nullptr };
|
||||
QTimer *m_offlineVideoTimer { nullptr };
|
||||
bool m_updateMutex { false };
|
||||
bool m_updateResult { true };
|
||||
bool m_updateQueued { false };
|
||||
bool m_queueItemDeletion { false }; // if e.g. zoom is changed, all events have to be refetched, but events should only be deleted if the update is actually executing, as queued updates are not guaranteed to be executed
|
||||
|
||||
int m_fakeId { 0 };
|
||||
qint64 m_zeroDurationItemWidthTime { 0 };
|
||||
static int s_minThreadCount;
|
||||
static int s_maxThreadCount;
|
||||
|
||||
bool m_isCurrentlyUpdating { false };
|
||||
int m_threads { 1 };
|
||||
|
||||
|
||||
|
||||
bool m_firstUpdate { true };
|
||||
int *m_lockyMcLockLock { nullptr };
|
||||
Rows **m_sharedThing { nullptr };
|
||||
|
||||
bool m_forceRebuildFilter { false };
|
||||
TimelineDialog *m_dialog;
|
||||
bool m_isLive { false };
|
||||
bool m_trackFetchedInLiveDone { false };
|
||||
QMap<int, QString> m_cnrStreams;
|
||||
QMap<int, QString> m_tvcStreams;
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Timeline
|
||||
Reference in new issue
Block a user