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 &current = 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 &current = 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