From 10d942e268201e8ed51abaeea7f49d89a8eacfb1 Mon Sep 17 00:00:00 2001 From: Ulf Hermann <ulf.hermann@digia.com> Date: Tue, 28 Oct 2014 19:01:43 +0100 Subject: [PATCH] QmlProfiler: Split AbstractTimelineModel in two classes We need a general purpose TimelineModel and a specialized QmlProfilerTimelineModel. Change-Id: I2da02d65efa11e160cab5fa9f8a21075beb0e2bf Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com> --- .../qmlprofiler/abstracttimelinemodel.cpp | 610 ------------------ src/plugins/qmlprofiler/qmlprofiler.pro | 8 +- src/plugins/qmlprofiler/qmlprofiler.qbs | 3 +- .../qmlprofileranimationsmodel.cpp | 15 +- .../qmlprofiler/qmlprofileranimationsmodel.h | 4 +- .../qmlprofiler/qmlprofilernotesmodel.cpp | 10 +- .../qmlprofiler/qmlprofilernotesmodel.h | 6 +- src/plugins/qmlprofiler/qmlprofilerplugin.cpp | 4 +- src/plugins/qmlprofiler/qmlprofilerplugin.h | 4 +- .../qmlprofiler/qmlprofilerrangemodel.cpp | 6 +- .../qmlprofiler/qmlprofilerrangemodel.h | 4 +- .../qmlprofiler/qmlprofilertimelinemodel.cpp | 112 ++++ .../qmlprofiler/qmlprofilertimelinemodel.h | 76 +++ .../qmlprofilertimelinemodelfactory.h | 4 +- src/plugins/qmlprofiler/timelinemodel.cpp | 511 +++++++++++++++ ...bstracttimelinemodel.h => timelinemodel.h} | 45 +- ...acttimelinemodel_p.h => timelinemodel_p.h} | 31 +- .../qmlprofiler/timelinemodelaggregator.cpp | 16 +- .../qmlprofiler/timelinemodelaggregator.h | 6 +- tests/auto/qmlprofiler/qmlprofiler.pro | 2 +- .../timelinemodel.pro} | 2 +- .../tst_timelinemodel.cpp} | 66 +- 22 files changed, 797 insertions(+), 748 deletions(-) delete mode 100644 src/plugins/qmlprofiler/abstracttimelinemodel.cpp create mode 100644 src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp create mode 100644 src/plugins/qmlprofiler/qmlprofilertimelinemodel.h create mode 100644 src/plugins/qmlprofiler/timelinemodel.cpp rename src/plugins/qmlprofiler/{abstracttimelinemodel.h => timelinemodel.h} (73%) rename src/plugins/qmlprofiler/{abstracttimelinemodel_p.h => timelinemodel_p.h} (82%) rename tests/auto/qmlprofiler/{abstracttimelinemodel/abstracttimelinemodel.pro => timelinemodel/timelinemodel.pro} (68%) rename tests/auto/qmlprofiler/{abstracttimelinemodel/tst_abstracttimelinemodel.cpp => timelinemodel/tst_timelinemodel.cpp} (78%) diff --git a/src/plugins/qmlprofiler/abstracttimelinemodel.cpp b/src/plugins/qmlprofiler/abstracttimelinemodel.cpp deleted file mode 100644 index 98196b0988e..00000000000 --- a/src/plugins/qmlprofiler/abstracttimelinemodel.cpp +++ /dev/null @@ -1,610 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://www.qt.io/licensing. For further information -** use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "abstracttimelinemodel.h" -#include "abstracttimelinemodel_p.h" - -#include <QLinkedList> - -namespace QmlProfiler { - -/*! - \class QmlProfiler::AbstractTimelineModel - \brief The AbstractTimelineModel class provides a sorted model for timeline data. - - The AbstractTimelineModel lets you keep range data sorted by both start and end times, so that - visible ranges can easily be computed. The only precondition for that to work is that the ranges - must be perfectly nested. A "parent" range of a range R is defined as a range for which the - start time is smaller than R's start time and the end time is greater than R's end time. A set - of ranges is perfectly nested if all parent ranges of any given range have a common parent - range. Mind that you can always make that happen by defining a range that spans the whole - available time span. That, however, will make any code that uses firstStartTime() and - lastEndTime() for selecting subsets of the model always select all of it. - - \note Indices returned from the various methods are only valid until a new range is inserted - before them. Inserting a new range before a given index moves the range pointed to by the - index by one. Incrementing the index by one will make it point to the item again. -*/ - -/*! - \fn qint64 AbstractTimelineModelPrivate::firstStartTime() const - Returns the begin of the first range in the model. -*/ - -/*! - \fn qint64 AbstractTimelineModelPrivate::lastEndTime() const - Returns the end of the last range in the model. -*/ - -/*! - \fn const AbstractTimelineModelPrivate::Range &AbstractTimelineModelPrivate::range(int index) const - Returns the range data at the specified index. -*/ - - -/*! - \fn void AbstractTimelineModel::computeNesting() - Compute all ranges' parents. - \sa findFirstIndex -*/ -void AbstractTimelineModel::computeNesting() -{ - Q_D(AbstractTimelineModel); - QLinkedList<int> parents; - for (int range = 0; range != count(); ++range) { - AbstractTimelineModelPrivate::Range ¤t = d->ranges[range]; - for (QLinkedList<int>::iterator parentIt = parents.begin();;) { - if (parentIt == parents.end()) { - parents.append(range); - break; - } - - AbstractTimelineModelPrivate::Range &parent = d->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 { - AbstractTimelineModelPrivate::Range &ancestor = d->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; - } - } - } -} - -int AbstractTimelineModel::collapsedRowCount() const -{ - Q_D(const AbstractTimelineModel); - return d->collapsedRowCount; -} - -void AbstractTimelineModel::setCollapsedRowCount(int rows) -{ - Q_D(AbstractTimelineModel); - d->collapsedRowCount = rows; -} - -int AbstractTimelineModel::expandedRowCount() const -{ - Q_D(const AbstractTimelineModel); - return d->expandedRowCount; -} - -void QmlProfiler::AbstractTimelineModel::setExpandedRowCount(int rows) -{ - Q_D(AbstractTimelineModel); - d->expandedRowCount = rows; -} - -void AbstractTimelineModel::AbstractTimelineModelPrivate::init(AbstractTimelineModel *q, - QmlProfilerModelManager *manager, - const QString &newDisplayName, - QmlDebug::Message newMessage, - QmlDebug::RangeType newRangeType) -{ - q_ptr = q; - modelId = manager->registerModelProxy(); - modelManager = manager; - expanded = false; - hidden = false; - displayName = newDisplayName; - message = newMessage; - rangeType = newRangeType; - expandedRowCount = 1; - collapsedRowCount = 1; - connect(modelManager->qmlModel(), SIGNAL(changed()), q, SLOT(_q_dataChanged())); - connect(q,SIGNAL(rowHeightChanged()),q,SIGNAL(heightChanged())); - connect(q,SIGNAL(expandedChanged()),q,SIGNAL(heightChanged())); - connect(q,SIGNAL(hiddenChanged()),q,SIGNAL(heightChanged())); -} - - -AbstractTimelineModel::AbstractTimelineModel(AbstractTimelineModelPrivate *dd, - QmlProfilerModelManager *manager, const QString &displayName, QmlDebug::Message message, - QmlDebug::RangeType rangeType, QObject *parent) : - QObject(parent), d_ptr(dd) -{ - d_ptr->init(this, manager, displayName, message, rangeType); -} - -AbstractTimelineModel::AbstractTimelineModel(QmlProfilerModelManager *manager, - const QString &displayName, QmlDebug::Message message, QmlDebug::RangeType rangeType, - QObject *parent) : - QObject(parent), d_ptr(new AbstractTimelineModelPrivate) -{ - d_ptr->init(this, manager, displayName, message, rangeType); -} - -AbstractTimelineModel::~AbstractTimelineModel() -{ - Q_D(AbstractTimelineModel); - delete d; -} - -QmlProfilerModelManager *AbstractTimelineModel::modelManager() const -{ - Q_D(const AbstractTimelineModel); - return d->modelManager; -} - -bool AbstractTimelineModel::isEmpty() const -{ - return count() == 0; -} - -int AbstractTimelineModel::modelId() const -{ - Q_D(const AbstractTimelineModel); - return d->modelId; -} - -int AbstractTimelineModel::rowHeight(int rowNumber) const -{ - Q_D(const AbstractTimelineModel); - if (!expanded()) - return AbstractTimelineModelPrivate::DefaultRowHeight; - - if (d->rowOffsets.size() > rowNumber) - return d->rowOffsets[rowNumber] - (rowNumber > 0 ? d->rowOffsets[rowNumber - 1] : 0); - return AbstractTimelineModelPrivate::DefaultRowHeight; -} - -int AbstractTimelineModel::rowOffset(int rowNumber) const -{ - Q_D(const AbstractTimelineModel); - if (rowNumber == 0) - return 0; - if (!expanded()) - return AbstractTimelineModelPrivate::DefaultRowHeight * rowNumber; - - if (d->rowOffsets.size() >= rowNumber) - return d->rowOffsets[rowNumber - 1]; - if (!d->rowOffsets.empty()) - return d->rowOffsets.last() + (rowNumber - d->rowOffsets.size()) * - AbstractTimelineModelPrivate::DefaultRowHeight; - return rowNumber * AbstractTimelineModelPrivate::DefaultRowHeight; -} - -void AbstractTimelineModel::setRowHeight(int rowNumber, int height) -{ - Q_D(AbstractTimelineModel); - if (d->hidden || !d->expanded) - return; - if (height < AbstractTimelineModelPrivate::DefaultRowHeight) - height = AbstractTimelineModelPrivate::DefaultRowHeight; - - int nextOffset = d->rowOffsets.empty() ? 0 : d->rowOffsets.last(); - while (d->rowOffsets.size() <= rowNumber) - d->rowOffsets << (nextOffset += AbstractTimelineModelPrivate::DefaultRowHeight); - int difference = height - d->rowOffsets[rowNumber] + - (rowNumber > 0 ? d->rowOffsets[rowNumber - 1] : 0); - if (difference != 0) { - for (; rowNumber < d->rowOffsets.size(); ++rowNumber) { - d->rowOffsets[rowNumber] += difference; - } - emit rowHeightChanged(); - } -} - -int AbstractTimelineModel::height() const -{ - Q_D(const AbstractTimelineModel); - int depth = rowCount(); - if (d->hidden || !d->expanded || d->rowOffsets.empty()) - return depth * AbstractTimelineModelPrivate::DefaultRowHeight; - - return d->rowOffsets.last() + (depth - d->rowOffsets.size()) * - AbstractTimelineModelPrivate::DefaultRowHeight; -} - -/*! - \fn int AbstractTimelineModel::count() const - Returns the number of ranges in the model. -*/ -int AbstractTimelineModel::count() const -{ - Q_D(const AbstractTimelineModel); - return d->ranges.count(); -} - -qint64 AbstractTimelineModel::duration(int index) const -{ - Q_D(const AbstractTimelineModel); - return d->ranges[index].duration; -} - -qint64 AbstractTimelineModel::startTime(int index) const -{ - Q_D(const AbstractTimelineModel); - return d->ranges[index].start; -} - -qint64 AbstractTimelineModel::endTime(int index) const -{ - Q_D(const AbstractTimelineModel); - return d->ranges[index].start + d->ranges[index].duration; -} - -/*! - Returns the type ID of the event with event ID \a index. The type ID is a globally valid ID which - can be used to communicate metainformation about events to other parts of the program. By default - it is -1, which means there is no global type information about the event. - */ -int AbstractTimelineModel::typeId(int index) const -{ - Q_UNUSED(index) - return -1; -} - -/*! - \fn int AbstractTimelineModel::firstIndex(qint64 startTime) const - Looks up the first range with an end time greater than the given time and - returns its parent's index. If no such range is found, it returns -1. If there - is no parent, it returns the found range's index. The parent of a range is the - range with the lowest start time that completely covers the child range. - "Completely covers" means: - parent.startTime <= child.startTime && parent.endTime >= child.endTime -*/ -int AbstractTimelineModel::firstIndex(qint64 startTime) const -{ - Q_D(const AbstractTimelineModel); - int index = firstIndexNoParents(startTime); - if (index == -1) - return -1; - int parent = d->ranges[index].parent; - return parent == -1 ? index : parent; -} - -/*! - \fn int AbstractTimelineModel::firstIndexNoParents(qint64 startTime) const - Looks up the first range with an end time greater than the given time and - returns its index. If no such range is found, it returns -1. -*/ -int AbstractTimelineModel::firstIndexNoParents(qint64 startTime) const -{ - Q_D(const AbstractTimelineModel); - // in the "endtime" list, find the first event that ends after startTime - if (d->endTimes.isEmpty()) - return -1; - if (d->endTimes.count() == 1 || d->endTimes.first().end > startTime) - return d->endTimes.first().startIndex; - if (d->endTimes.last().end <= startTime) - return -1; - - return d->endTimes[d->lowerBound(d->endTimes, startTime) + 1].startIndex; -} - -/*! - \fn int AbstractTimelineModel::lastIndex(qint64 endTime) const - Looks up the last range with a start time smaller than the given time and - returns its index. If no such range is found, it returns -1. -*/ -int AbstractTimelineModel::lastIndex(qint64 endTime) const -{ - Q_D(const AbstractTimelineModel); - // in the "starttime" list, find the last event that starts before endtime - if (d->ranges.isEmpty() || d->ranges.first().start >= endTime) - return -1; - if (d->ranges.count() == 1) - return 0; - if (d->ranges.last().start < endTime) - return d->ranges.count() - 1; - - return d->lowerBound(d->ranges, endTime); -} - -QVariantMap AbstractTimelineModel::location(int index) const -{ - Q_UNUSED(index); - QVariantMap map; - return map; -} - -/*! - Returns \c true if this model can contain events of global type Id \a typeIndex. Otherwise - returns \c false. - */ -bool AbstractTimelineModel::handlesTypeId(int typeIndex) const -{ - if (typeIndex < 0) - return false; - - Q_D(const AbstractTimelineModel); - return accepted(d->modelManager->qmlModel()->getEventTypes().at(typeIndex)); -} - -int AbstractTimelineModel::selectionIdForLocation(const QString &filename, int line, int column) const -{ - Q_UNUSED(filename); - Q_UNUSED(line); - Q_UNUSED(column); - return -1; -} - -int AbstractTimelineModel::bindingLoopDest(int index) const -{ - Q_UNUSED(index); - return -1; -} - -float AbstractTimelineModel::relativeHeight(int index) const -{ - Q_UNUSED(index); - return 1.0f; -} - -int AbstractTimelineModel::rowMinValue(int rowNumber) const -{ - Q_UNUSED(rowNumber); - return 0; -} - -int AbstractTimelineModel::rowMaxValue(int rowNumber) const -{ - Q_UNUSED(rowNumber); - return 0; -} - -int AbstractTimelineModel::defaultRowHeight() -{ - return AbstractTimelineModelPrivate::DefaultRowHeight; -} - -QmlDebug::RangeType AbstractTimelineModel::rangeType() const -{ - Q_D(const AbstractTimelineModel); - return d->rangeType; -} - -QmlDebug::Message AbstractTimelineModel::message() const -{ - Q_D(const AbstractTimelineModel); - return d->message; -} - -void AbstractTimelineModel::updateProgress(qint64 count, qint64 max) const -{ - Q_D(const AbstractTimelineModel); - d->modelManager->modelProxyCountUpdated(d->modelId, count, max); -} - -void AbstractTimelineModel::announceFeatures(quint64 features) const -{ - Q_D(const AbstractTimelineModel); - d->modelManager->announceFeatures(d->modelId, features); -} - -QColor AbstractTimelineModel::colorBySelectionId(int index) const -{ - return colorByHue(selectionId(index) * AbstractTimelineModelPrivate::SelectionIdHueMultiplier); -} - -QColor AbstractTimelineModel::colorByFraction(double fraction) const -{ - return colorByHue(fraction * AbstractTimelineModelPrivate::FractionHueMultiplier + - AbstractTimelineModelPrivate::FractionHueMininimum); -} - -QColor AbstractTimelineModel::colorByHue(int hue) const -{ - return QColor::fromHsl(hue % 360, AbstractTimelineModelPrivate::Saturation, - AbstractTimelineModelPrivate::Lightness); -} - -/*! - Inserts an event at the time specified by \a startTime with the given \a duration and returns - its index. The \a selectionId determines the selection group the new event belongs to. - \sa selectionId() -*/ -int AbstractTimelineModel::insert(qint64 startTime, qint64 duration, int selectionId) -{ - Q_D(AbstractTimelineModel); - /* 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 = d->insertSorted(d->ranges, - AbstractTimelineModelPrivate::Range(startTime, duration, selectionId)); - if (index < d->ranges.size() - 1) - d->incrementStartIndices(index); - d->insertSorted(d->endTimes, - AbstractTimelineModelPrivate::RangeEnd(index, startTime + duration)); - return index; -} - -/*! - Inserts a range start at the time given by \a startTime and returns its index. The range end is - not set. The \a selectionId determines the selection group the new event belongs to. - \sa selectionId() -*/ -int AbstractTimelineModel::insertStart(qint64 startTime, int selectionId) -{ - Q_D(AbstractTimelineModel); - int index = d->insertSorted(d->ranges, - AbstractTimelineModelPrivate::Range(startTime, 0, selectionId)); - if (index < d->ranges.size() - 1) - d->incrementStartIndices(index); - return index; -} - -/*! - \fn int AbstractTimelineModel::insertEnd(int index, qint64 duration) - Adds a range end for the given start index. -*/ -void AbstractTimelineModel::insertEnd(int index, qint64 duration) -{ - Q_D(AbstractTimelineModel); - d->ranges[index].duration = duration; - d->insertSorted(d->endTimes, AbstractTimelineModelPrivate::RangeEnd(index, - d->ranges[index].start + duration)); -} - -void AbstractTimelineModel::AbstractTimelineModelPrivate::_q_dataChanged() -{ - Q_Q(AbstractTimelineModel); - bool wasEmpty = q->isEmpty(); - switch (modelManager->state()) { - case QmlProfilerDataState::ProcessingData: - q->loadData(); - break; - case QmlProfilerDataState::ClearingData: - q->clear(); - break; - default: - break; - } - if (wasEmpty != q->isEmpty()) - emit q->emptyChanged(); -} - -bool AbstractTimelineModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const -{ - Q_D(const AbstractTimelineModel); - return (event.rangeType == d->rangeType && event.message == d->message); -} - -bool AbstractTimelineModel::expanded() const -{ - Q_D(const AbstractTimelineModel); - return d->expanded; -} - -void AbstractTimelineModel::setExpanded(bool expanded) -{ - Q_D(AbstractTimelineModel); - if (expanded != d->expanded) { - d->expanded = expanded; - emit expandedChanged(); - } -} - -bool AbstractTimelineModel::hidden() const -{ - Q_D(const AbstractTimelineModel); - return d->hidden; -} - -void AbstractTimelineModel::setHidden(bool hidden) -{ - Q_D(AbstractTimelineModel); - if (hidden != d->hidden) { - d->hidden = hidden; - emit hiddenChanged(); - } -} - -QString AbstractTimelineModel::displayName() const -{ - Q_D(const AbstractTimelineModel); - return d->displayName; -} - -int AbstractTimelineModel::rowCount() const -{ - Q_D(const AbstractTimelineModel); - if (d->hidden) - return 0; - if (isEmpty()) - return d->modelManager->isEmpty() ? 1 : 0; - return d->expanded ? d->expandedRowCount : d->collapsedRowCount; -} - -/*! - Returns the ID of the selection group the event with event Id \a index belongs to. Selection - groups are local to the model and the model can arbitrarily assign events to selection groups - when inserting them. - If one event from a selection group is selected, all visible other events from the same - selection group are highlighted. Rows are expected to correspond to selection IDs when the view - is expanded. - */ -int AbstractTimelineModel::selectionId(int index) const -{ - Q_D(const AbstractTimelineModel); - return d->ranges[index].selectionId; -} - -void AbstractTimelineModel::clear() -{ - Q_D(AbstractTimelineModel); - d->collapsedRowCount = d->expandedRowCount = 1; - bool wasExpanded = d->expanded; - bool wasHidden = d->hidden; - bool hadRowHeights = !d->rowOffsets.empty(); - d->rowOffsets.clear(); - d->expanded = false; - d->hidden = false; - d->ranges.clear(); - d->endTimes.clear(); - if (hadRowHeights) - emit rowHeightChanged(); - if (wasExpanded) - emit expandedChanged(); - if (wasHidden) - emit hiddenChanged(); - updateProgress(0, 1); -} - -} - -#include "moc_abstracttimelinemodel.cpp" diff --git a/src/plugins/qmlprofiler/qmlprofiler.pro b/src/plugins/qmlprofiler/qmlprofiler.pro index 30cfca8e663..5aaa5ddbdd9 100644 --- a/src/plugins/qmlprofiler/qmlprofiler.pro +++ b/src/plugins/qmlprofiler/qmlprofiler.pro @@ -5,7 +5,6 @@ QT += network qml quick include(../../qtcreatorplugin.pri) SOURCES += \ - abstracttimelinemodel.cpp \ localqmlprofilerrunner.cpp \ qmlprofileranimationsmodel.cpp \ qmlprofilerattachdialog.cpp \ @@ -23,6 +22,7 @@ SOURCES += \ qmlprofilerruncontrolfactory.cpp \ qmlprofilerstatemanager.cpp \ qmlprofilerstatewidget.cpp \ + qmlprofilertimelinemodel.cpp \ qmlprofilertimelinemodelfactory.cpp \ qmlprofilertool.cpp \ qmlprofilertracefile.cpp \ @@ -31,14 +31,13 @@ SOURCES += \ qmlprofilerviewmanager.cpp \ qv8profilerdatamodel.cpp \ qv8profilereventview.cpp \ + timelinemodel.cpp \ timelinemodelaggregator.cpp \ timelinerenderer.cpp \ timelinezoomcontrol.cpp HEADERS += \ abstractqmlprofilerrunner.h \ - abstracttimelinemodel.h \ - abstracttimelinemodel_p.h \ localqmlprofilerrunner.h \ qmlprofiler_global.h \ qmlprofileranimationsmodel.h \ @@ -59,6 +58,7 @@ HEADERS += \ qmlprofilerruncontrolfactory.h \ qmlprofilerstatemanager.h \ qmlprofilerstatewidget.h \ + qmlprofilertimelinemodel.h \ qmlprofilertimelinemodelfactory.h \ qmlprofilertool.h \ qmlprofilertracefile.h \ @@ -67,6 +67,8 @@ HEADERS += \ qmlprofilerviewmanager.h \ qv8profilerdatamodel.h \ qv8profilereventview.h \ + timelinemodel.h \ + timelinemodel_p.h \ timelinemodelaggregator.h \ timelinerenderer.h \ timelinezoomcontrol.h diff --git a/src/plugins/qmlprofiler/qmlprofiler.qbs b/src/plugins/qmlprofiler/qmlprofiler.qbs index e33030e9032..a6b36cb6a7f 100644 --- a/src/plugins/qmlprofiler/qmlprofiler.qbs +++ b/src/plugins/qmlprofiler/qmlprofiler.qbs @@ -21,7 +21,6 @@ QtcPlugin { name: "General" files: [ "abstractqmlprofilerrunner.h", - "abstracttimelinemodel.h", "abstracttimelinemodel_p.h", "abstracttimelinemodel.cpp", "localqmlprofilerrunner.cpp", "localqmlprofilerrunner.h", "qmlprofiler_global.h", "qmlprofileranimationsmodel.h", "qmlprofileranimationsmodel.cpp", @@ -41,6 +40,7 @@ QtcPlugin { "qmlprofilerstatemanager.cpp", "qmlprofilerstatemanager.h", "qmlprofilerstatewidget.cpp", "qmlprofilerstatewidget.h", "qmlprofilerrangemodel.cpp", "qmlprofilerrangemodel.h", + "qmlprofilertimelinemodel.cpp", "qmlprofilertimelinemodel.h", "qmlprofilertimelinemodelfactory.cpp", "qmlprofilertimelinemodelfactory.h", "qmlprofilertool.cpp", "qmlprofilertool.h", "qmlprofilertracefile.cpp", "qmlprofilertracefile.h", @@ -49,6 +49,7 @@ QtcPlugin { "qmlprofilerviewmanager.cpp", "qmlprofilerviewmanager.h", "qv8profilerdatamodel.cpp", "qv8profilerdatamodel.h", "qv8profilereventview.h", "qv8profilereventview.cpp", + "timelinemodel.cpp", "timelinemodel.h", "timelinemodel_p.h", "timelinemodelaggregator.cpp", "timelinemodelaggregator.h", "timelinerenderer.cpp", "timelinerenderer.h", "timelinezoomcontrol.cpp", "timelinezoomcontrol.h" diff --git a/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp b/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp index 534d7f06b2c..a6652ec1cca 100644 --- a/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp +++ b/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp @@ -31,7 +31,6 @@ #include "qmlprofileranimationsmodel.h" #include "qmlprofilermodelmanager.h" #include "qmlprofilerdatamodel.h" -#include "abstracttimelinemodel_p.h" #include <utils/qtcassert.h> #include <QCoreApplication> @@ -47,10 +46,10 @@ namespace QmlProfiler { namespace Internal { QmlProfilerAnimationsModel::QmlProfilerAnimationsModel(QmlProfilerModelManager *manager, - QObject *parent) - : AbstractTimelineModel(manager, - tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileAnimations)), - QmlDebug::Event, QmlDebug::MaximumRangeType, parent) + QObject *parent) : + QmlProfilerTimelineModel(manager, + tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileAnimations)), + QmlDebug::Event, QmlDebug::MaximumRangeType, parent) { m_maxGuiThreadAnimations = m_maxRenderThreadAnimations = 0; announceFeatures(1 << QmlDebug::ProfileAnimations); @@ -60,12 +59,12 @@ void QmlProfilerAnimationsModel::clear() { m_maxGuiThreadAnimations = m_maxRenderThreadAnimations = 0; m_data.clear(); - AbstractTimelineModel::clear(); + QmlProfilerTimelineModel::clear(); } bool QmlProfilerAnimationsModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const { - return AbstractTimelineModel::accepted(event) && + return QmlProfilerTimelineModel::accepted(event) && event.detailType== QmlDebug::AnimationFrame; } @@ -149,7 +148,7 @@ int QmlProfilerAnimationsModel::rowMaxValue(int rowNumber) const case 2: return m_maxRenderThreadAnimations; default: - return AbstractTimelineModel::rowMaxValue(rowNumber); + return QmlProfilerTimelineModel::rowMaxValue(rowNumber); } } diff --git a/src/plugins/qmlprofiler/qmlprofileranimationsmodel.h b/src/plugins/qmlprofiler/qmlprofileranimationsmodel.h index 55bcec96a62..8306e3a5682 100644 --- a/src/plugins/qmlprofiler/qmlprofileranimationsmodel.h +++ b/src/plugins/qmlprofiler/qmlprofileranimationsmodel.h @@ -33,7 +33,7 @@ #define QMLPROFILERANIMATIONSMODEL_H #include <QObject> -#include "abstracttimelinemodel.h" +#include "qmlprofilertimelinemodel.h" #include <qmldebug/qmlprofilereventtypes.h> #include <qmldebug/qmlprofilereventlocation.h> //#include <QHash> @@ -49,7 +49,7 @@ class QmlProfilerModelManager; namespace Internal { -class QmlProfilerAnimationsModel : public AbstractTimelineModel +class QmlProfilerAnimationsModel : public QmlProfilerTimelineModel { Q_OBJECT public: diff --git a/src/plugins/qmlprofiler/qmlprofilernotesmodel.cpp b/src/plugins/qmlprofiler/qmlprofilernotesmodel.cpp index 0d8aab106f0..12d5174181a 100644 --- a/src/plugins/qmlprofiler/qmlprofilernotesmodel.cpp +++ b/src/plugins/qmlprofiler/qmlprofilernotesmodel.cpp @@ -47,9 +47,9 @@ void QmlProfilerNotesModel::setModelManager(QmlProfilerModelManager *modelManage m_modelManager = modelManager; } -void QmlProfilerNotesModel::addTimelineModel(const AbstractTimelineModel *timelineModel) +void QmlProfilerNotesModel::addTimelineModel(const QmlProfilerTimelineModel *timelineModel) { - connect(timelineModel, &AbstractTimelineModel::destroyed, + connect(timelineModel, &QmlProfilerTimelineModel::destroyed, this, &QmlProfilerNotesModel::removeTimelineModel); m_timelineModels.insert(timelineModel->modelId(), timelineModel); } @@ -111,7 +111,7 @@ int QmlProfilerNotesModel::get(int timelineModel, int timelineIndex) const int QmlProfilerNotesModel::add(int timelineModel, int timelineIndex, const QString &text) { - const AbstractTimelineModel *model = m_timelineModels[timelineModel]; + const QmlProfilerTimelineModel *model = m_timelineModels[timelineModel]; int typeId = model->typeId(timelineIndex); Note note = { text, timelineModel, timelineIndex }; m_data << note; @@ -162,7 +162,7 @@ int QmlProfilerNotesModel::add(int typeId, qint64 start, qint64 duration, const int timelineIndex = -1; const QVector<QmlProfilerDataModel::QmlEventTypeData> &types = m_modelManager->qmlModel()->getEventTypes(); - foreach (const AbstractTimelineModel *model, m_timelineModels) { + foreach (const QmlProfilerTimelineModel *model, m_timelineModels) { if (model->accepted(types[typeId])) { for (int i = model->firstIndex(start); i <= model->lastIndex(start + duration); ++i) { if (i < 0) @@ -237,7 +237,7 @@ void QmlProfilerNotesModel::saveData() if (it == m_timelineModels.end()) continue; - const AbstractTimelineModel *model = it.value(); + const QmlProfilerTimelineModel *model = it.value(); QmlProfilerDataModel::QmlEventNoteData save = { model->typeId(note.timelineIndex), model->startTime(note.timelineIndex), model->duration(note.timelineIndex), note.text diff --git a/src/plugins/qmlprofiler/qmlprofilernotesmodel.h b/src/plugins/qmlprofiler/qmlprofilernotesmodel.h index 7869747016f..a9bf442268d 100644 --- a/src/plugins/qmlprofiler/qmlprofilernotesmodel.h +++ b/src/plugins/qmlprofiler/qmlprofilernotesmodel.h @@ -31,7 +31,7 @@ #ifndef NOTESMODEL_H #define NOTESMODEL_H -#include "abstracttimelinemodel.h" +#include "qmlprofilertimelinemodel.h" #include "qmlprofilermodelmanager.h" #include <QList> #include <QHash> @@ -54,7 +54,7 @@ public: int count() const; void setModelManager(QmlProfilerModelManager *modelManager); - void addTimelineModel(const AbstractTimelineModel *timelineModel); + void addTimelineModel(const QmlProfilerTimelineModel *timelineModel); Q_INVOKABLE int typeId(int index) const; Q_INVOKABLE QString text(int index) const; @@ -86,7 +86,7 @@ private slots: protected: QmlProfilerModelManager *m_modelManager; QList<Note> m_data; - QHash<int, const AbstractTimelineModel *> m_timelineModels; + QHash<int, const QmlProfilerTimelineModel *> m_timelineModels; bool m_modified; int add(int typeId, qint64 startTime, qint64 duration, const QString &text); diff --git a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp index 7fdec67cc72..d26a51f0f50 100644 --- a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp @@ -32,7 +32,7 @@ #include "qmlprofilerruncontrolfactory.h" #include "qmlprofilertool.h" -#include "abstracttimelinemodel.h" +#include "qmlprofilertimelinemodel.h" #include <analyzerbase/analyzermanager.h> #include <extensionsystem/pluginmanager.h> @@ -103,7 +103,7 @@ ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerPlugin::aboutToShutdown() return SynchronousShutdown; } -QList<AbstractTimelineModel *> QmlProfilerPlugin::getModels(QmlProfilerModelManager *manager) const +QList<QmlProfilerTimelineModel *> QmlProfilerPlugin::getModels(QmlProfilerModelManager *manager) const { return factory->create(manager); } diff --git a/src/plugins/qmlprofiler/qmlprofilerplugin.h b/src/plugins/qmlprofiler/qmlprofilerplugin.h index 19e12f6f089..cd8e6fd777c 100644 --- a/src/plugins/qmlprofiler/qmlprofilerplugin.h +++ b/src/plugins/qmlprofiler/qmlprofilerplugin.h @@ -35,7 +35,7 @@ #include "qmlprofilertimelinemodelfactory.h" #include <extensionsystem/iplugin.h> -#include "abstracttimelinemodel.h" +#include "qmlprofilertimelinemodel.h" namespace QmlProfiler { namespace Internal { @@ -55,7 +55,7 @@ public: static bool debugOutput; static QmlProfilerPlugin *instance; - QList<AbstractTimelineModel *> getModels(QmlProfilerModelManager *manager) const; + QList<QmlProfilerTimelineModel *> getModels(QmlProfilerModelManager *manager) const; private: QmlProfilerTimelineModelFactory *factory; diff --git a/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp b/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp index 16e3a1ce20f..47f37a4ca65 100644 --- a/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp @@ -46,8 +46,8 @@ namespace Internal { QmlProfilerRangeModel::QmlProfilerRangeModel(QmlProfilerModelManager *manager, - QmlDebug::RangeType range, QObject *parent) - : AbstractTimelineModel(manager, categoryLabel(range), QmlDebug::MaximumMessage, range, parent) + QmlDebug::RangeType range, QObject *parent) : + QmlProfilerTimelineModel(manager, categoryLabel(range), QmlDebug::MaximumMessage, range, parent) { m_expandedRowTypes << -1; announceFeatures(1ULL << QmlDebug::featureFromRangeType(rangeType())); @@ -58,7 +58,7 @@ void QmlProfilerRangeModel::clear() m_expandedRowTypes.clear(); m_expandedRowTypes << -1; m_data.clear(); - AbstractTimelineModel::clear(); + QmlProfilerTimelineModel::clear(); } void QmlProfilerRangeModel::loadData() diff --git a/src/plugins/qmlprofiler/qmlprofilerrangemodel.h b/src/plugins/qmlprofiler/qmlprofilerrangemodel.h index f19db063180..b9bc8ed6430 100644 --- a/src/plugins/qmlprofiler/qmlprofilerrangemodel.h +++ b/src/plugins/qmlprofiler/qmlprofilerrangemodel.h @@ -32,7 +32,7 @@ #ifndef QMLPROFILERRANGEMODEL_H #define QMLPROFILERRANGEMODEL_H -#include "abstracttimelinemodel.h" +#include "qmlprofilertimelinemodel.h" #include <qmldebug/qmlprofilereventtypes.h> #include <qmldebug/qmlprofilereventlocation.h> #include <QVariantList> @@ -44,7 +44,7 @@ class QmlProfilerModelManager; namespace Internal { -class QmlProfilerRangeModel : public AbstractTimelineModel +class QmlProfilerRangeModel : public QmlProfilerTimelineModel { Q_OBJECT public: diff --git a/src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp b/src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp new file mode 100644 index 00000000000..e3c22620f75 --- /dev/null +++ b/src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilertimelinemodel.h" + +namespace QmlProfiler { + +QmlProfilerTimelineModel::QmlProfilerTimelineModel(QmlProfilerModelManager *modelManager, + const QString &displayName, + QmlDebug::Message message, + QmlDebug::RangeType rangeType, QObject *parent) : + TimelineModel(modelManager->registerModelProxy(), displayName, parent), m_message(message), + m_rangeType(rangeType), m_modelManager(modelManager) +{ + connect(modelManager->qmlModel(), &QmlProfilerDataModel::changed, + this, &QmlProfilerTimelineModel::dataChanged); +} + +QmlDebug::RangeType QmlProfilerTimelineModel::rangeType() const +{ + return m_rangeType; +} + +QmlDebug::Message QmlProfilerTimelineModel::message() const +{ + return m_message; +} + +bool QmlProfilerTimelineModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const +{ + return (event.rangeType == m_rangeType && event.message == m_message); +} + +bool QmlProfilerTimelineModel::handlesTypeId(int typeIndex) const +{ + if (typeIndex < 0) + return false; + + return accepted(modelManager()->qmlModel()->getEventTypes().at(typeIndex)); +} + +void QmlProfilerTimelineModel::clear() +{ + TimelineModel::clear(); + updateProgress(0, 1); +} + +QmlProfilerModelManager *QmlProfilerTimelineModel::modelManager() const +{ + return m_modelManager; +} + +void QmlProfilerTimelineModel::updateProgress(qint64 count, qint64 max) const +{ + m_modelManager->modelProxyCountUpdated(modelId(), count, max); +} + +void QmlProfilerTimelineModel::announceFeatures(quint64 features) const +{ + m_modelManager->announceFeatures(modelId(), features); +} + +void QmlProfilerTimelineModel::dataChanged() +{ + + switch (m_modelManager->state()) { + case QmlProfilerDataState::ProcessingData: + loadData(); + emit emptyChanged(); + break; + case QmlProfilerDataState::ClearingData: + clear(); + break; + default: + break; + } +} + +int QmlProfilerTimelineModel::bindingLoopDest(int index) const +{ + Q_UNUSED(index); + return -1; +} + +} diff --git a/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h b/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h new file mode 100644 index 00000000000..aecc1e31b38 --- /dev/null +++ b/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERTIMELINEMODEL_H +#define QMLPROFILERTIMELINEMODEL_H + +#include "timelinemodel.h" + +namespace QmlProfiler { + +class QMLPROFILER_EXPORT QmlProfilerTimelineModel : public TimelineModel { + Q_OBJECT + Q_PROPERTY(QmlDebug::RangeType rangeType READ rangeType CONSTANT) + Q_PROPERTY(QmlDebug::Message message READ message CONSTANT) + Q_PROPERTY(QmlProfilerModelManager *modelManager READ modelManager CONSTANT) + +public: + QmlProfilerTimelineModel(QmlProfilerModelManager *modelManager, const QString &displayName, + QmlDebug::Message message, QmlDebug::RangeType rangeType, + QObject *parent); + + QmlProfilerModelManager *modelManager() const; + + QmlDebug::RangeType rangeType() const; + QmlDebug::Message message() const; + + virtual bool accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const; + bool handlesTypeId(int typeId) const; + Q_INVOKABLE virtual int bindingLoopDest(int index) const; + + virtual void loadData() = 0; + void clear(); + +private slots: + void dataChanged(); + +protected: + void updateProgress(qint64 count, qint64 max) const; + void announceFeatures(quint64 features) const; + +private: + const QmlDebug::Message m_message; + const QmlDebug::RangeType m_rangeType; + QmlProfilerModelManager *const m_modelManager; +}; + +} + +#endif // QMLPROFILERTIMELINEMODEL_H diff --git a/src/plugins/qmlprofiler/qmlprofilertimelinemodelfactory.h b/src/plugins/qmlprofiler/qmlprofilertimelinemodelfactory.h index a7e9f6d8fcf..3cd047d1ad6 100644 --- a/src/plugins/qmlprofiler/qmlprofilertimelinemodelfactory.h +++ b/src/plugins/qmlprofiler/qmlprofilertimelinemodelfactory.h @@ -31,7 +31,7 @@ #ifndef QMLPROFILERTIMELINEMODELFACTORY_H #define QMLPROFILERTIMELINEMODELFACTORY_H -#include "abstracttimelinemodel.h" +#include "qmlprofilertimelinemodel.h" #include "qmlprofilermodelmanager.h" namespace QmlProfiler { @@ -40,7 +40,7 @@ class QMLPROFILER_EXPORT QmlProfilerTimelineModelFactory : public QObject { Q_OBJECT public: - virtual QList<AbstractTimelineModel *> create(QmlProfilerModelManager *manager) = 0; + virtual QList<QmlProfilerTimelineModel *> create(QmlProfilerModelManager *manager) = 0; }; } diff --git a/src/plugins/qmlprofiler/timelinemodel.cpp b/src/plugins/qmlprofiler/timelinemodel.cpp new file mode 100644 index 00000000000..00dc72ed104 --- /dev/null +++ b/src/plugins/qmlprofiler/timelinemodel.cpp @@ -0,0 +1,511 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "timelinemodel.h" +#include "timelinemodel_p.h" + +#include <QLinkedList> + +namespace QmlProfiler { + +/*! + \class QmlProfiler::TimelineModel + \brief The TimelineModel class provides a sorted model for timeline data. + + The TimelineModel lets you keep range data sorted by both start and end times, so that + visible ranges can easily be computed. The only precondition for that to work is that the ranges + must be perfectly nested. A "parent" range of a range R is defined as a range for which the + start time is earlier than R's start time and the end time is later than R's end time. A set + of ranges is perfectly nested if all parent ranges of any given range have a common parent + range. Mind that you can always make that happen by defining a range that spans the whole + available time span. That, however, will make any code that uses firstIndex() and lastIndex() + for selecting subsets of the model always select all of it. + + \note Indices returned from the various methods are only valid until a new range is inserted + before them. Inserting a new range before a given index moves the range pointed to by the + index by one. Incrementing the index by one will make it point to the item again. +*/ + +/*! + Compute all ranges' parents. + \sa firstIndex() +*/ +void TimelineModel::computeNesting() +{ + Q_D(TimelineModel); + QLinkedList<int> parents; + for (int range = 0; range != count(); ++range) { + TimelineModelPrivate::Range ¤t = d->ranges[range]; + for (QLinkedList<int>::iterator parentIt = parents.begin();;) { + if (parentIt == parents.end()) { + parents.append(range); + break; + } + + TimelineModelPrivate::Range &parent = d->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 { + TimelineModelPrivate::Range &ancestor = d->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; + } + } + } +} + +int TimelineModel::collapsedRowCount() const +{ + Q_D(const TimelineModel); + return d->collapsedRowCount; +} + +void TimelineModel::setCollapsedRowCount(int rows) +{ + Q_D(TimelineModel); + d->collapsedRowCount = rows; +} + +int TimelineModel::expandedRowCount() const +{ + Q_D(const TimelineModel); + return d->expandedRowCount; +} + +void QmlProfiler::TimelineModel::setExpandedRowCount(int rows) +{ + Q_D(TimelineModel); + d->expandedRowCount = rows; +} + + +TimelineModel::TimelineModelPrivate::TimelineModelPrivate(int modelId, const QString &displayName) : + modelId(modelId), displayName(displayName), expanded(false), hidden(false), + expandedRowCount(1), collapsedRowCount(1), q_ptr(0) +{ +} + +void TimelineModel::TimelineModelPrivate::init(TimelineModel *q) +{ + q_ptr = q; + connect(q,SIGNAL(rowHeightChanged()),q,SIGNAL(heightChanged())); + connect(q,SIGNAL(expandedChanged()),q,SIGNAL(heightChanged())); + connect(q,SIGNAL(hiddenChanged()),q,SIGNAL(heightChanged())); +} + + +TimelineModel::TimelineModel(TimelineModelPrivate &dd, QObject *parent) : + QObject(parent), d_ptr(&dd) +{ + d_ptr->init(this); +} + +TimelineModel::TimelineModel(int modelId, const QString &displayName, QObject *parent) : + QObject(parent), d_ptr(new TimelineModelPrivate(modelId, displayName)) +{ + d_ptr->init(this); +} + +TimelineModel::~TimelineModel() +{ + Q_D(TimelineModel); + delete d; +} + +bool TimelineModel::isEmpty() const +{ + return count() == 0; +} + +int TimelineModel::modelId() const +{ + Q_D(const TimelineModel); + return d->modelId; +} + +int TimelineModel::rowHeight(int rowNumber) const +{ + Q_D(const TimelineModel); + if (!expanded()) + return TimelineModelPrivate::DefaultRowHeight; + + if (d->rowOffsets.size() > rowNumber) + return d->rowOffsets[rowNumber] - (rowNumber > 0 ? d->rowOffsets[rowNumber - 1] : 0); + return TimelineModelPrivate::DefaultRowHeight; +} + +int TimelineModel::rowOffset(int rowNumber) const +{ + Q_D(const TimelineModel); + if (rowNumber == 0) + return 0; + if (!expanded()) + return TimelineModelPrivate::DefaultRowHeight * rowNumber; + + if (d->rowOffsets.size() >= rowNumber) + return d->rowOffsets[rowNumber - 1]; + if (!d->rowOffsets.empty()) + return d->rowOffsets.last() + (rowNumber - d->rowOffsets.size()) * + TimelineModelPrivate::DefaultRowHeight; + return rowNumber * TimelineModelPrivate::DefaultRowHeight; +} + +void TimelineModel::setRowHeight(int rowNumber, int height) +{ + Q_D(TimelineModel); + if (d->hidden || !d->expanded) + return; + if (height < TimelineModelPrivate::DefaultRowHeight) + height = TimelineModelPrivate::DefaultRowHeight; + + int nextOffset = d->rowOffsets.empty() ? 0 : d->rowOffsets.last(); + while (d->rowOffsets.size() <= rowNumber) + d->rowOffsets << (nextOffset += TimelineModelPrivate::DefaultRowHeight); + int difference = height - d->rowOffsets[rowNumber] + + (rowNumber > 0 ? d->rowOffsets[rowNumber - 1] : 0); + if (difference != 0) { + for (; rowNumber < d->rowOffsets.size(); ++rowNumber) { + d->rowOffsets[rowNumber] += difference; + } + emit rowHeightChanged(); + } +} + +int TimelineModel::height() const +{ + Q_D(const TimelineModel); + int depth = rowCount(); + if (d->hidden || !d->expanded || d->rowOffsets.empty()) + return depth * TimelineModelPrivate::DefaultRowHeight; + + return d->rowOffsets.last() + (depth - d->rowOffsets.size()) * + TimelineModelPrivate::DefaultRowHeight; +} + +/*! + Returns the number of ranges in the model. +*/ +int TimelineModel::count() const +{ + Q_D(const TimelineModel); + return d->ranges.count(); +} + +qint64 TimelineModel::duration(int index) const +{ + Q_D(const TimelineModel); + return d->ranges[index].duration; +} + +qint64 TimelineModel::startTime(int index) const +{ + Q_D(const TimelineModel); + return d->ranges[index].start; +} + +qint64 TimelineModel::endTime(int index) const +{ + Q_D(const TimelineModel); + return d->ranges[index].start + d->ranges[index].duration; +} + +/*! + Returns the type ID of the event with event ID \a index. The type ID is a globally valid ID + which can be used to communicate meta information about events to other parts of the program. By + default it is -1, which means there is no global type information about the event. + */ +int TimelineModel::typeId(int index) const +{ + Q_UNUSED(index) + return -1; +} + +/*! + Looks up the first range with an end time later than the given time and + returns its parent's index. If no such range is found, it returns -1. If there + is no parent, it returns the found range's index. The parent of a range is the + range with the earliest start time that completely covers the child range. + "Completely covers" means: + parent.startTime <= child.startTime && parent.endTime >= child.endTime +*/ +int TimelineModel::firstIndex(qint64 startTime) const +{ + Q_D(const TimelineModel); + int index = firstIndexNoParents(startTime); + if (index == -1) + return -1; + int parent = d->ranges[index].parent; + return parent == -1 ? index : parent; +} + +/*! + Looks up the first range with an end time later than the specified \a startTime and + returns its index. If no such range is found, it returns -1. +*/ +int TimelineModel::firstIndexNoParents(qint64 startTime) const +{ + Q_D(const TimelineModel); + // in the "endtime" list, find the first event that ends after startTime + if (d->endTimes.isEmpty()) + return -1; + if (d->endTimes.count() == 1 || d->endTimes.first().end > startTime) + return d->endTimes.first().startIndex; + if (d->endTimes.last().end <= startTime) + return -1; + + return d->endTimes[d->lowerBound(d->endTimes, startTime) + 1].startIndex; +} + +/*! + Looks up the last range with a start time earlier than the specified \a endTime and + returns its index. If no such range is found, it returns -1. +*/ +int TimelineModel::lastIndex(qint64 endTime) const +{ + Q_D(const TimelineModel); + // in the "starttime" list, find the last event that starts before endtime + if (d->ranges.isEmpty() || d->ranges.first().start >= endTime) + return -1; + if (d->ranges.count() == 1) + return 0; + if (d->ranges.last().start < endTime) + return d->ranges.count() - 1; + + return d->lowerBound(d->ranges, endTime); +} + +QVariantMap TimelineModel::location(int index) const +{ + Q_UNUSED(index); + QVariantMap map; + return map; +} + +/*! + Returns \c true if this model can contain events of global type ID \a typeIndex. Otherwise + returns \c false. The base model does not know anything about type IDs and always returns + \c false. You should override this method if you implement \l typeId(). + */ +bool TimelineModel::handlesTypeId(int typeIndex) const +{ + Q_UNUSED(typeIndex); + return false; +} + +int TimelineModel::selectionIdForLocation(const QString &filename, int line, int column) const +{ + Q_UNUSED(filename); + Q_UNUSED(line); + Q_UNUSED(column); + return -1; +} + +float TimelineModel::relativeHeight(int index) const +{ + Q_UNUSED(index); + return 1.0f; +} + +int TimelineModel::rowMinValue(int rowNumber) const +{ + Q_UNUSED(rowNumber); + return 0; +} + +int TimelineModel::rowMaxValue(int rowNumber) const +{ + Q_UNUSED(rowNumber); + return 0; +} + +int TimelineModel::defaultRowHeight() +{ + return TimelineModelPrivate::DefaultRowHeight; +} + +QColor TimelineModel::colorBySelectionId(int index) const +{ + return colorByHue(selectionId(index) * TimelineModelPrivate::SelectionIdHueMultiplier); +} + +QColor TimelineModel::colorByFraction(double fraction) const +{ + return colorByHue(fraction * TimelineModelPrivate::FractionHueMultiplier + + TimelineModelPrivate::FractionHueMininimum); +} + +QColor TimelineModel::colorByHue(int hue) const +{ + return QColor::fromHsl(hue % 360, TimelineModelPrivate::Saturation, + TimelineModelPrivate::Lightness); +} + +/*! + Inserts the range defined by \a duration and \a selectionId at the specified \a startTime and + returns its index. The \a selectionId determines the selection group the new event belongs to. + \sa selectionId() +*/ +int TimelineModel::insert(qint64 startTime, qint64 duration, int selectionId) +{ + Q_D(TimelineModel); + /* 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 = d->insertSorted(d->ranges, + TimelineModelPrivate::Range(startTime, duration, selectionId)); + if (index < d->ranges.size() - 1) + d->incrementStartIndices(index); + d->insertSorted(d->endTimes, TimelineModelPrivate::RangeEnd(index, startTime + duration)); + return index; +} + +/*! + Inserts the specified \a selectionId as range start at the specified \a startTime and returns + its index. The range end is not set. The \a selectionId determines the selection group the new + event belongs to. + \sa selectionId() +*/ +int TimelineModel::insertStart(qint64 startTime, int selectionId) +{ + Q_D(TimelineModel); + int index = d->insertSorted(d->ranges, TimelineModelPrivate::Range(startTime, 0, selectionId)); + if (index < d->ranges.size() - 1) + d->incrementStartIndices(index); + return index; +} + +/*! + Adds the range \a duration at the specified start \a index. +*/ +void TimelineModel::insertEnd(int index, qint64 duration) +{ + Q_D(TimelineModel); + d->ranges[index].duration = duration; + d->insertSorted(d->endTimes, TimelineModelPrivate::RangeEnd(index, + d->ranges[index].start + duration)); +} + +bool TimelineModel::expanded() const +{ + Q_D(const TimelineModel); + return d->expanded; +} + +void TimelineModel::setExpanded(bool expanded) +{ + Q_D(TimelineModel); + if (expanded != d->expanded) { + d->expanded = expanded; + emit expandedChanged(); + } +} + +bool TimelineModel::hidden() const +{ + Q_D(const TimelineModel); + return d->hidden; +} + +void TimelineModel::setHidden(bool hidden) +{ + Q_D(TimelineModel); + if (hidden != d->hidden) { + d->hidden = hidden; + emit hiddenChanged(); + } +} + +QString TimelineModel::displayName() const +{ + Q_D(const TimelineModel); + return d->displayName; +} + +int TimelineModel::rowCount() const +{ + Q_D(const TimelineModel); + if (d->hidden || isEmpty()) + return 0; + return d->expanded ? d->expandedRowCount : d->collapsedRowCount; +} + +/*! + Returns the ID of the selection group the event with event ID \a index belongs to. Selection + groups are local to the model and the model can arbitrarily assign events to selection groups + when inserting them. + If one event from a selection group is selected, all visible other events from the same + selection group are highlighted. Rows are expected to correspond to selection IDs when the view + is expanded. + */ +int TimelineModel::selectionId(int index) const +{ + Q_D(const TimelineModel); + return d->ranges[index].selectionId; +} + +void TimelineModel::clear() +{ + Q_D(TimelineModel); + d->collapsedRowCount = d->expandedRowCount = 1; + bool wasExpanded = d->expanded; + bool wasHidden = d->hidden; + bool hadRowHeights = !d->rowOffsets.empty(); + d->rowOffsets.clear(); + d->expanded = false; + d->hidden = false; + d->ranges.clear(); + d->endTimes.clear(); + if (hadRowHeights) + emit rowHeightChanged(); + if (wasExpanded) + emit expandedChanged(); + if (wasHidden) + emit hiddenChanged(); +} + +} + +#include "moc_timelinemodel.cpp" diff --git a/src/plugins/qmlprofiler/abstracttimelinemodel.h b/src/plugins/qmlprofiler/timelinemodel.h similarity index 73% rename from src/plugins/qmlprofiler/abstracttimelinemodel.h rename to src/plugins/qmlprofiler/timelinemodel.h index 926364f9a3e..428473eab88 100644 --- a/src/plugins/qmlprofiler/abstracttimelinemodel.h +++ b/src/plugins/qmlprofiler/timelinemodel.h @@ -28,8 +28,8 @@ ** ****************************************************************************/ -#ifndef ABSTRACTTIMELINEMODEL_H -#define ABSTRACTTIMELINEMODEL_H +#ifndef TIMELINEMODEL_H +#define TIMELINEMODEL_H #include "qmlprofiler_global.h" @@ -40,30 +40,24 @@ namespace QmlProfiler { -class QMLPROFILER_EXPORT AbstractTimelineModel : public QObject +class QMLPROFILER_EXPORT TimelineModel : public QObject { Q_OBJECT + Q_PROPERTY(int modelId READ modelId CONSTANT) Q_PROPERTY(QString displayName READ displayName CONSTANT) Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged) Q_PROPERTY(bool hidden READ hidden WRITE setHidden NOTIFY hiddenChanged) Q_PROPERTY(int height READ height NOTIFY heightChanged) - Q_PROPERTY(QmlProfilerModelManager *modelManager READ modelManager) public: - class AbstractTimelineModelPrivate; + class TimelineModelPrivate; - AbstractTimelineModel(QmlProfilerModelManager *manager, const QString &displayName, - QmlDebug::Message message, QmlDebug::RangeType rangeType, - QObject *parent); - ~AbstractTimelineModel(); - - // Trivial methods implemented by the abstract model itself - QmlProfilerModelManager *modelManager() const; + TimelineModel(int modelId, const QString &displayName, QObject *parent); + ~TimelineModel(); + // Methods implemented by the abstract model itself bool isEmpty() const; int modelId() const; - - // Methods are directly passed on to the private model and relying on its virtual methods. int rowHeight(int rowNumber) const; int rowOffset(int rowNumber) const; void setRowHeight(int rowNumber, int height); @@ -96,9 +90,7 @@ public: virtual QVariantMap location(int index) const; virtual int typeId(int index) const; virtual bool handlesTypeId(int typeId) const; - virtual bool accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const; virtual int selectionIdForLocation(const QString &filename, int line, int column) const; - virtual int bindingLoopDest(int index) const; virtual float relativeHeight(int index) const; virtual int rowMinValue(int rowNumber) const; virtual int rowMaxValue(int rowNumber) const; @@ -128,26 +120,15 @@ protected: int expandedRowCount() const; void setExpandedRowCount(int rows); - QmlDebug::RangeType rangeType() const; - QmlDebug::Message message() const; - - void updateProgress(qint64 count, qint64 max) const; - void announceFeatures(quint64 features) const; - - explicit AbstractTimelineModel(AbstractTimelineModelPrivate *dd, - QmlProfilerModelManager *manager, const QString &displayName, - QmlDebug::Message message, QmlDebug::RangeType rangeType, - QObject *parent); - AbstractTimelineModelPrivate *d_ptr; - - virtual void loadData() = 0; virtual void clear(); + explicit TimelineModel(TimelineModelPrivate &dd, QObject *parent); + TimelineModelPrivate *d_ptr; + private: - Q_DECLARE_PRIVATE(AbstractTimelineModel) - Q_PRIVATE_SLOT(d_func(), void _q_dataChanged()) + Q_DECLARE_PRIVATE(TimelineModel) }; } -#endif // ABSTRACTTIMELINEMODEL_H +#endif // TIMELINEMODEL_H diff --git a/src/plugins/qmlprofiler/abstracttimelinemodel_p.h b/src/plugins/qmlprofiler/timelinemodel_p.h similarity index 82% rename from src/plugins/qmlprofiler/abstracttimelinemodel_p.h rename to src/plugins/qmlprofiler/timelinemodel_p.h index f6ed5868b00..dca047de51f 100644 --- a/src/plugins/qmlprofiler/abstracttimelinemodel_p.h +++ b/src/plugins/qmlprofiler/timelinemodel_p.h @@ -28,14 +28,14 @@ ** ****************************************************************************/ -#ifndef ABSTRACTTIMELINEMODEL_P_H -#define ABSTRACTTIMELINEMODEL_P_H +#ifndef TIMELINEMODEL_P_H +#define TIMELINEMODEL_P_H -#include "abstracttimelinemodel.h" +#include "timelinemodel.h" namespace QmlProfiler { -class QMLPROFILER_EXPORT AbstractTimelineModel::AbstractTimelineModelPrivate { +class QMLPROFILER_EXPORT TimelineModel::TimelineModelPrivate { public: static const int DefaultRowHeight = 30; @@ -67,11 +67,10 @@ public: inline qint64 timestamp() const {return end;} }; - void init(AbstractTimelineModel *q, QmlProfilerModelManager *manager, - const QString &displayName, QmlDebug::Message message, QmlDebug::RangeType rangeType); + TimelineModelPrivate(int modelId, const QString &displayName); + void init(TimelineModel *q); - inline qint64 lastEndTime() const { return endTimes.last().end; } - inline qint64 firstStartTime() const { return ranges.first().start; } + int firstIndexNoParents(qint64 startTime) const; void incrementStartIndices(int index) { @@ -112,28 +111,24 @@ public: return fromIndex; } - void _q_dataChanged(); - QVector<Range> ranges; QVector<RangeEnd> endTimes; QVector<int> rowOffsets; - QmlProfilerModelManager *modelManager; - int modelId; + const int modelId; + const QString displayName; + bool expanded; bool hidden; int expandedRowCount; int collapsedRowCount; - QString displayName; - QmlDebug::Message message; - QmlDebug::RangeType rangeType; protected: - AbstractTimelineModel *q_ptr; + TimelineModel *q_ptr; private: - Q_DECLARE_PUBLIC(AbstractTimelineModel) + Q_DECLARE_PUBLIC(TimelineModel) }; } -#endif // ABSTRACTTIMELINEMODEL_P_H +#endif // TIMELINEMODEL_P_H diff --git a/src/plugins/qmlprofiler/timelinemodelaggregator.cpp b/src/plugins/qmlprofiler/timelinemodelaggregator.cpp index ca8e9dababd..92285084aa6 100644 --- a/src/plugins/qmlprofiler/timelinemodelaggregator.cpp +++ b/src/plugins/qmlprofiler/timelinemodelaggregator.cpp @@ -52,7 +52,7 @@ public: // mapping of modelId assigned by manager to index in our list QList <int> modelManagerIndexMapping; - QList <AbstractTimelineModel *> modelList; + QList <QmlProfilerTimelineModel *> modelList; QmlProfilerModelManager *modelManager; }; @@ -80,7 +80,7 @@ void TimelineModelAggregator::setModelManager(QmlProfilerModelManager *modelMana connect(modelManager,SIGNAL(dataAvailable()),this,SIGNAL(dataAvailable())); // external models pushed on top - foreach (AbstractTimelineModel *timelineModel, + foreach (QmlProfilerTimelineModel *timelineModel, QmlProfilerPlugin::instance->getModels(modelManager)) { addModel(timelineModel); } @@ -96,7 +96,7 @@ void TimelineModelAggregator::setModelManager(QmlProfilerModelManager *modelMana this, SIGNAL(notesChanged(int,int,int))); } -void TimelineModelAggregator::addModel(AbstractTimelineModel *m) +void TimelineModelAggregator::addModel(QmlProfilerTimelineModel *m) { while (d->modelManagerIndexMapping.size() <= m->modelId()) d->modelManagerIndexMapping.append(-1); @@ -110,7 +110,7 @@ void TimelineModelAggregator::addModel(AbstractTimelineModel *m) emit modelsChanged(d->modelList.length(), d->modelList.length()); } -const AbstractTimelineModel *TimelineModelAggregator::model(int modelIndex) const +const QmlProfilerTimelineModel *TimelineModelAggregator::model(int modelIndex) const { return d->modelList[modelIndex]; } @@ -118,7 +118,7 @@ const AbstractTimelineModel *TimelineModelAggregator::model(int modelIndex) cons QVariantList TimelineModelAggregator::models() const { QVariantList ret; - foreach (AbstractTimelineModel *model, d->modelList) + foreach (QmlProfilerTimelineModel *model, d->modelList) ret << QVariant::fromValue(model); return ret; } @@ -140,7 +140,7 @@ int TimelineModelAggregator::count(int modelIndex) const bool TimelineModelAggregator::isEmpty() const { - foreach (const AbstractTimelineModel *modelProxy, d->modelList) + foreach (const QmlProfilerTimelineModel *modelProxy, d->modelList) if (!modelProxy->isEmpty()) return false; return true; @@ -297,8 +297,8 @@ int TimelineModelAggregator::selectionIdForLocation(int modelIndex, const QStrin void TimelineModelAggregator::swapModels(int modelIndex1, int modelIndex2) { - AbstractTimelineModel *&model1 = d->modelList[modelIndex1]; - AbstractTimelineModel *&model2 = d->modelList[modelIndex2]; + QmlProfilerTimelineModel *&model1 = d->modelList[modelIndex1]; + QmlProfilerTimelineModel *&model2 = d->modelList[modelIndex2]; std::swap(d->modelManagerIndexMapping[model1->modelId()], d->modelManagerIndexMapping[model2->modelId()]); std::swap(model1, model2); diff --git a/src/plugins/qmlprofiler/timelinemodelaggregator.h b/src/plugins/qmlprofiler/timelinemodelaggregator.h index 59a65a51935..6d594326104 100644 --- a/src/plugins/qmlprofiler/timelinemodelaggregator.h +++ b/src/plugins/qmlprofiler/timelinemodelaggregator.h @@ -31,7 +31,7 @@ #ifndef TIMELINEMODELAGGREGATOR_H #define TIMELINEMODELAGGREGATOR_H -#include "abstracttimelinemodel.h" +#include "qmlprofilertimelinemodel.h" #include "qmlprofilermodelmanager.h" namespace QmlProfiler { @@ -49,8 +49,8 @@ public: int height() const; void setModelManager(QmlProfilerModelManager *modelManager); - void addModel(AbstractTimelineModel *m); - const AbstractTimelineModel *model(int modelIndex) const; + void addModel(QmlProfilerTimelineModel *m); + const QmlProfilerTimelineModel *model(int modelIndex) const; QVariantList models() const; int modelIndexFromManagerIndex(int modelManagerIndex) const; diff --git a/tests/auto/qmlprofiler/qmlprofiler.pro b/tests/auto/qmlprofiler/qmlprofiler.pro index d14321e62e6..dcc36f1a6c3 100644 --- a/tests/auto/qmlprofiler/qmlprofiler.pro +++ b/tests/auto/qmlprofiler/qmlprofiler.pro @@ -1,4 +1,4 @@ TEMPLATE = subdirs SUBDIRS = \ - abstracttimelinemodel + timelinemodel diff --git a/tests/auto/qmlprofiler/abstracttimelinemodel/abstracttimelinemodel.pro b/tests/auto/qmlprofiler/timelinemodel/timelinemodel.pro similarity index 68% rename from tests/auto/qmlprofiler/abstracttimelinemodel/abstracttimelinemodel.pro rename to tests/auto/qmlprofiler/timelinemodel/timelinemodel.pro index 3f8de291616..c08a649f5e0 100644 --- a/tests/auto/qmlprofiler/abstracttimelinemodel/abstracttimelinemodel.pro +++ b/tests/auto/qmlprofiler/timelinemodel/timelinemodel.pro @@ -2,4 +2,4 @@ QTC_PLUGIN_DEPENDS += qmlprofiler include(../../qttest.pri) SOURCES += \ - tst_abstracttimelinemodel.cpp + tst_timelinemodel.cpp diff --git a/tests/auto/qmlprofiler/abstracttimelinemodel/tst_abstracttimelinemodel.cpp b/tests/auto/qmlprofiler/timelinemodel/tst_timelinemodel.cpp similarity index 78% rename from tests/auto/qmlprofiler/abstracttimelinemodel/tst_abstracttimelinemodel.cpp rename to tests/auto/qmlprofiler/timelinemodel/tst_timelinemodel.cpp index 3688c67edb5..90b73fbc135 100644 --- a/tests/auto/qmlprofiler/abstracttimelinemodel/tst_abstracttimelinemodel.cpp +++ b/tests/auto/qmlprofiler/timelinemodel/tst_timelinemodel.cpp @@ -29,8 +29,7 @@ ****************************************************************************/ #include <QtTest> -#include <qmlprofiler/abstracttimelinemodel.h> -#include <qmlprofiler/abstracttimelinemodel_p.h> +#include <qmlprofiler/timelinemodel.h> using namespace QmlProfiler; @@ -40,24 +39,24 @@ static const qint64 ItemDuration = 1 << 19; static const qint64 ItemSpacing = 1 << 20; class DummyModelPrivate; -class DummyModel : public AbstractTimelineModel +class DummyModel : public TimelineModel { Q_OBJECT - Q_DECLARE_PRIVATE(DummyModel) - friend class tst_AbstractTimelineModel; + friend class tst_TimelineModel; public: DummyModel(QString displayName = tr("dummy"), QObject *parent = 0); - int selectionId(int index) const { return index; } + int typeId(int index) const { return index; } QColor color(int) const { return QColor(); } QVariantList labels() const { return QVariantList(); } QVariantMap details(int) const { return QVariantMap(); } int row(int) const { return 1; } + quint64 features() const { return 0; } protected: void loadData(); }; -class tst_AbstractTimelineModel : public QObject +class tst_TimelineModel : public QObject { Q_OBJECT @@ -66,7 +65,6 @@ private slots: void rowHeight(); void rowOffset(); void height(); - void accepted(); void expand(); void hide(); void displayName(); @@ -77,20 +75,19 @@ private slots: }; DummyModel::DummyModel(QString displayName, QObject *parent) : - AbstractTimelineModel(new QmlProfilerModelManager(0, parent), displayName, - QmlDebug::MaximumMessage, QmlDebug::MaximumRangeType, parent) + TimelineModel(0, displayName, parent) { } void DummyModel::loadData() { for (int i = 0; i < NumItems; ++i) - insert(i * ItemSpacing, ItemDuration, 0); + insert(i * ItemSpacing, ItemDuration, 5); setCollapsedRowCount(2); setExpandedRowCount(2); } -void tst_AbstractTimelineModel::isEmpty() +void tst_TimelineModel::isEmpty() { DummyModel dummy; QVERIFY(dummy.isEmpty()); @@ -100,7 +97,7 @@ void tst_AbstractTimelineModel::isEmpty() QVERIFY(dummy.isEmpty()); } -void tst_AbstractTimelineModel::rowHeight() +void tst_TimelineModel::rowHeight() { DummyModel dummy; QCOMPARE(dummy.rowHeight(0), DefaultRowHeight); @@ -135,7 +132,7 @@ void tst_AbstractTimelineModel::rowHeight() QCOMPARE(dummy.rowHeight(1), 50); } -void tst_AbstractTimelineModel::rowOffset() +void tst_TimelineModel::rowOffset() { DummyModel dummy; QCOMPARE(dummy.rowOffset(0), 0); @@ -164,10 +161,10 @@ void tst_AbstractTimelineModel::rowOffset() QCOMPARE(dummy.rowOffset(1), 100); } -void tst_AbstractTimelineModel::height() +void tst_TimelineModel::height() { DummyModel dummy; - QCOMPARE(dummy.height(), DefaultRowHeight); + QCOMPARE(dummy.height(), 0); dummy.loadData(); QCOMPARE(dummy.height(), 2 * DefaultRowHeight); dummy.setExpanded(true); @@ -176,22 +173,7 @@ void tst_AbstractTimelineModel::height() QCOMPARE(dummy.height(), DefaultRowHeight + 80); } -void tst_AbstractTimelineModel::accepted() -{ - DummyModel dummy; - QmlProfilerDataModel::QmlEventTypeData event; - event.message = QmlDebug::MaximumMessage; - event.rangeType = QmlDebug::MaximumRangeType; - QVERIFY(dummy.accepted(event)); - event.message = QmlDebug::Event; - QVERIFY(!dummy.accepted(event)); - event.rangeType = QmlDebug::Painting; - QVERIFY(!dummy.accepted(event)); - event.message = QmlDebug::MaximumMessage; - QVERIFY(!dummy.accepted(event)); -} - -void tst_AbstractTimelineModel::expand() +void tst_TimelineModel::expand() { DummyModel dummy; QSignalSpy spy(&dummy, SIGNAL(expandedChanged())); @@ -210,7 +192,7 @@ void tst_AbstractTimelineModel::expand() QCOMPARE(spy.count(), 2); } -void tst_AbstractTimelineModel::hide() +void tst_TimelineModel::hide() { DummyModel dummy; QSignalSpy spy(&dummy, SIGNAL(hiddenChanged())); @@ -229,45 +211,45 @@ void tst_AbstractTimelineModel::hide() QCOMPARE(spy.count(), 2); } -void tst_AbstractTimelineModel::displayName() +void tst_TimelineModel::displayName() { QLatin1String name("testest"); DummyModel dummy(name); QCOMPARE(dummy.displayName(), name); } -void tst_AbstractTimelineModel::defaultValues() +void tst_TimelineModel::defaultValues() { DummyModel dummy; dummy.loadData(); QCOMPARE(dummy.location(0), QVariantMap()); + QCOMPARE(dummy.handlesTypeId(0), false); QCOMPARE(dummy.selectionIdForLocation(QString(), 0, 0), -1); - QCOMPARE(dummy.bindingLoopDest(0), -1); QCOMPARE(dummy.relativeHeight(0), 1.0); QCOMPARE(dummy.rowMinValue(0), 0); QCOMPARE(dummy.rowMaxValue(0), 0); } -void tst_AbstractTimelineModel::colorByHue() +void tst_TimelineModel::colorByHue() { DummyModel dummy; QCOMPARE(dummy.colorByHue(10), QColor::fromHsl(10, 150, 166)); QCOMPARE(dummy.colorByHue(500), QColor::fromHsl(140, 150, 166)); } -void tst_AbstractTimelineModel::colorBySelectionId() +void tst_TimelineModel::colorBySelectionId() { DummyModel dummy; dummy.loadData(); - QCOMPARE(dummy.colorBySelectionId(5), QColor::fromHsl(0, 150, 166)); + QCOMPARE(dummy.colorBySelectionId(5), QColor::fromHsl(5 * 25, 150, 166)); } -void tst_AbstractTimelineModel::colorByFraction() +void tst_TimelineModel::colorByFraction() { DummyModel dummy; QCOMPARE(dummy.colorByFraction(0.5), QColor::fromHsl(0.5 * 96 + 10, 150, 166)); } -QTEST_MAIN(tst_AbstractTimelineModel) +QTEST_MAIN(tst_TimelineModel) -#include "tst_abstracttimelinemodel.moc" +#include "tst_timelinemodel.moc" -- GitLab