diff --git a/src/libs/tracing/timelinemodel.cpp b/src/libs/tracing/timelinemodel.cpp index d0c88f55280..46ab37f3f5a 100644 --- a/src/libs/tracing/timelinemodel.cpp +++ b/src/libs/tracing/timelinemodel.cpp @@ -83,6 +83,54 @@ void TimelineModel::computeNesting() } } +/*! + Compute all ranges' nesting level. Sort them into rows by finding the + first row that has "an open spot". +*/ +QList TimelineModel::computeRows(int *maxlevel) const +{ + *maxlevel = 0; + std::list rows; + QList levels; + levels.reserve(d->ranges.count()); + for (int range = 0; range != count(); ++range) { + TimelineModelPrivate::Range ¤t = d->ranges[range]; + // find first row for inserting + int level = 0; + auto rowIt = rows.begin(); + forever { + if (rowIt == rows.end()) { + // didn't find a row, insert new one + rows.push_back(range); + break; + } + TimelineModelPrivate::Range &rowItem = d->ranges[*rowIt]; + if (rowItem.start + rowItem.duration < current.start) { + // We've completely passed the item + // Use this row for the range + *rowIt = range; + break; + } + ++rowIt; + ++level; + } + levels.append(level); + if (level > *maxlevel) + *maxlevel = level; + // remove other rows that we passed + while (rowIt != rows.end()) { + TimelineModelPrivate::Range &rowItem = d->ranges[*rowIt]; + if (rowItem.start + rowItem.duration < current.start) { + // We've completely passed the item, remove + rowIt = rows.erase(rowIt); + } else { + ++rowIt; + } + } + } + return levels; +} + int TimelineModel::collapsedRowCount() const { return d->collapsedRowCount; diff --git a/src/libs/tracing/timelinemodel.h b/src/libs/tracing/timelinemodel.h index dd89fb0c5f4..5720909d563 100644 --- a/src/libs/tracing/timelinemodel.h +++ b/src/libs/tracing/timelinemodel.h @@ -133,6 +133,7 @@ protected: int insertStart(qint64 startTime, int selectionId); void insertEnd(int index, qint64 duration); void computeNesting(); + QList computeRows(int *maxlevel) const; void setCollapsedRowCount(int rows); void setExpandedRowCount(int rows); diff --git a/src/plugins/ctfvisualizer/ctftimelinemodel.cpp b/src/plugins/ctfvisualizer/ctftimelinemodel.cpp index 2655a86c065..f558e3599f9 100644 --- a/src/plugins/ctfvisualizer/ctftimelinemodel.cpp +++ b/src/plugins/ctfvisualizer/ctftimelinemodel.cpp @@ -105,7 +105,7 @@ int CtfTimelineModel::expandedRow(int index) const if (counterIdx > 0) { return m_counterIndexToRow[counterIdx - 1] + 1; } - return m_nestingLevels.value(index) + m_counterData.size() + 1; + return m_rows.value(index) + m_counterData.size() + 1; } int CtfTimelineModel::collapsedRow(int index) const @@ -187,6 +187,8 @@ void CtfTimelineModel::finalize(double traceBegin, double traceEnd, const QStrin m_details[index].insert(6, {reuse(Tr::tr("Unfinished")), reuse(Tr::tr("true"))}); } computeNesting(); + m_rows = computeRows(&m_maxStackSize); + ++m_maxStackSize; // index -> count QVector sortedCounterNames = m_counterNames; std::sort(sortedCounterNames.begin(), sortedCounterNames.end()); @@ -233,8 +235,6 @@ qint64 CtfTimelineModel::newStackEvent(const json &event, qint64 normalizedTime, const std::string &eventPhase, const std::string &name, int selectionId) { - int nestingLevel = m_openEventIds.size(); - m_maxStackSize = std::max(qsizetype(m_maxStackSize), qsizetype(m_openEventIds.size() + 1)); int index = 0; qint64 duration = -1; if (eventPhase == CtfEventTypeBegin) { @@ -250,29 +250,21 @@ qint64 CtfTimelineModel::newStackEvent(const json &event, qint64 normalizedTime, duration = qint64(event[CtfDurationKey]) * 1000; index = insert(normalizedTime, duration, selectionId); for (int i = m_openEventIds.size() - 1; i >= 0; --i) { - if (m_openEventIds[i] >= index) { + if (m_openEventIds[i] >= index) ++m_openEventIds[i]; - // if the event is before an open event, the nesting level decreases: - --nestingLevel; - } } } else { index = insert(normalizedTime, 0, selectionId); for (int i = m_openEventIds.size() - 1; i >= 0; --i) { - if (m_openEventIds[i] >= index) { + if (m_openEventIds[i] >= index) ++m_openEventIds[i]; - --nestingLevel; - } } } if (index >= m_details.size()) { m_details.resize(index + 1); m_details[index] = QMap>(); - m_nestingLevels.resize(index + 1); - m_nestingLevels[index] = nestingLevel; } else { m_details.insert(index, QMap>()); - m_nestingLevels.insert(index, nestingLevel); } if (m_counterValues.size() > index) { // if the event was inserted before any counter, we need diff --git a/src/plugins/ctfvisualizer/ctftimelinemodel.h b/src/plugins/ctfvisualizer/ctftimelinemodel.h index 186a0dcefeb..fe7d8c4c0ad 100644 --- a/src/plugins/ctfvisualizer/ctftimelinemodel.h +++ b/src/plugins/ctfvisualizer/ctftimelinemodel.h @@ -73,7 +73,7 @@ protected: QString m_processName; int m_maxStackSize = 0; - QVector m_nestingLevels; + QVector m_rows; QVector>> m_details; QSet m_handledTypeIds; QStack m_openEventIds; diff --git a/tests/auto/tracing/timelinemodel/tst_timelinemodel.cpp b/tests/auto/tracing/timelinemodel/tst_timelinemodel.cpp index 559b827de2e..72f16510bce 100644 --- a/tests/auto/tracing/timelinemodel/tst_timelinemodel.cpp +++ b/tests/auto/tracing/timelinemodel/tst_timelinemodel.cpp @@ -57,6 +57,7 @@ private slots: void rowCount(); void prevNext(); void parentingOfEqualStarts(); + void rows(); private: TimelineModelAggregator aggregator; @@ -463,6 +464,18 @@ void tst_TimelineModel::parentingOfEqualStarts() QCOMPARE(dummy.lastIndex(2), 1); } +void tst_TimelineModel::rows() +{ + DummyModel dummy(&aggregator); + dummy.loadData(); + int maxlevel; + const QList levels = dummy.computeRows(&maxlevel); + QCOMPARE(levels.at(0), 0); + QCOMPARE(levels.at(7), 7); + QCOMPARE(levels.at(10), 2); + QCOMPARE(maxlevel, 15); +} + QTEST_GUILESS_MAIN(tst_TimelineModel) #include "tst_timelinemodel.moc"