Continues migration with DDS, Common

This commit is contained in:
torsten committed 2026-07-17 12:41:42 +02:00
1 parent 9b15cee841
commit fa48db111e
668 files changed
+111841 -2

No files matched your search

+283
View File
@@ -0,0 +1,283 @@
#include "AbstractTimelineModel.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
namespace LtsTimelineClassic
{
AbstractTimelineModel::AbstractTimelineModel(QObject *parent)
: QAbstractItemModel(parent)
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("Timeline.AbstractTimelineModel"))
, m_highestPositionedItem(0)
, m_lowestPositionedItem(0)
, m_getEventListsRecursive(true)
, m_rootItem(new Item(QLatin1String("#mwille/r00t/")))
, m_markersItem(new Item(tr("Markers"), QStringLiteral("Markers")))
{
m_rootItem->addItem(m_markersItem);
}
AbstractTimelineModel::~AbstractTimelineModel()
{
delete m_rootItem;
}
void AbstractTimelineModel::retranslate()
{
m_markersItem->setName(tr("Markers"));
}
void AbstractTimelineModel::invalidateTimeline()
{
const LtsTimelineClassic::ItemList il = m_rootItem->getFullItemList(true);
for (auto i = il.constBegin(); i != il.constEnd(); ++i)
{
LtsTimelineClassic::Item *item = *i;
if (item != nullptr)
item->setEventListChanged();
}
}
Event *AbstractTimelineModel::getEvent(int uniqueId)
{
const LtsTimelineClassic::ItemList il = m_rootItem->getFullItemList(true);
for (auto i = il.constBegin(); i != il.constEnd(); ++i)
{
LtsTimelineClassic::Item *item = *i;
if (item != nullptr && item->getIdentifier() != QStringLiteral("Markers"))
{
const LtsTimelineClassic::EventList el = item->getFullEventList(true, true);
for (LtsTimelineClassic::Event *event : el)
{
if (event->uniqueId() == uniqueId)
return event;
}
}
}
return nullptr;
}
void AbstractTimelineModel::addEvent(Event *event)
{
QStringList actuatorPath = event->getActuator();
Item *currentItem = m_rootItem;
QModelIndex currentIndex = QModelIndex();
for (const QString &curPath : qAsConst(actuatorPath))
{
Item *oldItem = currentItem;
const ItemList *itemList = currentItem->getChildren();
if (itemList != nullptr)
{
for (int row = 0; row < itemList->count(); row++)
{
Item *childItem = itemList->at(row);
if (childItem->getName() == curPath)
{
currentIndex = index(row, 0, currentIndex);
currentItem = childItem;
break;
}
}
}
if (oldItem == currentItem)
{
beginInsertRows(currentIndex, currentItem->childCount(), currentItem->childCount());
Item *newItem = new Item(curPath);
currentItem->addItem(newItem);
endInsertRows();
currentIndex = index(currentItem->childCount() - 1, 0, currentIndex);
currentItem = newItem;
}
}
currentItem->addEvent(event);
}
Item *AbstractTimelineModel::getRootItem()
{
return m_rootItem;
}
Item *AbstractTimelineModel::itemFromIndex(const QModelIndex &idx) const
{
if (!idx.isValid())
return m_rootItem;
return static_cast<Item *>(idx.internalPointer());
}
QVariant AbstractTimelineModel::data(const QModelIndex &index, int role) const
{
if (role != Qt::DisplayRole || !index.isValid())
return QVariant();
Item *item = itemFromIndex(index);
if (!item)
return QVariant();
if (index.column() == 1)
{
PassiveEventContainer *pevcon = item->getPevcon();
return QVariant::fromValue(pevcon);
}
QString name(item->getName());
if (name.isEmpty())
name = tr("[unknown]");
return QVariant(name);
}
Qt::ItemFlags AbstractTimelineModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return {};
return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}
QVariant AbstractTimelineModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
{
switch (section)
{
case 0: return QString(tr("Actuator") + QStringLiteral("\r\n"));
case 1: return QString(tr("Events") + QStringLiteral("\r\n"));
}
}
return QVariant();
}
QModelIndex AbstractTimelineModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
Item *item = itemFromIndex(parent);
Item *child = item ? item->child(row) : nullptr;
if (child)
{
return createIndex(row, column, child);
}
return QModelIndex();
}
QModelIndex AbstractTimelineModel::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
Item *item = itemFromIndex(index);
Item *parent = item ? item->getParent() : nullptr;
if (parent == m_rootItem || parent == nullptr)
return QModelIndex();
int idx = parent->indexOfParent();
if (idx == -1)
return QModelIndex();
return createIndex(idx, 0, parent);
}
int AbstractTimelineModel::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid())
{
int r = m_rootItem->visibleChildCount();
return r;
}
Item *item = itemFromIndex(parent);
if (item)
{
int r = item->visibleChildCount();
return r;
}
return 0;
}
int AbstractTimelineModel::columnCount(const QModelIndex &) const
{
return 2;
}
}
+112
View File
@@ -0,0 +1,112 @@
#pragma once
#include "Event.h"
#include "Item.h"
#include <LtsTimelineClassic/ltstimelineclassic_export.h>
#include <QAbstractItemModel>
#include <NGLLogger/INGLLogger.h>
namespace LtsTimelineClassic
{
class LTSTIMELINECLASSIC_EXPORT AbstractTimelineModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit AbstractTimelineModel( QObject *parent = nullptr);
~AbstractTimelineModel();
void retranslate();
Item *getRootItem();
Event *getEvent(int uniqueId);
void invalidateTimeline();
void refreshData();
qint64 highestPositionedItem() const { return m_highestPositionedItem; }
qint64 lowestPositionedItem() const { return m_lowestPositionedItem; }
protected:
NGL::INGLLogger &m_logger;
protected:
void addEvent(Event *event);
QVariant data(const QModelIndex &index, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
Item *itemFromIndex(const QModelIndex &idx) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &index) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
virtual qint64 currentTime() const = 0;
qint64 m_highestPositionedItem;
qint64 m_lowestPositionedItem;
bool m_getEventListsRecursive;
Item *m_rootItem;
Item *m_markersItem;
signals:
void signalContextMenu(const QPoint &position, Event *affectedEvent);
void signalClicked(Event *affectedEvent);
void signalToolTip(const QPoint &p, Event *e);
};
}
+82
View File
@@ -0,0 +1,82 @@
#
# CMakeLists.txt for Timeline Library
#
# $Id$
# $HeadURL$
# $Author$
#
# Created by Mike Wille, SLSE, 2017-02-10
#
SET(timeline_SRCS
EventDelegate.cpp
EventTools.cpp
Item.cpp
PassiveEventContainer.cpp
TimelineWidget.cpp
TimelineHeaderView.cpp
TimelineIndicator.cpp
TestTimelineModel.cpp
AbstractTimelineModel.cpp
TimelineView.cpp
Event.cpp
EventGraphic.cpp
EventDelegate.h
EventList.h
EventTools.h
Item.h
PassiveEventContainer.h
TimelineWidget.h
TimelineHeaderView.h
TimelineIndicator.h
AbstractTimelineModel.h
TimelineView.h
#timeline_export.h
Event.h
TestTimelineModel.h
EventGraphic.h
LineMap.h
)
SET(timeline_UICS
Ui/TimelineWidgetUi.ui
)
NGL_WRAP_UI(timeline_SRCS ${timeline_UICS})
NGL_ADD_LIBRARY2(WS LtsTimelineClassic SHARED ${timeline_SRCS} ${timeline_UICS})
NGL_TARGET_INCLUDE_DIRECTORIES(LtsTimelineClassic
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(LtsTimelineClassic
PRIVATE
NGLLogger
ngltools # DTG
Qt5::Core
Qt5::Gui
Qt5::Widgets
LtsSessionDataDds
)
IF(NEVER)
NGL_ADD_EXECUTABLE(WS LtsTimelineClassicTest main.cpp)
NGL_TARGET_LINK_LIBRARIES(LtsTimelineClassicTest
nglapplication
NGLLogger
Qt5::Core
Qt5::Gui
Qt5::Widgets
LtsTimelineClassic
svcEemCommon
svcEemClient
PdmDataPluginInterface
)
ENDIF()
NGL_INSTALL_TARGET(LtsTimelineClassic)
+219
View File
@@ -0,0 +1,219 @@
#include "Event.h"
#include <LtsSession/lts_session.h>
#include <QRect>
#include <QPainter>
#include <QPainterPath>
#include <time.h>
namespace LtsTimelineClassic
{
Event::Event(int uniqueId, int typeId, qint64 startTime,
qint64 endTime, int playerId, int partyId, int equipmentId, const QStringList &path,
const EventPaintFunc &paintFunc, const QColor &paintColor, const QJsonObject &detailData, int subEventId,
const LtsUtils::QPoint3D &pos, LtsSession::LtsSession *session)
: m_path(path)
, m_detailData(detailData)
, m_position(pos)
, m_paintFunc(paintFunc)
, m_session(session)
, m_eventColor(paintColor)
, m_startTime(startTime)
, m_endTime(endTime)
, m_uniqueId(uniqueId)
, m_typeId(typeId)
, m_subEventId(subEventId)
, m_playerId(playerId)
, m_partyId(partyId)
, m_equipmentId(equipmentId)
, m_deleted(false)
, m_visible(true)
{
checkDuration();
}
void Event::setVisible(bool visibility)
{
if (visibility)
show();
else
hide();
}
void Event::hide()
{
this->m_visible = false;
}
void Event::show()
{
this->m_visible = true;
}
QString Event::getShortActuator() const
{
return m_path.isEmpty() ? QString() : m_path.last();
}
void Event::setEndT(qint64 newEnd)
{
m_endTime = newEnd;
checkDuration();
}
bool Event::checkDuration()
{
return true;
}
qint64 Event::duration(bool ignoreLiveEvents) const
{
if (m_endTime > m_startTime)
{
if (m_duration == -1)
m_duration = m_endTime - m_startTime;
return m_duration;
}
if (m_endTime < 0 && !ignoreLiveEvents)
{
qint64 currentTime = (m_session != nullptr) ? m_session->partitionTime() : time(nullptr) ;
qint64 duration = currentTime - m_startTime;
return duration;
}
return 0;
}
void Event::drawMultipleEventGraphic(QPainter *painter, const QRect &rect)
{
painter->save();
painter->setBrush(Qt::white);
int x = rect.x();
int y = rect.y();
int h = rect.height();
int w = rect.width();
painter->drawRect(rect);
int s1 = y + h - (h * 0.4);
int s2 = y + h - (h * 0.2);
painter->drawLine(QPoint(x, s1),
QPoint(x + w, s1));
painter->drawLine(QPoint(x, s2),
QPoint(x + w, s2));
painter->restore();
}
void Event::drawCustomEventGraphicTriangle(QPainter *painter, const QRect &rect)
{
int x = rect.x();
int y = rect.y();
int h = rect.height();
int w = rect.width();
QPolygon pol;
pol.append(QPoint(x + 0, y + h));
pol.append(QPoint(x + (w / 2), y + 0));
pol.append(QPoint(x + w, y + h));
pol.append(QPoint(x + 0, y + h));
QPainterPath path;
path.moveTo(x, y);
path.addPolygon(pol);
painter->drawPath(path);
}
void Event::drawCustomEventGraphicInvertTriangle(QPainter *painter, const QRect &rect)
{
int x = rect.x();
int y = rect.y();
int h = rect.height();
int w = rect.width();
QPolygon pol;
pol.append(QPoint( x + 0 , y + 0));
pol.append(QPoint( x+ w , y + 0));
pol.append(QPoint(x + ( w / 2 ), y + h));
pol.append(QPoint( x + 0 , y + 0));
QPainterPath path;
path.moveTo(x, y);
path.addPolygon(pol);
painter->drawPath(path);
}
void Event::drawCustomEventGraphicEllipse(QPainter *painter, const QRect &rect)
{
QPoint ellipsePos = rect.center();
ellipsePos.rx()++;
ellipsePos.ry()++;
painter->drawEllipse(ellipsePos, rect.width() / 2, rect.height() / 2);
}
void Event::drawCustomEventGraphicRect(QPainter *painter, const QRect &rect)
{
painter->drawRect(rect);
}
void Event::drawCustomEventGraphicRoundedRect(QPainter *painter, const QRect &rect)
{
painter->drawRoundedRect(rect, 50, 50, Qt::RelativeSize);
}
}
+155
View File
@@ -0,0 +1,155 @@
#pragma once
#include <LtsTimelineClassic/ltstimelineclassic_export.h>
#include <QColor>
#include <QJsonObject>
#include <QStringList>
#include <LtsUtilsCore/qpoint3d.h>
class QPainter;
class QRect;
namespace LtsSession
{
class LtsSession;
}
namespace LtsTimelineClassic
{
class LTSTIMELINECLASSIC_EXPORT Event
{
public:
enum ButtonType
{
ActiveEvent,
EventBlock,
};
typedef void (*EventPaintFunc)(QPainter *, const QRect &);
static void drawCustomEventGraphicTriangle(QPainter *painter, const QRect &rect);
static void drawCustomEventGraphicInvertTriangle(QPainter *painter, const QRect &rect);
static void drawCustomEventGraphicEllipse(QPainter *painter, const QRect &rect);
static void drawCustomEventGraphicRect(QPainter *painter, const QRect &rect);
static void drawCustomEventGraphicRoundedRect(QPainter *painter, const QRect &rect);
static void drawMultipleEventGraphic(QPainter *painter, const QRect &rect);
Event() = default;
Event(int uniqueId, int typeId, qint64 startTime, qint64 endTime,
int playerId, int partyId, int equipmentId, const QStringList &path,
const EventPaintFunc &paintFunc, const QColor &paintColor,
const QJsonObject &detailData, int subEventId = -1,
const LtsUtils::QPoint3D &pos = LtsUtils::QPoint3D(),
LtsSession::LtsSession *session = nullptr);
QStringList getActuator() const { return m_path; }
int typeId() const { return m_typeId; }
int uniqueId() const { return m_uniqueId; }
int getSubEventID() const;
QColor getColor() const { return m_eventColor; }
EventPaintFunc getPaintFunc() const { return m_paintFunc; }
qint64 startTime() const { return m_startTime; }
qint64 endTime() const { return m_endTime; }
const QJsonObject &detailData() const { return m_detailData; }
void setDetailData(const QJsonObject &detailData) { m_detailData = detailData; }
void setEndT(qint64 newEnd);
qint64 duration(bool ignoreLiveEvents = false) const;
int playerId() const { return m_playerId; }
void setPlayerId(int playerId) { m_playerId = playerId; }
int partyId() const { return m_partyId; }
void setPartyId(int teamId) { m_partyId = teamId; }
int equipmentId() const { return m_equipmentId; }
void setEquipmentId(int eqId) { m_equipmentId = eqId; }
QString getShortActuator() const;
bool positionValid() const { return !std::isnan(m_position.x()) && !std::isnan(m_position.y()); }
const LtsUtils::QPoint3D &position() const { return m_position; }
QPointF pos2d() const { return QPointF(m_position.x(), m_position.y()); }
void setPosition(const LtsUtils::QPoint3D &pos) { m_position = pos; }
void hide();
void show();
bool isVisible() const { return m_visible; }
void setVisible(bool visibility = true);
void setDeleted() { m_deleted = true; }
bool isDeleted() const { return m_deleted; }
protected:
QStringList m_path;
QJsonObject m_detailData;
LtsUtils::QPoint3D m_position;
EventPaintFunc m_paintFunc = nullptr;
LtsSession::LtsSession *m_session = nullptr;
QColor m_eventColor;
qint64 m_startTime = -1;
qint64 m_endTime = -1;
mutable qint64 m_duration = -1;
int m_uniqueId = -1;
int m_typeId = -1;
int m_subEventId = -1;
int m_playerId = -1;
int m_partyId = -1;
int m_equipmentId = -1;
bool m_deleted = false;
bool m_visible = false;
private:
static bool checkDuration();
};
}
+62
View File
@@ -0,0 +1,62 @@
#include "EventDelegate.h"
#include "PassiveEventContainer.h"
#include <QModelIndex>
#include <QDebug>
namespace LtsTimelineClassic
{
EventDelegate::EventDelegate(QWidget *parent)
: QStyledItemDelegate(parent)
, m_liveTime(0)
{
}
QSize EventDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
(void)option;
(void)index;
return QSize(50, 20);
}
void EventDelegate::setKnownRanges(const QVector<Range> &knownRanges)
{
m_knownRanges = knownRanges;
}
void EventDelegate::setLiveTime(qint64 liveTime)
{
m_liveTime = liveTime;
}
void EventDelegate::slotAddLine(int posX, qint64 time)
{
m_lineMap.insert(posX, time);
}
void EventDelegate::slotResetLineList()
{
m_lineMap.clear();
}
void EventDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (index.data().canConvert<PassiveEventContainer *>())
{
PassiveEventContainer *passiveEventContainer = qvariant_cast<PassiveEventContainer *>(index.data());
passiveEventContainer->paint(painter, option, m_lineMap, m_knownRanges);
}
else
QStyledItemDelegate::paint(painter, option, index);
}
}
+55
View File
@@ -0,0 +1,55 @@
#pragma once
#include "AbstractTimelineModel.h"
#include "Range.h"
#include <QStyledItemDelegate>
namespace LtsTimelineClassic
{
class EventDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
EventDelegate(QWidget *parent = nullptr);
void setKnownRanges(const QVector<Range> &knownRanges);
QSize sizeHint(const QStyleOptionViewItem &option = QStyleOptionViewItem(), const QModelIndex &index = QModelIndex()) const;
void setLiveTime(qint64 liveTime);
private:
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
LineMap m_lineMap;
QVector<Range> m_knownRanges;
qint64 m_liveTime;
public slots:
void slotResetLineList();
void slotAddLine(int posX, qint64 time);
};
}
+175
View File
@@ -0,0 +1,175 @@
#include "EventGraphic.h"
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QGuiApplication>
#include <QPoint>
#include <QPalette>
#include <QDebug>
namespace LtsTimelineClassic
{
EventGraphic::EventGraphic(Event *event)
: m_lowest(0)
, m_duration(-1)
, m_isMultipleEvent(false)
{
m_eventList += event;
}
void EventGraphic::addEvent(Event *event)
{
if (event == nullptr)
return;
m_eventList += event;
m_isMultipleEvent = true;
m_lowest = 0;
m_duration = -1;
}
void EventGraphic::addEventList(const QVector<Event *> &eventList)
{
if (eventList.isEmpty())
return;
m_eventList += eventList;
m_isMultipleEvent = true;
m_lowest = 0;
m_duration = -1;
}
qint64 EventGraphic::getDuration()
{
if (m_duration != -1)
return m_duration;
qint64 highestDuration = 0;
qint64 lowest = lowestTime();
for (Event *event : qAsConst(m_eventList))
{
qint64 duration = (event->startTime() - lowest) + event->duration();
if (duration > highestDuration)
highestDuration = duration;
}
if (highestDuration < 0)
{
qWarning() << "duration < 0 !!" << highestDuration;
Q_ASSERT(false);
return 0;
}
m_duration = highestDuration;
return m_duration;
}
qint64 EventGraphic::lowestTime() const
{
if (m_lowest != 0)
return m_lowest;
auto i = std::min_element(m_eventList.begin(), m_eventList.end(), [](const Event *a, const Event *b)
{
return a->startTime() < b->startTime();
});
if (i == m_eventList.end())
return 0;
m_lowest = (*i)->startTime();
return m_lowest;
}
bool EventGraphic::isMultipleEvent() const
{
return m_isMultipleEvent;
}
void EventGraphic::drawEventGraphic(QPainter *painter, const QRect &rect) const
{
painter->save();
painter->setPen(QPen(QBrush(QGuiApplication::palette().text()), 1.0));
if (isMultipleEvent())
Event::drawMultipleEventGraphic(painter, rect);
else
{
Event *e = m_eventList.first();
if (e == nullptr)
{
painter->restore();
return;
}
painter->setBrush(QBrush(e->getColor()));
if (e->getPaintFunc() == nullptr)
{
painter->restore();
return;
}
e->getPaintFunc()(painter, rect);
}
painter->restore();
}
void EventGraphic::drawDurationBackground(QPainter *painter, const QRect &rect) const
{
painter->save();
if (!isMultipleEvent())
{
Event *e = m_eventList.first();
if (e == nullptr)
{
painter->restore();
return;
}
painter->setBrush(QBrush(e->getColor()));
painter->setPen(QPen(QBrush(e->getColor()), 0));
}
else
{
painter->setBrush(QBrush(QColor("white")));
}
painter->drawRect(rect.adjusted(0, 0, -2, 0));
painter->setPen(QPen(QBrush(QGuiApplication::palette().text()), 1.0));
painter->drawLine(rect.topLeft(), rect.topRight());
painter->drawLine(rect.bottomLeft() + QPoint(0, 1), rect.bottomRight() + QPoint(1, 1));
painter->restore();
}
}
+48
View File
@@ -0,0 +1,48 @@
#pragma once
#include "EventList.h"
#include "Event.h"
#include <LtsTimelineClassic/ltstimelineclassic_export.h>
namespace LtsTimelineClassic
{
class LTSTIMELINECLASSIC_EXPORT EventGraphic
{
public:
enum Action
{
ACTION_LEFT_CLICKED,
ACTION_RIGHT_CLICKED,
ACTION_TOOLTIP,
};
explicit EventGraphic(Event *event);
bool isMultipleEvent() const;
const QVector<Event *> eventList() const { return m_eventList; }
void addEventList(const QVector<Event *> &eventList);
void addEvent(Event *event);
qint64 lowestTime() const;
qint64 getDuration();
void drawEventGraphic(QPainter *painter, const QRect &rect) const;
void drawDurationBackground(QPainter *painter, const QRect &rect) const;
private:
EventList m_eventList;
mutable qint64 m_lowest;
mutable qint64 m_duration;
bool m_isMultipleEvent;
};
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include <QVector>
namespace LtsTimelineClassic
{
class Event;
using EventList = QVector<Event *>;
class EventGraphic;
using EventGraphicList = QVector<EventGraphic *>;
}
+420
View File
@@ -0,0 +1,420 @@
#include "EventTools.h"
#include "EventGraphic.h"
#include "Event.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <math.h>
#include <QPainter>
#include <QDebug>
namespace LtsTimelineClassic
{
#define logger NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("Timeline.EventTools")
#ifdef LTS_DEBUG
#endif
#ifdef VERBOSE
#define dbg_print(x) qWarning() << #x << x
#else
#define dbg_print(x) (void)x;
#endif
qint64 EventTools::s_minAdjusted = 0;
qint64 EventTools::s_maxAdjusted = 1;
qint64 EventTools::s_minTimeline = 0;
qint64 EventTools::s_maxTimeline = 1;
qint64 EventTools::s_sbPos = 0;
qint64 EventTools::s_zoomFactor = 1;
int EventTools::s_paintMin = 0;
int EventTools::s_paintDiff = 0;
bool EventTools::s_isValid = false;
qint64 EventTools::s_diff = 0;
int EventTools::s_sectionHeight = 0;
int EventTools::s_test = 0;
qint64 EventTools::s_blockSizeTime = 0;
bool EventTools::s_inUse = false;
void EventTools::setValues(const qint64 min, const qint64 max, const qint64 sbPos, const qint64 zoomFactor)
{
if (s_minTimeline == min && s_maxTimeline == max && s_sbPos == sbPos && s_zoomFactor == zoomFactor)
return;
s_sbPos = sbPos;
s_zoomFactor = zoomFactor;
s_isValid = false;
s_minAdjusted = s_sbPos;
double d_max = s_minAdjusted;
d_max += s_zoomFactor;
s_maxAdjusted = d_max;
s_diff = s_maxAdjusted - s_minAdjusted;
s_minTimeline = min;
s_maxTimeline = max - EventTools::s_diff + (EventTools::getBlockSizeTime() * 2);
recalcBlockSizeTime();
if (min > 0 && max > 1)
{
s_isValid = true;
}
else
{
}
#ifdef VERBOSE
qWarning() << "\r\n\r\nEventTools::setValues: " << "\r\n"
<< "s_sbPos" << s_sbPos << "\r\n"
<< "s_zoomFactor" << s_zoomFactor << "\r\n"
<< "s_minTimeline" << s_minTimeline << "\r\n"
<< "s_maxTimeline" << s_maxTimeline << "\r\n"
<< "s_isValid" << s_isValid << "\r\n"
<< "s_minAdjusted" << s_minAdjusted << "\r\n"
<< "s_maxAdjusted" << (long)s_maxAdjusted << "\r\n"
<< "s_diff" << s_diff << "\r\n"
;
#endif
}
void EventTools::setSection(const int x, const int length)
{
s_paintMin = x;
s_paintDiff = length;
}
bool EventTools::isValid()
{
#ifdef VERBOSE
if (!s_isValid)
qWarning() << "<<<< INVALID EVENT TOOLS!!";
qWarning() << "\r\nEventTools::isValid: " << "\r\n"
<< "s_isValid" << s_isValid << "\r\n"
;
#endif
return s_isValid;
}
qint64 EventTools::getAdjustedMin()
{
if (!isValid())
return 0;
return s_minAdjusted;
}
qint64 EventTools::getAdjustedMax()
{
if (!isValid())
return 1;
return s_maxAdjusted;
}
qint64 EventTools::getTimelineMin()
{
if (!isValid())
return 0;
return s_minTimeline;
}
qint64 EventTools::getScrollbarPosition()
{
return s_sbPos;
}
qint64 EventTools::getTimelineMax()
{
if (!isValid())
return 1;
return s_maxTimeline;
}
int EventTools::getEventPosition(qint64 eventTime)
{
qint64 min = s_minAdjusted;
qint64 diff = s_diff;
if (diff == 0)
{
#ifdef VERBOSE
qWarning() << "\n\ngetEventPosition: diff == 0\n";
#endif
return 0;
}
double pDiff = s_paintDiff;
double pMin = s_paintMin;
double x1 = eventTime;
x1 -= min;
x1 /= diff;
double x2 = x1;
x2 *= pDiff;
x2 += pMin;
#ifdef VERBOSE
qWarning() << "\r\n\r\nEventTools::getEventPosition: " << "\r\n"
<< "min" << min << "\r\n"
<< "diff" << diff << "\r\n"
<< "pDiff" << pDiff << "\r\n"
<< "pMin" << pMin << "\r\n"
<< (long)x1 << "[x1]" << "= (" << eventTime << "[eventTime]" << "-" << min << "[min]" << ") /" << diff << "[diff]" << "\r\n"
<< (long)x2 << "[x2]" << "= (" << (long)x1 << "[x1]" << "*" << pDiff << "[pDiff]" << ") +" << pMin << "[pMin]" << "\r\n"
;
dbg_print(min);
#endif
return qRound(x2);
}
qint64 EventTools::getEventTime(double eventPosition)
{
if (!isValid())
{
return 0;
}
if (eventPosition > 999999)
{
WARNING_LOG(logger) << "getEventTime: pos > 999999 => returning 0" ;
return 0;
}
double min = s_minAdjusted;
double diff = s_diff;
double pDiff = s_paintDiff;
if (pDiff < 1)
{
WARNING_LOG(logger) << "getEventTime: pDiff < 1" ;
return 0;
}
double pMin = s_paintMin;
double x1 = eventPosition;
x1 -= pMin;
x1 /= pDiff;
double x2 = x1;
x2 *= diff;
x2 += min;
return qRound64(x2);
}
void EventTools::drawMarkLines(QPainter *painter, const EventList &eventList, int viewHeight)
{
if (!isValid())
return;
for (int k = 0; k < eventList.count(); k++)
{
Event *e = eventList.at(k);
int pos = getEventPosition(e->startTime());
if (pos < (s_paintMin) || pos > (s_paintMin + s_paintDiff))
continue;
painter->drawLine(pos, 0, pos, viewHeight);
}
}
void EventTools::recalcBlockSizeTime()
{
s_blockSizeTime = _getBlockSizeTime();
}
qint64 EventTools::_getBlockSizeTime()
{
int startPos = getEventPosition(s_minAdjusted);
int endPos = getEventPosition(s_maxAdjusted);
int posDiff = endPos - startPos;
if (posDiff < 1)
{
return 0;
}
qint64 diff = s_maxAdjusted - s_minAdjusted;
double pixelWidthInSeconds = diff;
pixelWidthInSeconds /= posDiff;
int eventGraphicsWidth = eventWidth();
qint64 result = eventGraphicsWidth; result *= pixelWidthInSeconds;
#ifdef VERBOSE
qWarning() << "\r\n\r\nEventTools::recalcBlockSizeTime: " << "\r\n"
<< "minAdj" << s_minAdjusted << "\r\n"
<< "maxAdj" << s_maxAdjusted << "\r\n"
<< "endPos" << endPos << "\r\n"
<< "diff" << diff << "\r\n"
<< "pixelWidthInSeconds" << pixelWidthInSeconds << "\r\n"
<< "eventGraphicsWidth" << eventGraphicsWidth << "\r\n"
<< "result" << result << "\r\n"
<< "(duration > result) ?" << (duration > result)
;
#endif
return result;
}
qint64 EventTools::getBlockSizeTime(qint64 duration)
{
if (duration < s_blockSizeTime)
return s_blockSizeTime;
else
return duration;
}
void EventTools::drawEvents(QPainter *painter, const EventGraphicList &eventGraphicList, const int verticalPosition )
{
painter->save();
painter->setClipping(true);
painter->setClipRect(QRect(s_paintMin, verticalPosition, s_paintDiff, s_sectionHeight));
for (int i = 0; i < eventGraphicList.count(); i++)
{
EventGraphic *eg = eventGraphicList.at(i);
if (!eg)
{
continue;
}
qint64 eventStart = eg->lowestTime();
if (eventStart == 0)
continue;
#ifdef VERBOSE
qWarning() << "\r\n\r\nEventTools::drawEvents" << "\r\n"
<< "eventStart" << eventStart << "\r\n";
#endif
qint64 eventDuration = eg->getDuration();
int newEventPosition = getEventPosition(eventStart);
int newEventEndPosition = 0;
int finalEventEndPos = 0;
int eventGraphicsWidth = eventWidth();
if (eventDuration > 1)
{
qint64 eventPosition = eventStart;
eventPosition += eventDuration;
newEventEndPosition = getEventPosition(eventPosition);
finalEventEndPos = GetEndPos(newEventEndPosition, eventGraphicsWidth);
}
else
{
newEventEndPosition = newEventPosition;
}
if (newEventPosition + (newEventEndPosition - newEventPosition) < ((-eventGraphicsWidth) + s_paintMin) ||
newEventPosition > (s_paintMin + s_paintDiff))
{
#ifdef VERBOSE
qWarning() << "\n\ndrawEvents: boundary check result was negative\n" <<
" newEventPosition=" << newEventPosition << "\n" <<
" newEventEndPosition=" << newEventPosition << "\n" <<
" eventGraphicsWidth=" << eventGraphicsWidth << "\n" <<
" s_paintMin=" << s_paintMin << "\n" <<
" s_paintDiff=" << s_paintDiff << "\n";
#endif
continue;
}
int finalEventPos = newEventPosition;
QRect eventGraphicRect(finalEventPos, verticalPosition + 2, eventGraphicsWidth, s_sectionHeight - 6);
eg->drawEventGraphic(painter, eventGraphicRect);
#ifdef VERBOSE
qWarning() << "drawEvents > actually draw an event at "
"x=" << eventGraphicRect.x() << " "
"y=" << eventGraphicRect.y() << " "
"eventStart=" << eventStart ;
#endif
if (eventDuration > 1 &&
(finalEventEndPos - 1) > finalEventPos)
{
QRect eventGraphicEndRect(finalEventEndPos, verticalPosition + 2, eventGraphicsWidth, s_sectionHeight - 6);
eg->drawEventGraphic(painter, eventGraphicEndRect);
QRect eventWholeRect(newEventPosition + (eventGraphicsWidth / 2)
, verticalPosition + 2
, (newEventEndPosition - newEventPosition) - (eventGraphicsWidth)
, s_sectionHeight - 6);
eg->drawDurationBackground(painter, eventWholeRect);
}
}
painter->restore();
}
}
+152
View File
@@ -0,0 +1,152 @@
#pragma once
#include "EventList.h"
#include <LtsTimelineClassic/ltstimelineclassic_export.h>
#include <QRect>
#include <time.h>
class QPainter;
namespace LtsTimelineClassic
{
class LTSTIMELINECLASSIC_EXPORT EventTools
{
static const int s_EventTopPadding = 2;
static const int s_EventHeightPadding = -6;
static const int s_ButtonTopPadding = s_EventTopPadding + 2;
static const int s_ButtonHeightPadding = s_EventHeightPadding + 7;
public:
static int s_test;
static qint64 fromMsecsToSeconds(qint64 msecs)
{
return (msecs / 1000);
}
static qint64 fromSecondsToMsecs(qint64 minutes)
{
return (minutes * 1000);
}
static qint64 getBlockSizeTime(qint64 duration = 0);
static void setValues(const qint64 min, const qint64 max, const qint64 sbPos, const qint64 zoomFactor);
static void setSection(const int x, const int length);
static bool isValid();
static bool isRelative();
static int getEventPosition(qint64 eventTime);
static qint64 getAdjustedMin();
static qint64 getAdjustedMax();
static qint64 getTimelineMin();
static qint64 getTimelineMax();
static qint64 getScrollbarPosition();
static void recalcBlockSizeTime();
static qint64 getEventTime(double eventPosition);
static void drawEvents(QPainter *painter, const EventGraphicList &eventGraphicList, const int verticalPosition);
static void drawMarkLines(QPainter *painter, const EventList &eventList, int viewHeight);
static inline int eventWidth()
{
return s_sectionHeight / 2;
}
static inline int GetEndPos(int position, int graphicsWidth)
{
return position - graphicsWidth - 1;
}
static inline float zoomFactor() { return s_zoomFactor; }
static inline void setSectionHeight(int sectionHeight) { s_sectionHeight = sectionHeight; }
static bool s_inUse;
private:
static qint64 _getBlockSizeTime();
static qint64 s_minAdjusted;
static qint64 s_maxAdjusted;
static qint64 s_minTimeline;
static qint64 s_maxTimeline;
static qint64 s_sbPos;
static qint64 s_zoomFactor;
static int s_paintMin;
static int s_paintDiff;
static bool s_isValid;
static int s_sectionHeight;
static qint64 s_blockSizeTime;
public:
static qint64 s_diff;
};
}
+388
View File
@@ -0,0 +1,388 @@
#include <QDebug>
#include "Item.h"
#include "EventTools.h"
#include "EventGraphic.h"
#ifdef LTS_DEBUG
#endif
namespace LtsTimelineClassic
{
Item::Item(const QString &name, const QString &identifier)
: m_name(name)
, m_identifier(identifier)
, m_children(nullptr)
, m_parent(nullptr)
, m_pevcon(nullptr)
, m_eventListChanged(true)
{
}
Item::~Item()
{
delete m_pevcon;
if (m_children)
{
qDeleteAll(*m_children);
delete m_children;
}
qDeleteAll(m_eventList);
}
PassiveEventContainer *Item::getPevcon()
{
if (!m_pevcon)
m_pevcon = new PassiveEventContainer(m_name == QStringLiteral("Markers"));
if (m_eventListChanged)
{
m_eventListChanged = false;
m_pevcon->setEventList(getEventGraphics());
}
return m_pevcon;
}
const QString Item::path() const
{
if (m_parent == nullptr)
return m_name;
return QStringLiteral("%1/%2").arg(m_parent->path(), m_name);
}
const QString &Item::getName() const
{
return m_name;
}
Item *Item::getParent() const
{
return m_parent;
}
ItemList Item::getFullItemList(bool recursive) const
{
ItemList il;
if (m_children == nullptr)
return il;
il += *m_children;
if (!recursive)
return il;
auto end = m_children->constEnd();
for (auto i = m_children->constBegin(); i != end; ++i)
{
il += (*i)->getFullItemList(recursive);
}
return il;
}
const EventGraphicList Item::getCurrentEGLFromPevcon() const
{
if (m_pevcon == nullptr)
return EventGraphicList();
return m_pevcon->getEventGraphicList();
}
const EventGraphicList Item::getEventGraphics() const
{
EventGraphicList egl;
EventList el = getFullEventList(true, false);
std::sort(el.begin(), el.end(), [](const Event *a, const Event *b)
{
return a->startTime() < b->startTime();
});
for (auto i1 = el.begin(); i1 != el.end(); ++i1)
{
Event *e1 = (*i1);
if (e1->isDeleted())
continue;
qint64 egStart = e1->startTime();
qint64 egEnd = egStart + EventTools::getBlockSizeTime(e1->duration());
qint64 blockSizeTime = EventTools::getBlockSizeTime();
bool egChanged = false;
EventGraphic *eg = new EventGraphic(e1);
egl += eg;
auto i2 = i1 + 1;
for (; i2 != el.end(); ++i2)
{
if (egChanged)
{
egEnd = egStart + eg->getDuration();
if (egEnd - egStart < blockSizeTime)
egEnd = egStart + blockSizeTime;
egChanged = false;
}
Event *e2 = (*i2);
if (e2->isDeleted())
continue;
qint64 start2 = e2->startTime();
if (start2 >= egStart && egEnd >= start2)
{
eg->addEvent(e2);
egChanged = true;
}
else
{
--i2;
break;
}
}
if (i2 == el.end())
break;
i1 = i2;
}
return egl;
}
EventList Item::getFullEventList(bool recursive, bool getHiddenEvents) const
{
EventList el;
if (getHiddenEvents)
{
el = m_eventList;
}
else
{
el.reserve(m_eventList.count());
for (Event *e : m_eventList)
{
if (e == nullptr || !e->isVisible())
continue;
el.append(e);
}
}
if (!m_children || !recursive)
return el;
for (const Item *item : qAsConst(*m_children))
el += item->getFullEventList(recursive, getHiddenEvents);
return el;
}
void Item::setParent(Item *parent)
{
m_parent = parent;
}
void Item::addEvent(Event *event)
{
m_eventList.append(event);
setEventListChanged();
}
void Item::setEventListChanged()
{
m_eventListChanged = true;
if (m_parent != nullptr)
{
m_parent->setEventListChanged();
}
}
bool Item::removeEvent(int eventId)
{
for (auto i = m_eventList.begin(); i != m_eventList.end(); ++i)
{
Event *event = *i;
if (event->uniqueId() == eventId)
{
m_eventList.erase(i);
setEventListChanged();
return true;
}
}
return false;
}
void Item::addItem(Item *item)
{
if (!m_children)
m_children = new ItemList();
item->setParent(this);
m_children->append(item);
}
bool Item::hasVisibleEvents() const
{
if (!m_eventList.isEmpty() &&
std::find_if(m_eventList.constBegin(), m_eventList.constEnd(), [](Event *e) { return e->isVisible(); }) != m_eventList.constEnd())
return true;
if (m_children == nullptr)
return false;
for (auto i = m_children->constBegin(); i != m_children->constEnd(); ++i)
{
Item *item = *i;
if (item->hasVisibleEvents())
return true;
}
return false;
}
Item *Item::child(int row) const
{
if (m_children == nullptr)
return nullptr;
int idx = 0;
for (auto i = m_children->constBegin(); i != m_children->constEnd(); ++i)
{
Item *item = *i;
if (item->hasVisibleEvents())
{
if (row == idx)
return item;
else
idx++;
}
}
return nullptr;
}
int Item::childCount() const
{
if (m_children)
return m_children->count();
return 0;
}
int Item::visibleChildCount() const
{
if (m_children == nullptr)
return 0;
int result = 0;
for (auto i = m_children->constBegin(); i != m_children->constEnd(); ++i)
{
Item *item = *i;
if (item->hasVisibleEvents())
result++;
}
return result;
}
ItemList *Item::getChildren()
{
return m_children;
}
int Item::indexOfParent() const
{
if (m_parent == nullptr || m_parent->getChildren() == nullptr)
return -1;
int idx = 0;
ItemList *parentItemList = m_parent->getChildren();
for (auto i = parentItemList->constBegin(); i != parentItemList->constEnd(); ++i)
{
Item *item = *i;
if (item == this)
return idx;
idx++;
}
Q_ASSERT(false);
return -1;
}
}
+128
View File
@@ -0,0 +1,128 @@
#pragma once
#include <LtsTimelineClassic/ltstimelineclassic_export.h>
#include "EventList.h"
#include "PassiveEventContainer.h"
namespace LtsTimelineClassic
{
class Item;
using ItemList = QList<Item *>;
class LTSTIMELINECLASSIC_EXPORT Item
{
public:
Item(const Item &) = delete;
Item &operator=(const Item &) = delete;
const EventGraphicList getEventGraphics() const;
explicit Item(const QString &name, const QString &identifier = QString());
~Item();
void addItem(Item *item);
bool removeEvent(int eventId);
void setEventListChanged();
const QString path() const;
PassiveEventContainer *getPevcon();
const EventGraphicList getCurrentEGLFromPevcon() const;
void setParent(Item *parent);
const QString &getName() const;
void setName(const QString &name) { m_name = name; }
const QString &getIdentifier() const { return m_identifier; }
ItemList *getChildren();
Item *getParent() const;
void addEvent(Event *event);
EventList getFullEventList(bool recursive = true, bool getHiddenEvents = false) const;
ItemList getFullItemList(bool recursive = true) const;
Item *child(int row) const;
int indexOfParent() const;
int childCount() const;
int visibleChildCount() const;
bool hasVisibleEvents() const;
private:
QString m_name;
QString m_identifier;
ItemList *m_children;
Item *m_parent;
PassiveEventContainer *m_pevcon;
EventList m_eventList;
bool m_eventListChanged;
};
}
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <QMap>
namespace LtsTimelineClassic
{
using LineMap = QMap<int, qint64>;
}
+133
View File
@@ -0,0 +1,133 @@
#include "PassiveEventContainer.h"
#include "EventGraphic.h"
#include "EventTools.h"
#include <QGuiApplication>
#include <QPainter>
#include <QPen>
#include <QStyleOptionViewItem>
#include <QBrush>
#include <math.h>
#include <time.h>
#include <QDebug>
namespace LtsTimelineClassic
{
PassiveEventContainer::PassiveEventContainer(bool ignoreKnownRanges, QObject *parent)
: QObject(parent)
, m_ignoreKnownRanges(ignoreKnownRanges)
{
}
PassiveEventContainer::~PassiveEventContainer()
{
qDeleteAll(m_eventGraphicList);
}
EventGraphicList PassiveEventContainer::getEventGraphicList() const
{
return m_eventGraphicList;
}
void PassiveEventContainer::setEventList(const EventGraphicList &eventGraphicList)
{
qDeleteAll(m_eventGraphicList);
m_eventGraphicList = eventGraphicList;
}
void PassiveEventContainer::paint(QPainter *painter, const QStyleOptionViewItem &option, const LineMap &lineMap,
const QVector<Range> &knownRanges) const
{
EventTools::s_test++;
bool alternate = option.features.testFlag(QStyleOptionViewItem::ViewItemFeature::Alternate);
const QColor bg = QColor(alternate ? QRgb(0xF6D8CE) : QRgb(0xFBF2EF));
QColor cachedBg(Qt::white);
if (alternate)
cachedBg = cachedBg.darker(110);
painter->fillRect(option.rect, QBrush(bg));
int posX1 = option.rect.x();
int posX2 = option.rect.right();
int posY1 = option.rect.y();
int posY2 = option.rect.bottom();
int h = posY2 - posY1 + 1;
painter->save();
painter->setClipping(true);
painter->setClipRect(option.rect.adjusted(0, 0, 1, 1));
int eventWidth = EventTools::eventWidth();
if (m_ignoreKnownRanges)
{
painter->fillRect(QRect(posX1, posY1, posX2 - posX1, h), cachedBg);
}
else
{
for (const auto &range : knownRanges)
{
int rangeStart = EventTools::getEventPosition(range.start);
int rangeEnd = EventTools::getEventPosition(range.end);
if (rangeEnd >= posX1 && rangeStart <= posX2)
painter->fillRect(QRect(rangeStart, posY1, rangeEnd - rangeStart + eventWidth + 1, h), cachedBg);
}
}
painter->restore();
for (auto i = lineMap.constBegin(); i != lineMap.constEnd(); ++i)
{
int posX = i.key();
painter->setPen(QPen(QBrush(QGuiApplication::palette().shadow()), 1.0));
if (posX > option.rect.x() &&
posX < (option.rect.x() + option.rect.width()))
painter->drawLine(posX, posY1, posX, posY2);
}
EventTools::drawEvents(painter, m_eventGraphicList, option.rect.y());
}
}
+53
View File
@@ -0,0 +1,53 @@
#pragma once
#include "EventList.h"
#include "LineMap.h"
#include "Range.h"
#include <QObject>
class QPainter;
class QStyleOptionViewItem;
namespace LtsTimelineClassic
{
class PassiveEventContainer: public QObject
{
Q_OBJECT
public:
explicit PassiveEventContainer(bool ignoreKnownRanges, QObject *parent = nullptr);
~PassiveEventContainer();
void paint(QPainter *painter, const QStyleOptionViewItem &option, const LineMap &lineMap, const QVector<Range> &knownRanges) const;
EventGraphicList getEventGraphicList() const;
void setEventList(const EventGraphicList &eventGraphicList);
private:
EventGraphicList m_eventGraphicList;
bool m_ignoreKnownRanges;
};
}
Q_DECLARE_METATYPE(LtsTimelineClassic::PassiveEventContainer *)
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include <qglobal.h>
namespace LtsTimelineClassic
{
struct Range
{
qint64 start = 0;
qint64 end = 0;
Range() = default;
Range(qint64 s, qint64 e) : start(s), end(e) {}
};
}
+40
View File
@@ -0,0 +1,40 @@
#include "TestTimelineModel.h"
#include "EventGraphic.h"
#include <QToolTip>
#include <QDebug>
namespace LtsTimelineClassic
{
TestTimelineModel::TestTimelineModel()
: AbstractTimelineModel()
{
}
void TestTimelineModel::addTestEvent(Event *event)
{
AbstractTimelineModel::addEvent(event);
}
void TestTimelineModel::slotEventAction(EventGraphic *eg, int actionType)
{
(void)actionType;
QString content = tr("Event count: %1").arg(QString::number(eg->eventList().count()));
for (int i = 0; i < eg->eventList().count(); i++)
{
content += QLatin1String("\r\nTime: ");
content += QString::number(eg->eventList().at(i)->startTime());
}
}
}
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include "AbstractTimelineModel.h"
namespace LtsTimelineClassic
{
class LTSTIMELINECLASSIC_EXPORT TestTimelineModel : public AbstractTimelineModel
{
Q_OBJECT
public:
TestTimelineModel();
void addTestEvent(Event *event);
private slots:
void slotEventAction(EventGraphic *, int);
};
}
+149
View File
@@ -0,0 +1,149 @@
#include "TimelineWidget.h"
#include "TimelineHeaderView.h"
#include <QPainter>
#include <QPainterPath>
#include <QPen>
#include <QPoint>
#include <QRect>
#include <QGuiApplication>
namespace LtsTimelineClassic
{
TimelineHeaderView::TimelineHeaderView(QWidget *parent)
: QHeaderView(Qt::Horizontal, parent)
, m_posMarkTime(0)
, m_paintingRange(rect())
, m_liveTime(0)
{
setSectionsClickable(true);
setStretchLastSection(true);
connect(this, &TimelineHeaderView::sectionResized,
this, &TimelineHeaderView::slotSectionResized);
}
#define GET_LOGGER NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("Timeline.HeaderView")
void TimelineHeaderView::setPosMarkTime(qint64 time)
{
m_posMarkTime = time;
refreshData();
}
void TimelineHeaderView::setLiveTime(qint64 time)
{
m_liveTime = time;
refreshData();
}
void TimelineHeaderView::setPosMarkPos()
{
if (m_posMarkTime > 0)
{
int posMarkPos = EventTools::getEventPosition(m_posMarkTime);
emit signalSetPosMarkPos(posMarkPos);
refreshData();
}
}
void TimelineHeaderView::refreshData()
{
if (EventTools::getTimelineMin() > 0 && EventTools::getTimelineMax() > 1)
{
updateSection(1);
updateSection(0);
}
}
void TimelineHeaderView::slotSectionResized(int logicalIndex, int oldSize, int newSize)
{
(void)oldSize;
if (logicalIndex == 1)
m_paintingRange = QRect(0, 0, newSize, height());
refreshData();
}
void TimelineHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
painter->save();
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore();
if (logicalIndex == 1)
{
int h = (rect.height() / 3);
int y = rect.height() - h;
int w = h;
painter->save();
painter->setClipping(true);
if (m_posMarkTime != 0)
{
double posMark = EventTools::getEventPosition(m_posMarkTime);
int x = + posMark;
if (x >= sectionPosition(1))
{
painter->setPen(QPen(QGuiApplication::palette().color(QPalette::Inactive, QPalette::Highlight)));
painter->setBrush(QGuiApplication::palette().highlight());
QPolygon pol;
pol.append(QPoint(x + (-w / 2), y + 0));
pol.append(QPoint(x + 0, y + h));
pol.append(QPoint(x + (w / 2), y + 0));
pol.append(QPoint(x + (-w / 2), y + 0));
QPainterPath path;
path.moveTo(x, y);
path.addPolygon(pol);
painter->drawPath(path);
}
}
if (m_liveTime != 0)
{
int posLive = EventTools::getEventPosition(m_liveTime);
int x = posLive;
if (x >= sectionPosition(1))
{
painter->setPen(QPen(QColor("green")));
painter->setBrush(QBrush(QColor("green")));
QPolygon pol;
pol.append(QPoint(x + (-w / 2), y + 0));
pol.append(QPoint(x + 0, y + h));
pol.append(QPoint(x + (w / 2), y + 0));
pol.append(QPoint(x + (-w / 2), y + 0));
QPainterPath path;
path.moveTo(x, y);
path.addPolygon(pol);
painter->drawPath(path);
}
}
painter->restore();
}
}
}
+63
View File
@@ -0,0 +1,63 @@
#pragma once
#include "EventTools.h"
#include <QHeaderView>
class QPainter;
namespace LtsTimelineClassic
{
class TimelineHeaderView : public QHeaderView
{
Q_OBJECT
public:
explicit TimelineHeaderView(QWidget *parent = nullptr);
void refreshData();
void setLiveTime(qint64 time);
private:
qint64 m_posMarkTime;
QRect m_paintingRange;
qint64 m_liveTime;
protected:
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const;
signals:
void signalSetPosMarkPos(int pos);
public slots:
void slotSectionResized(int logicalIndex, int oldSize, int newSize);
void setPosMarkTime(qint64 time);
private:
void setPosMarkPos();
};
}
+519
View File
@@ -0,0 +1,519 @@
#include "TimelineWidget.h"
#include "TimelineIndicator.h"
#include "EventTools.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <ngltools/ngltools_dtg.h>
#include <QGuiApplication>
#include <QHeaderView>
#include <QFont>
#include <QFontMetrics>
#include <QPainter>
#include <QPalette>
#include <QPushButton>
#include <QApplication>
#include <QHBoxLayout>
#include <QDateTime>
#include <QPoint>
#include <QLabel>
#include <QComboBox>
#include <QDebug>
#ifdef LTS_DEBUG
#endif
#ifdef VERBOSE
#define dbg_print(x) qWarning() << #x << x
#else
#define dbg_print(x) (void)x;
#endif
namespace LtsTimelineClassic
{
TimelineIndicator::TimelineIndicator(QWidget *parent)
: QWidget(parent)
, m_zoomFactorPoints(0)
, m_pbZoom(new QPushButton(this))
, m_pbUnzoom(new QPushButton(this))
, m_cbZoomLevel(new QComboBox(this))
, m_currentTextHeight(0)
, m_currentTextWidth(0)
, m_sectionPos(0)
, m_sectionSize(0)
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("Timeline.Indicator"))
{
m_timeArray.reserve(11 + 11 + 7 + 10);
m_timeArray <<
1 << 2 << 3 << 4 << 5 << 6 << 12 << 15 << 20 << 30 << 60 <<
1 * 60 << 2 * 60 << 3 * 60 << 4 * 60 << 5 * 60 << 6 * 60 << 12 * 60 << 15 * 60 << 20 * 60 << 30 * 60 << 60 * 60 <<
1 * 60 * 60 << 2 * 60 * 60 << 4 * 60 * 60 << 6 * 60 * 60 << 8 * 60 * 60 << 12 * 60 * 60 << 24 * 60 * 60 <<
1 * 60 * 60 << 2 * 60 * 60 << 4 * 60 * 60 << 6 * 60 * 60 << 8 * 60 * 60 << 10 * 60 * 60 << 14 * 60 * 60 << 18 * 60 * 60 << 22 * 60 * 60 << 26 * 60 * 60 << 30 * 60 * 60;
QHBoxLayout *centralLayout = new QHBoxLayout();
centralLayout->setSpacing(0);
setLayout(centralLayout);
m_pbZoom->setText(QLatin1String("+"));
m_pbZoom->setFixedSize(s_pbSize, s_pbSize);
m_pbUnzoom->setText(QLatin1String("-"));
m_pbUnzoom->setFixedSize(s_pbSize, s_pbSize);
m_cbZoomLevel->addItem(tr("10 min"), 600);
m_cbZoomLevel->addItem(tr("30 min"), 1800);
m_cbZoomLevel->addItem(tr("1 h"), 3600);
m_cbZoomLevel->addItem(tr("2 h"), 7200);
m_cbZoomLevel->addItem(tr("4 h"), 14400);
m_cbZoomLevel->addItem(tr("8 h"), 28800);
m_cbZoomLevel->setCurrentIndex(0);
m_cbZoomLevel->setFixedHeight(s_pbSize);
m_zoomFactorPoints = m_cbZoomLevel->currentData().toLongLong();
connect(m_cbZoomLevel, &QComboBox::currentTextChanged,
this, &TimelineIndicator::afterZoom);
connect(m_pbZoom, &QPushButton::clicked,
this, &TimelineIndicator::slotZoom);
connect(m_pbUnzoom, &QPushButton::clicked,
this, &TimelineIndicator::slotUnzoom);
connect(this, &TimelineIndicator::signalAddLine,
this, &TimelineIndicator::slotAddLine);
connect(this, &TimelineIndicator::signalResetLineList,
this, &TimelineIndicator::slotResetLineList);
centralLayout->addWidget(m_pbZoom, 0, Qt::AlignLeft | Qt::AlignTop);
centralLayout->addWidget(m_pbUnzoom, 0, Qt::AlignLeft | Qt::AlignTop);
centralLayout->addWidget(m_cbZoomLevel, 1, Qt::AlignLeft | Qt::AlignTop);
QFontMetrics fm(QApplication::font());
m_currentTextHeight = fm.height();
#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
m_currentTextWidth = fm.width(DTG::toString(QDateTime::currentDateTimeUtc(), DTG::Short));
#else
m_currentTextWidth = fm.horizontalAdvance(DTG::toString(QDateTime::currentDateTimeUtc(), DTG::Short));
#endif
dbg_print(m_currentTextWidth);
}
TimelineIndicator::~TimelineIndicator()
{
}
void TimelineIndicator::afterZoom()
{
m_zoomFactorPoints = m_cbZoomLevel->currentData().toLongLong() * 1000;
emit signalSetZoomFactor(m_zoomFactorPoints);
update();
}
void TimelineIndicator::slotZoom()
{
int pos = m_cbZoomLevel->currentIndex();
if (pos == 0)
return;
m_cbZoomLevel->setCurrentIndex(pos - 1);
emit signalZoomChanged();
}
void TimelineIndicator::slotUnzoom()
{
int count = m_cbZoomLevel->count();
int pos = m_cbZoomLevel->currentIndex();
if (pos >= count - 1)
return;
m_cbZoomLevel->setCurrentIndex(pos + 1);
emit signalZoomChanged();
}
enum highestUnit
{
HU_INVALID,
HU_DAYS,
HU_HOURS,
HU_MINUTES,
HU_SECONDS
};
void TimelineIndicator::refreshData()
{
#ifdef VERBOSE
qWarning() << "<refreshData>";
#endif
emit signalResetLineList();
#ifdef VERBOSE
qWarning() << "section x" << m_sectionPos << "length" << m_sectionSize;
#endif
double abstand = m_sectionPos + m_currentTextWidth + s_TimeTextDistanceTolerancePixels;
dbg_print(abstand);
qint64 eventTimeOfAbstand = EventTools::getEventTime(abstand);
dbg_print(eventTimeOfAbstand);
qint64 adjustedMin = EventTools::getAdjustedMin();
dbg_print(adjustedMin);
qint64 textWidthTime = (eventTimeOfAbstand - adjustedMin);
if (textWidthTime < 0)
{
qWarning() << "TimelineIndicator: paintEvent: textWidthTime invalid! (" << textWidthTime << ")";
return;
}
qint64 eventTime = EventTools::getEventTime(abstand);
dbg_print(eventTime);
QDateTime textWidthDt = QDateTime::fromMSecsSinceEpoch(textWidthTime);
int days = textWidthDt.date().day() - 1;
int hours = textWidthDt.time().hour() - 1;
int minutes = textWidthDt.time().minute();
int seconds = textWidthDt.time().second() - 1;
highestUnit unit = HU_INVALID;
if (days == 0)
if (hours == 0)
if (minutes == 0)
if (seconds == 0)
{
#ifdef VERBOSE
qWarning() << "refreshData: no lower time unit available" ;
#endif
return;
}
else
{
unit = HU_SECONDS;
}
else
{
unit = HU_MINUTES;
}
else
{
unit = HU_HOURS;
}
else
{
unit = HU_DAYS;
}
if (unit == HU_INVALID)
{
#ifdef VERBOSE
qWarning() << "unit == HU_INVALID";
#endif
return;
}
int higherValue = 0;
for (int i = 0; i < m_timeArray.size(); i++)
{
qint64 time = (m_timeArray[i] * 1000);
if (time >= textWidthTime)
{
higherValue = time;
break;
}
else
{
continue;
}
#ifdef VERBOSE
qWarning() << "refreshData: no fitting highest unit found !" ;
#endif
return;
}
if (higherValue < 1)
{
return;
}
QDateTime minDt = QDateTime::fromMSecsSinceEpoch(adjustedMin);
dbg_print(minDt);
dbg_print(unit);
switch (unit)
{
case HU_SECONDS:
{
minDt = minDt.addSecs(-(minDt.time().second()));
#ifdef VERBOSE
qCritical() << "HU_SECONDS";
#endif
break;
}
case HU_MINUTES:
{
minDt = minDt.addSecs(-(minDt.time().second()));
minDt = minDt.addSecs(-(minDt.time().minute() * 60));
#ifdef VERBOSE
qCritical() << "HU_MINUTES";
#endif
break;
}
case HU_HOURS:
{
minDt = minDt.addSecs(-(minDt.time().second()));
minDt = minDt.addSecs(-(minDt.time().minute() * 60));
minDt = minDt.addSecs(-(minDt.time().hour() * 60 * 60));
#ifdef VERBOSE
qCritical() << "HU_HOURS";
#endif
break;
}
case HU_DAYS:
{
minDt = minDt.addSecs(-(minDt.time().second()));
minDt = minDt.addSecs(-(minDt.time().minute() * 60));
minDt = minDt.addSecs(-(minDt.time().hour() * 60 * 60));
minDt = minDt.addDays(-(minDt.date().day()));
#ifdef VERBOSE
qCritical() << "HU_DAYS";
#endif
break;
}
default:
{
#ifdef VERBOSE
qWarning() << "unit / scaling is off da charz !";
#endif
return;
}
}
dbg_print(minDt);
minDt = minDt.addMSecs(-higherValue);
dbg_print(minDt);
qint64 maxTimelineView = EventTools::getAdjustedMax() + (higherValue );
qint64 additional = textWidthTime / 2;
maxTimelineView += additional;
qint64 minTimeline = minDt.toMSecsSinceEpoch();
dbg_print(minTimeline);
dbg_print(maxTimelineView);
dbg_print(higherValue);
qint64 steps = (maxTimelineView - minTimeline) / higherValue;
if (steps < 0)
steps = steps * (-1);
if (steps > 60000 || steps < 1)
{
ERROR_LOG(m_logger) << "More than 60000 ("<<steps<<") or less than 1 lines to draw. Loop will exit after 60000 lines.";
}
if (steps < 1)
steps = 2;
uint16_t currentStep = 0;
dbg_print(steps);
for (qint64 indicatorTime = minTimeline;
indicatorTime < maxTimelineView + 1 ;
indicatorTime += higherValue)
{
if (currentStep > 60000)
break;
currentStep++;
int pos = EventTools::getEventPosition(indicatorTime);
dbg_print(indicatorTime);
if (pos + (m_currentTextWidth / 4) + 1 < m_sectionPos)
{
#ifdef VERBOSE
qCritical() << "Indicator: pos" << pos << "invisible #1";
#endif
continue;
}
else
if (pos - (m_currentTextWidth ) > (m_sectionPos + m_sectionSize))
{
#ifdef VERBOSE
qCritical() << "Indicator: pos" << pos << "invisible #2";
#endif
continue;
}
else
{
#ifdef VERBOSE
qCritical() << "Indicator: OKAY!! pos" << pos << "visible";
#endif
}
emit signalAddLine(pos, indicatorTime);
}
dbg_print(currentStep);
QFontMetrics fm(QApplication::font());
m_currentTextHeight = fm.height();
update();
}
void TimelineIndicator::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.save();
painter.setClipping(true);
painter.setClipRect(QRect(x() - 8 + m_sectionPos, 0, m_sectionSize, height()));
#ifdef VERBOSE
int textY = (height() - m_currentTextHeight - 5);
#endif
int h = height();
for (auto i = m_lineMap.constBegin(); i != m_lineMap.constEnd(); ++i)
{
int pos = i.key();
painter.setPen(QPen(QColor("black"), 1.0));
painter.drawLine(pos, m_currentTextHeight, pos, h);
int centeredPos = pos - (m_currentTextWidth / 2);
qint64 time = (*i);
painter.drawText(centeredPos, (m_currentTextHeight / 2) + 4,
DTG::toStringMSec(time, DTG::Short));
#ifdef VERBOSE
WARNING_LOG(m_logger) << "paintEvent: actual drawing position: x=" << centeredPos << " y=" << textY;
#endif
}
painter.restore();
}
void TimelineIndicator::slotSectionResized(int logicalIndex, int oldSize, int newSize)
{
(void)oldSize;
QHeaderView *header = qobject_cast<QHeaderView *>(QObject::sender());
if (!header)
return;
if (logicalIndex == 1)
{
m_sectionPos = header->sectionPosition(1);
m_sectionSize = newSize;
}
update();
}
void TimelineIndicator::slotAddLine(double posX, qint64 time)
{
#ifdef VERBOSE
qCritical() << "slotAddLine: posX" << posX << "time" << time;
#endif
m_lineMap.insert(posX, time);
}
void TimelineIndicator::slotResetLineList()
{
m_lineMap.clear();
}
}
+111
View File
@@ -0,0 +1,111 @@
#pragma once
#include "EventTools.h"
#include "LineMap.h"
#include <QWidget>
#include <QPoint>
#include <QPair>
namespace NGL
{
class INGLLogger;
}
class QPushButton;
class QLabel;
class QComboBox;
namespace LtsTimelineClassic
{
class TimelineIndicator : public QWidget
{
Q_OBJECT
static const int s_TimeTextDistanceTolerancePixels = 10;
static const int s_pbSize = 18;
public:
explicit TimelineIndicator(QWidget *parent);
~TimelineIndicator();
qint64 zoomFactorPoints() const { return m_zoomFactorPoints * 1000; }
void refreshData();
private:
QVector<qint64> m_timeArray;
qint64 m_zoomFactorPoints;
QPushButton *m_pbZoom;
QPushButton *m_pbUnzoom;
QComboBox *m_cbZoomLevel;
int m_currentTextHeight;
int m_currentTextWidth;
LineMap m_lineMap;
int m_sectionPos;
int m_sectionSize;
NGL::INGLLogger &m_logger;
protected:
void paintEvent(QPaintEvent *);
signals:
void signalSetTimelineRange(qint64 min, qint64 max);
void signalSetZoomFactor(qint64 zoomFactor);
void signalResetLineList();
void signalAddLine(int posX, qint64 time);
void signalZoomChanged();
private slots:
void afterZoom();
public slots:
void slotSectionResized(int logicalIndex, int oldSize, int newSize);
void slotZoom();
void slotUnzoom();
void slotResetLineList();
void slotAddLine(double posX, qint64 time);
};
}
+392
View File
@@ -0,0 +1,392 @@
#include "TimelineView.h"
#include "TimelineHeaderView.h"
#include "TimelineWidget.h"
#include "EventDelegate.h"
#include "EventGraphic.h"
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QGuiApplication>
#include <QHeaderView>
#include <QHelpEvent>
#include <QModelIndex>
#include <QRect>
#include <QDebug>
namespace LtsTimelineClassic
{
TimelineView::TimelineView(QWidget *parent)
: QTreeView(parent)
, m_model(nullptr)
, m_drawCache(false)
{
m_posMarkTime = 0;
setAlternatingRowColors(true);
setEditTriggers(QAbstractItemView::NoEditTriggers);
setSelectionBehavior(QAbstractItemView::SelectItems);
setSelectionMode(QAbstractItemView::NoSelection);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
}
void TimelineView::setHeader(QHeaderView *header)
{
if (header)
{
QTreeView::setHeader(header);
header->setMinimumSectionSize(150);
}
else
{
}
}
AbstractTimelineModel *TimelineView::timelineModel()
{
return m_model;
}
void TimelineView::setTimelineModel(AbstractTimelineModel *model)
{
m_model = model;
setMouseTracking(true);
setModel(m_model);
EventDelegate *ed = new EventDelegate(this);
EventTools::setSectionHeight(ed->sizeHint().height());
setItemDelegate(ed);
}
EventGraphic *TimelineView::getEventOnPosition(QPoint position)
{
position = viewport()->mapFromGlobal(position);
QModelIndex index = indexAt(position);
if (index.isValid() && position.x() > header()->sectionSize(0))
{
Item *item = static_cast<Item *>(index.internalPointer());
if (!item)
return nullptr;
qint64 curTime = EventTools::getEventTime(position.x());
EventGraphicList egl = item->getCurrentEGLFromPevcon();
qint64 blockSizeTime = EventTools::getBlockSizeTime();
for (int i = 0; i < egl.count(); i++)
{
EventGraphic *eg = egl.at(i);
if (!eg)
continue;
qint64 eventStartTime = eg->lowestTime();
if (eventStartTime == 0)
continue;
qint64 eventEndTime = eventStartTime;
qint64 eglDuration = eg->getDuration();
if (eglDuration > blockSizeTime)
eventEndTime += eglDuration;
else
eventEndTime += blockSizeTime;
if (curTime >= eventStartTime && curTime <= eventEndTime)
return eg;
}
}
return nullptr;
}
bool TimelineView::event(QEvent *event)
{
switch (event->type())
{
case QEvent::ToolTip:
{
QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
if (!helpEvent)
return true;
EventGraphic *eg = getEventOnPosition(helpEvent->globalPos());
if (!eg)
return true;
emit signalEventAction(eg, EventGraphic::ACTION_TOOLTIP);
return true;
}
default:
{
break;
}
}
return QTreeView::event(event);
}
void TimelineView::wheelEvent(QWheelEvent *event)
{
QTreeView::wheelEvent(event);
if (QGuiApplication::queryKeyboardModifiers() != Qt::ControlModifier)
return;
int scrolls = event->delta() / 120;
if (scrolls > 0)
{
for (int i = 0; i < scrolls; i++)
emit signalZoom();
}
if (scrolls < 0)
{
for (int i = 0; i > scrolls; i--)
emit signalUnzoom();
}
}
void TimelineView::mouseReleaseEvent(QMouseEvent *event)
{
QTreeView::mouseReleaseEvent(event);
QPoint position = event->globalPos();
EventGraphic *eg = getEventOnPosition(position);
if (!eg)
return;
switch (event->button())
{
case Qt::LeftButton:
{
emit signalEventAction(eg, EventGraphic::ACTION_LEFT_CLICKED);
break;
}
case Qt::RightButton:
{
emit signalEventAction(eg, EventGraphic::ACTION_RIGHT_CLICKED);
break;
}
default:
{
break;
}
}
}
void TimelineView::slotAddLine(int posX, qint64 time)
{
m_lineMap.insert(posX, time);
}
void TimelineView::slotResetLineList()
{
m_lineMap.clear();
}
void TimelineView::slotSetPosMarkTime(qint64 posMarkTime)
{
m_posMarkTime = posMarkTime;
TimelineHeaderView *headerView = qobject_cast<TimelineHeaderView *>(header());
if (headerView)
headerView->setPosMarkTime(posMarkTime);
refreshData();
}
void TimelineView::refreshData()
{
update();
viewport()->update();
}
void TimelineView::paintEvent(QPaintEvent *event)
{
if (!m_model)
return;
QWidget *viewp0rt = viewport();
QPainter painter(viewp0rt);
if (!painter.isActive())
{
}
painter.save();
int viewPortHeight = viewp0rt->height();
QHeaderView *head0r = header();
int sectionPos = head0r->sectionPosition(1);
int sectionSize = head0r->sectionSize(1);
int minSection = sectionPos;
int maxSection = minSection + sectionSize;
QRect paintRect(minSection, 0,
maxSection - minSection, height());
painter.setClipping(true);
painter.setClipRect(paintRect);
for (auto i = m_lineMap.constBegin(); i != m_lineMap.constEnd(); ++i)
{
int pos = i.key();
painter.setPen(QPen(QBrush(QGuiApplication::palette().shadow()), 1.0));
if (pos > minSection &&
pos < maxSection)
painter.drawLine(pos, 0, pos, viewPortHeight);
else
{
#ifdef VERBOSE
qCritical() << "out of view => pos" << pos << "min" << minSection << "max" << maxSection;
#endif
}
}
painter.restore();
QTreeView::paintEvent(event);
painter.save();
if (m_drawCache)
{
painter.setPen(QPen(QBrush("gray"), 1));
painter.setBrush(QBrush("gray"));
painter.drawRect(minSection, 0, maxSection, height());
painter.setPen(QPen(QBrush("white"), 1));
painter.setBrush(QBrush("white"));
int h = height();
for (const auto &range : qAsConst(m_knownRanges))
{
int start = EventTools::getEventPosition(range.start);
if (start < minSection)
start = minSection;
int end = EventTools::getEventPosition(range.end);
if (end > maxSection)
end = maxSection;
painter.drawRect(start, 0, end - start, h);
}
}
ItemList il = m_model->getRootItem()->getFullItemList(true);
for (int i = 0; i < il.count(); i++)
{
if (il.at(i)->getName() == tr("Markers"))
EventTools::drawMarkLines(&painter, il.at(i)->getFullEventList(true), height());
}
if (m_posMarkTime > 0)
{
int posMarkPosition = EventTools::getEventPosition(m_posMarkTime);
if (posMarkPosition > sectionPos &&
posMarkPosition < sectionSize + sectionPos)
{
painter.setPen(QPen(QGuiApplication::palette().highlight(), 1.0));
int xpos = posMarkPosition;
painter.drawLine(xpos, 0, xpos, height());
}
}
painter.restore();
}
}
+107
View File
@@ -0,0 +1,107 @@
#pragma once
#include "AbstractTimelineModel.h"
#include "TimelineIndicator.h"
#include "TimelineHeaderView.h"
#include "LineMap.h"
#include "Range.h"
#include <QTreeView>
namespace LtsTimelineClassic
{
class TimelineView : public QTreeView
{
Q_OBJECT
public:
explicit TimelineView(QWidget *parent);
EventGraphic *getEventOnPosition(QPoint position);
void setTimelineModel(AbstractTimelineModel *model);
AbstractTimelineModel *timelineModel();
void refreshData();
void setHeader(QHeaderView *header);
void setKnownRanges(const QVector<Range> &newRanges)
{
m_knownRanges = newRanges;
}
void setDrawCache(bool show)
{
m_drawCache = show;
}
private:
qint64 m_posMarkTime;
AbstractTimelineModel *m_model;
LineMap m_lineMap;
QVector<Range> m_knownRanges;
bool m_drawCache;
protected:
bool event(QEvent *event) override;
void mouseReleaseEvent(QMouseEvent *) override;
void wheelEvent(QWheelEvent *event) override;
virtual void paintEvent(QPaintEvent *event) override;
public slots:
void slotResetLineList();
void slotAddLine(int posX, qint64 time);
void slotSetPosMarkTime(qint64 posMarkTime);
signals:
void signalEventAction(EventGraphic *eg, int);
void signalZoom();
void signalUnzoom();
};
}
+324
View File
@@ -0,0 +1,324 @@
#include "TimelineWidget.h"
#include "EventDelegate.h"
#include "ui_TimelineWidgetUi.h"
#include "AbstractTimelineModel.h"
#include "EventGraphic.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <QSize>
#include <QPoint>
#include <QRect>
#include <QDateTime>
#include <QDebug>
namespace LtsTimelineClassic
{
TimelineWidget::TimelineWidget(QWidget *parent)
: QWidget(parent)
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("Timeline.Widget"))
, m_timelineUi(new Ui::Timeline)
, m_min(0)
, m_max(1)
, m_sbPos(0)
, m_zoomFactor(1)
, m_headerView(new TimelineHeaderView)
, m_model(nullptr)
{
m_timelineUi->setupUi(this);
m_timelineUi->view->setHeader(m_headerView);
m_headerView->setMinimumSectionSize(150);
m_timelineUi->scrollbar->setMouseTracking(true);
connect(m_timelineUi->scrollbar, &QScrollBar::sliderReleased, this, &TimelineWidget::scrollBarFilter2);
connect(m_timelineUi->scrollbar, &QScrollBar::actionTriggered, this, &TimelineWidget::scrollBarFilter1);
connect(m_headerView, &QHeaderView::sectionResized, m_timelineUi->indicator, &TimelineIndicator::slotSectionResized);
connect(m_headerView, &QHeaderView::sectionResized, this, &TimelineWidget::slotSectionResized);
connect(m_timelineUi->view, &TimelineView::signalZoom, m_timelineUi->indicator, &TimelineIndicator::slotZoom);
connect(m_timelineUi->view, &TimelineView::signalUnzoom, m_timelineUi->indicator, &TimelineIndicator::slotUnzoom);
connect(m_timelineUi->view, &TimelineView::signalZoom, this, &TimelineWidget::signalZoomChanged);
connect(m_timelineUi->view, &TimelineView::signalUnzoom, this, &TimelineWidget::signalZoomChanged);
connect(m_timelineUi->indicator, &TimelineIndicator::signalZoomChanged, this, &TimelineWidget::signalZoomChanged);
connect(m_timelineUi->indicator, &TimelineIndicator::signalSetZoomFactor, this, &TimelineWidget::slotSetZoomFactor);
connect(m_timelineUi->view, &TimelineView::signalEventAction,
this, &TimelineWidget::signalEventAction);
connect(m_timelineUi->cbDrawCache, &QCheckBox::toggled,
this, [this](bool toggled)
{
m_timelineUi->view->setDrawCache(toggled);
update();
});
connect(m_timelineUi->cbArm, &QCheckBox::toggled,
this, &TimelineWidget::signalArm);
connect(m_timelineUi->updateTimeline, &QPushButton::clicked,
this, &TimelineWidget::slotUpdateTimeline);
}
TimelineWidget::~TimelineWidget()
{
delete m_timelineUi;
}
void TimelineWidget::setLiveTime(qint64 time)
{
m_headerView->setLiveTime(time);
EventDelegate *ed = qobject_cast<EventDelegate *>(m_timelineUi->view->itemDelegate());
if (ed == nullptr)
{
qWarning() << "TimelineWidget::setLiveTime: ed == nullptr";
return;
}
ed->setLiveTime(time);
}
void TimelineWidget::hideDebugWidget()
{
m_timelineUi->debugWidget->hide();
m_timelineUi->lbMinMax->hide();
}
void TimelineWidget::knownRangesChanged(const QVector<Range> &newRanges)
{
EventDelegate *ed = qobject_cast<EventDelegate *>(m_timelineUi->view->itemDelegate());
if (ed == nullptr)
{
WARNING_LOG(m_logger) << "ed == nullptr";
return;
}
m_timelineUi->view->setKnownRanges(newRanges);
ed->setKnownRanges(newRanges);
m_timelineUi->view->refreshData();
}
void TimelineWidget::setMaxPos()
{
m_timelineUi->scrollbar->setValue(m_timelineUi->scrollbar->maximum());
}
int TimelineWidget::getMaxPos() const
{
return m_timelineUi->scrollbar->maximum();
}
int TimelineWidget::getPos() const
{
return m_timelineUi->scrollbar->value();
}
void TimelineWidget::setPos(qint64 pos)
{
m_timelineUi->scrollbar->setValue(pos / 1000);
}
void TimelineWidget::setPositionMarkerTime(const qint64 time)
{
m_timelineUi->view->slotSetPosMarkTime(time);
}
void TimelineWidget::slotUpdateTimeline()
{
qint64 min = m_model->lowestPositionedItem();
qint64 max = m_model->highestPositionedItem();
if (m_timelineUi->cbMinMax->isChecked())
{
QString minmax(QStringLiteral("%1 (%2) - %3 (%4)")
.arg(QDateTime::fromMSecsSinceEpoch(min).toString())
.arg(min)
.arg(QDateTime::fromMSecsSinceEpoch(max).toString())
.arg(max));
m_timelineUi->lbMinMax->setText(minmax);
}
setTimelineRange(min, max);
emit signalRangeChanged();
}
void TimelineWidget::setTimelineModel(AbstractTimelineModel *model)
{
m_model = model;
connect(m_model, &AbstractTimelineModel::dataChanged,
this, &TimelineWidget::slotRefreshData );
m_timelineUi->view->setTimelineModel(m_model);
connect(m_timelineUi->indicator, &TimelineIndicator::signalAddLine,
m_timelineUi->view, &TimelineView::slotAddLine);
connect(m_timelineUi->indicator, &TimelineIndicator::signalResetLineList,
m_timelineUi->view, &TimelineView::slotResetLineList);
EventDelegate *ed = qobject_cast<EventDelegate *>(m_timelineUi->view->itemDelegate());
if (ed != nullptr)
{
connect(m_timelineUi->indicator, &TimelineIndicator::signalAddLine,
ed, &EventDelegate::slotAddLine);
connect(m_timelineUi->indicator, &TimelineIndicator::signalResetLineList,
ed, &EventDelegate::slotResetLineList);
}
m_timelineUi->view->expandToDepth(1);
m_headerView->resizeSection(0, m_headerView->minimumSectionSize());
m_headerView->resizeSection(1, m_headerView->minimumSectionSize());
slotSetZoomFactor(m_timelineUi->indicator->zoomFactorPoints());
}
qint64 TimelineWidget::getRangeMinimum() const
{
return EventTools::getAdjustedMin();
}
qint64 TimelineWidget::getRangeMaximum() const
{
return EventTools::getAdjustedMax();
}
void TimelineWidget::setTimelineRange(qint64 min, qint64 max)
{
m_min = min;
m_max = max;
if (m_min > 0 && m_max > 2)
{
m_sbPos = EventTools::fromSecondsToMsecs(m_timelineUi->scrollbar->sliderPosition());
if (m_max <= m_min)
{
if (m_min > (10 * 60))
m_min -= (10 * 60);
}
else
{
qint64 diff = m_max - m_min;
if (diff < (10 * 60))
if (m_min > (10 * 60))
m_min -= (10 * 60);
}
EventTools::setValues(m_min, m_max, m_sbPos, m_zoomFactor);
m_timelineUi->scrollbar->setRange(EventTools::fromMsecsToSeconds(EventTools::getTimelineMin()), EventTools::fromMsecsToSeconds(EventTools::getTimelineMax()));
if (m_sbPos < m_min)
{
m_sbPos = m_min;
m_timelineUi->scrollbar->setSliderPosition(EventTools::fromMsecsToSeconds(m_sbPos));
}
int pagestep = EventTools::fromMsecsToSeconds(EventTools::s_diff);
if (pagestep < 0)
pagestep = 1;
m_timelineUi->scrollbar->setPageStep(pagestep);
m_timelineUi->bsz->setText(QString::number(EventTools::getBlockSizeTime()));
}
refreshData();
}
void TimelineWidget::slotRefreshData()
{
refreshData();
}
void TimelineWidget::refreshData()
{
m_headerView->refreshData();
m_timelineUi->indicator->refreshData();
m_timelineUi->view->refreshData();
}
void TimelineWidget::slotSetZoomFactor(qint64 zoomFactor)
{
m_zoomFactor = zoomFactor;
slotUpdateTimeline();
}
void TimelineWidget::scrollBarFilter1(int )
{
scrollBarFilter2();
}
void TimelineWidget::scrollBarFilter2()
{
slotUpdateTimeline();
}
void TimelineWidget::slotSectionResized(int logicalIndex, int oldSize, int newSize)
{
(void)oldSize;
if (logicalIndex == 1)
{
int viewScrollbarWidth = m_timelineUi->view->verticalScrollBar()->width();
m_timelineUi->scrollbar->setMinimumHeight(viewScrollbarWidth);
m_timelineUi->scrollbar->setMaximumHeight(viewScrollbarWidth);
m_timelineUi->scrollbar->setMaximumWidth(newSize);
m_timelineUi->scrollbar->setMinimumWidth(newSize);
EventTools::setSection(m_headerView->sectionPosition(1),
newSize );
}
slotUpdateTimeline();
}
}
+123
View File
@@ -0,0 +1,123 @@
#pragma once
#include <LtsTimelineClassic/ltstimelineclassic_export.h>
#include "Range.h"
#include <NGLLogger/INGLLogger.h>
#include <QWidget>
namespace Ui
{
class Timeline;
}
namespace LtsTimelineClassic
{
class AbstractTimelineModel;
class EventGraphic;
class TimelineHeaderView;
class LTSTIMELINECLASSIC_EXPORT TimelineWidget : public QWidget
{
Q_OBJECT
public:
explicit TimelineWidget(QWidget *parent = nullptr);
~TimelineWidget();
void setPositionMarkerTime(const qint64 time);
qint64 getRangeMinimum() const;
qint64 getRangeMaximum() const;
void setPos(qint64 pos);
void setMaxPos();
int getPos() const;
int getMaxPos() const;
void knownRangesChanged(const QVector<Range> &newRanges);
void hideDebugWidget();
void setLiveTime(qint64 time);
private:
void setTimelineRange(qint64 min, qint64 max);
void refreshData();
NGL::INGLLogger &m_logger;
Ui::Timeline *m_timelineUi;
qint64 m_min;
qint64 m_max;
qint64 m_sbPos;
qint64 m_zoomFactor;
TimelineHeaderView *m_headerView;
AbstractTimelineModel *m_model;
signals:
void signalLoadNewEvents(qint64 from, qint64 to);
void signalEventAction(EventGraphic *eg, int);
void signalRangeChanged();
void signalArm(bool arm);
void signalZoomChanged();
public slots:
void scrollBarFilter1(int x);
void scrollBarFilter2();
void slotSetZoomFactor(qint64 zoomFactor);
void slotSectionResized(int logicalIndex, int oldSize, int newSize);
void setTimelineModel(AbstractTimelineModel *model);
void slotUpdateTimeline();
void slotRefreshData();
};
}
+167
View File
@@ -0,0 +1,167 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Timeline</class>
<widget class="QWidget" name="Timeline">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>628</width>
<height>393</height>
</rect>
</property>
<property name="windowTitle">
<string>Timeline</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,999,0,0,0">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="debugWidget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="cbDrawCache">
<property name="text">
<string>[draw cache]</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbArm">
<property name="text">
<string>[arm]</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbMinMax">
<property name="text">
<string>[min/max]</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="updateTimeline">
<property name="text">
<string notr="true">[update timeline]</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Block size time:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="bsz">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="LtsTimelineClassic::TimelineView" name="view" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
</widget>
</item>
<item alignment="Qt::AlignRight">
<widget class="QScrollBar" name="scrollbar">
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="maximum">
<number>0</number>
</property>
<property name="sliderPosition">
<number>0</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="LtsTimelineClassic::TimelineIndicator" name="indicator" native="true">
<property name="minimumSize">
<size>
<width>100</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbMinMax">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsTimelineClassic::TimelineView</class>
<extends>QWidget</extends>
<header>LtsTimelineClassic/TimelineView.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LtsTimelineClassic::TimelineIndicator</class>
<extends>QWidget</extends>
<header>LtsTimelineClassic/TimelineIndicator.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
+66
View File
@@ -0,0 +1,66 @@
log4j.reset=true
# exclusivly for timelinetest build
log4j.rootLogger=ERROR, file
#log4j.rootLogger=WARN, stdout
log4j.logger.Timeline.EventInfoWindow=DEBUG
log4j.logger.Timeline.EventTools=DEBUG
log4j.logger.Timeline=WARN
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=9
log4j.appender.file.file=${LOG4QT_LOGDIR}/${LOG4QT_USER}_timeline.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %-5p %c |#| %m (%.50F:%L) %n
# Appnd_Console
###########################################################
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %d %p %c %c{1} - %m (%-.30F:%L) %n
###########################################################
###########################################################
###########################################################
# 1) Available Levels in LOG4CXX Version 0.10.0:
# TRACE,
# DEBUG,
# INFO,
# WARN,
# ERROR
# FATAL
#
# d = date/time
# p = priority (Level)
# c = category/channel
# m = message
# F = file
# L = line
# n = platform dependent line separator character or characters.
# ....
#
# Examples for console:
# a)
# %d %p %c #%m# (%.50F:%L)%n
# date/time
# priority
# category/channel
# #message#
# (Maximal 50Character des Filename von rechts:Line)
# line separator
#
# b)
# %d (%.15F:%L) %-5p %c |#| %m%n
# date/time
# (Maximal 15Character des Filename von rechts:Line)
# priority, Right pad with spaces if the priority name is less than 5 characters long.
# category/channel
# message
# line separator
#
# Examples for files:
+82
View File
@@ -0,0 +1,82 @@
#include "TimelineWidget.h"
#include "TestTimelineModel.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <nglapplication/nglapplication.h>
#include <Services/ProjectDataManagement/pdm_enums.hpp>
#include <Services/ProjectDataManagement/pdm_translation.h>
#include <time.h>
#include <QVBoxLayout>
#include <QPushButton>
#include <QDebug>
LtsTimelineClassic::TestTimelineModel *ttm;
void add(qint64 time_offset)
{
qint64 time = 1505292189000;
time += time_offset;
ttm->addTestEvent(new LtsTimelineClassic::Event(0, (int)ProjectDataManagement::EventType_def::Hit, time, 0, 0, 0, 0,
QStringList() << QStringLiteral("Test"),
LtsTimelineClassic::Event::drawCustomEventGraphicEllipse, QColor("green"), QString()));
}
int main(int argc, char *argv[])
{
qputenv("TDS_DEVEL", "yes, of course");
qWarning() << "LtsTimelineClassicTest";
NGLApplication app(argc, argv);
app.createLogger("Timeline", "log4cxx_timeline.props");
STARTUP_LOG(app.baseLogger());
int ret = 0;
#if 1
QWidget *widget = new QWidget();
widget->setMinimumWidth(500);
QVBoxLayout *layout = new QVBoxLayout();
widget->setLayout(layout);
LtsTimelineClassic::TimelineWidget *timelineWidget = new LtsTimelineClassic::TimelineWidget();
layout->addWidget(timelineWidget);
QHBoxLayout *btnLayout = new QHBoxLayout();
QWidget *btnLayoutWidget = new QWidget();
btnLayoutWidget->setLayout(btnLayout);
layout->addWidget(btnLayoutWidget);
btnLayout->addWidget(new QPushButton(QStringLiteral("Filter")));
btnLayout->addWidget(new QPushButton(QStringLiteral("CSV Export")));
btnLayout->addStretch(1);
widget->show();
ttm = new LtsTimelineClassic::TestTimelineModel();
timelineWidget->setTimelineModel(ttm);
add(0);
add(100 * 60 * 1000);
add(3000 * 60 * 1000);
ret = app.exec();
SHUTDOWN_LOG(app.baseLogger());
#endif
return ret;
}