From 18bf7113e06c1ed78f8d1f2a7fc56ad3928ee504 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 8 Jul 2014 17:18:51 +0200 Subject: [PATCH] QmlProfiler: Remove template/virtual magic from SortedTimelineModel We actually don't have to save the actual data in the SortedTimelineModel if we keep the data synchronized to the ranges. This is easy to do by just keeping track of the indices when new ranges are inserted. Like that we can eliminate the virtual function calls from AbstractTimelineModelPrivate and simplify the type hierarchy. Change-Id: Ia7aa02df57380932b689ddfe9a50ff2031198a7d Reviewed-by: Kai Koehne --- .../qmlprofiler/abstracttimelinemodel.cpp | 61 ++++---------- .../qmlprofiler/abstracttimelinemodel.h | 13 +-- .../qmlprofiler/abstracttimelinemodel_p.h | 11 --- .../qmlprofilerpainteventsmodelproxy.cpp | 42 +++++----- .../qmlprofilertimelinemodelproxy.cpp | 64 +++++++------- .../qmlprofiler/sortedtimelinemodel.cpp | 62 ++++++++++++-- src/plugins/qmlprofiler/sortedtimelinemodel.h | 83 +++++-------------- 7 files changed, 142 insertions(+), 194 deletions(-) diff --git a/src/plugins/qmlprofiler/abstracttimelinemodel.cpp b/src/plugins/qmlprofiler/abstracttimelinemodel.cpp index f9f5fe1874d..a3b486dedc6 100644 --- a/src/plugins/qmlprofiler/abstracttimelinemodel.cpp +++ b/src/plugins/qmlprofiler/abstracttimelinemodel.cpp @@ -35,7 +35,7 @@ namespace QmlProfiler { AbstractTimelineModel::AbstractTimelineModel(AbstractTimelineModelPrivate *dd, const QString &displayName, QmlDebug::Message message, QmlDebug::RangeType rangeType, QObject *parent) : - QObject(parent), d_ptr(dd) + SortedTimelineModel(parent), d_ptr(dd) { Q_D(AbstractTimelineModel); d->q_ptr = this; @@ -61,48 +61,6 @@ void AbstractTimelineModel::setModelManager(QmlProfilerModelManager *modelManage d->modelId = d->modelManager->registerModelProxy(); } -int AbstractTimelineModel::count() const -{ - Q_D(const AbstractTimelineModel); - return d->count(); -} - -int AbstractTimelineModel::firstIndex(qint64 startTime) const -{ - Q_D(const AbstractTimelineModel); - return d->firstIndex(startTime); -} - -int AbstractTimelineModel::firstIndexNoParents(qint64 startTime) const -{ - Q_D(const AbstractTimelineModel); - return d->firstIndexNoParents(startTime); -} - -int AbstractTimelineModel::lastIndex(qint64 endTime) const -{ - Q_D(const AbstractTimelineModel); - return d->lastIndex(endTime); -} - -qint64 AbstractTimelineModel::duration(int index) const -{ - Q_D(const AbstractTimelineModel); - return d->duration(index); -} - -qint64 AbstractTimelineModel::startTime(int index) const -{ - Q_D(const AbstractTimelineModel); - return d->startTime(index); -} - -qint64 AbstractTimelineModel::endTime(int index) const -{ - Q_D(const AbstractTimelineModel); - return d->startTime(index) + d->duration(index); -} - bool AbstractTimelineModel::isEmpty() const { return count() == 0; @@ -241,8 +199,6 @@ void AbstractTimelineModel::dataChanged() default: break; } - - d->rowOffsets.clear(); } bool AbstractTimelineModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const @@ -272,4 +228,19 @@ QString AbstractTimelineModel::displayName() const return d->displayName; } +void AbstractTimelineModel::clear() +{ + Q_D(AbstractTimelineModel); + bool wasExpanded = d->expanded; + bool hadRowHeights = !d->rowOffsets.empty(); + d->rowOffsets.clear(); + d->expanded = false; + SortedTimelineModel::clear(); + if (hadRowHeights) + emit rowHeightChanged(); + if (wasExpanded) + emit expandedChanged(); + d->modelManager->modelProxyCountUpdated(d->modelId, 0, 1); +} + } diff --git a/src/plugins/qmlprofiler/abstracttimelinemodel.h b/src/plugins/qmlprofiler/abstracttimelinemodel.h index d5a2409ad69..525a7263a68 100644 --- a/src/plugins/qmlprofiler/abstracttimelinemodel.h +++ b/src/plugins/qmlprofiler/abstracttimelinemodel.h @@ -34,13 +34,13 @@ #include "qmlprofiler_global.h" #include "qmlprofilermodelmanager.h" #include "qmlprofilerdatamodel.h" -#include +#include "sortedtimelinemodel.h" #include #include namespace QmlProfiler { -class QMLPROFILER_EXPORT AbstractTimelineModel : public QObject +class QMLPROFILER_EXPORT AbstractTimelineModel : public SortedTimelineModel { Q_OBJECT @@ -61,13 +61,6 @@ public: qint64 traceStartTime() const; qint64 traceEndTime() const; qint64 traceDuration() const; - qint64 duration(int index) const; - qint64 startTime(int index) const; - qint64 endTime(int index) const; - int firstIndex(qint64 startTime) const; - int firstIndexNoParents(qint64 startTime) const; - int lastIndex(qint64 endTime) const; - int count() const; bool accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const; bool expanded() const; void setExpanded(bool expanded); @@ -81,7 +74,6 @@ public: virtual QVariantMap details(int index) const = 0; virtual int row(int index) const = 0; virtual void loadData() = 0; - virtual void clear() = 0; // Methods which can optionally be implemented by child models. // returned map should contain "file", "line", "column" properties, or be empty @@ -92,6 +84,7 @@ public: virtual float height(int index) const; virtual int rowMinValue(int rowNumber) const; virtual int rowMaxValue(int rowNumber) const; + virtual void clear(); signals: void expandedChanged(); diff --git a/src/plugins/qmlprofiler/abstracttimelinemodel_p.h b/src/plugins/qmlprofiler/abstracttimelinemodel_p.h index 0ff7c85b577..421adb3b99d 100644 --- a/src/plugins/qmlprofiler/abstracttimelinemodel_p.h +++ b/src/plugins/qmlprofiler/abstracttimelinemodel_p.h @@ -36,17 +36,6 @@ namespace QmlProfiler { class QMLPROFILER_EXPORT AbstractTimelineModel::AbstractTimelineModelPrivate { public: - virtual ~AbstractTimelineModelPrivate() {} - - virtual int count() const = 0; - virtual qint64 duration(int index) const = 0; - virtual qint64 startTime(int index) const = 0; - virtual qint64 lastEndTime() const = 0; - virtual qint64 firstStartTime() const = 0; - virtual int firstIndex(qint64 startTime) const = 0; - virtual int firstIndexNoParents(qint64 startTime) const = 0; - virtual int lastIndex(qint64 endTime) const = 0; - QVector rowOffsets; QmlProfilerModelManager *modelManager; int modelId; diff --git a/src/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/src/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index f958b6ad11b..3d3760170be 100644 --- a/src/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -30,7 +30,6 @@ #include "qmlprofilerpainteventsmodelproxy.h" #include "qmlprofilermodelmanager.h" #include "qmlprofilerdatamodel.h" -#include "sortedtimelinemodel.h" #include "abstracttimelinemodel_p.h" #include #include @@ -46,12 +45,10 @@ namespace QmlProfiler { namespace Internal { -class PaintEventsModelProxy::PaintEventsModelProxyPrivate : - public SortedTimelineModel +class PaintEventsModelProxy::PaintEventsModelProxyPrivate : public AbstractTimelineModelPrivate { public: - + QVector data; int maxGuiThreadAnimations; int maxRenderThreadAnimations; int rowFromThreadId(QmlDebug::AnimationThread threadId) const; @@ -72,10 +69,9 @@ PaintEventsModelProxy::PaintEventsModelProxy(QObject *parent) void PaintEventsModelProxy::clear() { Q_D(PaintEventsModelProxy); - d->clear(); d->maxGuiThreadAnimations = d->maxRenderThreadAnimations = 0; - d->expanded = false; - d->modelManager->modelProxyCountUpdated(d->modelId, 0, 1); + d->data.clear(); + AbstractTimelineModel::clear(); } bool PaintEventsModelProxy::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const @@ -125,7 +121,7 @@ void PaintEventsModelProxy::loadData() lastEvent.animationcount = (int)event.numericData2; QTC_ASSERT(lastEvent.animationcount > 0, continue); - d->insert(realStartTime, realEndTime - realStartTime, lastEvent); + d->data.insert(insert(realStartTime, realEndTime - realStartTime), lastEvent); if (lastEvent.threadId == QmlDebug::GuiThread) d->maxGuiThreadAnimations = qMax(lastEvent.animationcount, d->maxGuiThreadAnimations); @@ -135,10 +131,10 @@ void PaintEventsModelProxy::loadData() minNextStartTimes[lastEvent.threadId] = event.startTime + 1; - d->modelManager->modelProxyCountUpdated(d->modelId, d->count(), referenceList.count()); + d->modelManager->modelProxyCountUpdated(d->modelId, count(), referenceList.count()); } - d->computeNesting(); + computeNesting(); d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); } @@ -163,7 +159,7 @@ int PaintEventsModelProxy::PaintEventsModelProxyPrivate::rowFromThreadId( int PaintEventsModelProxy::row(int index) const { Q_D(const PaintEventsModelProxy); - return d->rowFromThreadId(d->range(index).threadId); + return d->rowFromThreadId(d->data[index].threadId); } int PaintEventsModelProxy::rowMaxValue(int rowNumber) const @@ -183,13 +179,13 @@ int PaintEventsModelProxy::rowMaxValue(int rowNumber) const int PaintEventsModelProxy::eventId(int index) const { Q_D(const PaintEventsModelProxy); - return d->range(index).threadId; + return d->data[index].threadId; } QColor PaintEventsModelProxy::color(int index) const { Q_D(const PaintEventsModelProxy); - double fpsFraction = d->range(index).framerate / 60.0; + double fpsFraction = d->data[index].framerate / 60.0; if (fpsFraction > 1.0) fpsFraction = 1.0; if (fpsFraction < 0.0) @@ -200,16 +196,16 @@ QColor PaintEventsModelProxy::color(int index) const float PaintEventsModelProxy::height(int index) const { Q_D(const PaintEventsModelProxy); - const PaintEventsModelProxyPrivate::Range &range = d->range(index); + const QmlPaintEventData &data = d->data[index]; // Add some height to the events if we're far from the scale threshold of 2 * DefaultRowHeight. // Like that you can see the smaller events more easily. - int scaleThreshold = 2 * DefaultRowHeight - rowHeight(d->rowFromThreadId(range.threadId)); + int scaleThreshold = 2 * DefaultRowHeight - rowHeight(d->rowFromThreadId(data.threadId)); float boost = scaleThreshold > 0 ? (0.15 * scaleThreshold / DefaultRowHeight) : 0; - return boost + (1.0 - boost) * (float)range.animationcount / - (float)(range.threadId == QmlDebug::GuiThread ? d->maxGuiThreadAnimations : - d->maxRenderThreadAnimations); + return boost + (1.0 - boost) * (float)data.animationcount / + (float)(data.threadId == QmlDebug::GuiThread ? d->maxGuiThreadAnimations : + d->maxRenderThreadAnimations); } QVariantList PaintEventsModelProxy::labels() const @@ -242,10 +238,10 @@ QVariantMap PaintEventsModelProxy::details(int index) const QVariantMap result; result.insert(QStringLiteral("displayName"), displayName()); - result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(d->range(index).duration)); - result.insert(tr("Framerate"), QString::fromLatin1("%1 FPS").arg(d->range(index).framerate)); - result.insert(tr("Animations"), QString::fromLatin1("%1").arg(d->range(index).animationcount)); - result.insert(tr("Context"), tr(d->range(index).threadId == QmlDebug::GuiThread ? + result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(range(index).duration)); + result.insert(tr("Framerate"), QString::fromLatin1("%1 FPS").arg(d->data[index].framerate)); + result.insert(tr("Animations"), QString::fromLatin1("%1").arg(d->data[index].animationcount)); + result.insert(tr("Context"), tr(d->data[index].threadId == QmlDebug::GuiThread ? "GUI Thread" : "Render Thread")); return result; } diff --git a/src/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/src/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index 58455f80ca1..3482025e3c6 100644 --- a/src/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -30,7 +30,6 @@ #include "qmlprofilertimelinemodelproxy.h" #include "qmlprofilermodelmanager.h" #include "qmlprofilerdatamodel.h" -#include "sortedtimelinemodel.h" #include "abstracttimelinemodel_p.h" #include @@ -45,9 +44,7 @@ namespace QmlProfiler { namespace Internal { -class RangeTimelineModel::RangeTimelineModelPrivate : - public SortedTimelineModel +class RangeTimelineModel::RangeTimelineModelPrivate : public AbstractTimelineModelPrivate { public: // convenience functions @@ -55,6 +52,7 @@ public: void computeExpandedLevels(); void findBindingLoops(); + QVector data; QVector expandedRowTypes; int contractedRows; bool seenPaintEvent; @@ -68,7 +66,6 @@ RangeTimelineModel::RangeTimelineModel(QmlDebug::RangeType rangeType, QObject *p { Q_D(RangeTimelineModel); d->seenPaintEvent = false; - d->expandedRowTypes.clear(); d->expandedRowTypes << -1; d->contractedRows = 1; } @@ -76,14 +73,12 @@ RangeTimelineModel::RangeTimelineModel(QmlDebug::RangeType rangeType, QObject *p void RangeTimelineModel::clear() { Q_D(RangeTimelineModel); - d->clear(); d->expandedRowTypes.clear(); d->expandedRowTypes << -1; d->contractedRows = 1; d->seenPaintEvent = false; - d->expanded = false; - - d->modelManager->modelProxyCountUpdated(d->modelId, 0, 1); + d->data.clear(); + AbstractTimelineModel::clear(); } void RangeTimelineModel::loadData() @@ -105,15 +100,15 @@ void RangeTimelineModel::loadData() d->seenPaintEvent = true; // store starttime-based instance - d->insert(event.startTime, event.duration, QmlRangeEventStartInstance(event.typeIndex)); - - d->modelManager->modelProxyCountUpdated(d->modelId, d->count(), eventList.count() * 6); + d->data.insert(insert(event.startTime, event.duration), + QmlRangeEventStartInstance(event.typeIndex)); + d->modelManager->modelProxyCountUpdated(d->modelId, count(), eventList.count() * 6); } d->modelManager->modelProxyCountUpdated(d->modelId, 2, 6); // compute range nesting - d->computeNesting(); + computeNesting(); // compute nestingLevel - nonexpanded d->computeNestingContracted(); @@ -134,8 +129,9 @@ void RangeTimelineModel::loadData() void RangeTimelineModel::RangeTimelineModelPrivate::computeNestingContracted() { + Q_Q(RangeTimelineModel); int i; - int eventCount = count(); + int eventCount = q->count(); int nestingLevels = QmlDebug::Constants::QML_MIN_LEVEL; contractedRows = nestingLevels + 1; @@ -143,7 +139,7 @@ void RangeTimelineModel::RangeTimelineModelPrivate::computeNestingContracted() nestingEndTimes.fill(0, nestingLevels + 1); for (i = 0; i < eventCount; i++) { - qint64 st = ranges[i].start; + qint64 st = q->ranges[i].start; // per type if (nestingEndTimes[nestingLevels] > st) { @@ -156,57 +152,57 @@ void RangeTimelineModel::RangeTimelineModelPrivate::computeNestingContracted() nestingEndTimes[nestingLevels-1] <= st) nestingLevels--; } - nestingEndTimes[nestingLevels] = st + ranges[i].duration; + nestingEndTimes[nestingLevels] = st + q->ranges[i].duration; - ranges[i].displayRowCollapsed = nestingLevels; + data[i].displayRowCollapsed = nestingLevels; } } void RangeTimelineModel::RangeTimelineModelPrivate::computeExpandedLevels() { + Q_Q(RangeTimelineModel); QHash eventRow; - int eventCount = count(); + int eventCount = q->count(); for (int i = 0; i < eventCount; i++) { - int eventId = ranges[i].eventId; + int eventId = data[i].eventId; if (!eventRow.contains(eventId)) { eventRow[eventId] = expandedRowTypes.size(); expandedRowTypes << eventId; } - ranges[i].displayRowExpanded = eventRow[eventId]; + data[i].displayRowExpanded = eventRow[eventId]; } } void RangeTimelineModel::RangeTimelineModelPrivate::findBindingLoops() { + Q_Q(RangeTimelineModel); if (rangeType != QmlDebug::Binding && rangeType != QmlDebug::HandlingSignal) return; typedef QPair CallStackEntry; QStack callStack; - for (int i = 0; i < count(); ++i) { - Range *event = &ranges[i]; - + for (int i = 0; i < q->count(); ++i) { const Range *potentialParent = callStack.isEmpty() - ? 0 : &ranges[callStack.top().second]; + ? 0 : &q->ranges[callStack.top().second]; while (potentialParent - && !(potentialParent->start + potentialParent->duration > event->start)) { + && !(potentialParent->start + potentialParent->duration > q->ranges[i].start)) { callStack.pop(); potentialParent = callStack.isEmpty() ? 0 - : &ranges[callStack.top().second]; + : &q->ranges[callStack.top().second]; } // check whether event is already in stack for (int ii = 0; ii < callStack.size(); ++ii) { - if (callStack.at(ii).first == event->eventId) { - event->bindingLoopHead = callStack.at(ii).second; + if (callStack.at(ii).first == data[i].eventId) { + data[i].bindingLoopHead = callStack.at(ii).second; break; } } - CallStackEntry newEntry(event->eventId, i); + CallStackEntry newEntry(data[i].eventId, i); callStack.push(newEntry); } @@ -243,21 +239,21 @@ int RangeTimelineModel::row(int index) const { Q_D(const RangeTimelineModel); if (d->expanded) - return d->range(index).displayRowExpanded; + return d->data[index].displayRowExpanded; else - return d->range(index).displayRowCollapsed; + return d->data[index].displayRowCollapsed; } int RangeTimelineModel::eventId(int index) const { Q_D(const RangeTimelineModel); - return d->range(index).eventId; + return d->data[index].eventId; } int RangeTimelineModel::bindingLoopDest(int index) const { Q_D(const RangeTimelineModel); - return d->range(index).bindingLoopHead; + return d->data[index].bindingLoopHead; } QColor RangeTimelineModel::color(int index) const @@ -296,7 +292,7 @@ QVariantMap RangeTimelineModel::details(int index) const d->modelManager->qmlModel()->getEventTypes(); result.insert(QStringLiteral("displayName"), categoryLabel(d->rangeType)); - result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(d->range(index).duration)); + result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(range(index).duration)); QString detailsString = types[id].data; if (detailsString.length() > 40) diff --git a/src/plugins/qmlprofiler/sortedtimelinemodel.cpp b/src/plugins/qmlprofiler/sortedtimelinemodel.cpp index 2e13417b845..3ee4e27d045 100644 --- a/src/plugins/qmlprofiler/sortedtimelinemodel.cpp +++ b/src/plugins/qmlprofiler/sortedtimelinemodel.cpp @@ -27,6 +27,9 @@ ** ****************************************************************************/ +#include "sortedtimelinemodel.h" +namespace QmlProfiler { + /*! \class QmlProfiler::SortedTimelineModel \brief The SortedTimelineModel class provides a sorted model for timeline data. @@ -49,6 +52,11 @@ \fn SortedTimelineModel::clear() Clears the ranges and their end times. */ +void SortedTimelineModel::clear() +{ + ranges.clear(); + endTimes.clear(); +} /*! \fn int SortedTimelineModel::count() const @@ -66,18 +74,13 @@ */ /*! - \fn const SortedTimelineModel::Range &SortedTimelineModel::range(int index) const + \fn const SortedTimelineModel::Range &SortedTimelineModel::range(int index) const Returns the range data at the specified index. */ /*! - \fn Data &SortedTimelineModel::data(int index) - Returns modifiable user data for the range at the specified index. -*/ - -/*! - \fn int SortedTimelineModel::insert(qint64 startTime, qint64 duration, const Data &item) - Inserts the given data at the given time position and returns its index. + \fn int SortedTimelineModel::insert(qint64 startTime, qint64 duration) + Inserts a range at the given time position and returns its index. */ /*! @@ -114,7 +117,48 @@ */ /*! - \fn void computeNesting() + \fn void SortedTimelineModel::computeNesting() Compute all ranges' parents. \sa findFirstIndex */ +void SortedTimelineModel::computeNesting() +{ + QLinkedList parents; + for (int range = 0; range != count(); ++range) { + Range ¤t = ranges[range]; + for (QLinkedList::iterator parentIt = parents.begin();;) { + Range &parent = ranges[*parentIt]; + qint64 parentEnd = parent.start + parent.duration; + if (parentEnd < current.start) { + if (parent.start == current.start) { + if (parent.parent == -1) { + parent.parent = range; + } else { + Range &ancestor = ranges[parent.parent]; + if (ancestor.start == current.start && + ancestor.duration < current.duration) + parent.parent = range; + } + // Just switch the old parent range for the new, larger one + *parentIt = range; + break; + } else { + parentIt = parents.erase(parentIt); + } + } else if (parentEnd >= current.start + current.duration) { + // no need to insert + current.parent = *parentIt; + break; + } else { + ++parentIt; + } + + if (parentIt == parents.end()) { + parents.append(range); + break; + } + } + } +} + +} diff --git a/src/plugins/qmlprofiler/sortedtimelinemodel.h b/src/plugins/qmlprofiler/sortedtimelinemodel.h index 9412a457469..627cce62aa8 100644 --- a/src/plugins/qmlprofiler/sortedtimelinemodel.h +++ b/src/plugins/qmlprofiler/sortedtimelinemodel.h @@ -30,22 +30,21 @@ #ifndef SORTEDTIMELINEMODEL_H #define SORTEDTIMELINEMODEL_H -#include "abstracttimelinemodel_p.h" +#include "qmlprofiler_global.h" +#include #include #include namespace QmlProfiler { -// The template has to be inserted into the hierarchy of public/private classes when Data is known. -// Otherwise we'd have to add implementation details to the public headers. This is why the class to -// be derived from is given as template parameter. -template -class SortedTimelineModel : public Base { +class QMLPROFILER_EXPORT SortedTimelineModel : public QObject { + Q_OBJECT + public: - struct Range : public Data { - Range() : Data(), start(-1), duration(-1), parent(-1) {} - Range(qint64 start, qint64 duration, const Data &item) : - Data(item), start(start), duration(duration), parent(-1) {} + struct Range { + Range() : start(-1), duration(-1), parent(-1) {} + Range(qint64 start, qint64 duration) : + start(start), duration(duration), parent(-1) {} qint64 start; qint64 duration; int parent; @@ -61,37 +60,35 @@ public: inline qint64 timestamp() const {return end;} }; - void clear() - { - ranges.clear(); - endTimes.clear(); - } + SortedTimelineModel(QObject *parent = 0) : QObject(parent) {} + + void clear(); inline int count() const { return ranges.count(); } - qint64 duration(int index) const { return range(index).duration; } - qint64 startTime(int index) const { return range(index).start; } + qint64 duration(int index) const { return ranges[index].duration; } + qint64 startTime(int index) const { return ranges[index].start; } + qint64 endTime(int index) const { return ranges[index].start + ranges[index].duration; } inline qint64 lastEndTime() const { return endTimes.last().end; } inline qint64 firstStartTime() const { return ranges.first().start; } inline const Range &range(int index) const { return ranges[index]; } - inline Data &data(int index) { return ranges[index]; } - inline int insert(qint64 startTime, qint64 duration, const Data &item) + inline int insert(qint64 startTime, qint64 duration) { /* Doing insert-sort here is preferable as most of the time the times will actually be * presorted in the right way. So usually this will just result in appending. */ - int index = insertSorted(ranges, Range(startTime, duration, item)); + int index = insertSorted(ranges, Range(startTime, duration)); if (index < ranges.size() - 1) incrementStartIndices(index); insertSorted(endTimes, RangeEnd(index, startTime + duration)); return index; } - inline int insertStart(qint64 startTime, const Data &item) + inline int insertStart(qint64 startTime) { - int index = insertSorted(ranges, Range(startTime, 0, item)); + int index = insertSorted(ranges, Range(startTime, 0)); if (index < ranges.size() - 1) incrementStartIndices(index); return index; @@ -138,47 +135,9 @@ public: return lowerBound(ranges, endTime); } - inline void computeNesting() - { - QLinkedList parents; - for (int range = 0; range != count(); ++range) { - Range ¤t = ranges[range]; - for (QLinkedList::iterator parentIt = parents.begin();;) { - Range &parent = ranges[*parentIt]; - qint64 parentEnd = parent.start + parent.duration; - if (parentEnd < current.start) { - if (parent.start == current.start) { - if (parent.parent == -1) { - parent.parent = range; - } else { - Range &ancestor = ranges[parent.parent]; - if (ancestor.start == current.start && - ancestor.duration < current.duration) - parent.parent = range; - } - // Just switch the old parent range for the new, larger one - *parentIt = range; - break; - } else { - parentIt = parents.erase(parentIt); - } - } else if (parentEnd >= current.start + current.duration) { - // no need to insert - current.parent = *parentIt; - break; - } else { - ++parentIt; - } - - if (parentIt == parents.end()) { - parents.append(range); - break; - } - } - } - } - protected: + void computeNesting(); + void incrementStartIndices(int index) { for (int i = 0; i < endTimes.size(); ++i) {