Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Executable
+394
@@ -0,0 +1,394 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* manages & represents a row in view and contains children items & events
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Mike Wille, SLSE, 2014-10-01
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "Item.h"
|
||||
#include "EventTools.h"
|
||||
#include "EventGraphic.h"
|
||||
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
//#define VERBOSE
|
||||
#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) // true, as a NEW list is always changed
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
Item::~Item()
|
||||
{
|
||||
delete m_pevcon;
|
||||
|
||||
if (m_children)
|
||||
{
|
||||
qDeleteAll(*m_children);
|
||||
delete m_children;
|
||||
}
|
||||
|
||||
qDeleteAll(m_eventList);
|
||||
}
|
||||
|
||||
|
||||
PassiveEventContainer *Item::getPevcon()
|
||||
{
|
||||
if (!m_pevcon) // create a new pevcon if there is no pevcon
|
||||
m_pevcon = new PassiveEventContainer(m_name == QStringLiteral("Markers")); // this is a speedup!
|
||||
|
||||
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; // add current children list to list (dereference)
|
||||
|
||||
if (!recursive) // if search is not recursive, done
|
||||
return il;
|
||||
|
||||
auto end = m_children->constEnd();
|
||||
for (auto i = m_children->constBegin(); i != end; ++i) // if recursive search is wanted => recursive getFullItemList calls to children and their children, a.s.o.
|
||||
{
|
||||
il += (*i)->getFullItemList(recursive); // probably yes.. ;)
|
||||
}
|
||||
|
||||
return il;
|
||||
}
|
||||
|
||||
|
||||
///* PRIVATE*/ const EventGraphicList Item::getEventGraphicsRecursive() const
|
||||
//{
|
||||
// EventGraphicList egl;
|
||||
|
||||
// // first modify the HIGHEST item, then the children items (or grouped events will be grouped again in higher items, which is not working)
|
||||
// //auto end = ;
|
||||
// for (auto i = m_children->constBegin(); i != m_children->constEnd(); ++i)
|
||||
// {
|
||||
// egl += (*i)->getEventGraphics(true); // true, as this method is for recursive search
|
||||
// }
|
||||
|
||||
// return egl;
|
||||
//}
|
||||
|
||||
|
||||
const EventGraphicList Item::getCurrentEGLFromPevcon() const // .. without recreating one or refresh them
|
||||
{
|
||||
if (m_pevcon == nullptr)
|
||||
return EventGraphicList();
|
||||
return m_pevcon->getEventGraphicList();
|
||||
}
|
||||
|
||||
|
||||
const EventGraphicList Item::getEventGraphics() const // create active events and group events if they overlap in timeline view
|
||||
{
|
||||
EventGraphicList egl;
|
||||
EventList el = getFullEventList(true, false); // now get all events, but not hidden ones as we are going to draw all visible events only
|
||||
|
||||
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(); // list is sorted, so start time will never change in this process (so taking e1's start time is fine)
|
||||
qint64 egEnd = egStart + EventTools::getBlockSizeTime(e1->duration()); // don't use endTime directly as using the block size time on the duration is essential!
|
||||
qint64 blockSizeTime = EventTools::getBlockSizeTime();
|
||||
bool egChanged = false;
|
||||
|
||||
EventGraphic *eg = new EventGraphic(e1);
|
||||
egl += eg;
|
||||
|
||||
auto i2 = i1 + 1; /* start at i (+1) as everything behind it is already done (list is sorted!) */
|
||||
for (; i2 != el.end(); ++i2)
|
||||
{
|
||||
if (egChanged)
|
||||
{
|
||||
egEnd = egStart + eg->getDuration();
|
||||
|
||||
if (egEnd - egStart < blockSizeTime) // the collision check always refers to the complete event craphic - it must always be at least blockSizeTime wide
|
||||
egEnd = egStart + blockSizeTime;
|
||||
|
||||
egChanged = false;
|
||||
}
|
||||
|
||||
Event *e2 = (*i2);
|
||||
|
||||
if (e2->isDeleted())
|
||||
continue;
|
||||
|
||||
qint64 start2 = e2->startTime();
|
||||
|
||||
if (start2 >= egStart && egEnd >= start2) // e2 is inside eg, put e2 into eg
|
||||
{
|
||||
eg->addEvent(e2);
|
||||
egChanged = true;
|
||||
}
|
||||
else // if this event is not inside the current eg, then the following events won't either - loop can be stopped here!
|
||||
{
|
||||
// [never is begin, as i2 was initialized with 'i1 + 1'] if (i2 != el.begin()) // the primary loop has to use this event as a new eg, but the iterator will be ++'ed and therefore skipped, so do a --, but -- on an interator seems ugly..
|
||||
--i2;
|
||||
break;
|
||||
}
|
||||
} // i2
|
||||
|
||||
if (i2 == el.end()) // end if the secondary loop reached the end (must be done because the end of the loop would (probably) otherwise do a ++ on an invalid iterator)
|
||||
break;
|
||||
i1 = i2; // skip processed events (don't +1 here as the primary loop will do this anyways)
|
||||
|
||||
} // i1
|
||||
|
||||
return egl;
|
||||
}
|
||||
|
||||
|
||||
EventList Item::getFullEventList(bool recursive, bool getHiddenEvents) const
|
||||
{
|
||||
EventList el;
|
||||
|
||||
if (getHiddenEvents)
|
||||
{
|
||||
el = m_eventList; // add event list from this item first
|
||||
}
|
||||
else // only get visible events
|
||||
{
|
||||
el.reserve(m_eventList.count()); // TODO: spill some memory for a speedup ?
|
||||
//auto end = ;
|
||||
for (Event *e : m_eventList)
|
||||
{
|
||||
if (e == nullptr || !e->isVisible())
|
||||
continue;
|
||||
|
||||
el.append(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_children || !recursive) // recursive search in EXISTING children list ?
|
||||
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) // private! call TimelineModel::addEventToItem(...) to set possible latest event (by looking for the greates number in position)
|
||||
{
|
||||
m_eventList.append(event);
|
||||
setEventListChanged(); // say that the list has been changed and new event list has to be created when asked
|
||||
}
|
||||
|
||||
|
||||
void Item::setEventListChanged()
|
||||
{
|
||||
m_eventListChanged = true;
|
||||
|
||||
if (m_parent != nullptr)
|
||||
{
|
||||
// tell the parent that his event list changed, too, because it has to show all its children's events, too
|
||||
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); // set given item's parent on this, because it was added to this item
|
||||
m_children->append(item);
|
||||
}
|
||||
|
||||
|
||||
bool Item::hasVisibleEvents() const
|
||||
{
|
||||
// check if this item itself has events ..
|
||||
if (!m_eventList.isEmpty() &&
|
||||
std::find_if(m_eventList.constBegin(), m_eventList.constEnd(), [](Event *e) { return e->isVisible(); }) != m_eventList.constEnd())
|
||||
return true;
|
||||
|
||||
// .. no subitems, no chance to have events at this point
|
||||
if (m_children == nullptr)
|
||||
return false;
|
||||
|
||||
// .. otherwise check if subitems have events, what makes this item have events, too, as the subitems' events are printed as a summary channel on this item
|
||||
|
||||
for (auto i = m_children->constBegin(); i != m_children->constEnd(); ++i)
|
||||
{
|
||||
Item *item = *i;
|
||||
|
||||
if (item->hasVisibleEvents())
|
||||
return true;
|
||||
}
|
||||
|
||||
// no subitem had events? then this item has definitely no events
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Item *Item::child(int row) const
|
||||
{
|
||||
if (m_children == nullptr)
|
||||
return nullptr;
|
||||
|
||||
int idx = 0;
|
||||
|
||||
// only show children that have events aka. are not invisible
|
||||
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; // returns 0 if no list exists
|
||||
}
|
||||
|
||||
|
||||
int Item::indexOfParent() const
|
||||
{
|
||||
if (m_parent == nullptr || m_parent->getChildren() == nullptr)
|
||||
return -1;
|
||||
|
||||
int idx = 0;
|
||||
|
||||
ItemList *parentItemList = m_parent->getChildren();
|
||||
|
||||
// only show children that have events aka. are not invisible
|
||||
for (auto i = parentItemList->constBegin(); i != parentItemList->constEnd(); ++i)
|
||||
{
|
||||
Item *item = *i;
|
||||
|
||||
if (item == this)
|
||||
return idx;
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
Q_ASSERT(false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace LtsTimelineClassic
|
||||
Reference in new issue
Block a user