diff --git a/src/libs/qmljsdebugclient/qmljsdebugclient-lib.pri b/src/libs/qmljsdebugclient/qmljsdebugclient-lib.pri
index f15d920bf902f847f9d288a3eac7566601b367cf..69b0606451a1510fa77247982630f2c6c4e1a0be 100644
--- a/src/libs/qmljsdebugclient/qmljsdebugclient-lib.pri
+++ b/src/libs/qmljsdebugclient/qmljsdebugclient-lib.pri
@@ -7,11 +7,11 @@ contains(CONFIG, dll) {
 INCLUDEPATH += $$PWD/..
 
 HEADERS += \
+    $$PWD/qmlprofilereventlocation.h \
     $$PWD/qdeclarativedebugclient.h \
     $$PWD/qdeclarativeenginedebug.h \
     $$PWD/qdeclarativeoutputparser.h \
     $$PWD/qmljsdebugclient_global.h \
-    $$PWD/qmlprofilereventlist.h \
     $$PWD/qmlprofilereventtypes.h \
     $$PWD/qmlprofilertraceclient.h \
     $$PWD/qpacketprotocol.h \
@@ -23,7 +23,6 @@ SOURCES += \
     $$PWD/qdeclarativedebugclient.cpp \
     $$PWD/qdeclarativeenginedebug.cpp \
     $$PWD/qdeclarativeoutputparser.cpp \
-    $$PWD/qmlprofilereventlist.cpp \
     $$PWD/qmlprofilertraceclient.cpp \
     $$PWD/qpacketprotocol.cpp \
     $$PWD/qv8profilerclient.cpp \
diff --git a/src/libs/qmljsdebugclient/qmljsdebugclient.pro b/src/libs/qmljsdebugclient/qmljsdebugclient.pro
index c1462ecd5e7047cf68339d65dce6cd3c45e3fba9..893ef89d4841dfd9ff7a5c7bfdf4108a73dc035a 100644
--- a/src/libs/qmljsdebugclient/qmljsdebugclient.pro
+++ b/src/libs/qmljsdebugclient/qmljsdebugclient.pro
@@ -11,6 +11,3 @@ OTHER_FILES += \
     qmljsdebugclient.pri \
     qmljsdebugclient-lib.pri
 
-HEADERS += \
-    qmlprofilereventlocation.h
-
diff --git a/src/libs/qmljsdebugclient/qmljsdebugclient.qbs b/src/libs/qmljsdebugclient/qmljsdebugclient.qbs
index a975195e444398dcbc58b82fd3c0caf9633f364c..8cb51a197f737b50413874e08e1fd2a4c2c445dc 100644
--- a/src/libs/qmljsdebugclient/qmljsdebugclient.qbs
+++ b/src/libs/qmljsdebugclient/qmljsdebugclient.qbs
@@ -24,7 +24,7 @@ DynamicLibrary {
         "qdeclarativeoutputparser.h",
         "qmljsdebugclient_global.h",
         "qmljsdebugclientconstants.h",
-        "qmlprofilereventlist.h",
+        "qmlprofilereventlocation.h",
         "qmlprofilertraceclient.cpp",
         "qpacketprotocol.cpp",
         "qv8profilerclient.cpp",
@@ -36,7 +36,6 @@ DynamicLibrary {
         "qmlprofilertraceclient.h",
         "qpacketprotocol.h",
         "qdebugmessageclient.cpp",
-        "qmlprofilereventlist.cpp",
         "qdebugmessageclient.h"
     ]
 
diff --git a/src/libs/qmljsdebugclient/qmlprofilereventlist.cpp b/src/libs/qmljsdebugclient/qmlprofilereventlist.cpp
deleted file mode 100644
index 3576b94645fb8bec3febffd82ed1d8f2a74c2ee7..0000000000000000000000000000000000000000
--- a/src/libs/qmljsdebugclient/qmlprofilereventlist.cpp
+++ /dev/null
@@ -1,1881 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-**
-** GNU Lesser General Public License Usage
-**
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this file.
-** Please review the following information to ensure the GNU Lesser General
-** Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**************************************************************************/
-
-#include "qmlprofilereventlist.h"
-
-#include <QUrl>
-#include <QHash>
-#include <QtAlgorithms>
-#include <QString>
-#include <QStringList>
-
-#include <QFile>
-#include <QXmlStreamReader>
-#include <QXmlStreamWriter>
-
-#include <QTimer>
-#include <utils/qtcassert.h>
-
-#include <QDebug>
-
-namespace QmlJsDebugClient {
-
-namespace Constants {
-const char *const TYPE_PAINTING_STR = "Painting";
-const char *const TYPE_COMPILING_STR = "Compiling";
-const char *const TYPE_CREATING_STR = "Creating";
-const char *const TYPE_BINDING_STR = "Binding";
-const char *const TYPE_HANDLINGSIGNAL_STR = "HandlingSignal";
-const char *const PROFILER_FILE_VERSION = "1.02";
-}
-
-#define MIN_LEVEL 1
-
-QmlEventData::QmlEventData()
-{
-    eventType = MaximumQmlEventType;
-    eventId = -1;
-    duration = 0;
-    calls = 0;
-    minTime = 0;
-    maxTime = 0;
-    timePerCall = 0;
-    percentOfTime = 0;
-    medianTime = 0;
-    isBindingLoop = false;
-}
-
-QmlEventData::~QmlEventData()
-{
-    qDeleteAll(parentHash.values());
-    parentHash.clear();
-    qDeleteAll(childrenHash.values());
-    childrenHash.clear();
-}
-
-QmlEventData &QmlEventData::operator=(const QmlEventData &ref)
-{
-    if (this == &ref)
-        return *this;
-
-    displayname = ref.displayname;
-    location = ref.location;
-    eventHashStr = ref.eventHashStr;
-    details = ref.details;
-    eventType = ref.eventType;
-    duration = ref.duration;
-    calls = ref.calls;
-    minTime = ref.minTime;
-    maxTime = ref.maxTime;
-    timePerCall = ref.timePerCall;
-    percentOfTime = ref.percentOfTime;
-    medianTime = ref.medianTime;
-    eventId = ref.eventId;
-    isBindingLoop = ref.isBindingLoop;
-
-    qDeleteAll(parentHash.values());
-    parentHash.clear();
-    foreach (const QString &key, ref.parentHash.keys()) {
-        parentHash.insert(key, new QmlEventSub(ref.parentHash.value(key)));
-    }
-
-    qDeleteAll(childrenHash.values());
-    childrenHash.clear();
-    foreach (const QString &key, ref.childrenHash.keys()) {
-        childrenHash.insert(key, new QmlEventSub(ref.childrenHash.value(key)));
-    }
-
-    return *this;
-}
-
-QV8EventData::QV8EventData()
-{
-    line = -1;
-    eventId = -1;
-    totalTime = 0;
-    selfTime = 0;
-    totalPercent = 0;
-    selfPercent = 0;
-}
-
-QV8EventData::~QV8EventData()
-{
-    qDeleteAll(parentHash.values());
-    parentHash.clear();
-    qDeleteAll(childrenHash.values());
-    childrenHash.clear();
-}
-
-QV8EventData &QV8EventData::operator=(const QV8EventData &ref)
-{
-    if (this == &ref)
-        return *this;
-
-    displayName = ref.displayName;
-    filename = ref.filename;
-    functionName = ref.functionName;
-    line = ref.line;
-    totalTime = ref.totalTime;
-    totalPercent = ref.totalPercent;
-    selfTime = ref.selfTime;
-    selfPercent = ref.selfPercent;
-    eventId = ref.eventId;
-
-    qDeleteAll(parentHash.values());
-    parentHash.clear();
-    foreach (const QString &key, ref.parentHash.keys()) {
-        parentHash.insert(key, new QV8EventSub(ref.parentHash.value(key)));
-    }
-
-    qDeleteAll(childrenHash.values());
-    childrenHash.clear();
-    foreach (const QString &key, ref.childrenHash.keys()) {
-        childrenHash.insert(key, new QV8EventSub(ref.childrenHash.value(key)));
-    }
-    return *this;
-}
-
-// endtimedata
-struct QmlEventEndTimeData {
-    qint64 endTime;
-    int startTimeIndex;
-    QmlEventData *description;
-};
-
-// starttimedata
-struct QmlEventStartTimeData {
-    qint64 startTime;
-    qint64 length;
-    qint64 level;
-    int endTimeIndex;
-    qint64 nestingLevel;
-    qint64 nestingDepth;
-    QmlEventData *description;
-
-    // animation-related data
-    int frameRate;
-    int animationCount;
-
-    int bindingLoopHead;
-};
-
-struct QmlEventTypeCount {
-    QList <int> eventIds;
-    int nestingCount;
-};
-
-// used by quicksort
-bool compareEndTimes(const QmlEventEndTimeData &t1, const QmlEventEndTimeData &t2)
-{
-    return t1.endTime < t2.endTime;
-}
-
-bool compareStartTimes(const QmlEventStartTimeData &t1, const QmlEventStartTimeData &t2)
-{
-    return t1.startTime < t2.startTime;
-}
-
-bool compareStartIndexes(const QmlEventEndTimeData &t1, const QmlEventEndTimeData &t2)
-{
-    return t1.startTimeIndex < t2.startTimeIndex;
-}
-
-QString qmlEventType(QmlEventType typeEnum)
-{
-    switch (typeEnum) {
-    case Painting:
-        return QLatin1String(Constants::TYPE_PAINTING_STR);
-        break;
-    case Compiling:
-        return QLatin1String(Constants::TYPE_COMPILING_STR);
-        break;
-    case Creating:
-        return QLatin1String(Constants::TYPE_CREATING_STR);
-        break;
-    case Binding:
-        return QLatin1String(Constants::TYPE_BINDING_STR);
-        break;
-    case HandlingSignal:
-        return QLatin1String(Constants::TYPE_HANDLINGSIGNAL_STR);
-        break;
-    default:
-        return QString::number((int)typeEnum);
-    }
-}
-
-QmlEventType qmlEventType(const QString &typeString)
-{
-    if (typeString == QLatin1String(Constants::TYPE_PAINTING_STR)) {
-        return Painting;
-    } else if (typeString == QLatin1String(Constants::TYPE_COMPILING_STR)) {
-        return Compiling;
-    } else if (typeString == QLatin1String(Constants::TYPE_CREATING_STR)) {
-        return Creating;
-    } else if (typeString == QLatin1String(Constants::TYPE_BINDING_STR)) {
-        return Binding;
-    } else if (typeString == QLatin1String(Constants::TYPE_HANDLINGSIGNAL_STR)) {
-        return HandlingSignal;
-    } else {
-        bool isNumber = false;
-        int type = typeString.toUInt(&isNumber);
-        if (isNumber) {
-            return (QmlEventType)type;
-        } else {
-            return MaximumQmlEventType;
-        }
-    }
-}
-
-QString getHashStringForQmlEvent(QmlEventLocation location, int eventType)
-{
-    return QString("%1:%2:%3:%4").arg(location.filename, QString::number(location.line), QString::number(location.column), QString::number(eventType));
-}
-
-class QmlProfilerEventList::QmlProfilerEventListPrivate
-{
-public:
-    QmlProfilerEventListPrivate(QmlProfilerEventList *qq) : q(qq) {}
-
-    QmlProfilerEventList *q;
-
-    QmlProfilerEventList::State m_state;
-
-    // convenience functions
-    void clearQmlRootEvent();
-    void clearV8RootEvent();
-
-    // Stored data
-    QmlEventHash m_eventDescriptions;
-    QList<QmlEventEndTimeData> m_endTimeSortedList;
-    QList<QmlEventStartTimeData> m_startTimeSortedList;
-
-    void collectV8Statistics();
-    QV8EventDescriptions m_v8EventList;
-    QHash<int, QV8EventData *> m_v8parents;
-
-    QmlEventData m_qmlRootEvent;
-    QV8EventData m_v8RootEvent;
-    QString m_rootEventName;
-    QString m_rootEventDesc;
-
-    QHash<int, QmlEventTypeCount *> m_typeCounts;
-
-    qint64 m_traceEndTime;
-    qint64 m_traceStartTime;
-    qint64 m_qmlMeasuredTime;
-    qint64 m_v8MeasuredTime;
-
-    QmlEventStartTimeData *m_lastFrameEvent;
-    qint64 m_maximumAnimationCount;
-    qint64 m_minimumAnimationCount;
-
-    // file to load
-    QString m_filename;
-};
-
-
-////////////////////////////////////////////////////////////////////////////////////
-
-
-QmlProfilerEventList::QmlProfilerEventList(QObject *parent) :
-    QObject(parent), d(new QmlProfilerEventListPrivate(this))
-{
-    setObjectName("QmlProfilerEventStatistics");
-
-    d->m_state = Empty;
-
-    d->m_traceEndTime = 0;
-    d->m_traceStartTime = -1;
-    d->m_qmlMeasuredTime = 0;
-    d->m_v8MeasuredTime = 0;
-    d->m_rootEventName = tr("<program>");
-    d->m_rootEventDesc = tr("Main Program");
-    d->clearQmlRootEvent();
-    d->clearV8RootEvent();
-    d->m_lastFrameEvent = 0;
-    d->m_maximumAnimationCount = 0;
-    d->m_minimumAnimationCount = 0;
-}
-
-QmlProfilerEventList::~QmlProfilerEventList()
-{
-    clear();
-}
-
-void QmlProfilerEventList::clear()
-{
-    qDeleteAll(d->m_eventDescriptions.values());
-    d->m_eventDescriptions.clear();
-
-    qDeleteAll(d->m_v8EventList);
-    d->m_v8EventList.clear();
-
-    d->m_endTimeSortedList.clear();
-    d->m_startTimeSortedList.clear();
-
-    d->m_v8parents.clear();
-
-    d->clearQmlRootEvent();
-    d->clearV8RootEvent();
-
-    foreach (QmlEventTypeCount *typeCount, d->m_typeCounts.values())
-        delete typeCount;
-    d->m_typeCounts.clear();
-
-    d->m_traceEndTime = 0;
-    d->m_traceStartTime = -1;
-    d->m_qmlMeasuredTime = 0;
-    d->m_v8MeasuredTime = 0;
-
-    d->m_lastFrameEvent = 0;
-    d->m_maximumAnimationCount = 0;
-    d->m_minimumAnimationCount = 0;
-
-    emit countChanged();
-    setState(Empty);
-}
-
-QList <QmlEventData *> QmlProfilerEventList::getEventDescriptions() const
-{
-    return d->m_eventDescriptions.values();
-}
-
-QmlEventData *QmlProfilerEventList::eventDescription(int eventId) const
-{
-    foreach (QmlEventData *event, d->m_eventDescriptions.values()) {
-        if (event->eventId == eventId)
-            return event;
-    }
-    return 0;
-}
-
-QV8EventData *QmlProfilerEventList::v8EventDescription(int eventId) const
-{
-    foreach (QV8EventData *event, d->m_v8EventList) {
-        if (event->eventId == eventId)
-            return event;
-    }
-    return 0;
-}
-
-const QV8EventDescriptions& QmlProfilerEventList::getV8Events() const
-{
-    return d->m_v8EventList;
-}
-
-void QmlProfilerEventList::addRangedEvent(int type, qint64 startTime, qint64 length,
-                                          const QStringList &data, const QmlJsDebugClient::QmlEventLocation &location)
-{
-    const QChar colon = QLatin1Char(':');
-    QString displayName, eventHashStr, details;
-    QmlJsDebugClient::QmlEventLocation eventLocation = location;
-
-    setState(AcquiringData);
-
-    // generate details string
-    if (data.isEmpty())
-        details = tr("Source code not available");
-    else {
-        details = data.join(" ").replace('\n'," ").simplified();
-        QRegExp rewrite("\\(function \\$(\\w+)\\(\\) \\{ (return |)(.+) \\}\\)");
-        bool match = rewrite.exactMatch(details);
-        if (match) {
-            details = rewrite.cap(1) + ": " + rewrite.cap(3);
-        }
-        if (details.startsWith(QString("file://")))
-            details = details.mid(details.lastIndexOf(QChar('/')) + 1);
-    }
-
-    // backwards compatibility: "compiling" events don't have a proper location in older
-    // version of the protocol, but the filename is passed in the details string
-    if (type == QmlJsDebugClient::Compiling && eventLocation.filename.isEmpty()) {
-        eventLocation.filename = details;
-        eventLocation.line = 1;
-        eventLocation.column = 1;
-    }
-
-    // generate hash
-    if (eventLocation.filename.isEmpty()) {
-        displayName = tr("<bytecode>");
-        eventHashStr = getHashStringForQmlEvent(eventLocation, type);
-    } else {
-        const QString filePath = QUrl(eventLocation.filename).path();
-        displayName = filePath.mid(filePath.lastIndexOf(QChar('/')) + 1) + colon + QString::number(eventLocation.line);
-        eventHashStr = getHashStringForQmlEvent(eventLocation, type);
-    }
-
-    QmlEventData *newEvent;
-    if (d->m_eventDescriptions.contains(eventHashStr)) {
-        newEvent = d->m_eventDescriptions[eventHashStr];
-    } else {
-        newEvent = new QmlEventData;
-        newEvent->displayname = displayName;
-        newEvent->location = eventLocation;
-        newEvent->eventHashStr = eventHashStr;
-        newEvent->eventType = (QmlJsDebugClient::QmlEventType)type;
-        newEvent->details = details;
-        d->m_eventDescriptions.insert(eventHashStr, newEvent);
-    }
-
-    QmlEventEndTimeData endTimeData;
-    endTimeData.endTime = startTime + length;
-    endTimeData.description = newEvent;
-    endTimeData.startTimeIndex = d->m_startTimeSortedList.count();
-
-    QmlEventStartTimeData startTimeData;
-    startTimeData.startTime = startTime;
-    startTimeData.length = length;
-    startTimeData.description = newEvent;
-    startTimeData.endTimeIndex = d->m_endTimeSortedList.count();
-    startTimeData.animationCount = -1;
-    startTimeData.frameRate = 1e9/length;
-
-    d->m_endTimeSortedList << endTimeData;
-    d->m_startTimeSortedList << startTimeData;
-
-    emit countChanged();
-}
-
-void QmlProfilerEventList::addV8Event(int depth, const QString &function, const QString &filename, int lineNumber, double totalTime, double selfTime)
-{
-    QString displayName = filename.mid(filename.lastIndexOf(QLatin1Char('/')) + 1) + QLatin1Char(':') + QString::number(lineNumber);
-    QV8EventData *eventData = 0;
-
-    setState(AcquiringData);
-
-    // time is given in milliseconds, but internally we store it in microseconds
-    totalTime *= 1e6;
-    selfTime *= 1e6;
-
-    // cumulate information
-    // TODO: use hashes
-    foreach (QV8EventData *v8event, d->m_v8EventList) {
-        if (v8event->displayName == displayName && v8event->functionName == function) {
-            eventData = v8event;
-            break;
-        }
-    }
-
-    if (!eventData) {
-        eventData = new QV8EventData;
-        eventData->displayName = displayName;
-        eventData->filename = filename;
-        eventData->functionName = function;
-        eventData->line = lineNumber;
-        eventData->totalTime = totalTime;
-        eventData->selfTime = selfTime;
-        d->m_v8EventList << eventData;
-    } else {
-        eventData->totalTime += totalTime;
-        eventData->selfTime += selfTime;
-    }
-    d->m_v8parents[depth] = eventData;
-
-    QV8EventData *parentEvent = 0;
-    if (depth == 0) {
-        parentEvent = &d->m_v8RootEvent;
-        d->m_v8MeasuredTime += totalTime;
-    }
-    if (depth > 0 && d->m_v8parents.contains(depth-1)) {
-        parentEvent = d->m_v8parents.value(depth-1);
-    }
-
-    if (parentEvent != 0) {
-        if (!eventData->parentHash.contains(parentEvent->displayName)) {
-            QV8EventSub *newParentSub = new QV8EventSub(parentEvent);
-            newParentSub->totalTime = totalTime;
-
-            eventData->parentHash.insert(parentEvent->displayName, newParentSub );
-        } else {
-            QV8EventSub *newParentSub = eventData->parentHash.value(parentEvent->displayName);
-            newParentSub->totalTime += totalTime;
-        }
-
-        if (!parentEvent->childrenHash.contains(eventData->displayName)) {
-            QV8EventSub *newChildSub = new QV8EventSub(eventData);
-            newChildSub->totalTime = totalTime;
-
-            parentEvent->childrenHash.insert(eventData->displayName, newChildSub);
-        } else {
-            QV8EventSub *newChildSub = parentEvent->childrenHash.value(eventData->displayName);
-            newChildSub->totalTime += totalTime;
-        }
-    }
-}
-
-void QmlProfilerEventList::addFrameEvent(qint64 time, int framerate, int animationcount)
-{
-    QString displayName, eventHashStr, details;
-
-    setState(AcquiringData);
-
-    details = tr("Animation Timer Update");
-    displayName = tr("<Animation Update>");
-    eventHashStr = displayName;
-
-    QmlEventData *newEvent;
-    if (d->m_eventDescriptions.contains(eventHashStr)) {
-        newEvent = d->m_eventDescriptions[eventHashStr];
-    } else {
-        newEvent = new QmlEventData;
-        newEvent->displayname = displayName;
-        newEvent->eventHashStr = eventHashStr;
-        newEvent->eventType = QmlJsDebugClient::Painting;
-        newEvent->details = details;
-        d->m_eventDescriptions.insert(eventHashStr, newEvent);
-    }
-
-    qint64 length = 1e9/framerate;
-    // avoid overlap
-    if (d->m_lastFrameEvent && d->m_lastFrameEvent->startTime + d->m_lastFrameEvent->length >= time) {
-        d->m_lastFrameEvent->length = time - 1 - d->m_lastFrameEvent->startTime;
-        d->m_endTimeSortedList[d->m_lastFrameEvent->endTimeIndex].endTime = d->m_lastFrameEvent->startTime + d->m_lastFrameEvent->length;
-    }
-
-    QmlEventEndTimeData endTimeData;
-    endTimeData.endTime = time + length;
-    endTimeData.description = newEvent;
-    endTimeData.startTimeIndex = d->m_startTimeSortedList.count();
-
-    QmlEventStartTimeData startTimeData;
-    startTimeData.startTime = time;
-    startTimeData.length = length;
-    startTimeData.description = newEvent;
-    startTimeData.endTimeIndex = d->m_endTimeSortedList.count();
-    startTimeData.animationCount = animationcount;
-    startTimeData.frameRate = framerate;
-
-    d->m_endTimeSortedList << endTimeData;
-    d->m_startTimeSortedList << startTimeData;
-
-    d->m_lastFrameEvent = &d->m_startTimeSortedList.last();
-
-    emit countChanged();
-}
-
-void QmlProfilerEventList::QmlProfilerEventListPrivate::collectV8Statistics()
-{
-    if (!m_v8EventList.isEmpty()) {
-        double totalTimes = m_v8MeasuredTime;
-        double selfTimes = 0;
-        foreach (QV8EventData *v8event, m_v8EventList) {
-            selfTimes += v8event->selfTime;
-        }
-
-        // prevent divisions by 0
-        if (totalTimes == 0)
-            totalTimes = 1;
-        if (selfTimes == 0)
-            selfTimes = 1;
-
-        // insert root event in eventlist
-        // the +1 ns is to get it on top of the sorted list
-        m_v8RootEvent.totalTime = m_v8MeasuredTime + 1;
-        m_v8RootEvent.selfTime = 0;
-
-        int rootEventIndex = -1;
-        for (int ndx = 0; ndx < m_v8EventList.count(); ndx++)
-        {
-            if (m_v8EventList.at(ndx)->displayName == m_rootEventName) {
-                m_v8RootEvent = *m_v8EventList.at(ndx);
-                rootEventIndex = ndx;
-                break;
-            }
-        }
-        if (rootEventIndex == -1) {
-            rootEventIndex = m_v8EventList.count();
-            QV8EventData *newRootEvent = new QV8EventData;
-            *newRootEvent = m_v8RootEvent;
-            m_v8EventList << newRootEvent;
-        }
-
-        foreach (QV8EventData *v8event, m_v8EventList) {
-            v8event->totalPercent = v8event->totalTime * 100.0 / totalTimes;
-            v8event->selfPercent = v8event->selfTime * 100.0 / selfTimes;
-        }
-
-        int index = 0;
-        foreach (QV8EventData *v8event, m_v8EventList) {
-            v8event->eventId = index++;
-        }
-        m_v8RootEvent.eventId = m_v8EventList[rootEventIndex]->eventId;
-    }
-}
-
-void QmlProfilerEventList::setTraceEndTime( qint64 time )
-{
-    d->m_traceEndTime = time;
-}
-
-void QmlProfilerEventList::setTraceStartTime( qint64 time )
-{
-    d->m_traceStartTime = time;
-}
-
-void QmlProfilerEventList::complete()
-{
-    setState(ProcessingData);
-    d->collectV8Statistics();
-    postProcess();
-}
-
-void QmlProfilerEventList::QmlProfilerEventListPrivate::clearQmlRootEvent()
-{
-    m_qmlRootEvent.displayname = m_rootEventName;
-    m_qmlRootEvent.location = QmlEventLocation();
-    m_qmlRootEvent.eventHashStr = m_rootEventName;
-    m_qmlRootEvent.details = m_rootEventDesc;
-    m_qmlRootEvent.eventType = QmlJsDebugClient::Binding;
-    m_qmlRootEvent.duration = 0;
-    m_qmlRootEvent.calls = 0;
-    m_qmlRootEvent.minTime = 0;
-    m_qmlRootEvent.maxTime = 0;
-    m_qmlRootEvent.timePerCall = 0;
-    m_qmlRootEvent.percentOfTime = 0;
-    m_qmlRootEvent.medianTime = 0;
-    m_qmlRootEvent.eventId = -1;
-
-    qDeleteAll(m_qmlRootEvent.parentHash.values());
-    qDeleteAll(m_qmlRootEvent.childrenHash.values());
-    m_qmlRootEvent.parentHash.clear();
-    m_qmlRootEvent.childrenHash.clear();
-}
-
-void QmlProfilerEventList::QmlProfilerEventListPrivate::clearV8RootEvent()
-{
-    m_v8RootEvent.displayName = m_rootEventName;
-    m_v8RootEvent.functionName = m_rootEventDesc;
-    m_v8RootEvent.line = -1;
-    m_v8RootEvent.totalTime = 0;
-    m_v8RootEvent.totalPercent = 0;
-    m_v8RootEvent.selfTime = 0;
-    m_v8RootEvent.selfPercent = 0;
-    m_v8RootEvent.eventId = -1;
-
-    qDeleteAll(m_v8RootEvent.parentHash.values());
-    qDeleteAll(m_v8RootEvent.childrenHash.values());
-    m_v8RootEvent.parentHash.clear();
-    m_v8RootEvent.childrenHash.clear();
-}
-
-void QmlProfilerEventList::compileStatistics(qint64 startTime, qint64 endTime)
-{
-    int index;
-    int fromIndex = findFirstIndex(startTime);
-    int toIndex = findLastIndex(endTime);
-    double totalTime = 0;
-
-    // clear existing statistics
-    foreach (QmlEventData *eventDescription, d->m_eventDescriptions.values()) {
-        eventDescription->calls = 0;
-        // maximum possible value
-        eventDescription->minTime = d->m_endTimeSortedList.last().endTime;
-        eventDescription->maxTime = 0;
-        eventDescription->medianTime = 0;
-        eventDescription->duration = 0;
-        qDeleteAll(eventDescription->parentHash);
-        qDeleteAll(eventDescription->childrenHash);
-        eventDescription->parentHash.clear();
-        eventDescription->childrenHash.clear();
-    }
-
-    // create root event for statistics & insert into list
-    d->clearQmlRootEvent();
-    QmlEventData *listedRootEvent = d->m_eventDescriptions.value(d->m_rootEventName);
-    if (!listedRootEvent) {
-        listedRootEvent = new QmlEventData;
-        d->m_eventDescriptions.insert(d->m_rootEventName, listedRootEvent);
-    }
-    *listedRootEvent = d->m_qmlRootEvent;
-
-    // compute parent-child relationship and call count
-    QHash<int, QmlEventData*> lastParent;
-    for (index = fromIndex; index <= toIndex; index++) {
-        QmlEventData *eventDescription = d->m_startTimeSortedList[index].description;
-
-        if (d->m_startTimeSortedList[index].startTime > endTime ||
-                d->m_startTimeSortedList[index].startTime+d->m_startTimeSortedList[index].length < startTime) {
-            continue;
-        }
-
-        if (eventDescription->eventType == QmlJsDebugClient::Painting) {
-            // skip animation/paint events
-            continue;
-        }
-
-        eventDescription->calls++;
-        qint64 duration = d->m_startTimeSortedList[index].length;
-        eventDescription->duration += duration;
-        if (eventDescription->maxTime < duration)
-            eventDescription->maxTime = duration;
-        if (eventDescription->minTime > duration)
-            eventDescription->minTime = duration;
-
-        int level = d->m_startTimeSortedList[index].level;
-
-        QmlEventData *parentEvent = listedRootEvent;
-        if (level > MIN_LEVEL && lastParent.contains(level-1)) {
-            parentEvent = lastParent[level-1];
-        }
-
-        if (!eventDescription->parentHash.contains(parentEvent->eventHashStr)) {
-            QmlEventSub *newParentEvent = new QmlEventSub(parentEvent);
-            newParentEvent->calls = 1;
-            newParentEvent->duration = duration;
-
-            eventDescription->parentHash.insert(parentEvent->eventHashStr, newParentEvent);
-        } else {
-            QmlEventSub *newParentEvent = eventDescription->parentHash.value(parentEvent->eventHashStr);
-            newParentEvent->duration += duration;
-            newParentEvent->calls++;
-        }
-
-        if (!parentEvent->childrenHash.contains(eventDescription->eventHashStr)) {
-            QmlEventSub *newChildEvent = new QmlEventSub(eventDescription);
-            newChildEvent->calls = 1;
-            newChildEvent->duration = duration;
-
-            parentEvent->childrenHash.insert(eventDescription->eventHashStr, newChildEvent);
-        } else {
-            QmlEventSub *newChildEvent = parentEvent->childrenHash.value(eventDescription->eventHashStr);
-            newChildEvent->duration += duration;
-            newChildEvent->calls++;
-        }
-
-        lastParent[level] = eventDescription;
-
-        if (level == MIN_LEVEL) {
-            totalTime += duration;
-        }
-    }
-
-    // fake rootEvent statistics
-    // the +1 nanosecond is to force it to be on top of the sorted list
-    listedRootEvent->duration = totalTime+1;
-    listedRootEvent->minTime = totalTime+1;
-    listedRootEvent->maxTime = totalTime+1;
-    listedRootEvent->medianTime = totalTime+1;
-    if (totalTime > 0)
-        listedRootEvent->calls = 1;
-
-    // copy to the global root reference
-    d->m_qmlRootEvent = *listedRootEvent;
-
-    // compute percentages
-    foreach (QmlEventData *binding, d->m_eventDescriptions.values()) {
-        binding->percentOfTime = binding->duration * 100.0 / totalTime;
-        binding->timePerCall = binding->calls > 0 ? double(binding->duration) / binding->calls : 0;
-    }
-
-    // compute median time
-    QHash < QmlEventData* , QList<qint64> > durationLists;
-    for (index = fromIndex; index <= toIndex; index++) {
-        QmlEventData *desc = d->m_startTimeSortedList[index].description;
-        qint64 len = d->m_startTimeSortedList[index].length;
-        durationLists[desc].append(len);
-    }
-    QMutableHashIterator < QmlEventData* , QList<qint64> > iter(durationLists);
-    while (iter.hasNext()) {
-        iter.next();
-        if (!iter.value().isEmpty()) {
-            qSort(iter.value());
-            iter.key()->medianTime = iter.value().at(iter.value().count()/2);
-        }
-    }
-
-    // find binding loops
-    findBindingLoops(startTime, endTime);
-}
-
-void QmlProfilerEventList::prepareForDisplay()
-{
-    // generate numeric ids
-    int ndx = 0;
-    foreach (QmlEventData *binding, d->m_eventDescriptions.values()) {
-        binding->eventId = ndx++;
-    }
-
-    // collect type counts
-    foreach (const QmlEventStartTimeData &eventStartData, d->m_startTimeSortedList) {
-        int typeNumber = eventStartData.description->eventType;
-        if (!d->m_typeCounts.contains(typeNumber)) {
-            d->m_typeCounts[typeNumber] = new QmlEventTypeCount;
-            d->m_typeCounts[typeNumber]->nestingCount = 0;
-        }
-        if (eventStartData.nestingLevel > d->m_typeCounts[typeNumber]->nestingCount) {
-            d->m_typeCounts[typeNumber]->nestingCount = eventStartData.nestingLevel;
-        }
-        if (!d->m_typeCounts[typeNumber]->eventIds.contains(eventStartData.description->eventId))
-            d->m_typeCounts[typeNumber]->eventIds << eventStartData.description->eventId;
-    }
-}
-
-void QmlProfilerEventList::sortStartTimes()
-{
-    if (d->m_startTimeSortedList.count() < 2)
-        return;
-
-    // assuming startTimes is partially sorted
-    // identify blocks of events and sort them with quicksort
-    QList<QmlEventStartTimeData>::iterator itFrom = d->m_startTimeSortedList.end() - 2;
-    QList<QmlEventStartTimeData>::iterator itTo = d->m_startTimeSortedList.end() - 1;
-
-    while (itFrom != d->m_startTimeSortedList.begin() && itTo != d->m_startTimeSortedList.begin()) {
-        // find block to sort
-        while ( itFrom != d->m_startTimeSortedList.begin()
-                && itTo->startTime > itFrom->startTime ) {
-            itTo--;
-            itFrom = itTo - 1;
-        }
-
-        // if we're at the end of the list
-        if (itFrom == d->m_startTimeSortedList.begin())
-            break;
-
-        // find block length
-        while ( itFrom != d->m_startTimeSortedList.begin()
-                && itTo->startTime <= itFrom->startTime )
-            itFrom--;
-
-        if (itTo->startTime <= itFrom->startTime)
-            qSort(itFrom, itTo + 1, compareStartTimes);
-        else
-            qSort(itFrom + 1, itTo + 1, compareStartTimes);
-
-        // move to next block
-        itTo = itFrom;
-        itFrom = itTo - 1;
-    }
-
-    // link back the endTimes
-    for (int i = 0; i < d->m_startTimeSortedList.length(); i++)
-        d->m_endTimeSortedList[d->m_startTimeSortedList[i].endTimeIndex].startTimeIndex = i;
-}
-
-void QmlProfilerEventList::sortEndTimes()
-{
-    // assuming endTimes is partially sorted
-    // identify blocks of events and sort them with quicksort
-
-    if (d->m_endTimeSortedList.count() < 2)
-        return;
-
-    QList<QmlEventEndTimeData>::iterator itFrom = d->m_endTimeSortedList.begin();
-    QList<QmlEventEndTimeData>::iterator itTo = d->m_endTimeSortedList.begin() + 1;
-
-    while (itTo != d->m_endTimeSortedList.end() && itFrom != d->m_endTimeSortedList.end()) {
-        // find block to sort
-        while ( itTo != d->m_endTimeSortedList.end()
-                && d->m_startTimeSortedList[itTo->startTimeIndex].startTime >
-                d->m_startTimeSortedList[itFrom->startTimeIndex].startTime +
-                d->m_startTimeSortedList[itFrom->startTimeIndex].length ) {
-            itFrom++;
-            itTo = itFrom+1;
-        }
-
-        // if we're at the end of the list
-        if (itTo == d->m_endTimeSortedList.end())
-            break;
-
-        // find block length
-        while ( itTo != d->m_endTimeSortedList.end()
-                && d->m_startTimeSortedList[itTo->startTimeIndex].startTime <=
-                d->m_startTimeSortedList[itFrom->startTimeIndex].startTime +
-                d->m_startTimeSortedList[itFrom->startTimeIndex].length )
-            itTo++;
-
-        // sort block
-        qSort(itFrom, itTo, compareEndTimes);
-
-        // move to next block
-        itFrom = itTo;
-        itTo = itFrom+1;
-
-    }
-
-    // link back the startTimes
-    for (int i = 0; i < d->m_endTimeSortedList.length(); i++)
-        d->m_startTimeSortedList[d->m_endTimeSortedList[i].startTimeIndex].endTimeIndex = i;
-}
-
-void QmlProfilerEventList::findAnimationLimits()
-{
-    d->m_maximumAnimationCount = 0;
-    d->m_minimumAnimationCount = 0;
-    d->m_lastFrameEvent = 0;
-
-    for (int i = 0; i < d->m_startTimeSortedList.count(); i++) {
-        if (d->m_startTimeSortedList[i].description->eventType == QmlJsDebugClient::Painting &&
-                d->m_startTimeSortedList[i].animationCount >= 0) {
-            int animationcount = d->m_startTimeSortedList[i].animationCount;
-            if (d->m_lastFrameEvent) {
-                if (animationcount > d->m_maximumAnimationCount)
-                    d->m_maximumAnimationCount = animationcount;
-                if (animationcount < d->m_minimumAnimationCount)
-                    d->m_minimumAnimationCount = animationcount;
-            } else {
-                d->m_maximumAnimationCount = animationcount;
-                d->m_minimumAnimationCount = animationcount;
-            }
-            d->m_lastFrameEvent = &d->m_startTimeSortedList[i];
-        }
-    }
-}
-
-void QmlProfilerEventList::computeNestingLevels()
-{
-    // compute levels
-    QHash <int, qint64> endtimesPerLevel;
-    QList <int> nestingLevels;
-    QList < QHash <int, qint64> > endtimesPerNestingLevel;
-    int level = MIN_LEVEL;
-    endtimesPerLevel[MIN_LEVEL] = 0;
-
-    for (int i = 0; i < QmlJsDebugClient::MaximumQmlEventType; i++) {
-        nestingLevels << MIN_LEVEL;
-        QHash <int, qint64> dummyHash;
-        dummyHash[MIN_LEVEL] = 0;
-        endtimesPerNestingLevel << dummyHash;
-    }
-
-    for (int i=0; i<d->m_startTimeSortedList.count(); i++) {
-        qint64 st = d->m_startTimeSortedList[i].startTime;
-        int type = d->m_startTimeSortedList[i].description->eventType;
-
-        if (type == QmlJsDebugClient::Painting) {
-            // animation/paint events have level 1 by definition,
-            // but are not considered parents of other events for statistical purposes
-            d->m_startTimeSortedList[i].level = MIN_LEVEL;
-            d->m_startTimeSortedList[i].nestingLevel = MIN_LEVEL;
-            continue;
-        }
-
-        // general level
-        if (endtimesPerLevel[level] > st) {
-            level++;
-        } else {
-            while (level > MIN_LEVEL && endtimesPerLevel[level-1] <= st)
-                level--;
-        }
-        endtimesPerLevel[level] = st + d->m_startTimeSortedList[i].length;
-
-        // per type
-        if (endtimesPerNestingLevel[type][nestingLevels[type]] > st) {
-            nestingLevels[type]++;
-        } else {
-            while (nestingLevels[type] > MIN_LEVEL &&
-                   endtimesPerNestingLevel[type][nestingLevels[type]-1] <= st)
-                nestingLevels[type]--;
-        }
-        endtimesPerNestingLevel[type][nestingLevels[type]] = st + d->m_startTimeSortedList[i].length;
-
-        d->m_startTimeSortedList[i].level = level;
-        d->m_startTimeSortedList[i].nestingLevel = nestingLevels[type];
-
-        if (level == MIN_LEVEL) {
-            d->m_qmlMeasuredTime += d->m_startTimeSortedList[i].length;
-        }
-    }
-}
-
-void QmlProfilerEventList::computeNestingDepth()
-{
-    QHash <int, int> nestingDepth;
-    for (int i = 0; i < d->m_endTimeSortedList.count(); i++) {
-        int type = d->m_endTimeSortedList[i].description->eventType;
-        int nestingInType = d->m_startTimeSortedList[ d->m_endTimeSortedList[i].startTimeIndex ].nestingLevel;
-        if (!nestingDepth.contains(type))
-            nestingDepth[type] = nestingInType;
-        else {
-            int nd = nestingDepth[type];
-            nestingDepth[type] = nd > nestingInType ? nd : nestingInType;
-        }
-
-        d->m_startTimeSortedList[ d->m_endTimeSortedList[i].startTimeIndex ].nestingDepth = nestingDepth[type];
-        if (nestingInType == MIN_LEVEL)
-            nestingDepth[type] = MIN_LEVEL;
-    }
-}
-
-void QmlProfilerEventList::postProcess()
-{
-    if (count() != 0) {
-        sortStartTimes();
-        sortEndTimes();
-        findAnimationLimits();
-        computeLevels();
-        linkEndsToStarts();
-        reloadDetails();
-        compileStatistics(traceStartTime(), traceEndTime());
-        prepareForDisplay();
-        setState(Done);
-    } else {
-        setState(Empty);
-    }
-}
-
-void QmlProfilerEventList::linkEndsToStarts()
-{
-    for (int i = 0; i < d->m_startTimeSortedList.count(); i++)
-        d->m_endTimeSortedList[d->m_startTimeSortedList[i].endTimeIndex].startTimeIndex = i;
-}
-
-void QmlProfilerEventList::computeLevels()
-{
-    computeNestingLevels();
-    computeNestingDepth();
-}
-
-void QmlProfilerEventList::reloadDetails()
-{
-    // request binding/signal details from the AST
-    foreach (QmlEventData *event, d->m_eventDescriptions.values()) {
-        if (event->eventType != Binding && event->eventType != HandlingSignal)
-            continue;
-
-        // This skips anonymous bindings in Qt4.8 (we don't have valid location data for them)
-        if (event->location.filename.isEmpty())
-            continue;
-
-        // Skip non-anonymous bindings from Qt4.8 (we already have correct details for them)
-        if (event->location.column == -1)
-            continue;
-
-        emit requestDetailsForLocation(event->eventType, event->location);
-    }
-    emit reloadDocumentsForDetails();
-}
-
-void QmlProfilerEventList::rewriteDetailsString(int eventType, const QmlJsDebugClient::QmlEventLocation &location, const QString &newString)
-{
-    QString eventHashStr = getHashStringForQmlEvent(location, eventType);
-    QTC_ASSERT(d->m_eventDescriptions.contains(eventHashStr), return);
-    d->m_eventDescriptions.value(eventHashStr)->details = newString;
-    emit detailsChanged(d->m_eventDescriptions.value(eventHashStr)->eventId, newString);
-}
-
-void QmlProfilerEventList::finishedRewritingDetails()
-{
-    emit reloadDetailLabels();
-}
-
-void QmlProfilerEventList::findBindingLoops(qint64 startTime, qint64 endTime)
-{
-    // first clear existing data
-    foreach (QmlEventData *event, d->m_eventDescriptions.values()) {
-        event->isBindingLoop = false;
-        foreach (QmlEventSub *parentEvent, event->parentHash.values())
-            parentEvent->inLoopPath = false;
-        foreach (QmlEventSub *childEvent, event->childrenHash.values())
-            childEvent->inLoopPath = false;
-    }
-
-    QList <QmlEventData *> stackRefs;
-    QList <QmlEventStartTimeData *> stack;
-    int fromIndex = findFirstIndex(startTime);
-    int toIndex = findLastIndex(endTime);
-
-    for (int i = 0; i < d->m_startTimeSortedList.count(); i++) {
-        QmlEventData *currentEvent = d->m_startTimeSortedList[i].description;
-        QmlEventStartTimeData *inTimeEvent = &d->m_startTimeSortedList[i];
-        inTimeEvent->bindingLoopHead = -1;
-
-        // managing call stack
-        for (int j = stack.count() - 1; j >= 0; j--) {
-            if (stack[j]->startTime + stack[j]->length <= inTimeEvent->startTime) {
-                stack.removeAt(j);
-                stackRefs.removeAt(j);
-            }
-        }
-
-        bool loopDetected = stackRefs.contains(currentEvent);
-        stack << inTimeEvent;
-        stackRefs << currentEvent;
-
-        if (loopDetected) {
-            if (i >= fromIndex && i <= toIndex) {
-                // for the statistics
-                currentEvent->isBindingLoop = true;
-                for (int j = stackRefs.indexOf(currentEvent); j < stackRefs.count()-1; j++) {
-                    QmlEventSub *nextEventSub = stackRefs[j]->childrenHash.value(stackRefs[j+1]->eventHashStr);
-                    nextEventSub->inLoopPath = true;
-                    QmlEventSub *prevEventSub = stackRefs[j+1]->parentHash.value(stackRefs[j]->eventHashStr);
-                    prevEventSub->inLoopPath = true;
-                }
-            }
-
-            // use crossed references to find index in starttimesortedlist
-            QmlEventStartTimeData *head = stack[stackRefs.indexOf(currentEvent)];
-            inTimeEvent->bindingLoopHead = d->m_endTimeSortedList[head->endTimeIndex].startTimeIndex;
-            d->m_startTimeSortedList[inTimeEvent->bindingLoopHead].bindingLoopHead = i;
-        }
-    }
-}
-
-// get list of events between A and B:
-// find fist event with endtime after A -> aa
-// find last event with starttime before B -> bb
-// list is from parent of aa with level=0 to bb, in the "sorted by starttime" list
-int QmlProfilerEventList::findFirstIndex(qint64 startTime) const
-{
-    int candidate = -1;
-    // in the "endtime" list, find the first event that ends after startTime
-    if (d->m_endTimeSortedList.isEmpty())
-        return 0; // -1
-    if (d->m_endTimeSortedList.length() == 1 || d->m_endTimeSortedList.first().endTime >= startTime)
-        candidate = 0;
-    else
-        if (d->m_endTimeSortedList.last().endTime <= startTime)
-            return 0; // -1
-
-    if (candidate == -1)
-    {
-        int fromIndex = 0;
-        int toIndex = d->m_endTimeSortedList.count()-1;
-        while (toIndex - fromIndex > 1) {
-            int midIndex = (fromIndex + toIndex)/2;
-            if (d->m_endTimeSortedList[midIndex].endTime < startTime)
-                fromIndex = midIndex;
-            else
-                toIndex = midIndex;
-        }
-
-        candidate = toIndex;
-    }
-
-    int ndx = d->m_endTimeSortedList[candidate].startTimeIndex;
-
-    // and then go to the parent
-    while (d->m_startTimeSortedList[ndx].level != MIN_LEVEL && ndx > 0)
-        ndx--;
-
-    return ndx;
-}
-
-int QmlProfilerEventList::findFirstIndexNoParents(qint64 startTime) const
-{
-    int candidate = -1;
-    // in the "endtime" list, find the first event that ends after startTime
-    if (d->m_endTimeSortedList.isEmpty())
-        return 0; // -1
-    if (d->m_endTimeSortedList.length() == 1 || d->m_endTimeSortedList.first().endTime >= startTime)
-        candidate = 0;
-    else
-        if (d->m_endTimeSortedList.last().endTime <= startTime)
-            return 0; // -1
-
-    if (candidate == -1) {
-        int fromIndex = 0;
-        int toIndex = d->m_endTimeSortedList.count()-1;
-        while (toIndex - fromIndex > 1) {
-            int midIndex = (fromIndex + toIndex)/2;
-            if (d->m_endTimeSortedList[midIndex].endTime < startTime)
-                fromIndex = midIndex;
-            else
-                toIndex = midIndex;
-        }
-
-        candidate = toIndex;
-    }
-
-    int ndx = d->m_endTimeSortedList[candidate].startTimeIndex;
-
-    return ndx;
-}
-
-int QmlProfilerEventList::findLastIndex(qint64 endTime) const
-{
-    // in the "starttime" list, find the last event that starts before endtime
-    if (d->m_startTimeSortedList.isEmpty())
-        return 0; // -1
-    if (d->m_startTimeSortedList.first().startTime >= endTime)
-        return 0; // -1
-    if (d->m_startTimeSortedList.length() == 1)
-        return 0;
-    if (d->m_startTimeSortedList.last().startTime <= endTime)
-        return d->m_startTimeSortedList.count()-1;
-
-    int fromIndex = 0;
-    int toIndex = d->m_startTimeSortedList.count()-1;
-    while (toIndex - fromIndex > 1) {
-        int midIndex = (fromIndex + toIndex)/2;
-        if (d->m_startTimeSortedList[midIndex].startTime < endTime)
-            fromIndex = midIndex;
-        else
-            toIndex = midIndex;
-    }
-
-    return fromIndex;
-}
-
-qint64 QmlProfilerEventList::firstTimeMark() const
-{
-    if (d->m_startTimeSortedList.isEmpty())
-        return 0;
-    else {
-        return d->m_startTimeSortedList[0].startTime;
-    }
-}
-
-qint64 QmlProfilerEventList::lastTimeMark() const
-{
-    if (d->m_endTimeSortedList.isEmpty())
-        return 0;
-    else {
-        return d->m_endTimeSortedList.last().endTime;
-    }
-}
-
-qint64 QmlProfilerEventList::traceStartTime() const
-{
-    return d->m_traceStartTime != -1? d->m_traceStartTime : firstTimeMark();
-}
-
-qint64 QmlProfilerEventList::traceEndTime() const
-{
-    return d->m_traceEndTime ? d->m_traceEndTime : lastTimeMark();
-}
-
-qint64 QmlProfilerEventList::traceDuration() const
-{
-    return traceEndTime() - traceStartTime();
-}
-
-qint64 QmlProfilerEventList::qmlMeasuredTime() const
-{
-    return d->m_qmlMeasuredTime;
-}
-qint64 QmlProfilerEventList::v8MeasuredTime() const
-{
-    return d->m_v8MeasuredTime;
-}
-
-int QmlProfilerEventList::count() const
-{
-    return d->m_startTimeSortedList.count();
-}
-
-////////////////////////////////////////////////////////////////////////////////////
-
-
-bool QmlProfilerEventList::save(const QString &filename)
-{
-    if (count() == 0) {
-        emit error(tr("No data to save"));
-        return false;
-    }
-
-    QFile file(filename);
-    if (!file.open(QIODevice::WriteOnly)) {
-        emit error(tr("Could not open %1 for writing").arg(filename));
-        return false;
-    }
-
-    QXmlStreamWriter stream(&file);
-    stream.setAutoFormatting(true);
-    stream.writeStartDocument();
-
-    stream.writeStartElement("trace");
-    stream.writeAttribute("version", Constants::PROFILER_FILE_VERSION);
-
-    stream.writeAttribute("traceStart", QString::number(traceStartTime()));
-    stream.writeAttribute("traceEnd", QString::number(traceEndTime()));
-
-    stream.writeStartElement("eventData");
-    stream.writeAttribute("totalTime", QString::number(d->m_qmlMeasuredTime));
-
-    foreach (const QmlEventData *eventData, d->m_eventDescriptions.values()) {
-        stream.writeStartElement("event");
-        stream.writeAttribute("index", QString::number(d->m_eventDescriptions.keys().indexOf(eventData->eventHashStr)));
-        stream.writeTextElement("displayname", eventData->displayname);
-        stream.writeTextElement("type", qmlEventType(eventData->eventType));
-        if (!eventData->location.filename.isEmpty()) {
-            stream.writeTextElement("filename", eventData->location.filename);
-            stream.writeTextElement("line", QString::number(eventData->location.line));
-            stream.writeTextElement("column", QString::number(eventData->location.column));
-        }
-        stream.writeTextElement("details", eventData->details);
-        stream.writeEndElement();
-    }
-    stream.writeEndElement(); // eventData
-
-    stream.writeStartElement("eventList");
-    foreach (const QmlEventStartTimeData &rangedEvent, d->m_startTimeSortedList) {
-        stream.writeStartElement("range");
-        stream.writeAttribute("startTime", QString::number(rangedEvent.startTime));
-        stream.writeAttribute("duration", QString::number(rangedEvent.length));
-        stream.writeAttribute("eventIndex", QString::number(d->m_eventDescriptions.keys().indexOf(rangedEvent.description->eventHashStr)));
-        if (rangedEvent.description->eventType == QmlJsDebugClient::Painting && rangedEvent.animationCount >= 0) {
-            // animation frame
-            stream.writeAttribute("framerate", QString::number(rangedEvent.frameRate));
-            stream.writeAttribute("animationcount", QString::number(rangedEvent.animationCount));
-        }
-        stream.writeEndElement();
-    }
-    stream.writeEndElement(); // eventList
-
-    stream.writeStartElement("v8profile"); // v8 profiler output
-    stream.writeAttribute("totalTime", QString::number(d->m_v8MeasuredTime));
-    foreach (QV8EventData *v8event, d->m_v8EventList) {
-        stream.writeStartElement("event");
-        stream.writeAttribute("index", QString::number(d->m_v8EventList.indexOf(v8event)));
-        stream.writeTextElement("displayname", v8event->displayName);
-        stream.writeTextElement("functionname", v8event->functionName);
-        if (!v8event->filename.isEmpty()) {
-            stream.writeTextElement("filename", v8event->filename);
-            stream.writeTextElement("line", QString::number(v8event->line));
-        }
-        stream.writeTextElement("totalTime", QString::number(v8event->totalTime));
-        stream.writeTextElement("selfTime", QString::number(v8event->selfTime));
-        if (!v8event->childrenHash.isEmpty()) {
-            stream.writeStartElement("childrenEvents");
-            QStringList childrenIndexes;
-            QStringList childrenTimes;
-            QStringList parentTimes;
-            foreach (QV8EventSub *v8child, v8event->childrenHash.values()) {
-                childrenIndexes << QString::number(v8child->reference->eventId);
-                childrenTimes << QString::number(v8child->totalTime);
-                parentTimes << QString::number(d->m_v8EventList[v8child->reference->eventId]->parentHash[v8event->displayName]->totalTime);
-            }
-
-            stream.writeAttribute("list", childrenIndexes.join(QString(", ")));
-            stream.writeAttribute("childrenTimes", childrenTimes.join(QString(", ")));
-            stream.writeAttribute("parentTimes", parentTimes.join(QString(", ")));
-            stream.writeEndElement();
-        }
-        stream.writeEndElement();
-    }
-    stream.writeEndElement(); // v8 profiler output
-
-    stream.writeEndElement(); // trace
-    stream.writeEndDocument();
-
-    file.close();
-    return true;
-}
-
-void QmlProfilerEventList::setFilename(const QString &filename)
-{
-    d->m_filename = filename;
-}
-
-void QmlProfilerEventList::load(const QString &filename)
-{
-    setFilename(filename);
-    load();
-}
-
-// "be strict in your output but tolerant in your inputs"
-void QmlProfilerEventList::load()
-{
-    QString filename = d->m_filename;
-
-    QFile file(filename);
-
-    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
-        emit error(tr("Could not open %1 for reading").arg(filename));
-        return;
-    }
-
-    // erase current
-    clear();
-
-    setState(AcquiringData);
-
-    bool readingQmlEvents = false;
-    bool readingV8Events = false;
-    QHash <int, QmlEventData *> descriptionBuffer;
-    QmlEventData *currentEvent = 0;
-    QHash <int, QV8EventData *> v8eventBuffer;
-    QHash <int, QString> childrenIndexes;
-    QHash <int, QString> childrenTimes;
-    QHash <int, QString> parentTimes;
-    QV8EventData *v8event = 0;
-    bool startTimesAreSorted = true;
-    bool validVersion = true;
-
-    // time computation
-    d->m_v8MeasuredTime = 0;
-    d->m_qmlMeasuredTime = 0;
-    double cumulatedV8Time = 0;
-
-    QXmlStreamReader stream(&file);
-
-    while (validVersion && !stream.atEnd() && !stream.hasError()) {
-        QXmlStreamReader::TokenType token = stream.readNext();
-        QString elementName = stream.name().toString();
-        switch (token) {
-        case QXmlStreamReader::StartDocument :  continue;
-        case QXmlStreamReader::StartElement : {
-            if (elementName == "trace") {
-                QXmlStreamAttributes attributes = stream.attributes();
-                if (attributes.hasAttribute("version"))
-                    validVersion = attributes.value("version").toString() == Constants::PROFILER_FILE_VERSION;
-                else
-                    validVersion = false;
-                if (attributes.hasAttribute("traceStart"))
-                    setTraceStartTime(attributes.value("traceStart").toString().toLongLong());
-                if (attributes.hasAttribute("traceEnd"))
-                    setTraceEndTime(attributes.value("traceEnd").toString().toLongLong());
-            }
-            if (elementName == "eventData" && !readingV8Events) {
-                readingQmlEvents = true;
-                QXmlStreamAttributes attributes = stream.attributes();
-                if (attributes.hasAttribute("totalTime"))
-                    d->m_qmlMeasuredTime = attributes.value("totalTime").toString().toDouble();
-                break;
-            }
-            if (elementName == "v8profile" && !readingQmlEvents) {
-                readingV8Events = true;
-                QXmlStreamAttributes attributes = stream.attributes();
-                if (attributes.hasAttribute("totalTime"))
-                    d->m_v8MeasuredTime = attributes.value("totalTime").toString().toDouble();
-                break;
-            }
-
-            if (elementName == "trace") {
-                QXmlStreamAttributes attributes = stream.attributes();
-                if (attributes.hasAttribute("traceStart"))
-                    setTraceStartTime(attributes.value("traceStart").toString().toLongLong());
-                if (attributes.hasAttribute("traceEnd"))
-                    setTraceEndTime(attributes.value("traceEnd").toString().toLongLong());
-            }
-
-            if (elementName == "range") {
-                QmlEventStartTimeData rangedEvent;
-                QXmlStreamAttributes attributes = stream.attributes();
-                if (attributes.hasAttribute("startTime"))
-                    rangedEvent.startTime = attributes.value("startTime").toString().toLongLong();
-                if (attributes.hasAttribute("duration"))
-                    rangedEvent.length = attributes.value("duration").toString().toLongLong();
-                if (attributes.hasAttribute("framerate"))
-                    rangedEvent.frameRate = attributes.value("framerate").toString().toInt();
-                if (attributes.hasAttribute("animationcount"))
-                    rangedEvent.animationCount = attributes.value("animationcount").toString().toInt();
-                else
-                    rangedEvent.animationCount = -1;
-                if (attributes.hasAttribute("eventIndex")) {
-                    int ndx = attributes.value("eventIndex").toString().toInt();
-                    if (!descriptionBuffer.value(ndx))
-                        descriptionBuffer[ndx] = new QmlEventData;
-                    rangedEvent.description = descriptionBuffer.value(ndx);
-                }
-                rangedEvent.endTimeIndex = d->m_endTimeSortedList.length();
-
-                if (!d->m_startTimeSortedList.isEmpty()
-                        && rangedEvent.startTime < d->m_startTimeSortedList.last().startTime)
-                    startTimesAreSorted = false;
-                d->m_startTimeSortedList << rangedEvent;
-
-                QmlEventEndTimeData endTimeEvent;
-                endTimeEvent.endTime = rangedEvent.startTime + rangedEvent.length;
-                endTimeEvent.startTimeIndex = d->m_startTimeSortedList.length()-1;
-                endTimeEvent.description = rangedEvent.description;
-                d->m_endTimeSortedList << endTimeEvent;
-                break;
-            }
-
-            if (readingQmlEvents) {
-                if (elementName == "event") {
-                    QXmlStreamAttributes attributes = stream.attributes();
-                    if (attributes.hasAttribute("index")) {
-                        int ndx = attributes.value("index").toString().toInt();
-                        if (!descriptionBuffer.value(ndx))
-                            descriptionBuffer[ndx] = new QmlEventData;
-                        currentEvent = descriptionBuffer[ndx];
-                    } else {
-                        currentEvent = 0;
-                    }
-                    break;
-                }
-
-                // the remaining are eventdata or v8eventdata elements
-                if (!currentEvent)
-                    break;
-
-                stream.readNext();
-                if (stream.tokenType() != QXmlStreamReader::Characters)
-                    break;
-                QString readData = stream.text().toString();
-
-                if (elementName == "displayname") {
-                    currentEvent->displayname = readData;
-                    break;
-                }
-                if (elementName == "type") {
-                    currentEvent->eventType = qmlEventType(readData);
-                    break;
-                }
-                if (elementName == "filename") {
-                    currentEvent->location.filename = readData;
-                    break;
-                }
-                if (elementName == "line") {
-                    currentEvent->location.line = readData.toInt();
-                    break;
-                }
-                if (elementName == "column") {
-                    currentEvent->location.column = readData.toInt();
-                }
-                if (elementName == "details") {
-                    currentEvent->details = readData;
-                    break;
-                }
-            }
-
-            if (readingV8Events) {
-                if (elementName == "event") {
-                    QXmlStreamAttributes attributes = stream.attributes();
-                    if (attributes.hasAttribute("index")) {
-                        int ndx = attributes.value("index").toString().toInt();
-                        if (!v8eventBuffer.value(ndx))
-                            v8eventBuffer[ndx] = new QV8EventData;
-                        v8event = v8eventBuffer[ndx];
-                    } else {
-                        v8event = 0;
-                    }
-                    break;
-                }
-
-                // the remaining are eventdata or v8eventdata elements
-                if (!v8event)
-                    break;
-
-                if (elementName == "childrenEvents") {
-                    QXmlStreamAttributes attributes = stream.attributes();
-                    int eventIndex = v8eventBuffer.key(v8event);
-                    if (attributes.hasAttribute("list")) {
-                        // store for later parsing (we haven't read all the events yet)
-                        childrenIndexes[eventIndex] = attributes.value("list").toString();
-                    }
-                    if (attributes.hasAttribute("childrenTimes")) {
-                        childrenTimes[eventIndex] = attributes.value("childrenTimes").toString();
-                    }
-                    if (attributes.hasAttribute("parentTimes")) {
-                        parentTimes[eventIndex] = attributes.value("parentTimes").toString();
-                    }
-                }
-
-                stream.readNext();
-                if (stream.tokenType() != QXmlStreamReader::Characters)
-                    break;
-                QString readData = stream.text().toString();
-
-                if (elementName == "displayname") {
-                    v8event->displayName = readData;
-                    break;
-                }
-
-                if (elementName == "functionname") {
-                    v8event->functionName = readData;
-                    break;
-                }
-
-                if (elementName == "filename") {
-                    v8event->filename = readData;
-                    break;
-                }
-
-                if (elementName == "line") {
-                    v8event->line = readData.toInt();
-                    break;
-                }
-
-                if (elementName == "totalTime") {
-                    v8event->totalTime = readData.toDouble();
-                    cumulatedV8Time += v8event->totalTime;
-                    break;
-                }
-
-                if (elementName == "selfTime") {
-                    v8event->selfTime = readData.toDouble();
-                    break;
-                }
-            }
-
-            break;
-        }
-        case QXmlStreamReader::EndElement : {
-            if (elementName == "event") {
-                currentEvent = 0;
-                break;
-            }
-            if (elementName == "eventData") {
-                readingQmlEvents = false;
-                break;
-            }
-            if (elementName == "v8profile") {
-                readingV8Events = false;
-            }
-        }
-        default: break;
-        }
-    }
-
-    file.close();
-
-    if (stream.hasError()) {
-        emit error(tr("Error while parsing %1").arg(filename));
-        clear();
-        return;
-    }
-
-    stream.clear();
-
-    if (!validVersion) {
-        clear();
-        emit error(tr("Invalid version of QML Trace file."));
-        return;
-    }
-
-    // backwards compatibility
-    if (d->m_v8MeasuredTime == 0)
-        d->m_v8MeasuredTime = cumulatedV8Time;
-
-    // move the buffered data to the details cache
-    foreach (QmlEventData *desc, descriptionBuffer.values()) {
-        desc->eventHashStr = getHashStringForQmlEvent(desc->location, desc->eventType);;
-        d->m_eventDescriptions[desc->eventHashStr] = desc;
-    }
-
-    // sort startTimeSortedList
-    if (!startTimesAreSorted) {
-        qSort(d->m_startTimeSortedList.begin(), d->m_startTimeSortedList.end(), compareStartTimes);
-        for (int i = 0; i< d->m_startTimeSortedList.length(); i++) {
-            QmlEventStartTimeData startTimeData = d->m_startTimeSortedList[i];
-            d->m_endTimeSortedList[startTimeData.endTimeIndex].startTimeIndex = i;
-        }
-        qSort(d->m_endTimeSortedList.begin(), d->m_endTimeSortedList.end(), compareStartIndexes);
-    }
-
-    // find v8events' children and parents
-    foreach (int parentIndex, childrenIndexes.keys()) {
-        QStringList childrenStrings = childrenIndexes.value(parentIndex).split(",");
-        QStringList childrenTimesStrings = childrenTimes.value(parentIndex).split(", ");
-        QStringList parentTimesStrings = parentTimes.value(parentIndex).split(", ");
-        for (int ndx = 0; ndx < childrenStrings.count(); ndx++) {
-            int childIndex = childrenStrings[ndx].toInt();
-            if (v8eventBuffer.value(childIndex)) {
-                QV8EventSub *newChild = new QV8EventSub(v8eventBuffer[childIndex]);
-                QV8EventSub *newParent = new QV8EventSub(v8eventBuffer[parentIndex]);
-                if (childrenTimesStrings.count() > ndx)
-                    newChild->totalTime = childrenTimesStrings[ndx].toDouble();
-                if (parentTimesStrings.count() > ndx)
-                    newParent->totalTime = parentTimesStrings[ndx].toDouble();
-                v8eventBuffer[parentIndex]->childrenHash.insert(newChild->reference->displayName, newChild);
-                v8eventBuffer[childIndex]->parentHash.insert(newParent->reference->displayName, newParent);
-            }
-        }
-    }
-    // store v8 events
-    d->m_v8EventList = v8eventBuffer.values();
-
-    emit countChanged();
-
-    descriptionBuffer.clear();
-
-    setState(ProcessingData);
-    d->collectV8Statistics();
-    postProcess();
-}
-
-///////////////////////////////////////////////
-qint64 QmlProfilerEventList::getStartTime(int index) const
-{
-    return d->m_startTimeSortedList[index].startTime;
-}
-
-qint64 QmlProfilerEventList::getEndTime(int index) const
-{
-    return d->m_startTimeSortedList[index].startTime + d->m_startTimeSortedList[index].length;
-}
-
-qint64 QmlProfilerEventList::getDuration(int index) const
-{
-    return d->m_startTimeSortedList[index].length;
-}
-
-int QmlProfilerEventList::getType(int index) const
-{
-    return d->m_startTimeSortedList[index].description->eventType;
-}
-
-int QmlProfilerEventList::getNestingLevel(int index) const
-{
-    return d->m_startTimeSortedList[index].nestingLevel;
-}
-
-int QmlProfilerEventList::getNestingDepth(int index) const
-{
-    return d->m_startTimeSortedList[index].nestingDepth;
-}
-
-QString QmlProfilerEventList::getFilename(int index) const
-{
-    return d->m_startTimeSortedList[index].description->location.filename;
-}
-
-int QmlProfilerEventList::getLine(int index) const
-{
-    return d->m_startTimeSortedList[index].description->location.line;
-}
-
-int QmlProfilerEventList::getColumn(int index) const
-{
-    return d->m_startTimeSortedList[index].description->location.column;
-}
-
-QString QmlProfilerEventList::getDetails(int index) const
-{
-    // special: animations
-    if (d->m_startTimeSortedList[index].description->eventType == QmlJsDebugClient::Painting &&
-            d->m_startTimeSortedList[index].animationCount >= 0)
-        return tr("%1 animations at %2 FPS").arg(
-                    QString::number(d->m_startTimeSortedList[index].animationCount),
-                    QString::number(d->m_startTimeSortedList[index].frameRate));
-    return d->m_startTimeSortedList[index].description->details;
-}
-
-int QmlProfilerEventList::getEventId(int index) const
-{
-    return d->m_startTimeSortedList[index].description->eventId;
-}
-
-int QmlProfilerEventList::getBindingLoopDest(int index) const
-{
-    return d->m_startTimeSortedList[index].bindingLoopHead;
-}
-
-int QmlProfilerEventList::getFramerate(int index) const
-{
-    return d->m_startTimeSortedList[index].frameRate;
-}
-
-int QmlProfilerEventList::getAnimationCount(int index) const
-{
-    return d->m_startTimeSortedList[index].animationCount;
-}
-
-int QmlProfilerEventList::getMaximumAnimationCount() const
-{
-    return d->m_maximumAnimationCount;
-}
-
-int QmlProfilerEventList::getMinimumAnimationCount() const
-{
-    return d->m_minimumAnimationCount;
-}
-
-int QmlProfilerEventList::uniqueEventsOfType(int type) const
-{
-    if (!d->m_typeCounts.contains(type))
-        return 0;
-    return d->m_typeCounts[type]->eventIds.count();
-}
-
-int QmlProfilerEventList::maxNestingForType(int type) const
-{
-    if (!d->m_typeCounts.contains(type))
-        return 0;
-    return d->m_typeCounts[type]->nestingCount;
-}
-
-QString QmlProfilerEventList::eventTextForType(int type, int index) const
-{
-    if (!d->m_typeCounts.contains(type))
-        return QString();
-    return d->m_eventDescriptions.values().at(d->m_typeCounts[type]->eventIds[index])->details;
-}
-
-QString QmlProfilerEventList::eventDisplayNameForType(int type, int index) const
-{
-    if (!d->m_typeCounts.contains(type))
-        return QString();
-    return d->m_eventDescriptions.values().at(d->m_typeCounts[type]->eventIds[index])->displayname;
-}
-
-int QmlProfilerEventList::eventIdForType(int type, int index) const
-{
-    if (!d->m_typeCounts.contains(type))
-        return -1;
-    return d->m_typeCounts[type]->eventIds[index];
-}
-
-int QmlProfilerEventList::eventPosInType(int index) const
-{
-    int eventType = d->m_startTimeSortedList[index].description->eventType;
-    return d->m_typeCounts[eventType]->eventIds.indexOf(d->m_startTimeSortedList[index].description->eventId);
-}
-
-/////////////////////////////////////////
-QmlProfilerEventList::State QmlProfilerEventList::currentState() const
-{
-    return d->m_state;
-}
-
-int QmlProfilerEventList::getCurrentStateFromQml() const
-{
-    return (int)d->m_state;
-}
-
-void QmlProfilerEventList::setState(QmlProfilerEventList::State state)
-{
-    // It's not an error, we are continuously calling "AcquiringData" for example
-    if (d->m_state == state)
-        return;
-
-    switch (state) {
-        case Empty:
-            // if it's not empty, complain but go on
-            QTC_ASSERT(count() == 0, /**/);
-        break;
-        case AcquiringData:
-            // we're not supposed to receive new data while processing older data
-            QTC_ASSERT(d->m_state != ProcessingData, return);
-        break;
-        case ProcessingData:
-            QTC_ASSERT(d->m_state == AcquiringData, return);
-        break;
-        case Done:
-            QTC_ASSERT(d->m_state == ProcessingData, return);
-        break;
-        default:
-        qDebug() << "Trying to set unknown state in events list at" << __FILE__ << __LINE__;
-        break;
-    }
-
-    d->m_state = state;
-    emit stateChanged();
-    return;
-}
-
-} // namespace QmlJsDebugClient
diff --git a/src/libs/qmljsdebugclient/qmlprofilereventlocation.h b/src/libs/qmljsdebugclient/qmlprofilereventlocation.h
index 45b7df6ae6a1e0be7dac7ccaaf73ba1195beee41..cb317fd2e5bc1d4cffc611052db214bcd7ed1d3e 100644
--- a/src/libs/qmljsdebugclient/qmlprofilereventlocation.h
+++ b/src/libs/qmljsdebugclient/qmlprofilereventlocation.h
@@ -35,6 +35,8 @@
 
 #include "qmljsdebugclient_global.h"
 
+#include <QString>
+
 namespace QmlJsDebugClient {
 
 struct QMLJSDEBUGCLIENT_EXPORT QmlEventLocation
diff --git a/src/libs/qmljsdebugclient/qmlprofilereventtypes.h b/src/libs/qmljsdebugclient/qmlprofilereventtypes.h
index ae1c490002965848adf34f76464eeb70c8162355..02e102f039ed1adbb1c04dbf0458977582934c2d 100644
--- a/src/libs/qmljsdebugclient/qmlprofilereventtypes.h
+++ b/src/libs/qmljsdebugclient/qmlprofilereventtypes.h
@@ -33,8 +33,6 @@
 #ifndef QMLPROFILEREVENTTYPES_H
 #define QMLPROFILEREVENTTYPES_H
 
-#include <QString>
-
 namespace QmlJsDebugClient {
 
 enum QmlEventType {
@@ -47,8 +45,15 @@ enum QmlEventType {
     MaximumQmlEventType
 };
 
-QString qmlEventType(QmlEventType typeEnum);
-QmlEventType qmlEventType(const QString &typeString);
+namespace Constants {
+const char TYPE_PAINTING_STR[] = "Painting";
+const char TYPE_COMPILING_STR[] = "Compiling";
+const char TYPE_CREATING_STR[] = "Creating";
+const char TYPE_BINDING_STR[] = "Binding";
+const char TYPE_HANDLINGSIGNAL_STR[] = "HandlingSignal";
+const char PROFILER_FILE_VERSION[] = "1.02";
+const int QML_MIN_LEVEL = 1;
+}
 
 } // namespace QmlJsDebugClient
 
diff --git a/src/libs/qmljsdebugclient/qmlprofilertraceclient.cpp b/src/libs/qmljsdebugclient/qmlprofilertraceclient.cpp
index cc130bba736b66abae899bfa879c71227261c5f6..01eb3f56b3ae851290367d7b985d60cc0062abe6 100644
--- a/src/libs/qmljsdebugclient/qmlprofilertraceclient.cpp
+++ b/src/libs/qmljsdebugclient/qmlprofilertraceclient.cpp
@@ -159,6 +159,12 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
         int event;
         stream >> event;
 
+        // stop with the first data
+        if (d->recording && event != StartTrace)
+            setRecordingFromServer(false);
+        else if ((!d->recording) && event == StartTrace)
+            setRecordingFromServer(true);
+
         if (event == EndTrace) {
             emit this->traceFinished(time);
             d->maximumTime = time;
@@ -169,9 +175,6 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
             emit this->frame(time, frameRate, animationCount);
             d->maximumTime = qMax(time, d->maximumTime);
         } else if (event == StartTrace) {
-            // special: StartTrace is now asynchronous
-            if (!d->recording)
-                setRecordingFromServer(true);
             emit this->traceStarted(time);
             d->maximumTime = time;
         } else if (event < MaximumEventType) {
@@ -191,6 +194,9 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
             d->rangeStartTimes[range].push(time);
             d->inProgressRanges |= (static_cast<qint64>(1) << range);
             ++d->rangeCount[range];
+            // stop with the first data
+            if (d->recording)
+                setRecordingFromServer(false);
         } else if (messageType == RangeData) {
             QString data;
             stream >> data;
diff --git a/src/libs/qmljsdebugclient/qmlprofilertraceclient.h b/src/libs/qmljsdebugclient/qmlprofilertraceclient.h
index 4d37c067e36209ba2f37d1ef3580f147f5f46827..3ed2071d7391c8f0696c7bf43158b96ede495bbd 100644
--- a/src/libs/qmljsdebugclient/qmlprofilertraceclient.h
+++ b/src/libs/qmljsdebugclient/qmlprofilertraceclient.h
@@ -80,10 +80,9 @@ public:
 
     bool isEnabled() const;
     bool isRecording() const;
+    void setRecording(bool);
 
 public slots:
-    void setRecording(bool);
-    void setRecordingFromServer(bool);
     void clearData();
     void sendRecordingStatus();
 
@@ -106,6 +105,9 @@ protected:
     virtual void statusChanged(Status);
     virtual void messageReceived(const QByteArray &);
 
+private:
+    void setRecordingFromServer(bool);
+
 private:
     class QmlProfilerTraceClientPrivate *d;
 };
diff --git a/src/libs/qmljsdebugclient/qv8profilerclient.cpp b/src/libs/qmljsdebugclient/qv8profilerclient.cpp
index 432ed6c41c8bb02f7e1ca5a5b606b470d72b4b00..7853efcdb3d90a59b19c5dbe39ef19a839e27ddf 100644
--- a/src/libs/qmljsdebugclient/qv8profilerclient.cpp
+++ b/src/libs/qmljsdebugclient/qv8profilerclient.cpp
@@ -118,6 +118,16 @@ void QV8ProfilerClient::setRecording(bool v)
     emit recordingChanged(v);
 }
 
+void QV8ProfilerClient::setRecordingFromServer(bool v)
+{
+    if (v == d->recording)
+        return;
+
+    d->recording = v;
+
+    emit recordingChanged(v);
+}
+
 void QV8ProfilerClient::statusChanged(Status /*status*/)
 {
     emit enabledChanged();
@@ -133,7 +143,10 @@ void QV8ProfilerClient::messageReceived(const QByteArray &data)
     stream >> messageType;
 
     if (messageType == V8Complete) {
+        setRecordingFromServer(false);
         emit complete();
+    } else if (messageType == V8ProfilingStarted) {
+        setRecordingFromServer(true);
     } else if (messageType == V8Entry) {
         QString filename;
         QString function;
diff --git a/src/libs/qmljsdebugclient/qv8profilerclient.h b/src/libs/qmljsdebugclient/qv8profilerclient.h
index 25e1328c7350f2b848f35b3c7d7f4e092b40f17a..48d191a45885c29178a603535e75cacf4eca8579 100644
--- a/src/libs/qmljsdebugclient/qv8profilerclient.h
+++ b/src/libs/qmljsdebugclient/qv8profilerclient.h
@@ -52,6 +52,9 @@ public:
     enum Message {
         V8Entry,
         V8Complete,
+        V8SnapshotChunk,
+        V8SnapshotComplete,
+        V8ProfilingStarted,
 
         V8MaximumMessage
     };
@@ -61,9 +64,9 @@ public:
 
     bool isEnabled() const;
     bool isRecording() const;
+    void setRecording(bool);
 
 public slots:
-    void setRecording(bool);
     void clearData();
     void sendRecordingStatus();
 
@@ -77,6 +80,9 @@ signals:
     void enabledChanged();
     void cleared();
 
+private:
+    void setRecordingFromServer(bool);
+
 protected:
     virtual void statusChanged(Status);
     virtual void messageReceived(const QByteArray &);
diff --git a/src/plugins/qmlprofiler/qml/Label.qml b/src/plugins/qmlprofiler/qml/Label.qml
index 0d89c057abd615373c079f1f07365b84e9bcf9cf..21e322d5be59c60c2be46c161f5516731ada7482 100644
--- a/src/plugins/qmlprofiler/qml/Label.qml
+++ b/src/plugins/qmlprofiler/qml/Label.qml
@@ -60,17 +60,19 @@ Item {
 
     function updateHeight() {
         height = root.singleRowHeight * (1 +
-            (expanded ? qmlEventList.uniqueEventsOfType(typeIndex) : qmlEventList.maxNestingForType(typeIndex)));
+            (expanded ? qmlProfilerDataModel.uniqueEventsOfType(typeIndex) :
+                        qmlProfilerDataModel.maxNestingForType(typeIndex)));
     }
 
     function getDescriptions() {
         var desc=[];
         var ids=[];
         var extdesc=[];
-        for (var i=0; i<qmlEventList.uniqueEventsOfType(typeIndex); i++) {
-            desc[i] = qmlEventList.eventTextForType(typeIndex, i);
-            ids[i] = qmlEventList.eventIdForType(typeIndex, i);
-            extdesc[i] = qmlEventList.eventDisplayNameForType(typeIndex, i) + " : " + desc[i];
+        for (var i=0; i<qmlProfilerDataModel.uniqueEventsOfType(typeIndex); i++) {
+            desc[i] = qmlProfilerDataModel.eventTextForType(typeIndex, i);
+            ids[i] = qmlProfilerDataModel.eventIdForType(typeIndex, i);
+            extdesc[i] = qmlProfilerDataModel.eventDisplayNameForType(typeIndex, i) +
+                        " : " + desc[i];
         }
         descriptions = desc;
         eventIds = ids;
@@ -79,18 +81,18 @@ Item {
     }
 
     Connections {
-        target: qmlEventList
+        target: qmlProfilerDataModel
         onReloadDetailLabels: getDescriptions();
         onStateChanged: {
             // Empty
-            if (qmlEventList.getCurrentStateFromQml() == 0) {
+            if (qmlProfilerDataModel.getCurrentStateFromQml() == 0) {
                 descriptions = [];
                 eventIds = [];
                 extdescriptions = [];
                 updateHeight();
             } else
             // Done
-            if (qmlEventList.getCurrentStateFromQml() == 3) {
+            if (qmlProfilerDataModel.getCurrentStateFromQml() == 3) {
                 getDescriptions();
             }
         }
diff --git a/src/plugins/qmlprofiler/qml/MainView.qml b/src/plugins/qmlprofiler/qml/MainView.qml
index 9fc2e8e44ed67693679d762627f0f4c92cc3cac0..b810a78530365d0e16e1b488e75b6be2b4dfd695 100644
--- a/src/plugins/qmlprofiler/qml/MainView.qml
+++ b/src/plugins/qmlprofiler/qml/MainView.qml
@@ -51,11 +51,16 @@ Rectangle {
     property alias selectionLocked : view.selectionLocked
     signal updateLockButton
     property alias selectedItem: view.selectedItem
-    signal selectedEventIdChanged(int eventId)
+    signal selectedEventChanged(int eventId)
     property bool lockItemSelection : false
 
-    property variant names: [ qsTr("Painting"), qsTr("Compiling"), qsTr("Creating"), qsTr("Binding"), qsTr("Handling Signal")]
-    property variant colors : [ "#99CCB3", "#99CCCC", "#99B3CC", "#9999CC", "#CC99B3", "#CC99CC", "#CCCC99", "#CCB399" ]
+    property variant names: [ qsTr("Painting"),
+                              qsTr("Compiling"),
+                              qsTr("Creating"),
+                              qsTr("Binding"),
+                              qsTr("Handling Signal")]
+    property variant colors : [ "#99CCB3", "#99CCCC", "#99B3CC",
+        "#9999CC", "#CC99B3", "#CC99CC", "#CCCC99", "#CCB399" ]
 
     property variant mainviewTimePerPixel : 0
 
@@ -64,9 +69,6 @@ Rectangle {
     property int lineNumber: -1
     property int columnNumber: 0
 
-    property real elapsedTime
-    signal updateTimer
-
     signal updateRangeButton
     property bool selectionRangeMode: false
 
@@ -77,7 +79,11 @@ Rectangle {
     signal changeToolTip(string text)
     signal updateVerticalScroll(int newPosition)
 
-    property bool applicationDied : false
+    property bool recordingEnabled: false
+    property bool appKilled : false
+
+    property date recordingStartDate
+    property real elapsedTime
 
     // ***** connections with external objects
     Connections {
@@ -92,7 +98,8 @@ Rectangle {
             backgroundMarks.updateMarks(startTime, endTime);
             view.updateFlickRange(startTime, endTime);
             if (duration > 0) {
-                var candidateWidth = qmlEventList.traceDuration() * flick.width / duration;
+                var candidateWidth = qmlProfilerDataModel.traceDuration() *
+                        flick.width / duration;
                 if (flick.contentWidth !== candidateWidth)
                     flick.contentWidth = candidateWidth;
             }
@@ -101,20 +108,21 @@ Rectangle {
     }
 
     Connections {
-        target: qmlEventList
+        target: qmlProfilerDataModel
         onCountChanged: {
-            eventCount = qmlEventList.count();
+            eventCount = qmlProfilerDataModel.count();
             if (eventCount === 0)
                 root.clearAll();
             if (eventCount > 1) {
                 root.progress = Math.min(1.0,
-                    (qmlEventList.lastTimeMark() - qmlEventList.traceStartTime()) / root.elapsedTime * 1e-9 );
+                    (qmlProfilerDataModel.lastTimeMark() -
+                     qmlProfilerDataModel.traceStartTime()) / root.elapsedTime * 1e-9 );
             } else {
                 root.progress = 0;
             }
         }
         onStateChanged: {
-            switch (qmlEventList.getCurrentStateFromQml()) {
+            switch (qmlProfilerDataModel.getCurrentStateFromQml()) {
             case 0: {
                 root.clearAll();
                 break;
@@ -133,7 +141,9 @@ Rectangle {
                 dataAvailable = true;
                 view.visible = true;
                 view.requestPaint();
-                zoomControl.setRange(qmlEventList.traceStartTime(), qmlEventList.traceStartTime() + qmlEventList.traceDuration()/10);
+                zoomControl.setRange(qmlProfilerDataModel.traceStartTime(),
+                                     qmlProfilerDataModel.traceStartTime() +
+                                     qmlProfilerDataModel.traceDuration()/10);
                 break;
             }
             }
@@ -151,7 +161,7 @@ Rectangle {
     function clearData() {
         view.clearData();
         dataAvailable = false;
-        applicationDied = false;
+        appKilled = false;
         eventCount = 0;
         hideRangeDetails();
         selectionRangeMode = false;
@@ -166,8 +176,6 @@ Rectangle {
 
     function clearAll() {
         clearDisplay();
-        root.elapsedTime = 0;
-        root.updateTimer();
     }
 
     function nextEvent() {
@@ -180,9 +188,10 @@ Rectangle {
 
     function updateWindowLength(absoluteFactor) {
         var windowLength = view.endTime - view.startTime;
-        if (qmlEventList.traceEndTime() <= qmlEventList.traceStartTime() || windowLength <= 0)
+        if (qmlProfilerDataModel.traceEndTime() <= qmlProfilerDataModel.traceStartTime() ||
+                windowLength <= 0)
             return;
-        var currentFactor = windowLength / qmlEventList.traceDuration();
+        var currentFactor = windowLength / qmlProfilerDataModel.traceDuration();
         updateZoom(absoluteFactor / currentFactor);
     }
 
@@ -193,8 +202,8 @@ Rectangle {
             windowLength = min_length;
         var newWindowLength = windowLength * relativeFactor;
 
-        if (newWindowLength > qmlEventList.traceDuration()) {
-            newWindowLength = qmlEventList.traceDuration();
+        if (newWindowLength > qmlProfilerDataModel.traceDuration()) {
+            newWindowLength = qmlProfilerDataModel.traceDuration();
             relativeFactor = newWindowLength / windowLength;
         }
         if (newWindowLength < min_length) {
@@ -205,7 +214,7 @@ Rectangle {
         var fixedPoint = (view.startTime + view.endTime) / 2;
         if (view.selectedItem !== -1) {
             // center on selected item if it's inside the current screen
-            var newFixedPoint = qmlEventList.getStartTime(view.selectedItem);
+            var newFixedPoint = qmlProfilerDataModel.getStartTime(view.selectedItem);
             if (newFixedPoint >= view.startTime && newFixedPoint < view.endTime)
                 fixedPoint = newFixedPoint;
         }
@@ -222,8 +231,8 @@ Rectangle {
             windowLength = min_length;
         var newWindowLength = windowLength * relativeFactor;
 
-        if (newWindowLength > qmlEventList.traceDuration()) {
-            newWindowLength = qmlEventList.traceDuration();
+        if (newWindowLength > qmlProfilerDataModel.traceDuration()) {
+            newWindowLength = qmlProfilerDataModel.traceDuration();
             relativeFactor = newWindowLength / windowLength;
         }
         if (newWindowLength < min_length) {
@@ -241,8 +250,8 @@ Rectangle {
         var newStart = Math.floor(centerPoint - windowLength/2);
         if (newStart < 0)
             newStart = 0;
-        if (newStart + windowLength > qmlEventList.traceEndTime())
-            newStart = qmlEventList.traceEndTime() - windowLength;
+        if (newStart + windowLength > qmlProfilerDataModel.traceEndTime())
+            newStart = qmlProfilerDataModel.traceEndTime() - windowLength;
         zoomControl.setRange(newStart, newStart + windowLength);
     }
 
@@ -252,17 +261,16 @@ Rectangle {
             return;
 
         // if item is outside of the view, jump back to its position
-        if (qmlEventList.getEndTime(itemIndex) < view.startTime || qmlEventList.getStartTime(itemIndex) > view.endTime) {
-            recenter((qmlEventList.getStartTime(itemIndex) + qmlEventList.getEndTime(itemIndex)) / 2);
+        if (qmlProfilerDataModel.getEndTime(itemIndex) < view.startTime ||
+                qmlProfilerDataModel.getStartTime(itemIndex) > view.endTime) {
+            recenter((qmlProfilerDataModel.getStartTime(itemIndex) +
+                      qmlProfilerDataModel.getEndTime(itemIndex)) / 2);
         }
     }
 
-    function globalZoom() {
-        zoomControl.setRange(qmlEventList.traceStartTime(), qmlEventList.traceEndTime());
-    }
-
     function wheelZoom(wheelCenter, wheelDelta) {
-        if (qmlEventList.traceEndTime() > qmlEventList.traceStartTime() && wheelDelta !== 0) {
+        if (qmlProfilerDataModel.traceEndTime() > qmlProfilerDataModel.traceStartTime() &&
+                wheelDelta !== 0) {
             if (wheelDelta>0)
                 updateZoomCentered(wheelCenter, 1/1.2);
             else
@@ -311,34 +319,22 @@ Rectangle {
     onSelectedItemChanged: {
         if (selectedItem != -1 && !lockItemSelection) {
             lockItemSelection = true;
-            selectedEventIdChanged( qmlEventList.getEventId(selectedItem) );
+            selectedEventChanged( qmlProfilerDataModel.getEventId(selectedItem) );
             lockItemSelection = false;
         }
     }
 
-    // ***** child items
-    Timer {
-        id: elapsedTimer
-        property date startDate
-        property bool reset: true
-        running: connection.recording && connection.enabled
-        repeat: true
-        onRunningChanged: {
-            if (running) reset = true;
-        }
-        interval:  100
-        triggeredOnStart: true
-        onTriggered: {
-            if (reset) {
-                startDate = new Date();
-                reset = false;
-            }
-            var time = (new Date() - startDate)/1000;
-            root.elapsedTime = time.toFixed(1);
-            root.updateTimer();
+    onRecordingEnabledChanged: {
+        if (recordingEnabled) {
+            recordingStartDate = new Date();
+            elapsedTime = 0;
+        } else {
+            elapsedTime = (new Date() - recordingStartDate)/1000.0;
         }
     }
 
+
+    // ***** child items
     TimeMarks {
         id: backgroundMarks
         y: labels.y
@@ -380,7 +376,8 @@ Rectangle {
                 selectionRange.isDragging = false;
             }
             onDoubleClicked: {
-                zoomControl.setRange(selectionRange.startTime, selectionRange.startTime + selectionRange.duration);
+                zoomControl.setRange(selectionRange.startTime,
+                                     selectionRange.startTime + selectionRange.duration);
                 root.selectionRangeMode = false;
                 root.updateRangeButton();
             }
@@ -394,10 +391,10 @@ Rectangle {
             z: 2
         }
 
-        TimelineView {
+        TimelineRenderer {
             id: view
 
-            eventList: qmlEventList
+            profilerDataModel: qmlProfilerDataModel
 
             x: flick.contentX
             width: flick.width
@@ -405,9 +402,13 @@ Rectangle {
 
             property variant startX: 0
             onStartXChanged: {
-                var newStartTime = Math.round(startX * (endTime - startTime) / flick.width) + qmlEventList.traceStartTime();
+                var newStartTime = Math.round(startX * (endTime - startTime) / flick.width) +
+                        qmlProfilerDataModel.traceStartTime();
                 if (Math.abs(newStartTime - startTime) > 1) {
-                    var newEndTime = Math.round((startX+flick.width)* (endTime - startTime) / flick.width) + qmlEventList.traceStartTime();
+                    var newEndTime = Math.round((startX+flick.width) *
+                                                (endTime - startTime) /
+                                                flick.width) +
+                                                qmlProfilerDataModel.traceStartTime();
                     zoomControl.setRange(newStartTime, newEndTime);
                 }
 
@@ -419,7 +420,8 @@ Rectangle {
                 if (start !== startTime || end !== endTime) {
                     startTime = start;
                     endTime = end;
-                    var newStartX = (startTime - qmlEventList.traceStartTime())  * flick.width / (endTime-startTime);
+                    var newStartX = (startTime - qmlProfilerDataModel.traceStartTime()) *
+                            flick.width / (endTime-startTime);
                     if (Math.abs(newStartX - startX) >= 1)
                         startX = newStartX;
                 }
@@ -428,24 +430,25 @@ Rectangle {
             onSelectedItemChanged: {
                 if (selectedItem !== -1) {
                     // display details
-                    rangeDetails.duration = qmlEventList.getDuration(selectedItem)/1000.0;
-                    rangeDetails.label = qmlEventList.getDetails(selectedItem);
-                    rangeDetails.file = qmlEventList.getFilename(selectedItem);
-                    rangeDetails.line = qmlEventList.getLine(selectedItem);
-                    rangeDetails.column = qmlEventList.getColumn(selectedItem);
-                    rangeDetails.type = root.names[qmlEventList.getType(selectedItem)];
-                    rangeDetails.isBindingLoop = qmlEventList.getBindingLoopDest(selectedItem)!==-1;
+                    rangeDetails.duration = qmlProfilerDataModel.getDuration(selectedItem)/1000.0;
+                    rangeDetails.label = qmlProfilerDataModel.getDetails(selectedItem);
+                    rangeDetails.file = qmlProfilerDataModel.getFilename(selectedItem);
+                    rangeDetails.line = qmlProfilerDataModel.getLine(selectedItem);
+                    rangeDetails.column = qmlProfilerDataModel.getColumn(selectedItem);
+                    rangeDetails.type = root.names[qmlProfilerDataModel.getType(selectedItem)];
+                    rangeDetails.isBindingLoop = qmlProfilerDataModel.getBindingLoopDest(selectedItem)!==-1;
 
                     rangeDetails.visible = true;
 
                     // center view (horizontally)
                     var windowLength = view.endTime - view.startTime;
-                    var eventStartTime = qmlEventList.getStartTime(selectedItem);
-                    var eventEndTime = eventStartTime + qmlEventList.getDuration(selectedItem);
+                    var eventStartTime = qmlProfilerDataModel.getStartTime(selectedItem);
+                    var eventEndTime = eventStartTime +
+                            qmlProfilerDataModel.getDuration(selectedItem);
 
                     if (eventEndTime < view.startTime || eventStartTime > view.endTime) {
                         var center = (eventStartTime + eventEndTime)/2;
-                        var from = Math.min(qmlEventList.traceEndTime()-windowLength,
+                        var from = Math.min(qmlProfilerDataModel.traceEndTime()-windowLength,
                                             Math.max(0, Math.floor(center - windowLength/2)));
 
                         zoomControl.setRange(from, from + windowLength);
@@ -456,8 +459,10 @@ Rectangle {
                     if (itemY < root.scrollY) {
                         root.updateVerticalScroll(itemY);
                     } else
-                        if (itemY + root.singleRowHeight > root.scrollY + root.candidateHeight) {
-                            root.updateVerticalScroll(itemY + root.singleRowHeight - root.candidateHeight);
+                        if (itemY + root.singleRowHeight >
+                                root.scrollY + root.candidateHeight) {
+                            root.updateVerticalScroll(itemY + root.singleRowHeight -
+                                                      root.candidateHeight);
                     }
                 } else {
                     root.hideRangeDetails();
@@ -466,14 +471,18 @@ Rectangle {
 
             onItemPressed: {
                 if (pressedItem !== -1) {
-                    root.gotoSourceLocation(qmlEventList.getFilename(pressedItem), qmlEventList.getLine(pressedItem), qmlEventList.getColumn(pressedItem));
+                    root.gotoSourceLocation(qmlProfilerDataModel.getFilename(pressedItem),
+                                            qmlProfilerDataModel.getLine(pressedItem),
+                                            qmlProfilerDataModel.getColumn(pressedItem));
                 }
             }
 
          // hack to pass mouse events to the other mousearea if enabled
-            startDragArea: selectionRangeDrag.enabled ? selectionRangeDrag.x : -flick.contentX
+            startDragArea: selectionRangeDrag.enabled ? selectionRangeDrag.x :
+                                                        -flick.contentX
             endDragArea: selectionRangeDrag.enabled ?
-                             selectionRangeDrag.x + selectionRangeDrag.width : -flick.contentX-1
+                             selectionRangeDrag.x + selectionRangeDrag.width :
+                             -flick.contentX-1
         }
         MouseArea {
             id: selectionRangeControl
diff --git a/src/plugins/qmlprofiler/qml/Overview.js b/src/plugins/qmlprofiler/qml/Overview.js
index 4fe625a7fd10e7cc5e7346ae2b5e208358051386..821f3446532cc5e6ddf63bfbcf945b577527cca5 100644
--- a/src/plugins/qmlprofiler/qml/Overview.js
+++ b/src/plugins/qmlprofiler/qml/Overview.js
@@ -32,7 +32,7 @@
 
 .pragma library
 
-var qmlEventList = 0;
+var qmlProfilerDataModel = 0;
 
 //draw background of the graph
 function drawGraph(canvas, ctxt, region)
@@ -44,7 +44,7 @@ function drawGraph(canvas, ctxt, region)
 //draw the actual data to be graphed
 function drawData(canvas, ctxt, region)
 {
-    if ((!qmlEventList) || qmlEventList.count() == 0)
+    if ((!qmlProfilerDataModel) || qmlProfilerDataModel.count() == 0)
         return;
 
     var typeCount = 5;
@@ -53,17 +53,18 @@ function drawData(canvas, ctxt, region)
     var height = canvas.height - bump;
     var blockHeight = height / typeCount;
 
-    var spacing = width / qmlEventList.traceDuration();
+    var spacing = width / qmlProfilerDataModel.traceDuration();
 
     var highest = [0,0,0,0,0]; // note: change if typeCount changes
 
-    for (var ii = 0; ii < qmlEventList.count(); ++ii) {
+    for (var ii = 0; ii < qmlProfilerDataModel.count(); ++ii) {
 
-        var xx = (qmlEventList.getStartTime(ii) - qmlEventList.traceStartTime()) * spacing;
+        var xx = (qmlProfilerDataModel.getStartTime(ii) -
+                  qmlProfilerDataModel.traceStartTime()) * spacing;
         if (xx > region.x + region.width)
             continue;
 
-        var eventWidth = qmlEventList.getDuration(ii) * spacing;
+        var eventWidth = qmlProfilerDataModel.getDuration(ii) * spacing;
         if (xx + eventWidth < region.x)
             continue;
 
@@ -71,24 +72,26 @@ function drawData(canvas, ctxt, region)
             eventWidth = 1;
 
         xx = Math.round(xx);
-        var ty = qmlEventList.getType(ii);
+        var ty = qmlProfilerDataModel.getType(ii);
         if (xx + eventWidth > highest[ty]) {
             // special: animations
-            if (ty === 0 && qmlEventList.getAnimationCount(ii) >= 0) {
-                var vertScale = qmlEventList.getMaximumAnimationCount() - qmlEventList.getMinimumAnimationCount();
+            if (ty === 0 && qmlProfilerDataModel.getAnimationCount(ii) >= 0) {
+                var vertScale = qmlProfilerDataModel.getMaximumAnimationCount() -
+                        qmlProfilerDataModel.getMinimumAnimationCount();
                 if (vertScale < 1)
                     vertScale = 1;
-                var fraction = (qmlEventList.getAnimationCount(ii) - qmlEventList.getMinimumAnimationCount()) / vertScale;
+                var fraction = (qmlProfilerDataModel.getAnimationCount(ii) -
+                                qmlProfilerDataModel.getMinimumAnimationCount()) / vertScale;
                 var eventHeight = blockHeight * (fraction * 0.85 + 0.15);
                 var yy = bump + ty*blockHeight + blockHeight - eventHeight;
 
-                var fpsFraction = qmlEventList.getFramerate(ii) / 60.0;
+                var fpsFraction = qmlProfilerDataModel.getFramerate(ii) / 60.0;
                 if (fpsFraction > 1.0)
                     fpsFraction = 1.0;
                 ctxt.fillStyle = "hsl("+(fpsFraction*0.27+0.028)+",0.3,0.65)";
                 ctxt.fillRect(xx, yy, eventWidth, eventHeight);
             } else {
-                var hue = ( qmlEventList.getEventId(ii) * 25 ) % 360;
+                var hue = ( qmlProfilerDataModel.getEventId(ii) * 25 ) % 360;
                 ctxt.fillStyle = "hsl("+(hue/360.0+0.001)+",0.3,0.65)";
                 ctxt.fillRect(xx, bump + ty*blockHeight, eventWidth, blockHeight);
             }
@@ -100,12 +103,13 @@ function drawData(canvas, ctxt, region)
     ctxt.strokeStyle = "orange";
     ctxt.lineWidth = 2;
     var radius = 1;
-    for (var ii = 0; ii < qmlEventList.count(); ++ii) {
-        if (qmlEventList.getBindingLoopDest(ii) >= 0) {
-            var xcenter = Math.round(qmlEventList.getStartTime(ii) +
-                                     qmlEventList.getDuration(ii) -
-                                     qmlEventList.traceStartTime()) * spacing;
-            var ycenter = Math.round(bump + qmlEventList.getType(ii) * blockHeight + blockHeight/2);
+    for (var ii = 0; ii < qmlProfilerDataModel.count(); ++ii) {
+        if (qmlProfilerDataModel.getBindingLoopDest(ii) >= 0) {
+            var xcenter = Math.round(qmlProfilerDataModel.getStartTime(ii) +
+                                     qmlProfilerDataModel.getDuration(ii) -
+                                     qmlProfilerDataModel.traceStartTime()) * spacing;
+            var ycenter = Math.round(bump + qmlProfilerDataModel.getType(ii) *
+                                     blockHeight + blockHeight/2);
             ctxt.arc(xcenter, ycenter, radius, 0, 2*Math.PI, true);
             ctxt.stroke();
         }
@@ -114,19 +118,20 @@ function drawData(canvas, ctxt, region)
 
 function drawTimeBar(canvas, ctxt, region)
 {
-    if (!qmlEventList)
+    if (!qmlProfilerDataModel)
         return;
 
     var width = canvas.width;
     var height = 10;
-    var startTime = qmlEventList.traceStartTime();
-    var endTime = qmlEventList.traceEndTime();
+    var startTime = qmlProfilerDataModel.traceStartTime();
+    var endTime = qmlProfilerDataModel.traceEndTime();
 
-    var totalTime = qmlEventList.traceDuration();
+    var totalTime = qmlProfilerDataModel.traceDuration();
     var spacing = width / totalTime;
 
     var initialBlockLength = 120;
-    var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / width * initialBlockLength ) / Math.LN2 ) );
+    var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / width *
+                       initialBlockLength ) / Math.LN2 ) );
     var pixelsPerBlock = timePerBlock * spacing;
     var pixelsPerSection = pixelsPerBlock / 5;
     var blockCount = width / pixelsPerBlock;
diff --git a/src/plugins/qmlprofiler/qml/Overview.qml b/src/plugins/qmlprofiler/qml/Overview.qml
index 552650216903f1187c854df70afb0a05e8f381f1..c82277bc26d5d65bb6169d1037b3d696ef2580ea 100644
--- a/src/plugins/qmlprofiler/qml/Overview.qml
+++ b/src/plugins/qmlprofiler/qml/Overview.qml
@@ -51,8 +51,8 @@ Canvas2D {
     }
 
     function updateRange() {
-        var newStartTime = Math.round(rangeMover.x * qmlEventList.traceDuration() / width) + qmlEventList.traceStartTime();
-        var newEndTime = Math.round((rangeMover.x + rangeMover.width) * qmlEventList.traceDuration() / width) + qmlEventList.traceStartTime();
+        var newStartTime = Math.round(rangeMover.x * qmlProfilerDataModel.traceDuration() / width) + qmlProfilerDataModel.traceStartTime();
+        var newEndTime = Math.round((rangeMover.x + rangeMover.width) * qmlProfilerDataModel.traceDuration() / width) + qmlProfilerDataModel.traceStartTime();
         if (startTime !== newStartTime || endTime !== newEndTime) {
             zoomControl.setRange(newStartTime, newEndTime);
         }
@@ -62,13 +62,13 @@ Canvas2D {
     Connections {
         target: zoomControl
         onRangeChanged: {
-            if (qmlEventList) {
+            if (qmlProfilerDataModel) {
                 startTime = zoomControl.startTime();
                 endTime = zoomControl.endTime();
-                var newRangeX = (startTime - qmlEventList.traceStartTime()) * width / qmlEventList.traceDuration();
+                var newRangeX = (startTime - qmlProfilerDataModel.traceStartTime()) * width / qmlProfilerDataModel.traceDuration();
                 if (rangeMover.x !== newRangeX)
                     rangeMover.x = newRangeX;
-                var newWidth = (endTime-startTime) * width / qmlEventList.traceDuration();
+                var newWidth = (endTime-startTime) * width / qmlProfilerDataModel.traceDuration();
                 if (rangeMover.width !== newWidth)
                     rangeMover.width = newWidth;
             }
@@ -76,10 +76,10 @@ Canvas2D {
     }
 
     Connections {
-        target: qmlEventList
+        target: qmlProfilerDataModel
         onStateChanged: {
             // State is "done"
-            if (qmlEventList.getCurrentStateFromQml() == 3) {
+            if (qmlProfilerDataModel.getCurrentStateFromQml() == 3) {
                 dataAvailable = true;
                 requestRedraw();
             }
@@ -88,7 +88,7 @@ Canvas2D {
 
     // ***** slots
     onDrawRegion: {
-        Plotter.qmlEventList = qmlEventList;
+        Plotter.qmlProfilerDataModel = qmlProfilerDataModel;
         if (dataAvailable) {
             Plotter.plot(canvas, ctxt, region);
         } else {
diff --git a/src/plugins/qmlprofiler/qml/SelectionRange.qml b/src/plugins/qmlprofiler/qml/SelectionRange.qml
index 616fd895986c33abf9f2112a92d1a4634856c5cc..b8b650725823718d340710fc20eb0ce2eb0caea4 100644
--- a/src/plugins/qmlprofiler/qml/SelectionRange.qml
+++ b/src/plugins/qmlprofiler/qml/SelectionRange.qml
@@ -50,7 +50,7 @@ Rectangle {
     property string endTimeString: detailedPrintTime(startTime+duration)
     property string durationString: detailedPrintTime(duration)
 
-    property variant startTime: x * selectionRange.viewTimePerPixel + qmlEventList.traceStartTime()
+    property variant startTime: x * selectionRange.viewTimePerPixel + qmlProfilerDataModel.traceStartTime()
     property variant duration: width * selectionRange.viewTimePerPixel
     property variant viewTimePerPixel: 1
     property variant creationState : 0
diff --git a/src/plugins/qmlprofiler/qml/StatusDisplay.qml b/src/plugins/qmlprofiler/qml/StatusDisplay.qml
index d4507a37d63c7941e907909e8044675df3303f91..8919d07b1396c2e264b31e10781ab6630410a88d 100644
--- a/src/plugins/qmlprofiler/qml/StatusDisplay.qml
+++ b/src/plugins/qmlprofiler/qml/StatusDisplay.qml
@@ -69,7 +69,7 @@ Item {
     states: [
         // no data available
         State {
-            when: (root.eventCount == 0) && !elapsedTimer.running
+            when: (root.eventCount == 0) && !root.recordingEnabled
             PropertyChanges {
                 target: statusDisplay
                 visible: true
@@ -85,7 +85,7 @@ Item {
         },
         // running app
         State {
-            when: elapsedTimer.running
+            when: root.recordingEnabled
             PropertyChanges {
                 target: statusDisplay
                 visible: true
@@ -99,7 +99,7 @@ Item {
         // loading data
         State {
             name: "loading"
-            when: (!root.dataAvailable) && (root.eventCount > 0) && !root.applicationDied
+            when: !root.dataAvailable && (root.eventCount > 0) && !root.appKilled
             PropertyChanges {
                 target: statusDisplay
                 visible: true
@@ -118,7 +118,7 @@ Item {
         // application died
         State {
             name: "deadApp"
-            when: (!root.dataAvailable) && (root.eventCount > 0) && root.applicationDied
+            when: !root.dataAvailable && (root.eventCount > 0) && root.appKilled
             PropertyChanges {
                 target: statusDisplay
                 visible: true
diff --git a/src/plugins/qmlprofiler/qml/TimeMarks.qml b/src/plugins/qmlprofiler/qml/TimeMarks.qml
index 2cb176c0a15fd84e4848aa927a42b590fb08e73d..d38e4de7417161ff47aef485a9b4ab0f0490ba37 100644
--- a/src/plugins/qmlprofiler/qml/TimeMarks.qml
+++ b/src/plugins/qmlprofiler/qml/TimeMarks.qml
@@ -91,15 +91,15 @@ Canvas2D {
 
         // gray off out-of-bounds areas
         var rectWidth;
-        if (startTime < qmlEventList.traceStartTime()) {
+        if (startTime < qmlProfilerDataModel.traceStartTime()) {
             ctxt.fillStyle = "rgba(127,127,127,0.2)";
-            rectWidth = (qmlEventList.traceStartTime() - startTime) * spacing;
+            rectWidth = (qmlProfilerDataModel.traceStartTime() - startTime) * spacing;
             ctxt.fillRect(0, 0, rectWidth, height);
         }
-        if (endTime > qmlEventList.traceEndTime()) {
+        if (endTime > qmlProfilerDataModel.traceEndTime()) {
             ctxt.fillStyle = "rgba(127,127,127,0.2)";
-            var rectX = (qmlEventList.traceEndTime() - startTime) * spacing;
-            rectWidth = (endTime - qmlEventList.traceEndTime()) * spacing;
+            var rectX = (qmlProfilerDataModel.traceEndTime() - startTime) * spacing;
+            rectWidth = (endTime - qmlProfilerDataModel.traceEndTime()) * spacing;
             ctxt.fillRect(rectX, 0, rectWidth, height);
         }
     }
@@ -126,8 +126,8 @@ Canvas2D {
         var cumulatedHeight = 0;
         for (var i=0; i<labels.rowCount; i++) {
             cumulatedHeight += root.singleRowHeight + (labels.rowExpanded[i] ?
-                    qmlEventList.uniqueEventsOfType(i) * root.singleRowHeight :
-                    qmlEventList.maxNestingForType(i) * root.singleRowHeight);
+                    qmlProfilerDataModel.uniqueEventsOfType(i) * root.singleRowHeight :
+                    qmlProfilerDataModel.maxNestingForType(i) * root.singleRowHeight);
 
             ctxt.strokeStyle = "#B0B0B0";
             ctxt.beginPath();
diff --git a/src/plugins/qmlprofiler/qmlprofiler.pro b/src/plugins/qmlprofiler/qmlprofiler.pro
index 7403b1fb68aba82b6fc49d4e23a89b2b10f301ee..4dc919bef2560e24586056856efeca308e4ddd36 100644
--- a/src/plugins/qmlprofiler/qmlprofiler.pro
+++ b/src/plugins/qmlprofiler/qmlprofiler.pro
@@ -24,14 +24,19 @@ SOURCES += \
     qmlprofilerplugin.cpp \
     qmlprofilertool.cpp \
     qmlprofilerengine.cpp \
-    tracewindow.cpp \
-    timelineview.cpp \
     qmlprofilerattachdialog.cpp \
     localqmlprofilerrunner.cpp \
     codaqmlprofilerrunner.cpp \
     remotelinuxqmlprofilerrunner.cpp \
     qmlprofilereventview.cpp \
-    qmlprofilerdetailsrewriter.cpp
+    qmlprofilerdetailsrewriter.cpp \
+    qmlprofilertraceview.cpp \
+    timelinerenderer.cpp \
+    qmlprofilerstatemanager.cpp \
+    qv8profilerdatamodel.cpp \
+    qmlprofilerdatamodel.cpp \
+    qmlprofilerclientmanager.cpp \
+    qmlprofilerviewmanager.cpp
 
 HEADERS += \
     qmlprofilerconstants.h \
@@ -39,22 +44,26 @@ HEADERS += \
     qmlprofilerplugin.h \
     qmlprofilertool.h \
     qmlprofilerengine.h \
-    tracewindow.h \
-    timelineview.h \
     qmlprofilerattachdialog.h \
     abstractqmlprofilerrunner.h \
     localqmlprofilerrunner.h \
     codaqmlprofilerrunner.h \
     remotelinuxqmlprofilerrunner.h \
     qmlprofilereventview.h \
-    qmlprofilerdetailsrewriter.h
+    qmlprofilerdetailsrewriter.h \
+    qmlprofilertraceview.h \
+    timelinerenderer.h \
+    qmlprofilerstatemanager.h \
+    qv8profilerdatamodel.h \
+    qmlprofilerdatamodel.h \
+    qmlprofilerclientmanager.h \
+    qmlprofilerviewmanager.h
 
 RESOURCES += \
     qml/qmlprofiler.qrc
 
 OTHER_FILES += \
     qml/Detail.qml \
-    qml/Elapsed.qml \
     qml/Label.qml \
     qml/MainView.qml \
     qml/RangeDetails.qml \
@@ -64,8 +73,7 @@ OTHER_FILES += \
     qml/StatusDisplay.qml \
     qml/SelectionRange.qml \
     qml/SelectionRangeDetails.qml \
-    qml/Overview.qml \
-    qml/Overview.js
+    qml/Overview.qml
 
 FORMS += \
     qmlprofilerattachdialog.ui
diff --git a/src/plugins/qmlprofiler/qmlprofiler.qbs b/src/plugins/qmlprofiler/qmlprofiler.qbs
index 13cbca838c652f47073b7e66e4cafb24d1241f43..f4af4e4366312d718eef27cde31b2a69210ecec9 100644
--- a/src/plugins/qmlprofiler/qmlprofiler.qbs
+++ b/src/plugins/qmlprofiler/qmlprofiler.qbs
@@ -35,27 +35,37 @@ QtcPlugin {
         "codaqmlprofilerrunner.h",
         "localqmlprofilerrunner.cpp",
         "localqmlprofilerrunner.h",
-        "qmlprofiler_global.h",
         "qmlprofilerattachdialog.cpp",
         "qmlprofilerattachdialog.h",
         "qmlprofilerattachdialog.ui",
+        "qmlprofilerclientmanager.cpp",
+        "qmlprofilerclientmanager.h",
         "qmlprofilerconstants.h",
+        "qmlprofilerdatamodel.cpp",
+        "qmlprofilerdatamodel.h",
         "qmlprofilerdetailsrewriter.cpp",
         "qmlprofilerdetailsrewriter.h",
         "qmlprofilerengine.cpp",
         "qmlprofilerengine.h",
         "qmlprofilereventview.cpp",
         "qmlprofilereventview.h",
+        "qmlprofiler_global.h",
         "qmlprofilerplugin.cpp",
         "qmlprofilerplugin.h",
+        "qmlprofilerstatemanager.cpp",
+        "qmlprofilerstatemanager.h",
         "qmlprofilertool.cpp",
         "qmlprofilertool.h",
+        "qmlprofilertraceview.cpp",
+        "qmlprofilertraceview.h",
+        "qmlprofilerviewmanager.cpp",
+        "qmlprofilerviewmanager.h",
+        "qv8profilerdatamodel.cpp",
+        "qv8profilerdatamodel.h",
         "remotelinuxqmlprofilerrunner.cpp",
         "remotelinuxqmlprofilerrunner.h",
-        "timelineview.cpp",
-        "timelineview.h",
-        "tracewindow.cpp",
-        "tracewindow.h",
+        "timelinerenderer.cpp",
+        "timelinerenderer.h",
         "canvas/qdeclarativecanvas.cpp",
         "canvas/qdeclarativecanvas_p.h",
         "canvas/qdeclarativecanvastimer.cpp",
@@ -75,7 +85,8 @@ QtcPlugin {
         "qml/StatusDisplay.qml",
         "qml/TimeDisplay.qml",
         "qml/TimeMarks.qml",
-        "qml/qmlprofiler.qrc"
+        "qml/qmlprofiler.qrc",
+        "qml/Overview.js"
     ]
 }
 
diff --git a/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..01a0d787a2d74d9ecd9562ea9880adeaf7a09cc0
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp
@@ -0,0 +1,426 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "qmlprofilerclientmanager.h"
+#include "qmlprofilertool.h"
+#include "qmlprofilerplugin.h"
+
+#include <qmljsdebugclient/qdeclarativedebugclient.h>
+#include <qmljsdebugclient/qmlprofilertraceclient.h>
+#include <qmljsdebugclient/qv8profilerclient.h>
+
+#include <utils/qtcassert.h>
+#include <QWeakPointer>
+#include <QTimer>
+#include <QMessageBox>
+
+using namespace QmlJsDebugClient;
+using namespace Core;
+
+namespace QmlProfiler {
+namespace Internal {
+
+class QmlProfilerClientManager::QmlProfilerClientManagerPrivate {
+public:
+    QmlProfilerClientManagerPrivate(QmlProfilerClientManager *qq) { Q_UNUSED(qq); }
+
+    QmlProfilerStateManager* profilerState;
+
+    QDeclarativeDebugConnection *connection;
+    QWeakPointer<QmlProfilerTraceClient> qmlclientplugin;
+    QWeakPointer<QV8ProfilerClient> v8clientplugin;
+
+    QTimer connectionTimer;
+    int connectionAttempts;
+
+    enum ConnectMode {
+        TcpConnection, OstConnection
+    };
+    ConnectMode connectMode;
+    QString tcpHost;
+    quint64 tcpPort;
+    QString ostDevice;
+    QString sysroot;
+
+    bool v8DataReady;
+    bool qmlDataReady;
+};
+
+QmlProfilerClientManager::QmlProfilerClientManager(QObject *parent) :
+    QObject(parent), d(new QmlProfilerClientManagerPrivate(this))
+{
+    setObjectName("QML Profiler Connections");
+
+    d->profilerState = 0;
+
+    d->connection = 0;
+    d->connectionAttempts = 0;
+    d->v8DataReady = false;
+    d->qmlDataReady = false;
+
+    d->connectionTimer.setInterval(200);
+    connect(&d->connectionTimer, SIGNAL(timeout()), SLOT(tryToConnect()));
+}
+
+QmlProfilerClientManager::~QmlProfilerClientManager()
+{
+    disconnectClientSignals();
+    delete d->connection;
+    delete d->qmlclientplugin.data();
+    delete d->v8clientplugin.data();
+
+    delete d;
+}
+////////////////////////////////////////////////////////////////
+// Interface
+void QmlProfilerClientManager::setTcpConnection(QString host, quint64 port)
+{
+    d->connectMode = QmlProfilerClientManagerPrivate::TcpConnection;
+    d->tcpHost = host;
+    d->tcpPort = port;
+}
+
+void QmlProfilerClientManager::setOstConnection(QString ostDevice)
+{
+    d->connectMode = QmlProfilerClientManagerPrivate::OstConnection;
+    d->ostDevice = ostDevice;
+}
+
+void QmlProfilerClientManager::clearBufferedData()
+{
+    if (d->qmlclientplugin)
+        d->qmlclientplugin.data()->clearData();
+    if (d->v8clientplugin)
+        d->v8clientplugin.data()->clearData();
+}
+
+////////////////////////////////////////////////////////////////
+// Internal
+void QmlProfilerClientManager::connectClient(quint16 port)
+{
+    if (d->connection)
+        delete d->connection;
+    d->connection = new QDeclarativeDebugConnection;
+    enableServices();
+    connect(d->connection, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
+            this, SLOT(connectionStateChanged()));
+    d->connectionTimer.start();
+    d->tcpPort = port;
+}
+
+void QmlProfilerClientManager::enableServices()
+{
+    QTC_ASSERT(d->profilerState, return);
+
+    disconnectClientSignals();
+    d->profilerState->setServerRecording(false); // false by default (will be set to true when connected)
+    delete d->qmlclientplugin.data();
+    d->qmlclientplugin = new QmlProfilerTraceClient(d->connection);
+    delete d->v8clientplugin.data();
+    d->v8clientplugin = new QV8ProfilerClient(d->connection);
+    connectClientSignals();
+}
+
+void QmlProfilerClientManager::connectClientSignals()
+{
+    QTC_ASSERT(d->profilerState, return);
+    if (d->qmlclientplugin) {
+        connect(d->qmlclientplugin.data(), SIGNAL(complete()),
+                this, SLOT(qmlComplete()));
+        connect(d->qmlclientplugin.data(),
+                SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)),
+                this,
+                SIGNAL(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
+        connect(d->qmlclientplugin.data(), SIGNAL(traceFinished(qint64)),
+                this, SIGNAL(traceFinished(qint64)));
+        connect(d->qmlclientplugin.data(), SIGNAL(traceStarted(qint64)),
+                this, SIGNAL(traceStarted(qint64)));
+        connect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)),
+                this, SIGNAL(addFrameEvent(qint64,int,int)));
+        connect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()),
+                d->qmlclientplugin.data(), SLOT(sendRecordingStatus()));
+        // fixme: this should be unified for both clients
+        connect(d->qmlclientplugin.data(), SIGNAL(recordingChanged(bool)),
+                d->profilerState, SLOT(setServerRecording(bool)));
+    }
+    if (d->v8clientplugin) {
+        connect(d->v8clientplugin.data(), SIGNAL(complete()), this, SLOT(v8Complete()));
+        connect(d->v8clientplugin.data(),
+                SIGNAL(v8range(int,QString,QString,int,double,double)),
+                this,
+                SIGNAL(addV8Event(int,QString,QString,int,double,double)));
+        connect(d->v8clientplugin.data(), SIGNAL(enabledChanged()),
+                d->v8clientplugin.data(), SLOT(sendRecordingStatus()));
+    }
+}
+
+void QmlProfilerClientManager::disconnectClientSignals()
+{
+    if (d->qmlclientplugin) {
+        disconnect(d->qmlclientplugin.data(), SIGNAL(complete()),
+                   this, SLOT(qmlComplete()));
+        disconnect(d->qmlclientplugin.data(),
+                   SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)),
+                   this,
+                   SIGNAL(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
+        disconnect(d->qmlclientplugin.data(), SIGNAL(traceFinished(qint64)),
+                   this, SIGNAL(traceFinished(qint64)));
+        disconnect(d->qmlclientplugin.data(), SIGNAL(traceStarted(qint64)),
+                   this, SIGNAL(traceStarted(qint64)));
+        disconnect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)),
+                   this, SIGNAL(addFrameEvent(qint64,int,int)));
+        disconnect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()),
+                   d->qmlclientplugin.data(), SLOT(sendRecordingStatus()));
+        // fixme: this should be unified for both clients
+        disconnect(d->qmlclientplugin.data(), SIGNAL(recordingChanged(bool)),
+                   d->profilerState, SLOT(setServerRecording(bool)));
+    }
+    if (d->v8clientplugin) {
+        disconnect(d->v8clientplugin.data(), SIGNAL(complete()), this, SLOT(v8Complete()));
+        disconnect(d->v8clientplugin.data(),
+                   SIGNAL(v8range(int,QString,QString,int,double,double)),
+                   this,
+                   SIGNAL(addV8Event(int,QString,QString,int,double,double)));
+        disconnect(d->v8clientplugin.data(), SIGNAL(enabledChanged()),
+                   d->v8clientplugin.data(), SLOT(sendRecordingStatus()));
+    }
+}
+
+void QmlProfilerClientManager::connectToClient()
+{
+    if (!d->connection || d->connection->state() != QAbstractSocket::UnconnectedState)
+        return;
+
+    if (d->connectMode == QmlProfilerClientManagerPrivate::TcpConnection) {
+        QmlProfilerTool::logStatus(QString("QML Profiler: Connecting to %1:%2 ...").arg(d->tcpHost, QString::number(d->tcpPort)));
+        d->connection->connectToHost(d->tcpHost, d->tcpPort);
+    } else {
+        QmlProfilerTool::logStatus(QString("QML Profiler: Connecting to %1 ...").arg(d->tcpHost));
+        d->connection->connectToOst(d->ostDevice);
+    }
+}
+
+void QmlProfilerClientManager::disconnectClient()
+{
+    // this might be actually be called indirectly by QDDConnectionPrivate::readyRead(), therefore allow
+    // method to complete before deleting object
+    if (d->connection) {
+        d->connection->deleteLater();
+        d->connection = 0;
+    }
+}
+
+void QmlProfilerClientManager::tryToConnect()
+{
+    ++d->connectionAttempts;
+
+    if (d->connection && d->connection->isConnected()) {
+        d->connectionTimer.stop();
+        d->connectionAttempts = 0;
+    } else if (d->connectionAttempts == 50) {
+        d->connectionTimer.stop();
+        d->connectionAttempts = 0;
+
+        QMessageBox *infoBox = QmlProfilerTool::requestMessageBox();
+        infoBox->setIcon(QMessageBox::Critical);
+        infoBox->setWindowTitle(tr("Qt Creator"));
+        infoBox->setText(tr("Could not connect to the in-process QML profiler.\n"
+                            "Do you want to retry?"));
+        infoBox->setStandardButtons(QMessageBox::Retry |
+                                    QMessageBox::Cancel |
+                                    QMessageBox::Help);
+        infoBox->setDefaultButton(QMessageBox::Retry);
+        infoBox->setModal(true);
+
+        connect(infoBox, SIGNAL(finished(int)),
+                this, SLOT(retryMessageBoxFinished(int)));
+
+        infoBox->show();
+    } else {
+        connectToClient();
+    }
+}
+
+void QmlProfilerClientManager::connectionStateChanged()
+{
+    if (!d->connection)
+        return;
+    switch (d->connection->state()) {
+    case QAbstractSocket::UnconnectedState:
+    {
+        if (QmlProfilerPlugin::debugOutput)
+            qWarning("QML Profiler: disconnected");
+        break;
+    }
+    case QAbstractSocket::HostLookupState:
+        break;
+    case QAbstractSocket::ConnectingState: {
+        if (QmlProfilerPlugin::debugOutput)
+            qWarning("QML Profiler: Connecting to debug server ...");
+        break;
+    }
+    case QAbstractSocket::ConnectedState:
+    {
+        if (QmlProfilerPlugin::debugOutput)
+            qWarning("QML Profiler: connected and running");
+            // notify the client recording status
+            clientRecordingChanged();
+        break;
+    }
+    case QAbstractSocket::ClosingState:
+        if (QmlProfilerPlugin::debugOutput)
+            qWarning("QML Profiler: closing ...");
+        break;
+    case QAbstractSocket::BoundState:
+    case QAbstractSocket::ListeningState:
+        break;
+    }
+}
+
+void QmlProfilerClientManager::retryMessageBoxFinished(int result)
+{
+    switch (result) {
+    case QMessageBox::Retry: {
+        d->connectionAttempts = 0;
+        d->connectionTimer.start();
+        break;
+    }
+    case QMessageBox::Help: {
+        QmlProfilerTool::handleHelpRequest(QString("qthelp://com.nokia.qtcreator/doc/creator-debugging-qml.html"));
+        // fall through
+    }
+    default: {
+        if (d->connection) {
+            QmlProfilerTool::logStatus("QML Profiler: Failed to connect! " + d->connection->errorString());
+        } else {
+            QmlProfilerTool::logStatus("QML Profiler: Failed to connect!");
+        }
+
+        emit connectionFailed();
+        break;
+    }
+    }
+}
+
+void QmlProfilerClientManager::qmlComplete()
+{
+    d->qmlDataReady = true;
+    if (!d->v8clientplugin || d->v8clientplugin.data()->status() != QDeclarativeDebugClient::Enabled || d->v8DataReady) {
+        emit dataReadyForProcessing();
+        // once complete is sent, reset the flags
+        d->qmlDataReady = false;
+        d->v8DataReady = false;
+    }
+}
+
+void QmlProfilerClientManager::v8Complete()
+{
+    d->v8DataReady = true;
+    if (!d->qmlclientplugin || d->qmlclientplugin.data()->status() != QDeclarativeDebugClient::Enabled || d->qmlDataReady) {
+        emit dataReadyForProcessing();
+        // once complete is sent, reset the flags
+        d->v8DataReady = false;
+        d->qmlDataReady = false;
+    }
+}
+
+void QmlProfilerClientManager::stopClientsRecording()
+{
+    if (d->qmlclientplugin)
+        d->qmlclientplugin.data()->setRecording(false);
+    if (d->v8clientplugin)
+        d->v8clientplugin.data()->setRecording(false);
+}
+
+////////////////////////////////////////////////////////////////
+// Profiler State
+void QmlProfilerClientManager::registerProfilerStateManager( QmlProfilerStateManager *profilerState )
+{
+    if (d->profilerState) {
+        disconnect(d->profilerState, SIGNAL(stateChanged()),
+                   this, SLOT(profilerStateChanged()));
+        disconnect(d->profilerState, SIGNAL(clientRecordingChanged()),
+                   this, SLOT(clientRecordingChanged()));
+        disconnect(d->profilerState, SIGNAL(serverRecordingChanged()),
+                   this, SLOT(serverRecordingChanged()));
+    }
+
+    d->profilerState = profilerState;
+
+    // connect
+    if (d->profilerState) {
+        connect(d->profilerState, SIGNAL(stateChanged()),
+                this, SLOT(profilerStateChanged()));
+        connect(d->profilerState, SIGNAL(clientRecordingChanged()),
+                this, SLOT(clientRecordingChanged()));
+        connect(d->profilerState, SIGNAL(serverRecordingChanged()),
+                this, SLOT(serverRecordingChanged()));
+    }
+}
+
+void QmlProfilerClientManager::profilerStateChanged()
+{
+    QTC_ASSERT(d->profilerState, return);
+    switch (d->profilerState->currentState()) {
+    case QmlProfilerStateManager::AppStopRequested :
+        if (d->profilerState->serverRecording()) {
+            stopClientsRecording();
+        }
+        else
+            d->profilerState->setCurrentState(QmlProfilerStateManager::AppReadyToStop);
+        break;
+    default:
+        break;
+    }
+}
+
+void QmlProfilerClientManager::clientRecordingChanged()
+{
+    QTC_ASSERT(d->profilerState, return);
+    if (d->profilerState->currentState() == QmlProfilerStateManager::AppRunning) {
+        if (d->qmlclientplugin)
+            d->qmlclientplugin.data()->setRecording(d->profilerState->clientRecording());
+        if (d->v8clientplugin)
+            d->v8clientplugin.data()->setRecording(d->profilerState->clientRecording());
+    }
+}
+
+void QmlProfilerClientManager::serverRecordingChanged()
+{
+    if (d->profilerState->serverRecording()) {
+        d->v8DataReady = false;
+        d->qmlDataReady = false;
+    }
+}
+
+} // namespace Internal
+} // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/qmlprofilerclientmanager.h b/src/plugins/qmlprofiler/qmlprofilerclientmanager.h
new file mode 100644
index 0000000000000000000000000000000000000000..35766e7a5a833a6992648f43d092b47e5864480f
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilerclientmanager.h
@@ -0,0 +1,102 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef QMLPROFILERCLIENTMANAGER_H
+#define QMLPROFILERCLIENTMANAGER_H
+
+#include <QObject>
+#include <QStringList>
+
+#include "qmlprofilerstatemanager.h"
+#include <qmljsdebugclient/qmlprofilereventlocation.h>
+
+namespace QmlProfiler {
+namespace Internal {
+
+class QmlProfilerClientManager : public QObject
+{
+    Q_OBJECT
+public:
+    explicit QmlProfilerClientManager(QObject *parent = 0);
+    ~QmlProfilerClientManager();
+
+    void registerProfilerStateManager(QmlProfilerStateManager *profilerState);
+
+    void setTcpConnection(QString host, quint64 port);
+    void setOstConnection(QString ostDevice);
+
+    void clearBufferedData();
+
+signals:
+    void connectionFailed();
+
+    // data
+    void addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation);
+    void addV8Event(int,QString,QString,int,double,double);
+    void addFrameEvent(qint64,int,int);
+    void traceStarted(qint64);
+    void traceFinished(qint64);
+    void dataReadyForProcessing();
+
+public slots:
+    void connectClient(quint16 port);
+    void disconnectClient();
+
+private slots:
+    void tryToConnect();
+    void connectionStateChanged();
+    void retryMessageBoxFinished(int result);
+
+    void qmlComplete();
+    void v8Complete();
+
+    void profilerStateChanged();
+    void clientRecordingChanged();
+    void serverRecordingChanged();
+
+private:
+    class QmlProfilerClientManagerPrivate;
+    QmlProfilerClientManagerPrivate *d;
+
+    void connectToClient();
+
+    void enableServices();
+    void connectClientSignals();
+    void disconnectClientSignals();
+
+    void stopClientsRecording();
+};
+
+}
+}
+
+#endif // QMLPROFILERCLIENTMANAGER_H
diff --git a/src/plugins/qmlprofiler/qmlprofilerconstants.h b/src/plugins/qmlprofiler/qmlprofilerconstants.h
index 38a47c11f10325436c1fe469e2630c250d074d3c..fec1b6b539add9a7ae8b0fe7679262d08d9fb6c1 100644
--- a/src/plugins/qmlprofiler/qmlprofilerconstants.h
+++ b/src/plugins/qmlprofiler/qmlprofilerconstants.h
@@ -37,6 +37,7 @@ namespace QmlProfiler {
 namespace Constants {
 
 const char ATTACH[] = "Menu.Analyzer.Attach";
+const char TraceFileExtension[] = ".qtd";
 
 } // namespace Constants
 } // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp b/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..750bbb0f0db0b40773f14f3227282b0e6ad04914
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp
@@ -0,0 +1,1652 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "qmlprofilerdatamodel.h"
+
+#include <QUrl>
+#include <QHash>
+#include <QtAlgorithms>
+#include <QString>
+#include <QStringList>
+
+#include <QFile>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+
+#include <QTimer>
+#include <utils/qtcassert.h>
+
+using namespace QmlJsDebugClient;
+
+namespace QmlProfiler {
+namespace Internal {
+
+///////////////////////////////////////////////////////////
+QmlRangeEventData::QmlRangeEventData()
+{
+    eventType = MaximumQmlEventType;
+    eventId = -1;
+    duration = 0;
+    calls = 0;
+    minTime = 0;
+    maxTime = 0;
+    timePerCall = 0;
+    percentOfTime = 0;
+    medianTime = 0;
+    isBindingLoop = false;
+}
+
+QmlRangeEventData::~QmlRangeEventData()
+{
+    qDeleteAll(parentHash.values());
+    parentHash.clear();
+    qDeleteAll(childrenHash.values());
+    childrenHash.clear();
+}
+
+QmlRangeEventData &QmlRangeEventData::operator=(const QmlRangeEventData &ref)
+{
+    if (this == &ref)
+        return *this;
+
+    displayName = ref.displayName;
+    location = ref.location;
+    eventHashStr = ref.eventHashStr;
+    details = ref.details;
+    eventType = ref.eventType;
+    duration = ref.duration;
+    calls = ref.calls;
+    minTime = ref.minTime;
+    maxTime = ref.maxTime;
+    timePerCall = ref.timePerCall;
+    percentOfTime = ref.percentOfTime;
+    medianTime = ref.medianTime;
+    eventId = ref.eventId;
+    isBindingLoop = ref.isBindingLoop;
+
+    qDeleteAll(parentHash.values());
+    parentHash.clear();
+    foreach (const QString &key, ref.parentHash.keys()) {
+        parentHash.insert(key, new QmlRangeEventRelative(ref.parentHash.value(key)));
+    }
+
+    qDeleteAll(childrenHash.values());
+    childrenHash.clear();
+    foreach (const QString &key, ref.childrenHash.keys()) {
+        childrenHash.insert(key, new QmlRangeEventRelative(ref.childrenHash.value(key)));
+    }
+
+    return *this;
+}
+
+///////////////////////////////////////////////////////////
+
+// endtimedata
+struct QmlRangeEventEndInstance {
+    qint64 endTime;
+    int startTimeIndex;
+    QmlRangeEventData *description;
+};
+
+// starttimedata
+struct QmlRangeEventStartInstance {
+    qint64 startTime;
+    qint64 duration;
+    qint64 level;
+    int endTimeIndex;
+    qint64 nestingLevel;
+    qint64 nestingDepth;
+    QmlRangeEventData *statsInfo;
+
+    // animation-related data
+    int frameRate;
+    int animationCount;
+
+    int bindingLoopHead;
+};
+
+struct QmlRangeEventTypeCount {
+    QVector<int> eventIds;
+    int nestingCount;
+};
+
+// used by quicksort
+bool compareEndTimes(const QmlRangeEventEndInstance &t1, const QmlRangeEventEndInstance &t2)
+{
+    return t1.endTime < t2.endTime;
+}
+
+bool compareStartTimes(const QmlRangeEventStartInstance &t1, const QmlRangeEventStartInstance &t2)
+{
+    return t1.startTime < t2.startTime;
+}
+
+bool compareStartIndexes(const QmlRangeEventEndInstance &t1, const QmlRangeEventEndInstance &t2)
+{
+    return t1.startTimeIndex < t2.startTimeIndex;
+}
+
+//////////////////////////////////////////////////////////////
+class QmlProfilerDataModel::QmlProfilerDataModelPrivate
+{
+public:
+    QmlProfilerDataModelPrivate(QmlProfilerDataModel *qq) : q(qq) {}
+
+    QmlProfilerDataModel *q;
+
+    // convenience functions
+    void clearQmlRootEvent();
+    void insertQmlRootEvent();
+    void postProcess();
+    void sortEndTimes();
+    void findAnimationLimits();
+    void sortStartTimes();
+    void computeNestingLevels();
+    void computeNestingDepth();
+    void prepareForDisplay();
+    void linkStartsToEnds();
+    void linkEndsToStarts();
+    bool checkBindingLoop(QmlRangeEventData *from, QmlRangeEventData *current, QList<QmlRangeEventData *>visited);
+
+
+    // stats
+    void clearStatistics();
+    void redoTree(qint64 fromTime, qint64 toTime);
+    void computeMedianTime(qint64 fromTime, qint64 toTime);
+    void findBindingLoops(qint64 fromTime, qint64 toTime);
+
+    QmlProfilerDataModel::State listState;
+
+    // Stored data
+    QHash<QString, QmlRangeEventData *> rangeEventDictionary;
+    QVector<QmlRangeEventEndInstance> endInstanceList;
+    QVector<QmlRangeEventStartInstance> startInstanceList;
+
+    QmlRangeEventData qmlRootEvent;
+
+    QV8ProfilerDataModel *v8DataModel;
+
+    QHash<int, QmlRangeEventTypeCount *> typeCounts;
+
+    qint64 traceEndTime;
+    qint64 traceStartTime;
+    qint64 qmlMeasuredTime;
+
+    QmlRangeEventStartInstance *lastFrameEvent;
+    qint64 maxAnimationCount;
+    qint64 minAnimationCount;
+
+    // file to load
+    QString fileName;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////
+
+
+QmlProfilerDataModel::QmlProfilerDataModel(QObject *parent) :
+    QObject(parent), d(new QmlProfilerDataModelPrivate(this))
+{
+    setObjectName("QmlProfilerDataModel");
+
+    d->listState = Empty;
+
+    d->traceEndTime = 0;
+    d->traceStartTime = -1;
+    d->qmlMeasuredTime = 0;
+    d->clearQmlRootEvent();
+    d->lastFrameEvent = 0;
+    d->maxAnimationCount = 0;
+    d->minAnimationCount = 0;
+    d->v8DataModel = new QV8ProfilerDataModel(this, this);
+}
+
+QmlProfilerDataModel::~QmlProfilerDataModel()
+{
+    clear();
+    delete d;
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+QList<QmlRangeEventData *> QmlProfilerDataModel::getEventDescriptions() const
+{
+    return d->rangeEventDictionary.values();
+}
+
+QmlRangeEventData *QmlProfilerDataModel::eventDescription(int eventId) const
+{
+    foreach (QmlRangeEventData *event, d->rangeEventDictionary.values()) {
+        if (event->eventId == eventId)
+            return event;
+    }
+    return 0;
+}
+
+QList<QV8EventData *> QmlProfilerDataModel::getV8Events() const
+{
+    return d->v8DataModel->getV8Events();
+}
+
+QV8EventData *QmlProfilerDataModel::v8EventDescription(int eventId) const
+{
+    return d->v8DataModel->v8EventDescription(eventId);
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+
+void QmlProfilerDataModel::clear()
+{
+    qDeleteAll(d->rangeEventDictionary.values());
+    d->rangeEventDictionary.clear();
+
+    d->endInstanceList.clear();
+    d->startInstanceList.clear();
+
+    d->clearQmlRootEvent();
+
+    foreach (QmlRangeEventTypeCount *typeCount, d->typeCounts.values())
+        delete typeCount;
+    d->typeCounts.clear();
+
+    d->traceEndTime = 0;
+    d->traceStartTime = -1;
+    d->qmlMeasuredTime = 0;
+
+    d->lastFrameEvent = 0;
+    d->maxAnimationCount = 0;
+    d->minAnimationCount = 0;
+
+    d->v8DataModel->clear();
+
+    emit countChanged();
+    setState(Empty);
+}
+
+void QmlProfilerDataModel::addRangedEvent(int type, qint64 startTime, qint64 length,
+                                          const QStringList &data,
+                                          const QmlJsDebugClient::QmlEventLocation &location)
+{
+    const QChar colon = QLatin1Char(':');
+    QString displayName, eventHashStr, details;
+    QmlJsDebugClient::QmlEventLocation eventLocation = location;
+
+    setState(AcquiringData);
+
+    // generate details string
+    if (data.isEmpty())
+        details = tr("Source code not available");
+    else {
+        details = data.join(" ").replace('\n'," ").simplified();
+        QRegExp rewrite("\\(function \\$(\\w+)\\(\\) \\{ (return |)(.+) \\}\\)");
+        bool match = rewrite.exactMatch(details);
+        if (match) {
+            details = rewrite.cap(1) + ": " + rewrite.cap(3);
+        }
+        if (details.startsWith(QString("file://")))
+            details = details.mid(details.lastIndexOf(QChar('/')) + 1);
+    }
+
+    // backwards compatibility: "compiling" events don't have a proper location in older
+    // version of the protocol, but the filename is passed in the details string
+    if (type == QmlJsDebugClient::Compiling && eventLocation.filename.isEmpty()) {
+        eventLocation.filename = details;
+        eventLocation.line = 1;
+        eventLocation.column = 1;
+    }
+
+    // generate hash
+    if (eventLocation.filename.isEmpty()) {
+        displayName = tr("<bytecode>");
+        eventHashStr = getHashStringForQmlEvent(eventLocation, type);
+    } else {
+        const QString filePath = QUrl(eventLocation.filename).path();
+        displayName = filePath.mid(filePath.lastIndexOf(QChar('/')) + 1) + colon +
+                QString::number(eventLocation.line);
+        eventHashStr = getHashStringForQmlEvent(eventLocation, type);
+    }
+
+    QmlRangeEventData *newEvent;
+    if (d->rangeEventDictionary.contains(eventHashStr)) {
+        newEvent = d->rangeEventDictionary[eventHashStr];
+    } else {
+        newEvent = new QmlRangeEventData;
+        newEvent->displayName = displayName;
+        newEvent->location = eventLocation;
+        newEvent->eventHashStr = eventHashStr;
+        newEvent->eventType = (QmlJsDebugClient::QmlEventType)type;
+        newEvent->details = details;
+        d->rangeEventDictionary.insert(eventHashStr, newEvent);
+    }
+
+    QmlRangeEventEndInstance endTimeData;
+    endTimeData.endTime = startTime + length;
+    endTimeData.description = newEvent;
+    endTimeData.startTimeIndex = d->startInstanceList.count();
+
+    QmlRangeEventStartInstance startTimeData;
+    startTimeData.startTime = startTime;
+    startTimeData.duration = length;
+    startTimeData.statsInfo = newEvent;
+    startTimeData.endTimeIndex = d->endInstanceList.count();
+    startTimeData.animationCount = -1;
+    startTimeData.frameRate = 1e9/length;
+
+    d->endInstanceList << endTimeData;
+    d->startInstanceList << startTimeData;
+
+    emit countChanged();
+}
+
+void QmlProfilerDataModel::addV8Event(int depth, const QString &function,
+                                      const QString &filename, int lineNumber,
+                                      double totalTime, double selfTime)
+{
+    d->v8DataModel->addV8Event(depth, function, filename, lineNumber, totalTime, selfTime);
+}
+
+void QmlProfilerDataModel::addFrameEvent(qint64 time, int framerate, int animationcount)
+{
+    QString displayName, eventHashStr, details;
+
+    setState(AcquiringData);
+
+    details = tr("Animation Timer Update");
+    displayName = tr("<Animation Update>");
+    eventHashStr = displayName;
+
+    QmlRangeEventData *newEvent;
+    if (d->rangeEventDictionary.contains(eventHashStr)) {
+        newEvent = d->rangeEventDictionary[eventHashStr];
+    } else {
+        newEvent = new QmlRangeEventData;
+        newEvent->displayName = displayName;
+        newEvent->eventHashStr = eventHashStr;
+        newEvent->eventType = QmlJsDebugClient::Painting;
+        newEvent->details = details;
+        d->rangeEventDictionary.insert(eventHashStr, newEvent);
+    }
+
+    qint64 length = 1e9/framerate;
+    // avoid overlap
+    if (d->lastFrameEvent &&
+            d->lastFrameEvent->startTime + d->lastFrameEvent->duration >= time) {
+        d->lastFrameEvent->duration = time - 1 - d->lastFrameEvent->startTime;
+        d->endInstanceList[d->lastFrameEvent->endTimeIndex].endTime =
+                d->lastFrameEvent->startTime + d->lastFrameEvent->duration;
+    }
+
+    QmlRangeEventEndInstance endTimeData;
+    endTimeData.endTime = time + length;
+    endTimeData.description = newEvent;
+    endTimeData.startTimeIndex = d->startInstanceList.count();
+
+    QmlRangeEventStartInstance startTimeData;
+    startTimeData.startTime = time;
+    startTimeData.duration = length;
+    startTimeData.statsInfo = newEvent;
+    startTimeData.endTimeIndex = d->endInstanceList.count();
+    startTimeData.animationCount = animationcount;
+    startTimeData.frameRate = framerate;
+
+    d->endInstanceList << endTimeData;
+    d->startInstanceList << startTimeData;
+
+    d->lastFrameEvent = &d->startInstanceList.last();
+
+    emit countChanged();
+}
+
+void QmlProfilerDataModel::setTraceEndTime(qint64 time)
+{
+    d->traceEndTime = time;
+}
+
+void QmlProfilerDataModel::setTraceStartTime(qint64 time)
+{
+    d->traceStartTime = time;
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+
+QString QmlProfilerDataModel::getHashStringForQmlEvent(
+        const QmlJsDebugClient::QmlEventLocation &location, int eventType)
+{
+    return QString("%1:%2:%3:%4").arg(location.filename,
+                                      QString::number(location.line),
+                                      QString::number(location.column),
+                                      QString::number(eventType));
+}
+
+QString QmlProfilerDataModel::getHashStringForV8Event(const QString &displayName,
+                                                      const QString &function)
+{
+    return QString("%1:%2").arg(displayName, function);
+}
+
+QString QmlProfilerDataModel::rootEventName()
+{
+    return tr("<program>");
+}
+
+QString QmlProfilerDataModel::rootEventDescription()
+{
+    return tr("Main Program");
+}
+
+QString QmlProfilerDataModel::qmlEventTypeAsString(QmlEventType typeEnum)
+{
+    switch (typeEnum) {
+    case Painting:
+        return QLatin1String(Constants::TYPE_PAINTING_STR);
+        break;
+    case Compiling:
+        return QLatin1String(Constants::TYPE_COMPILING_STR);
+        break;
+    case Creating:
+        return QLatin1String(Constants::TYPE_CREATING_STR);
+        break;
+    case Binding:
+        return QLatin1String(Constants::TYPE_BINDING_STR);
+        break;
+    case HandlingSignal:
+        return QLatin1String(Constants::TYPE_HANDLINGSIGNAL_STR);
+        break;
+    default:
+        return QString::number((int)typeEnum);
+    }
+}
+
+QmlEventType QmlProfilerDataModel::qmlEventTypeAsEnum(const QString &typeString)
+{
+    if (typeString == QLatin1String(Constants::TYPE_PAINTING_STR)) {
+        return Painting;
+    } else if (typeString == QLatin1String(Constants::TYPE_COMPILING_STR)) {
+        return Compiling;
+    } else if (typeString == QLatin1String(Constants::TYPE_CREATING_STR)) {
+        return Creating;
+    } else if (typeString == QLatin1String(Constants::TYPE_BINDING_STR)) {
+        return Binding;
+    } else if (typeString == QLatin1String(Constants::TYPE_HANDLINGSIGNAL_STR)) {
+        return HandlingSignal;
+    } else {
+        bool isNumber = false;
+        int type = typeString.toUInt(&isNumber);
+        if (isNumber) {
+            return (QmlEventType)type;
+        } else {
+            return MaximumQmlEventType;
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+
+int QmlProfilerDataModel::findFirstIndex(qint64 startTime) const
+{
+    int candidate = -1;
+    // in the "endtime" list, find the first event that ends after startTime
+    if (d->endInstanceList.isEmpty())
+        return 0; // -1
+    if (d->endInstanceList.count() == 1 || d->endInstanceList.first().endTime >= startTime)
+        candidate = 0;
+    else
+        if (d->endInstanceList.last().endTime <= startTime)
+            return 0; // -1
+
+    if (candidate == -1)
+    {
+        int fromIndex = 0;
+        int toIndex = d->endInstanceList.count()-1;
+        while (toIndex - fromIndex > 1) {
+            int midIndex = (fromIndex + toIndex)/2;
+            if (d->endInstanceList[midIndex].endTime < startTime)
+                fromIndex = midIndex;
+            else
+                toIndex = midIndex;
+        }
+
+        candidate = toIndex;
+    }
+
+    int ndx = d->endInstanceList[candidate].startTimeIndex;
+
+    // and then go to the parent
+    while (ndx > 0 && d->startInstanceList[ndx].level > d->startInstanceList[ndx-1].level )
+        ndx--;
+
+    return ndx;
+}
+
+int QmlProfilerDataModel::findFirstIndexNoParents(qint64 startTime) const
+{
+    int candidate = -1;
+    // in the "endtime" list, find the first event that ends after startTime
+    if (d->endInstanceList.isEmpty())
+        return 0; // -1
+    if (d->endInstanceList.count() == 1 || d->endInstanceList.first().endTime >= startTime)
+        candidate = 0;
+    else
+        if (d->endInstanceList.last().endTime <= startTime)
+            return 0; // -1
+
+    if (candidate == -1) {
+        int fromIndex = 0;
+        int toIndex = d->endInstanceList.count()-1;
+        while (toIndex - fromIndex > 1) {
+            int midIndex = (fromIndex + toIndex)/2;
+            if (d->endInstanceList[midIndex].endTime < startTime)
+                fromIndex = midIndex;
+            else
+                toIndex = midIndex;
+        }
+
+        candidate = toIndex;
+    }
+
+    int ndx = d->endInstanceList[candidate].startTimeIndex;
+
+    return ndx;
+}
+
+int QmlProfilerDataModel::findLastIndex(qint64 endTime) const
+{
+    // in the "starttime" list, find the last event that starts before endtime
+    if (d->startInstanceList.isEmpty())
+        return 0; // -1
+    if (d->startInstanceList.first().startTime >= endTime)
+        return 0; // -1
+    if (d->startInstanceList.count() == 1)
+        return 0;
+    if (d->startInstanceList.last().startTime <= endTime)
+        return d->startInstanceList.count()-1;
+
+    int fromIndex = 0;
+    int toIndex = d->startInstanceList.count()-1;
+    while (toIndex - fromIndex > 1) {
+        int midIndex = (fromIndex + toIndex)/2;
+        if (d->startInstanceList[midIndex].startTime < endTime)
+            fromIndex = midIndex;
+        else
+            toIndex = midIndex;
+    }
+
+    return fromIndex;
+}
+
+qint64 QmlProfilerDataModel::firstTimeMark() const
+{
+    if (d->startInstanceList.isEmpty())
+        return 0;
+    else {
+        return d->startInstanceList[0].startTime;
+    }
+}
+
+qint64 QmlProfilerDataModel::lastTimeMark() const
+{
+    if (d->endInstanceList.isEmpty())
+        return 0;
+    else {
+        return d->endInstanceList.last().endTime;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+
+int QmlProfilerDataModel::count() const
+{
+    return d->startInstanceList.count();
+}
+
+bool QmlProfilerDataModel::isEmpty() const
+{
+    return d->startInstanceList.isEmpty() && d->v8DataModel->isEmpty();
+}
+
+qint64 QmlProfilerDataModel::getStartTime(int index) const
+{
+    return d->startInstanceList[index].startTime;
+}
+
+qint64 QmlProfilerDataModel::getEndTime(int index) const
+{
+    return d->startInstanceList[index].startTime + d->startInstanceList[index].duration;
+}
+
+qint64 QmlProfilerDataModel::getDuration(int index) const
+{
+    return d->startInstanceList[index].duration;
+}
+
+int QmlProfilerDataModel::getType(int index) const
+{
+    return d->startInstanceList[index].statsInfo->eventType;
+}
+
+int QmlProfilerDataModel::getNestingLevel(int index) const
+{
+    return d->startInstanceList[index].nestingLevel;
+}
+
+int QmlProfilerDataModel::getNestingDepth(int index) const
+{
+    return d->startInstanceList[index].nestingDepth;
+}
+
+QString QmlProfilerDataModel::getFilename(int index) const
+{
+    return d->startInstanceList[index].statsInfo->location.filename;
+}
+
+int QmlProfilerDataModel::getLine(int index) const
+{
+    return d->startInstanceList[index].statsInfo->location.line;
+}
+
+int QmlProfilerDataModel::getColumn(int index) const
+{
+    return d->startInstanceList[index].statsInfo->location.column;
+}
+
+QString QmlProfilerDataModel::getDetails(int index) const
+{
+    // special: animations
+    if (d->startInstanceList[index].statsInfo->eventType == QmlJsDebugClient::Painting &&
+            d->startInstanceList[index].animationCount >= 0)
+        return tr("%1 animations at %2 FPS").arg(
+                    QString::number(d->startInstanceList[index].animationCount),
+                    QString::number(d->startInstanceList[index].frameRate));
+    return d->startInstanceList[index].statsInfo->details;
+}
+
+int QmlProfilerDataModel::getEventId(int index) const
+{
+    return d->startInstanceList[index].statsInfo->eventId;
+}
+
+int QmlProfilerDataModel::getBindingLoopDest(int index) const
+{
+    return d->startInstanceList[index].bindingLoopHead;
+}
+
+int QmlProfilerDataModel::getFramerate(int index) const
+{
+    return d->startInstanceList[index].frameRate;
+}
+
+int QmlProfilerDataModel::getAnimationCount(int index) const
+{
+    return d->startInstanceList[index].animationCount;
+}
+
+int QmlProfilerDataModel::getMaximumAnimationCount() const
+{
+    return d->maxAnimationCount;
+}
+
+int QmlProfilerDataModel::getMinimumAnimationCount() const
+{
+    return d->minAnimationCount;
+}
+
+/////////////////////////////////////////
+
+int QmlProfilerDataModel::uniqueEventsOfType(int type) const
+{
+    if (!d->typeCounts.contains(type))
+        return 0;
+    return d->typeCounts[type]->eventIds.count();
+}
+
+int QmlProfilerDataModel::maxNestingForType(int type) const
+{
+    if (!d->typeCounts.contains(type))
+        return 0;
+    return d->typeCounts[type]->nestingCount;
+}
+
+QString QmlProfilerDataModel::eventTextForType(int type, int index) const
+{
+    if (!d->typeCounts.contains(type))
+        return QString();
+    return d->rangeEventDictionary.values().at(d->typeCounts[type]->eventIds[index])->details;
+}
+
+QString QmlProfilerDataModel::eventDisplayNameForType(int type, int index) const
+{
+    if (!d->typeCounts.contains(type))
+        return QString();
+    return d->rangeEventDictionary.values().at(d->typeCounts[type]->eventIds[index])->displayName;
+}
+
+int QmlProfilerDataModel::eventIdForType(int type, int index) const
+{
+    if (!d->typeCounts.contains(type))
+        return -1;
+    return d->typeCounts[type]->eventIds[index];
+}
+
+int QmlProfilerDataModel::eventPosInType(int index) const
+{
+    int eventType = d->startInstanceList[index].statsInfo->eventType;
+    return d->typeCounts[eventType]->eventIds.indexOf(d->startInstanceList[index].statsInfo->eventId);
+}
+
+/////////////////////////////////////////
+
+qint64 QmlProfilerDataModel::traceStartTime() const
+{
+    return d->traceStartTime != -1? d->traceStartTime : firstTimeMark();
+}
+
+qint64 QmlProfilerDataModel::traceEndTime() const
+{
+    return d->traceEndTime ? d->traceEndTime : lastTimeMark();
+}
+
+qint64 QmlProfilerDataModel::traceDuration() const
+{
+    return traceEndTime() - traceStartTime();
+}
+
+qint64 QmlProfilerDataModel::qmlMeasuredTime() const
+{
+    return d->qmlMeasuredTime;
+}
+qint64 QmlProfilerDataModel::v8MeasuredTime() const
+{
+    return d->v8DataModel->v8MeasuredTime();
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+
+void QmlProfilerDataModel::complete()
+{
+    if (currentState() == AcquiringData) {
+        setState(ProcessingData);
+        d->v8DataModel->collectV8Statistics();
+        d->postProcess();
+    } else
+    if (currentState() == Empty) {
+        setState(Done);
+    } else {
+        emit error("Unexpected complete signal in data model");
+    }
+}
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::postProcess()
+{
+    if (q->count() != 0) {
+        sortStartTimes();
+        sortEndTimes();
+        findAnimationLimits();
+        computeNestingLevels();
+        computeNestingDepth();
+        linkEndsToStarts();
+        insertQmlRootEvent();
+        q->reloadDetails();
+        prepareForDisplay();
+        q->compileStatistics(q->traceStartTime(), q->traceEndTime());
+
+    }
+    q->setState(Done);
+}
+
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::prepareForDisplay()
+{
+    // generate numeric ids
+    int ndx = 0;
+    foreach (QmlRangeEventData *binding, rangeEventDictionary.values()) {
+        binding->eventId = ndx++;
+    }
+
+    // collect type counts
+    foreach (const QmlRangeEventStartInstance &eventStartData, startInstanceList) {
+        int typeNumber = eventStartData.statsInfo->eventType;
+        if (!typeCounts.contains(typeNumber)) {
+            typeCounts[typeNumber] = new QmlRangeEventTypeCount;
+            typeCounts[typeNumber]->nestingCount = 0;
+        }
+        if (eventStartData.nestingLevel > typeCounts[typeNumber]->nestingCount) {
+            typeCounts[typeNumber]->nestingCount = eventStartData.nestingLevel;
+        }
+        if (!typeCounts[typeNumber]->eventIds.contains(eventStartData.statsInfo->eventId))
+            typeCounts[typeNumber]->eventIds << eventStartData.statsInfo->eventId;
+    }
+}
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::sortStartTimes()
+{
+    if (startInstanceList.count() < 2)
+        return;
+
+    // assuming startTimes is partially sorted
+    // identify blocks of events and sort them with quicksort
+    QVector<QmlRangeEventStartInstance>::iterator itFrom = startInstanceList.end() - 2;
+    QVector<QmlRangeEventStartInstance>::iterator itTo = startInstanceList.end() - 1;
+
+    while (itFrom != startInstanceList.begin() && itTo != startInstanceList.begin()) {
+        // find block to sort
+        while (itFrom != startInstanceList.begin()
+                && itTo->startTime > itFrom->startTime) {
+            itTo--;
+            itFrom = itTo - 1;
+        }
+
+        // if we're at the end of the list
+        if (itFrom == startInstanceList.begin())
+            break;
+
+        // find block length
+        while (itFrom != startInstanceList.begin()
+                && itTo->startTime <= itFrom->startTime)
+            itFrom--;
+
+        if (itTo->startTime <= itFrom->startTime)
+            qSort(itFrom, itTo + 1, compareStartTimes);
+        else
+            qSort(itFrom + 1, itTo + 1, compareStartTimes);
+
+        // move to next block
+        itTo = itFrom;
+        itFrom = itTo - 1;
+    }
+
+    // link back the endTimes
+    linkEndsToStarts();
+}
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::sortEndTimes()
+{
+    // assuming endTimes is partially sorted
+    // identify blocks of events and sort them with quicksort
+
+    if (endInstanceList.count() < 2)
+        return;
+
+    QVector<QmlRangeEventEndInstance>::iterator itFrom = endInstanceList.begin();
+    QVector<QmlRangeEventEndInstance>::iterator itTo = endInstanceList.begin() + 1;
+
+    while (itTo != endInstanceList.end() && itFrom != endInstanceList.end()) {
+        // find block to sort
+        while (itTo != endInstanceList.end()
+                && startInstanceList[itTo->startTimeIndex].startTime >
+                startInstanceList[itFrom->startTimeIndex].startTime +
+                startInstanceList[itFrom->startTimeIndex].duration) {
+            itFrom++;
+            itTo = itFrom+1;
+        }
+
+        // if we're at the end of the list
+        if (itTo == endInstanceList.end())
+            break;
+
+        // find block length
+        while (itTo != endInstanceList.end()
+                && startInstanceList[itTo->startTimeIndex].startTime <=
+                startInstanceList[itFrom->startTimeIndex].startTime +
+                startInstanceList[itFrom->startTimeIndex].duration)
+            itTo++;
+
+        // sort block
+        qSort(itFrom, itTo, compareEndTimes);
+
+        // move to next block
+        itFrom = itTo;
+        itTo = itFrom+1;
+
+    }
+
+    // link back the startTimes
+    linkStartsToEnds();
+}
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::linkStartsToEnds()
+{
+    for (int i = 0; i < endInstanceList.count(); i++)
+        startInstanceList[endInstanceList[i].startTimeIndex].endTimeIndex = i;
+}
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::findAnimationLimits()
+{
+    maxAnimationCount = 0;
+    minAnimationCount = 0;
+    lastFrameEvent = 0;
+
+    for (int i = 0; i < startInstanceList.count(); i++) {
+        if (startInstanceList[i].statsInfo->eventType == QmlJsDebugClient::Painting &&
+                startInstanceList[i].animationCount >= 0) {
+            int animationcount = startInstanceList[i].animationCount;
+            if (lastFrameEvent) {
+                if (animationcount > maxAnimationCount)
+                    maxAnimationCount = animationcount;
+                if (animationcount < minAnimationCount)
+                    minAnimationCount = animationcount;
+            } else {
+                maxAnimationCount = animationcount;
+                minAnimationCount = animationcount;
+            }
+            lastFrameEvent = &startInstanceList[i];
+        }
+    }
+}
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::computeNestingLevels()
+{
+    // compute levels
+    QHash<int, qint64> endtimesPerLevel;
+    QList<int> nestingLevels;
+    QList< QHash<int, qint64> > endtimesPerNestingLevel;
+    int level = Constants::QML_MIN_LEVEL;
+    endtimesPerLevel[Constants::QML_MIN_LEVEL] = 0;
+
+    for (int i = 0; i < QmlJsDebugClient::MaximumQmlEventType; i++) {
+        nestingLevels << Constants::QML_MIN_LEVEL;
+        QHash<int, qint64> dummyHash;
+        dummyHash[Constants::QML_MIN_LEVEL] = 0;
+        endtimesPerNestingLevel << dummyHash;
+    }
+
+    for (int i=0; i<startInstanceList.count(); i++) {
+        qint64 st = startInstanceList[i].startTime;
+        int type = startInstanceList[i].statsInfo->eventType;
+
+        if (type == QmlJsDebugClient::Painting) {
+            // animation/paint events have level 0 by definition (same as "mainprogram"),
+            // but are not considered parents of other events for statistical purposes
+            startInstanceList[i].level = Constants::QML_MIN_LEVEL - 1;
+            startInstanceList[i].nestingLevel = Constants::QML_MIN_LEVEL;
+            continue;
+        }
+
+        // general level
+        if (endtimesPerLevel[level] > st) {
+            level++;
+        } else {
+            while (level > Constants::QML_MIN_LEVEL && endtimesPerLevel[level-1] <= st)
+                level--;
+        }
+        endtimesPerLevel[level] = st + startInstanceList[i].duration;
+
+        // per type
+        if (endtimesPerNestingLevel[type][nestingLevels[type]] > st) {
+            nestingLevels[type]++;
+        } else {
+            while (nestingLevels[type] > Constants::QML_MIN_LEVEL &&
+                   endtimesPerNestingLevel[type][nestingLevels[type]-1] <= st)
+                nestingLevels[type]--;
+        }
+        endtimesPerNestingLevel[type][nestingLevels[type]] =
+                st + startInstanceList[i].duration;
+
+        startInstanceList[i].level = level;
+        startInstanceList[i].nestingLevel = nestingLevels[type];
+
+        if (level == Constants::QML_MIN_LEVEL) {
+            qmlMeasuredTime += startInstanceList[i].duration;
+        }
+    }
+}
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::computeNestingDepth()
+{
+    QHash<int, int> nestingDepth;
+    for (int i = 0; i < endInstanceList.count(); i++) {
+        int type = endInstanceList[i].description->eventType;
+        int nestingInType = startInstanceList[endInstanceList[i].startTimeIndex].nestingLevel;
+        if (!nestingDepth.contains(type))
+            nestingDepth[type] = nestingInType;
+        else {
+            int nd = nestingDepth[type];
+            nestingDepth[type] = nd > nestingInType ? nd : nestingInType;
+        }
+
+        startInstanceList[endInstanceList[i].startTimeIndex].nestingDepth = nestingDepth[type];
+        if (nestingInType == Constants::QML_MIN_LEVEL)
+            nestingDepth[type] = Constants::QML_MIN_LEVEL;
+    }
+}
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::linkEndsToStarts()
+{
+    for (int i = 0; i < startInstanceList.count(); i++)
+        endInstanceList[startInstanceList[i].endTimeIndex].startTimeIndex = i;
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+
+void QmlProfilerDataModel::compileStatistics(qint64 startTime, qint64 endTime)
+{
+    d->clearStatistics();
+    d->redoTree(startTime, endTime);
+    d->computeMedianTime(startTime, endTime);
+    d->findBindingLoops(startTime, endTime);
+}
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::clearStatistics()
+{
+    // clear existing statistics
+    foreach (QmlRangeEventData *eventDescription, rangeEventDictionary.values()) {
+        eventDescription->calls = 0;
+        // maximum possible value
+        eventDescription->minTime = endInstanceList.last().endTime;
+        eventDescription->maxTime = 0;
+        eventDescription->medianTime = 0;
+        eventDescription->duration = 0;
+        qDeleteAll(eventDescription->parentHash);
+        qDeleteAll(eventDescription->childrenHash);
+        eventDescription->parentHash.clear();
+        eventDescription->childrenHash.clear();
+    }
+}
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::redoTree(qint64 fromTime,
+                                                                 qint64 toTime)
+{
+    double totalTime = 0;
+    int fromIndex = q->findFirstIndex(fromTime);
+    int toIndex = q->findLastIndex(toTime);
+
+    QmlRangeEventData *listedRootEvent = rangeEventDictionary.value(rootEventName());
+    QTC_ASSERT(listedRootEvent, /**/);
+
+    // compute parent-child relationship and call count
+    QHash<int, QmlRangeEventData*> lastParent;
+    for (int index = fromIndex; index <= toIndex; index++) {
+        QmlRangeEventData *eventDescription = startInstanceList[index].statsInfo;
+
+        if (startInstanceList[index].startTime > toTime ||
+                startInstanceList[index].startTime+startInstanceList[index].duration < fromTime) {
+            continue;
+        }
+
+        if (eventDescription->eventType == QmlJsDebugClient::Painting) {
+            // skip animation/paint events
+            continue;
+        }
+
+        eventDescription->calls++;
+        qint64 duration = startInstanceList[index].duration;
+        eventDescription->duration += duration;
+        if (eventDescription->maxTime < duration)
+            eventDescription->maxTime = duration;
+        if (eventDescription->minTime > duration)
+            eventDescription->minTime = duration;
+
+        int level = startInstanceList[index].level;
+
+        QmlRangeEventData *parentEvent = listedRootEvent;
+        if (level > Constants::QML_MIN_LEVEL && lastParent.contains(level-1)) {
+            parentEvent = lastParent[level-1];
+        }
+
+        if (!eventDescription->parentHash.contains(parentEvent->eventHashStr)) {
+            QmlRangeEventRelative *newParentEvent = new QmlRangeEventRelative(parentEvent);
+            newParentEvent->calls = 1;
+            newParentEvent->duration = duration;
+
+            eventDescription->parentHash.insert(parentEvent->eventHashStr, newParentEvent);
+        } else {
+            QmlRangeEventRelative *newParentEvent =
+                    eventDescription->parentHash.value(parentEvent->eventHashStr);
+            newParentEvent->duration += duration;
+            newParentEvent->calls++;
+        }
+
+        if (!parentEvent->childrenHash.contains(eventDescription->eventHashStr)) {
+            QmlRangeEventRelative *newChildEvent = new QmlRangeEventRelative(eventDescription);
+            newChildEvent->calls = 1;
+            newChildEvent->duration = duration;
+
+            parentEvent->childrenHash.insert(eventDescription->eventHashStr, newChildEvent);
+        } else {
+            QmlRangeEventRelative *newChildEvent =
+                    parentEvent->childrenHash.value(eventDescription->eventHashStr);
+            newChildEvent->duration += duration;
+            newChildEvent->calls++;
+        }
+
+        lastParent[level] = eventDescription;
+
+        if (level == Constants::QML_MIN_LEVEL) {
+            totalTime += duration;
+        }
+    }
+
+    // fake rootEvent statistics
+    // the +1 nanosecond is to force it to be on top of the sorted list
+    listedRootEvent->duration = totalTime+1;
+    listedRootEvent->minTime = totalTime+1;
+    listedRootEvent->maxTime = totalTime+1;
+    listedRootEvent->medianTime = totalTime+1;
+    if (totalTime > 0)
+        listedRootEvent->calls = 1;
+
+    // copy to the global root reference
+    qmlRootEvent = *listedRootEvent;
+
+    // compute percentages
+    foreach (QmlRangeEventData *binding, rangeEventDictionary.values()) {
+        binding->percentOfTime = binding->duration * 100.0 / totalTime;
+        binding->timePerCall = binding->calls > 0 ? double(binding->duration) / binding->calls : 0;
+    }
+}
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::computeMedianTime(qint64 fromTime,
+                                                                          qint64 toTime)
+{
+    int fromIndex = q->findFirstIndex(fromTime);
+    int toIndex = q->findLastIndex(toTime);
+
+    // compute median time
+    QHash< QmlRangeEventData* , QList<qint64> > durationLists;
+    for (int index = fromIndex; index <= toIndex; index++) {
+        QmlRangeEventData *desc = startInstanceList[index].statsInfo;
+        qint64 len = startInstanceList[index].duration;
+        durationLists[desc].append(len);
+    }
+    QMutableHashIterator < QmlRangeEventData* , QList<qint64> > iter(durationLists);
+    while (iter.hasNext()) {
+        iter.next();
+        if (!iter.value().isEmpty()) {
+            qSort(iter.value());
+            iter.key()->medianTime = iter.value().at(iter.value().count()/2);
+        }
+    }
+}
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::findBindingLoops(qint64 fromTime,
+                                                                         qint64 toTime)
+{
+    int fromIndex = q->findFirstIndex(fromTime);
+    int toIndex = q->findLastIndex(toTime);
+
+    // first clear existing data
+    foreach (QmlRangeEventData *event, rangeEventDictionary.values()) {
+        event->isBindingLoop = false;
+        foreach (QmlRangeEventRelative *parentEvent, event->parentHash.values())
+            parentEvent->inLoopPath = false;
+        foreach (QmlRangeEventRelative *childEvent, event->childrenHash.values())
+            childEvent->inLoopPath = false;
+    }
+
+    QList<QmlRangeEventData *> stackRefs;
+    QList<QmlRangeEventStartInstance *> stack;
+
+    for (int i = 0; i < startInstanceList.count(); i++) {
+        QmlRangeEventData *currentEvent = startInstanceList[i].statsInfo;
+        QmlRangeEventStartInstance *inTimeEvent = &startInstanceList[i];
+        inTimeEvent->bindingLoopHead = -1;
+
+        // managing call stack
+        for (int j = stack.count() - 1; j >= 0; j--) {
+            if (stack[j]->startTime + stack[j]->duration <= inTimeEvent->startTime) {
+                stack.removeAt(j);
+                stackRefs.removeAt(j);
+            }
+        }
+
+        bool loopDetected = stackRefs.contains(currentEvent);
+        stack << inTimeEvent;
+        stackRefs << currentEvent;
+
+        if (loopDetected) {
+            if (i >= fromIndex && i <= toIndex) {
+                // for the statistics
+                currentEvent->isBindingLoop = true;
+                for (int j = stackRefs.indexOf(currentEvent); j < stackRefs.count()-1; j++) {
+                    QmlRangeEventRelative *nextEventSub =
+                            stackRefs[j]->childrenHash.value(stackRefs[j+1]->eventHashStr);
+                    nextEventSub->inLoopPath = true;
+                    QmlRangeEventRelative *prevEventSub =
+                            stackRefs[j+1]->parentHash.value(stackRefs[j]->eventHashStr);
+                    prevEventSub->inLoopPath = true;
+                }
+            }
+
+            // use crossed references to find index in starttimesortedlist
+            QmlRangeEventStartInstance *head = stack[stackRefs.indexOf(currentEvent)];
+            inTimeEvent->bindingLoopHead = endInstanceList[head->endTimeIndex].startTimeIndex;
+            startInstanceList[inTimeEvent->bindingLoopHead].bindingLoopHead = i;
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::clearQmlRootEvent()
+{
+    qmlRootEvent.displayName = rootEventName();
+    qmlRootEvent.location = QmlEventLocation();
+    qmlRootEvent.eventHashStr = rootEventName();
+    qmlRootEvent.details = rootEventDescription();
+    qmlRootEvent.eventType = QmlJsDebugClient::Binding;
+    qmlRootEvent.duration = 0;
+    qmlRootEvent.calls = 0;
+    qmlRootEvent.minTime = 0;
+    qmlRootEvent.maxTime = 0;
+    qmlRootEvent.timePerCall = 0;
+    qmlRootEvent.percentOfTime = 0;
+    qmlRootEvent.medianTime = 0;
+    qmlRootEvent.eventId = -1;
+
+    qDeleteAll(qmlRootEvent.parentHash.values());
+    qDeleteAll(qmlRootEvent.childrenHash.values());
+    qmlRootEvent.parentHash.clear();
+    qmlRootEvent.childrenHash.clear();
+}
+
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::insertQmlRootEvent()
+{
+    // create root event for statistics & insert into list
+    clearQmlRootEvent();
+    QmlRangeEventData *listedRootEvent = rangeEventDictionary.value(rootEventName());
+    if (!listedRootEvent) {
+        listedRootEvent = new QmlRangeEventData;
+        rangeEventDictionary.insert(rootEventName(), listedRootEvent);
+    }
+    *listedRootEvent = qmlRootEvent;
+}
+
+void QmlProfilerDataModel::reloadDetails()
+{
+    // request binding/signal details from the AST
+    foreach (QmlRangeEventData *event, d->rangeEventDictionary.values()) {
+        if (event->eventType != Binding && event->eventType != HandlingSignal)
+            continue;
+
+        // This skips anonymous bindings in Qt4.8 (we don't have valid location data for them)
+        if (event->location.filename.isEmpty())
+            continue;
+
+        // Skip non-anonymous bindings from Qt4.8 (we already have correct details for them)
+        if (event->location.column == -1)
+            continue;
+
+        emit requestDetailsForLocation(event->eventType, event->location);
+    }
+    emit reloadDocumentsForDetails();
+}
+
+void QmlProfilerDataModel::rewriteDetailsString(int eventType,
+                                                const QmlJsDebugClient::QmlEventLocation &location,
+                                                const QString &newString)
+{
+    QString eventHashStr = getHashStringForQmlEvent(location, eventType);
+    QTC_ASSERT(d->rangeEventDictionary.contains(eventHashStr), return);
+    d->rangeEventDictionary.value(eventHashStr)->details = newString;
+    emit detailsChanged(d->rangeEventDictionary.value(eventHashStr)->eventId, newString);
+}
+
+void QmlProfilerDataModel::finishedRewritingDetails()
+{
+    emit reloadDetailLabels();
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+
+bool QmlProfilerDataModel::save(const QString &filename)
+{
+    if (isEmpty()) {
+        emit error(tr("No data to save"));
+        return false;
+    }
+
+    QFile file(filename);
+    if (!file.open(QIODevice::WriteOnly)) {
+        emit error(tr("Could not open %1 for writing").arg(filename));
+        return false;
+    }
+
+    QXmlStreamWriter stream(&file);
+    stream.setAutoFormatting(true);
+    stream.writeStartDocument();
+
+    stream.writeStartElement("trace");
+    stream.writeAttribute("version", Constants::PROFILER_FILE_VERSION);
+
+    stream.writeAttribute("traceStart", QString::number(traceStartTime()));
+    stream.writeAttribute("traceEnd", QString::number(traceEndTime()));
+
+    stream.writeStartElement("eventData");
+    stream.writeAttribute("totalTime", QString::number(d->qmlMeasuredTime));
+
+    foreach (const QmlRangeEventData *eventData, d->rangeEventDictionary.values()) {
+        stream.writeStartElement("event");
+        stream.writeAttribute("index", QString::number(d->rangeEventDictionary.keys().indexOf(eventData->eventHashStr)));
+        stream.writeTextElement("displayname", eventData->displayName);
+        stream.writeTextElement("type", qmlEventTypeAsString(eventData->eventType));
+        if (!eventData->location.filename.isEmpty()) {
+            stream.writeTextElement("filename", eventData->location.filename);
+            stream.writeTextElement("line", QString::number(eventData->location.line));
+            stream.writeTextElement("column", QString::number(eventData->location.column));
+        }
+        stream.writeTextElement("details", eventData->details);
+        stream.writeEndElement();
+    }
+    stream.writeEndElement(); // eventData
+
+    stream.writeStartElement("profilerDataModel");
+    foreach (const QmlRangeEventStartInstance &rangedEvent, d->startInstanceList) {
+        stream.writeStartElement("range");
+        stream.writeAttribute("startTime", QString::number(rangedEvent.startTime));
+        stream.writeAttribute("duration", QString::number(rangedEvent.duration));
+        stream.writeAttribute("eventIndex", QString::number(d->rangeEventDictionary.keys().indexOf(rangedEvent.statsInfo->eventHashStr)));
+        if (rangedEvent.statsInfo->eventType == QmlJsDebugClient::Painting && rangedEvent.animationCount >= 0) {
+            // animation frame
+            stream.writeAttribute("framerate", QString::number(rangedEvent.frameRate));
+            stream.writeAttribute("animationcount", QString::number(rangedEvent.animationCount));
+        }
+        stream.writeEndElement();
+    }
+    stream.writeEndElement(); // profilerDataModel
+
+    d->v8DataModel->save(stream);
+
+    stream.writeEndElement(); // trace
+    stream.writeEndDocument();
+
+    file.close();
+    return true;
+}
+
+void QmlProfilerDataModel::setFilename(const QString &filename)
+{
+    d->fileName = filename;
+}
+
+void QmlProfilerDataModel::load(const QString &filename)
+{
+    setFilename(filename);
+    load();
+}
+
+// "be strict in your output but tolerant in your inputs"
+void QmlProfilerDataModel::load()
+{
+    QString filename = d->fileName;
+
+    QFile file(filename);
+
+    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+        emit error(tr("Could not open %1 for reading").arg(filename));
+        return;
+    }
+
+    // erase current
+    clear();
+
+    setState(AcquiringData);
+
+    bool readingQmlEvents = false;
+    QHash<int, QmlRangeEventData *> descriptionBuffer;
+    QmlRangeEventData *currentEvent = 0;
+    bool startTimesAreSorted = true;
+    bool validVersion = true;
+
+    // time computation
+    d->qmlMeasuredTime = 0;
+
+    QXmlStreamReader stream(&file);
+
+    while (validVersion && !stream.atEnd() && !stream.hasError()) {
+        QXmlStreamReader::TokenType token = stream.readNext();
+        QString elementName = stream.name().toString();
+        switch (token) {
+        case QXmlStreamReader::StartDocument :  continue;
+        case QXmlStreamReader::StartElement : {
+            if (elementName == "trace") {
+                QXmlStreamAttributes attributes = stream.attributes();
+                if (attributes.hasAttribute("version"))
+                    validVersion = attributes.value("version").toString() == Constants::PROFILER_FILE_VERSION;
+                else
+                    validVersion = false;
+                if (attributes.hasAttribute("traceStart"))
+                    setTraceStartTime(attributes.value("traceStart").toString().toLongLong());
+                if (attributes.hasAttribute("traceEnd"))
+                    setTraceEndTime(attributes.value("traceEnd").toString().toLongLong());
+            }
+            if (elementName == "eventData") {
+                readingQmlEvents = true;
+                QXmlStreamAttributes attributes = stream.attributes();
+                if (attributes.hasAttribute("totalTime"))
+                    d->qmlMeasuredTime = attributes.value("totalTime").toString().toDouble();
+                break;
+            }
+            if (elementName == "v8profile" && !readingQmlEvents) {
+                d->v8DataModel->load(stream);
+                break;
+            }
+
+            if (elementName == "trace") {
+                QXmlStreamAttributes attributes = stream.attributes();
+                if (attributes.hasAttribute("traceStart"))
+                    setTraceStartTime(attributes.value("traceStart").toString().toLongLong());
+                if (attributes.hasAttribute("traceEnd"))
+                    setTraceEndTime(attributes.value("traceEnd").toString().toLongLong());
+            }
+
+            if (elementName == "range") {
+                QmlRangeEventStartInstance rangedEvent;
+                QXmlStreamAttributes attributes = stream.attributes();
+                if (attributes.hasAttribute("startTime"))
+                    rangedEvent.startTime = attributes.value("startTime").toString().toLongLong();
+                if (attributes.hasAttribute("duration"))
+                    rangedEvent.duration = attributes.value("duration").toString().toLongLong();
+                if (attributes.hasAttribute("framerate"))
+                    rangedEvent.frameRate = attributes.value("framerate").toString().toInt();
+                if (attributes.hasAttribute("animationcount"))
+                    rangedEvent.animationCount = attributes.value("animationcount").toString().toInt();
+                else
+                    rangedEvent.animationCount = -1;
+                if (attributes.hasAttribute("eventIndex")) {
+                    int ndx = attributes.value("eventIndex").toString().toInt();
+                    if (!descriptionBuffer.value(ndx))
+                        descriptionBuffer[ndx] = new QmlRangeEventData;
+                    rangedEvent.statsInfo = descriptionBuffer.value(ndx);
+                }
+                rangedEvent.endTimeIndex = d->endInstanceList.count();
+
+                if (!d->startInstanceList.isEmpty()
+                        && rangedEvent.startTime < d->startInstanceList.last().startTime)
+                    startTimesAreSorted = false;
+                d->startInstanceList << rangedEvent;
+
+                QmlRangeEventEndInstance endTimeEvent;
+                endTimeEvent.endTime = rangedEvent.startTime + rangedEvent.duration;
+                endTimeEvent.startTimeIndex = d->startInstanceList.count()-1;
+                endTimeEvent.description = rangedEvent.statsInfo;
+                d->endInstanceList << endTimeEvent;
+                break;
+            }
+
+            if (readingQmlEvents) {
+                if (elementName == "event") {
+                    QXmlStreamAttributes attributes = stream.attributes();
+                    if (attributes.hasAttribute("index")) {
+                        int ndx = attributes.value("index").toString().toInt();
+                        if (!descriptionBuffer.value(ndx))
+                            descriptionBuffer[ndx] = new QmlRangeEventData;
+                        currentEvent = descriptionBuffer[ndx];
+                    } else {
+                        currentEvent = 0;
+                    }
+                    break;
+                }
+
+                // the remaining are eventdata or v8eventdata elements
+                if (!currentEvent)
+                    break;
+
+                stream.readNext();
+                if (stream.tokenType() != QXmlStreamReader::Characters)
+                    break;
+                QString readData = stream.text().toString();
+
+                if (elementName == "displayname") {
+                    currentEvent->displayName = readData;
+                    break;
+                }
+                if (elementName == "type") {
+                    currentEvent->eventType = qmlEventTypeAsEnum(readData);
+                    break;
+                }
+                if (elementName == "filename") {
+                    currentEvent->location.filename = readData;
+                    break;
+                }
+                if (elementName == "line") {
+                    currentEvent->location.line = readData.toInt();
+                    break;
+                }
+                if (elementName == "column") {
+                    currentEvent->location.column = readData.toInt();
+                }
+                if (elementName == "details") {
+                    currentEvent->details = readData;
+                    break;
+                }
+            }
+            break;
+        }
+        case QXmlStreamReader::EndElement : {
+            if (elementName == "event") {
+                currentEvent = 0;
+                break;
+            }
+            if (elementName == "eventData") {
+                readingQmlEvents = false;
+                break;
+            }
+        }
+        default: break;
+        }
+    }
+
+    file.close();
+
+    if (stream.hasError()) {
+        emit error(tr("Error while parsing %1").arg(filename));
+        clear();
+        return;
+    }
+
+    stream.clear();
+
+    if (!validVersion) {
+        clear();
+        emit error(tr("Invalid version of QML Trace file."));
+        return;
+    }
+
+    // move the buffered data to the details cache
+    foreach (QmlRangeEventData *desc, descriptionBuffer.values()) {
+        desc->eventHashStr = getHashStringForQmlEvent(desc->location, desc->eventType);;
+        d->rangeEventDictionary[desc->eventHashStr] = desc;
+    }
+
+    // sort startTimeSortedList
+    if (!startTimesAreSorted) {
+        qSort(d->startInstanceList.begin(), d->startInstanceList.end(), compareStartTimes);
+        for (int i = 0; i< d->startInstanceList.count(); i++) {
+            QmlRangeEventStartInstance startTimeData = d->startInstanceList[i];
+            d->endInstanceList[startTimeData.endTimeIndex].startTimeIndex = i;
+        }
+        qSort(d->endInstanceList.begin(), d->endInstanceList.end(), compareStartIndexes);
+    }
+
+    emit countChanged();
+
+    descriptionBuffer.clear();
+
+    setState(ProcessingData);
+    d->postProcess();
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+
+QmlProfilerDataModel::State QmlProfilerDataModel::currentState() const
+{
+    return d->listState;
+}
+
+int QmlProfilerDataModel::getCurrentStateFromQml() const
+{
+    return (int)d->listState;
+}
+
+void QmlProfilerDataModel::setState(QmlProfilerDataModel::State state)
+{
+    // It's not an error, we are continuously calling "AcquiringData" for example
+    if (d->listState == state)
+        return;
+
+    switch (state) {
+        case Empty:
+            // if it's not empty, complain but go on
+            QTC_ASSERT(isEmpty(), /**/);
+        break;
+        case AcquiringData:
+            // we're not supposed to receive new data while processing older data
+            QTC_ASSERT(d->listState != ProcessingData, return);
+        break;
+        case ProcessingData:
+            QTC_ASSERT(d->listState == AcquiringData, return);
+        break;
+        case Done:
+            QTC_ASSERT(d->listState == ProcessingData || d->listState == Empty, return);
+        break;
+        default:
+            emit error("Trying to set unknown state in events list");
+        break;
+    }
+
+    d->listState = state;
+    emit stateChanged();
+
+    // special: if we were done with an empty list, clean internal data and go back to empty
+    if (d->listState == Done && isEmpty()) {
+        clear();
+    }
+    return;
+}
+
+} // namespace Internal
+} // namespace QmlProfiler
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QmlRangeEventData, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QmlRangeEventStartInstance, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QmlRangeEventEndInstance, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QmlRangeEventRelative, Q_MOVABLE_TYPE);
+QT_END_NAMESPACE
diff --git a/src/libs/qmljsdebugclient/qmlprofilereventlist.h b/src/plugins/qmlprofiler/qmlprofilerdatamodel.h
similarity index 64%
rename from src/libs/qmljsdebugclient/qmlprofilereventlist.h
rename to src/plugins/qmlprofiler/qmlprofilerdatamodel.h
index 32f5203c2a0a275e39355fba6c8063fa212e9028..7e2ab0347094358e3178e5a746831cd60990538c 100644
--- a/src/libs/qmljsdebugclient/qmlprofilereventlist.h
+++ b/src/plugins/qmlprofiler/qmlprofilerdatamodel.h
@@ -30,33 +30,37 @@
 **
 **************************************************************************/
 
-#ifndef QMLPROFILEREVENTLIST_H
-#define QMLPROFILEREVENTLIST_H
+#ifndef QMLPROFILERDATAMODEL_H
+#define QMLPROFILERDATAMODEL_H
 
-#include "qmlprofilereventtypes.h"
-#include "qmlprofilereventlocation.h"
-#include "qmljsdebugclient_global.h"
+#include <qmljsdebugclient/qmlprofilereventtypes.h>
+#include <qmljsdebugclient/qmlprofilereventlocation.h>
+#include "qv8profilerdatamodel.h"
 
 #include <QHash>
 #include <QObject>
 
-namespace QmlJsDebugClient {
+namespace QmlProfiler {
+namespace Internal {
 
-struct QmlEventSub;
-struct QV8EventSub;
+// used for parents and children
+struct QmlRangeEventRelative;
 
-struct QMLJSDEBUGCLIENT_EXPORT QmlEventData
+struct QmlRangeEventData
 {
-    QmlEventData();
-    ~QmlEventData();
+    QmlRangeEventData();
+    ~QmlRangeEventData();
 
-    QString displayname;
+    int eventId;
+    QString displayName;
     QString eventHashStr;
     QString details;
-    QmlEventLocation location;
+    QmlJsDebugClient::QmlEventLocation location;
     QmlJsDebugClient::QmlEventType eventType;
-    QHash <QString, QmlEventSub *> parentHash;
-    QHash <QString, QmlEventSub *> childrenHash;
+
+    QHash <QString, QmlRangeEventRelative *> parentHash;
+    QHash <QString, QmlRangeEventRelative *> childrenHash;
+
     qint64 duration;
     qint64 calls;
     qint64 minTime;
@@ -64,54 +68,22 @@ struct QMLJSDEBUGCLIENT_EXPORT QmlEventData
     double timePerCall;
     double percentOfTime;
     qint64 medianTime;
-    int eventId;
+
     bool isBindingLoop;
 
-    QmlEventData &operator=(const QmlEventData &ref);
+    QmlRangeEventData &operator=(const QmlRangeEventData &ref);
 };
 
-struct QMLJSDEBUGCLIENT_EXPORT QmlEventSub {
-    QmlEventSub(QmlEventData *from) : reference(from), duration(0), calls(0), inLoopPath(false) {}
-    QmlEventSub(QmlEventSub *from) : reference(from->reference), duration(from->duration), calls(from->calls), inLoopPath(from->inLoopPath) {}
-    QmlEventData *reference;
+struct QmlRangeEventRelative {
+    QmlRangeEventRelative(QmlRangeEventData *from) : reference(from), duration(0), calls(0), inLoopPath(false) {}
+    QmlRangeEventRelative(QmlRangeEventRelative *from) : reference(from->reference), duration(from->duration), calls(from->calls), inLoopPath(from->inLoopPath) {}
+    QmlRangeEventData *reference;
     qint64 duration;
     qint64 calls;
     bool inLoopPath;
 };
 
-struct QMLJSDEBUGCLIENT_EXPORT QV8EventData
-{
-    QV8EventData();
-    ~QV8EventData();
-
-    QString displayName;
-    QString filename;
-    QString functionName;
-    int line;
-    double totalTime; // given in milliseconds
-    double totalPercent;
-    double selfTime;
-    double selfPercent;
-    QHash <QString, QV8EventSub *> parentHash;
-    QHash <QString, QV8EventSub *> childrenHash;
-    int eventId;
-
-    QV8EventData &operator=(const QV8EventData &ref);
-};
-
-struct QMLJSDEBUGCLIENT_EXPORT QV8EventSub {
-    QV8EventSub(QV8EventData *from) : reference(from), totalTime(0) {}
-    QV8EventSub(QV8EventSub *from) : reference(from->reference), totalTime(from->totalTime) {}
-
-    QV8EventData *reference;
-    qint64 totalTime;
-};
-
-typedef QHash<QString, QmlEventData *> QmlEventHash;
-typedef QList<QmlEventData *> QmlEventDescriptions;
-typedef QList<QV8EventData *> QV8EventDescriptions;
-
-class QMLJSDEBUGCLIENT_EXPORT QmlProfilerEventList : public QObject
+class QmlProfilerDataModel : public QObject
 {
     Q_OBJECT
 public:
@@ -122,23 +94,30 @@ public:
         Done
     };
 
-    explicit QmlProfilerEventList(QObject *parent = 0);
-    ~QmlProfilerEventList();
+    explicit QmlProfilerDataModel(QObject *parent = 0);
+    ~QmlProfilerDataModel();
 
-    QmlEventDescriptions getEventDescriptions() const;
-    QmlEventData *eventDescription(int eventId) const;
-    const QV8EventDescriptions& getV8Events() const;
+    QList<QmlRangeEventData *> getEventDescriptions() const;
+    QmlRangeEventData *eventDescription(int eventId) const;
+    QList<QV8EventData *> getV8Events() const;
     QV8EventData *v8EventDescription(int eventId) const;
 
+    static QString getHashStringForQmlEvent(const QmlJsDebugClient::QmlEventLocation &location, int eventType);
+    static QString getHashStringForV8Event(const QString &displayName, const QString &function);
+    static QString rootEventName();
+    static QString rootEventDescription();
+    static QString qmlEventTypeAsString(QmlJsDebugClient::QmlEventType typeEnum);
+    static QmlJsDebugClient::QmlEventType qmlEventTypeAsEnum(const QString &typeString);
+
     int findFirstIndex(qint64 startTime) const;
     int findFirstIndexNoParents(qint64 startTime) const;
     int findLastIndex(qint64 endTime) const;
     Q_INVOKABLE qint64 firstTimeMark() const;
     Q_INVOKABLE qint64 lastTimeMark() const;
 
-    Q_INVOKABLE int count() const;
-
     // data access
+    Q_INVOKABLE int count() const;
+    Q_INVOKABLE bool isEmpty() const;
     Q_INVOKABLE qint64 getStartTime(int index) const;
     Q_INVOKABLE qint64 getEndTime(int index) const;
     Q_INVOKABLE qint64 getDuration(int index) const;
@@ -171,7 +150,6 @@ public:
     Q_INVOKABLE qint64 qmlMeasuredTime() const;
     Q_INVOKABLE qint64 v8MeasuredTime() const;
 
-    void showErrorDialog(const QString &st ) const;
     void compileStatistics(qint64 startTime, qint64 endTime);
     State currentState() const;
     Q_INVOKABLE int getCurrentStateFromQml() const;
@@ -188,44 +166,37 @@ signals:
 
 public slots:
     void clear();
+
     void addRangedEvent(int type, qint64 startTime, qint64 length,
                         const QStringList &data, const QmlJsDebugClient::QmlEventLocation &location);
-    void complete();
-
     void addV8Event(int depth,const QString &function,const QString &filename, int lineNumber, double totalTime, double selfTime);
     void addFrameEvent(qint64 time, int framerate, int animationcount);
+    void setTraceStartTime(qint64 time);
+    void setTraceEndTime(qint64 time);
+
+    void complete();
+
     bool save(const QString &filename);
     void load(const QString &filename);
     void setFilename(const QString &filename);
     void load();
 
-    void setTraceEndTime( qint64 time );
-    void setTraceStartTime( qint64 time );
-
     void rewriteDetailsString(int eventType, const QmlJsDebugClient::QmlEventLocation &location, const QString &newString);
     void finishedRewritingDetails();
 
 private:
-    void postProcess();
-    void sortEndTimes();
-    void findAnimationLimits();
-    void sortStartTimes();
-    void computeLevels();
-    void computeNestingLevels();
-    void computeNestingDepth();
-    void prepareForDisplay();
-    void linkEndsToStarts();
-    void reloadDetails();
-    void findBindingLoops(qint64 startTime, qint64 endTime);
-    bool checkBindingLoop(QmlEventData *from, QmlEventData *current, QList<QmlEventData *>visited);
     void setState(State state);
+    void reloadDetails();
 
 private:
-    class QmlProfilerEventListPrivate;
-    QmlProfilerEventListPrivate *d;
+    class QmlProfilerDataModelPrivate;
+    QmlProfilerDataModelPrivate *d;
+
+    friend class QV8ProfilerDataModel;
 };
 
 
-} // namespace QmlJsDebugClient
+} // namespace Internal
+} // namespace QmlProfiler
 
-#endif // QMLPROFILEREVENTLIST_H
+#endif // QMLPROFILERDATAMODEL_H
diff --git a/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h b/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h
index 561717c890d6a42dd819c10ddb7f3e4b7054ac5c..4f61f8a64089ca41fa7830844eac82a92af3545e 100644
--- a/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h
+++ b/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h
@@ -35,7 +35,7 @@
 
 #include <QObject>
 
-#include "qmljsdebugclient/qmlprofilereventlocation.h"
+#include <qmljsdebugclient/qmlprofilereventlocation.h>
 #include <qmljs/qmljsdocument.h>
 
 namespace QmlProfiler {
diff --git a/src/plugins/qmlprofiler/qmlprofilerengine.cpp b/src/plugins/qmlprofiler/qmlprofilerengine.cpp
index 5487711e68d7273a0599a400025c5002a49d4308..5990df7c4c09016d6ddd85ec49c8ada60ed19403 100644
--- a/src/plugins/qmlprofiler/qmlprofilerengine.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerengine.cpp
@@ -35,8 +35,6 @@
 #include "codaqmlprofilerrunner.h"
 #include "localqmlprofilerrunner.h"
 #include "remotelinuxqmlprofilerrunner.h"
-#include "qmlprofilerplugin.h"
-#include "qmlprofilertool.h"
 
 #include <analyzerbase/analyzermanager.h>
 #include <coreplugin/icore.h>
@@ -76,16 +74,11 @@ public:
 
     QmlProfilerEngine *q;
 
-    //AnalyzerStartParameters m_params;
+    QmlProfilerStateManager *m_profilerState;
+
     AbstractQmlProfilerRunner *m_runner;
-    bool m_running;
-    bool m_fetchingData;
-    bool m_hasData;
-    bool m_fetchDataFromStart;
-    bool m_delayedDelete;
     QTimer m_noDebugOutputTimer;
     QmlJsDebugClient::QDeclarativeOutputParser m_outputParser;
-    QTimer m_runningTimer;
 };
 
 AbstractQmlProfilerRunner *
@@ -137,10 +130,7 @@ QmlProfilerEngine::QmlProfilerEngine(IAnalyzerTool *tool,
     : IAnalyzerEngine(tool, sp, runConfiguration)
     , d(new QmlProfilerEnginePrivate(this))
 {
-    d->m_running = false;
-    d->m_fetchingData = false;
-    d->m_fetchDataFromStart = false;
-    d->m_delayedDelete = false;
+    d->m_profilerState = 0;
 
     // Only wait 4 seconds for the 'Waiting for connection' on application ouput, then just try to connect
     // (application output might be redirected / blocked)
@@ -157,29 +147,31 @@ QmlProfilerEngine::QmlProfilerEngine(IAnalyzerTool *tool,
             this, SLOT(processIsRunning()));
     connect(&d->m_outputParser, SIGNAL(errorMessage(QString)),
             this, SLOT(wrongSetupMessageBox(QString)));
-
-    d->m_runningTimer.setInterval(100); // ten times per second
-    connect(&d->m_runningTimer, SIGNAL(timeout()), this, SIGNAL(timeUpdate()));
 }
 
 QmlProfilerEngine::~QmlProfilerEngine()
 {
-    if (d->m_running)
+    if (d->m_profilerState && d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning)
         stop();
     delete d;
 }
 
 bool QmlProfilerEngine::start()
 {
+    QTC_ASSERT(d->m_profilerState, return false);
+
     if (d->m_runner) {
         delete d->m_runner;
         d->m_runner = 0;
     }
 
+    d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStarting);
+
     if (QmlProjectManager::QmlProjectRunConfiguration *rc =
             qobject_cast<QmlProjectManager::QmlProjectRunConfiguration *>(runConfiguration())) {
         if (rc->observerPath().isEmpty()) {
             QmlProjectManager::QmlProjectPlugin::showQmlObserverToolWarning();
+            d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle);
             AnalyzerManager::stopTool();
             return false;
         }
@@ -190,13 +182,14 @@ bool QmlProfilerEngine::start()
     if (LocalQmlProfilerRunner *qmlRunner = qobject_cast<LocalQmlProfilerRunner *>(d->m_runner)) {
         if (!qmlRunner->hasExecutable()) {
             showNonmodalWarning(tr("No executable file to launch."));
+            d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle);
             AnalyzerManager::stopTool();
             return false;
         }
     }
 
     if (d->m_runner) {
-        connect(d->m_runner, SIGNAL(stopped()), this, SLOT(stopped()));
+        connect(d->m_runner, SIGNAL(stopped()), this, SLOT(processEnded()));
         connect(d->m_runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)),
                 this, SLOT(logApplicationMessage(QString,Utils::OutputFormat)));
         d->m_runner->start();
@@ -205,81 +198,80 @@ bool QmlProfilerEngine::start()
         emit processRunning(startParameters().connParams.port);
     }
 
-
-    d->m_running = true;
-    d->m_delayedDelete = false;
-    d->m_runningTimer.start();
-
-    if (d->m_fetchDataFromStart) {
-        d->m_fetchingData = true;
-        d->m_hasData = false;
-    }
-
+    d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppRunning);
     emit starting(this);
     return true;
 }
 
 void QmlProfilerEngine::stop()
 {
-    if (d->m_fetchingData) {
-        if (d->m_running)
-            d->m_delayedDelete = true;
-        // will result in dataReceived() call
-        emit stopRecording();
-        d->m_fetchDataFromStart = true;
-    } else {
-        finishProcess();
-        d->m_fetchDataFromStart = false;
+    QTC_ASSERT(d->m_profilerState, return);
+
+    switch (d->m_profilerState->currentState()) {
+    case QmlProfilerStateManager::AppRunning : {
+        d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopRequested);
+        break;
+    }
+    case QmlProfilerStateManager::AppReadyToStop : {
+        cancelProcess();
+        break;
+    }
+    case QmlProfilerStateManager::AppKilled : {
+        d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle);
+        break;
+    }
+    default:
+        qDebug() << tr("Unexpected engine stop from state %1 in %2:%3").arg(d->m_profilerState->currentStateAsString(), QString(__FILE__), QString::number(__LINE__));
+        break;
     }
 }
 
-void QmlProfilerEngine::stopped()
+void QmlProfilerEngine::processEnded()
 {
-    // if it was killed, preserve recording flag
-    if (d->m_running)
-        d->m_fetchDataFromStart = d->m_fetchingData;
-
-    // user feedback
-    if (d->m_running && d->m_fetchingData && !d->m_hasData) {
-        showNonmodalWarning(tr("Application finished before loading profiled data.\n Please use the stop button instead."));
-        emit applicationDied();
-    }
+    QTC_ASSERT(d->m_profilerState, return);
 
-    d->m_running = false;
-    d->m_runningTimer.stop();
-    AnalyzerManager::stopTool();
-    emit finished();
-    emit recordingChanged(d->m_fetchDataFromStart);
-}
+    switch (d->m_profilerState->currentState()) {
+    case QmlProfilerStateManager::AppRunning : {
+        d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled);
+        AnalyzerManager::stopTool();
 
-void QmlProfilerEngine::setFetchingData(bool b)
-{
-    d->m_fetchingData = b;
-    if (d->m_running && b)
-        d->m_hasData = false;
-    if (!d->m_running)
-        d->m_fetchDataFromStart = b;
+        emit finished();
+        break;
+    }
+    case QmlProfilerStateManager::AppStopped :
+        // fallthrough
+    case QmlProfilerStateManager::AppKilled : {
+        d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle);
+        break;
+    }
+    default:
+        qDebug() << tr("Process died unexpectedly from state %1 in %2:%3").arg(d->m_profilerState->currentStateAsString(), QString(__FILE__), QString::number(__LINE__));
+        break;
+    }
 }
 
-void QmlProfilerEngine::dataReceived()
+void QmlProfilerEngine::cancelProcess()
 {
-    if (d->m_delayedDelete)
-        finishProcess();
-    d->m_delayedDelete = false;
-    d->m_hasData = true;
-}
+    QTC_ASSERT(d->m_profilerState, return);
 
-void QmlProfilerEngine::finishProcess()
-{
-    // user stop?
-    if (d->m_running) {
-        d->m_running = false;
-        d->m_runningTimer.stop();
-        if (d->m_runner)
-            d->m_runner->stop();
-        emit finished();
-        emit recordingChanged(d->m_fetchDataFromStart);
+    switch (d->m_profilerState->currentState()) {
+    case QmlProfilerStateManager::AppReadyToStop : {
+        d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopped);
+        break;
+    }
+    case QmlProfilerStateManager::AppRunning : {
+        d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled);
+        break;
+    }
+    default: {
+        qDebug() << tr("Unexpected process termination requested with state %1 in %2:%3").arg(d->m_profilerState->currentStateAsString(), QString(__FILE__), QString::number(__LINE__));
+        return;
+    }
     }
+
+    if (d->m_runner)
+        d->m_runner->stop();
+    emit finished();
 }
 
 void QmlProfilerEngine::logApplicationMessage(const QString &msg, Utils::OutputFormat format)
@@ -305,11 +297,10 @@ void QmlProfilerEngine::wrongSetupMessageBox(const QString &errorMessage)
 
     infoBox->show();
 
-    d->m_running = false;
-    d->m_runningTimer.stop();
+    // KILL
+    d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled);
     AnalyzerManager::stopTool();
     emit finished();
-    emit recordingChanged(d->m_fetchDataFromStart);
 }
 
 void QmlProfilerEngine::wrongSetupMessageBoxFinished(int button)
@@ -348,5 +339,44 @@ void QmlProfilerEngine::processIsRunning(quint16 port)
         emit processRunning(d->m_runner->debugPort());
 }
 
+////////////////////////////////////////////////////////////////
+// Profiler State
+void QmlProfilerEngine::registerProfilerStateManager( QmlProfilerStateManager *profilerState )
+{
+    // disconnect old
+    if (d->m_profilerState) {
+        disconnect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged()));
+    }
+
+    d->m_profilerState = profilerState;
+
+    // connect
+    if (d->m_profilerState) {
+        connect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged()));
+    }
+}
+
+void QmlProfilerEngine::profilerStateChanged()
+{
+    switch (d->m_profilerState->currentState()) {
+    case QmlProfilerStateManager::AppReadyToStop : {
+        cancelProcess();
+        break;
+    }
+    case QmlProfilerStateManager::Idle : {
+        // for some reason the engine is not deleted when it goes to idle
+        // a new one will be created on the next run, and this one will
+        // be only deleted if the new one is running the same app
+
+        // we need to explictly disconnect it here without expecting a deletion
+        // as it will not be run any more, otherwise we will get funny side effects
+        registerProfilerStateManager(0);
+        break;
+    }
+    default:
+        break;
+    }
+}
+
 } // namespace Internal
 } // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/qmlprofilerengine.h b/src/plugins/qmlprofiler/qmlprofilerengine.h
index aade80edb731c6136c00defcbedd933a6ae18a5b..c438e69329638d31511702431d60da65f5c9f8ed 100644
--- a/src/plugins/qmlprofiler/qmlprofilerengine.h
+++ b/src/plugins/qmlprofiler/qmlprofilerengine.h
@@ -34,6 +34,7 @@
 #define QMLPROFILERENGINE_H
 
 #include <analyzerbase/ianalyzerengine.h>
+#include "qmlprofilerstatemanager.h"
 #include <utils/outputformat.h>
 
 namespace QmlProfiler {
@@ -49,29 +50,29 @@ public:
                       ProjectExplorer::RunConfiguration *runConfiguration);
     ~QmlProfilerEngine();
 
+    void registerProfilerStateManager( QmlProfilerStateManager *profilerState );
+
     static void showNonmodalWarning(const QString &warningMsg);
 signals:
     void processRunning(quint16 port);
-    void stopRecording();
     void timeUpdate();
-    void recordingChanged(bool recording);
-    void applicationDied();
 
 public slots:
     bool start();
     void stop();
 
 private slots:
-    void stopped();
+    void processEnded();
 
-    void setFetchingData(bool);
-    void dataReceived();
-    void finishProcess();
+    void cancelProcess();
     void logApplicationMessage(const QString &msg, Utils::OutputFormat format);
     void wrongSetupMessageBox(const QString &errorMessage);
     void wrongSetupMessageBoxFinished(int);
     void processIsRunning(quint16 port = 0);
 
+private slots:
+    void profilerStateChanged();
+
 private:
     class QmlProfilerEnginePrivate;
     QmlProfilerEnginePrivate *d;
diff --git a/src/plugins/qmlprofiler/qmlprofilereventview.cpp b/src/plugins/qmlprofiler/qmlprofilereventview.cpp
index b59fdc4c7a2e74ffe8f7de7150dc7b0a6013097f..3630626cacb3816756570ada6380880d99050639 100644
--- a/src/plugins/qmlprofiler/qmlprofilereventview.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilereventview.cpp
@@ -48,6 +48,11 @@
 #include <QVBoxLayout>
 #include <QHBoxLayout>
 
+#include "qmlprofilerviewmanager.h"
+#include "qmlprofilertool.h"
+#include <QMenu>
+
+#include <utils/qtcassert.h>
 
 using namespace QmlJsDebugClient;
 
@@ -90,31 +95,63 @@ public:
 
 ////////////////////////////////////////////////////////////////////////////////////
 
-QmlProfilerEventsWidget::QmlProfilerEventsWidget(QmlJsDebugClient::QmlProfilerEventList *model, QWidget *parent) : QWidget(parent)
+class QmlProfilerEventsWidget::QmlProfilerEventsWidgetPrivate
 {
-    setObjectName("QmlProfilerEventsView");
+public:
+    QmlProfilerEventsWidgetPrivate(QmlProfilerEventsWidget *qq):q(qq) {}
+    ~QmlProfilerEventsWidgetPrivate() {}
 
-    m_eventTree = new QmlProfilerEventsMainView(model, this);
-    m_eventTree->setViewType(QmlProfilerEventsMainView::EventsView);
-    connect(m_eventTree, SIGNAL(gotoSourceLocation(QString,int,int)), this, SIGNAL(gotoSourceLocation(QString,int,int)));
-    connect(m_eventTree, SIGNAL(showEventInTimeline(int)), this, SIGNAL(showEventInTimeline(int)));
+    QmlProfilerEventsWidget *q;
 
-    m_eventChildren = new QmlProfilerEventsParentsAndChildrenView(model, QmlProfilerEventsParentsAndChildrenView::ChildrenView, this);
-    m_eventParents = new QmlProfilerEventsParentsAndChildrenView(model, QmlProfilerEventsParentsAndChildrenView::ParentsView, this);
-    connect(m_eventTree, SIGNAL(eventSelected(int)), m_eventChildren, SLOT(displayEvent(int)));
-    connect(m_eventTree, SIGNAL(eventSelected(int)), m_eventParents, SLOT(displayEvent(int)));
-    connect(m_eventChildren, SIGNAL(eventClicked(int)), m_eventTree, SLOT(selectEvent(int)));
-    connect(m_eventParents, SIGNAL(eventClicked(int)), m_eventTree, SLOT(selectEvent(int)));
+    Analyzer::IAnalyzerTool *m_profilerTool;
+    QmlProfilerViewManager *m_viewContainer;
+
+    QmlProfilerEventsMainView *m_eventTree;
+    QmlProfilerEventsParentsAndChildrenView *m_eventChildren;
+    QmlProfilerEventsParentsAndChildrenView *m_eventParents;
+    QmlProfilerDataModel *m_profilerDataModel;
+
+    bool m_globalStatsEnabled;
+};
+
+QmlProfilerEventsWidget::QmlProfilerEventsWidget(QWidget *parent,
+                                 Analyzer::IAnalyzerTool *profilerTool,
+                                 QmlProfilerViewManager *container,
+                                 QmlProfilerDataModel *profilerDataModel )
+    : QWidget(parent), d(new QmlProfilerEventsWidgetPrivate(this))
+{
+    setObjectName("QmlProfilerEventsView");
+
+    d->m_profilerDataModel = profilerDataModel;
+    connect(d->m_profilerDataModel, SIGNAL(stateChanged()),
+            this, SLOT(profilerDataModelStateChanged()));
+
+    d->m_eventTree = new QmlProfilerEventsMainView(QmlProfilerEventsMainView::EventsView, this, d->m_profilerDataModel);
+    connect(d->m_eventTree, SIGNAL(gotoSourceLocation(QString,int,int)), this, SIGNAL(gotoSourceLocation(QString,int,int)));
+    connect(d->m_eventTree, SIGNAL(showEventInTimeline(int)), this, SIGNAL(showEventInTimeline(int)));
+
+    d->m_eventChildren = new QmlProfilerEventsParentsAndChildrenView(
+                QmlProfilerEventsParentsAndChildrenView::ChildrenView,
+                this,
+                d->m_profilerDataModel);
+    d->m_eventParents = new QmlProfilerEventsParentsAndChildrenView(
+                QmlProfilerEventsParentsAndChildrenView::ParentsView,
+                this,
+                d->m_profilerDataModel);
+    connect(d->m_eventTree, SIGNAL(eventSelected(int)), d->m_eventChildren, SLOT(displayEvent(int)));
+    connect(d->m_eventTree, SIGNAL(eventSelected(int)), d->m_eventParents, SLOT(displayEvent(int)));
+    connect(d->m_eventChildren, SIGNAL(eventClicked(int)), d->m_eventTree, SLOT(selectEvent(int)));
+    connect(d->m_eventParents, SIGNAL(eventClicked(int)), d->m_eventTree, SLOT(selectEvent(int)));
 
     // widget arrangement
     QVBoxLayout *groupLayout = new QVBoxLayout;
     groupLayout->setContentsMargins(0,0,0,0);
     groupLayout->setSpacing(0);
     Core::MiniSplitter *splitterVertical = new Core::MiniSplitter;
-    splitterVertical->addWidget(m_eventTree);
+    splitterVertical->addWidget(d->m_eventTree);
     Core::MiniSplitter *splitterHorizontal = new Core::MiniSplitter;
-    splitterHorizontal->addWidget(m_eventParents);
-    splitterHorizontal->addWidget(m_eventChildren);
+    splitterHorizontal->addWidget(d->m_eventParents);
+    splitterHorizontal->addWidget(d->m_eventChildren);
     splitterHorizontal->setOrientation(Qt::Horizontal);
     splitterVertical->addWidget(splitterHorizontal);
     splitterVertical->setOrientation(Qt::Vertical);
@@ -123,23 +160,21 @@ QmlProfilerEventsWidget::QmlProfilerEventsWidget(QmlJsDebugClient::QmlProfilerEv
     groupLayout->addWidget(splitterVertical);
     setLayout(groupLayout);
 
-    m_eventStatistics = model;
-    if (model) {
-        connect(model, SIGNAL(stateChanged()), this, SLOT(eventListStateChanged()));
-    }
-
-    m_globalStatsEnabled = true;
+    d->m_profilerTool = profilerTool;
+    d->m_viewContainer = container;
+    d->m_globalStatsEnabled = true;
 }
 
 QmlProfilerEventsWidget::~QmlProfilerEventsWidget()
 {
+    delete d;
 }
 
-void QmlProfilerEventsWidget::eventListStateChanged()
+void QmlProfilerEventsWidget::profilerDataModelStateChanged()
 {
-    if (m_eventStatistics) {
-        QmlProfilerEventList::State newState = m_eventStatistics->currentState();
-        if (newState == QmlProfilerEventList::Empty) {
+    if (d->m_profilerDataModel) {
+        QmlProfilerDataModel::State newState = d->m_profilerDataModel->currentState();
+        if (newState == QmlProfilerDataModel::Empty) {
             clear();
         }
     }
@@ -148,57 +183,119 @@ void QmlProfilerEventsWidget::eventListStateChanged()
 void QmlProfilerEventsWidget::switchToV8View()
 {
     setObjectName("QmlProfilerV8ProfileView");
-    m_eventTree->setViewType(QmlProfilerEventsMainView::V8ProfileView);
-    m_eventParents->setViewType(QmlProfilerEventsParentsAndChildrenView::V8ParentsView);
-    m_eventChildren->setViewType(QmlProfilerEventsParentsAndChildrenView::V8ChildrenView);
+    d->m_eventTree->setViewType(QmlProfilerEventsMainView::V8ProfileView);
+    d->m_eventParents->setViewType(QmlProfilerEventsParentsAndChildrenView::V8ParentsView);
+    d->m_eventChildren->setViewType(QmlProfilerEventsParentsAndChildrenView::V8ChildrenView);
     setToolTip(tr("Trace information from the v8 JavaScript engine. Available only in Qt5 based applications"));
 }
 
 void QmlProfilerEventsWidget::clear()
 {
-    m_eventTree->clear();
-    m_eventChildren->clear();
-    m_eventParents->clear();
+    d->m_eventTree->clear();
+    d->m_eventChildren->clear();
+    d->m_eventParents->clear();
 }
 
 void QmlProfilerEventsWidget::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd)
 {
     clear();
-    m_eventTree->getStatisticsInRange(rangeStart, rangeEnd);
-    m_globalStatsEnabled = m_eventTree->isRangeGlobal(rangeStart, rangeEnd);
+    d->m_eventTree->getStatisticsInRange(rangeStart, rangeEnd);
+    d->m_globalStatsEnabled = d->m_eventTree->isRangeGlobal(rangeStart, rangeEnd);
 }
 
 QModelIndex QmlProfilerEventsWidget::selectedItem() const
 {
-    return m_eventTree->selectedItem();
+    return d->m_eventTree->selectedItem();
 }
 
 void QmlProfilerEventsWidget::contextMenuEvent(QContextMenuEvent *ev)
 {
-    emit contextMenuRequested(ev->globalPos());
+    QTC_ASSERT(d->m_viewContainer, return;);
+
+    QMenu menu;
+    QAction *copyRowAction = 0;
+    QAction *copyTableAction = 0;
+    QAction *showExtendedStatsAction = 0;
+    QAction *getLocalStatsAction = 0;
+    QAction *getGlobalStatsAction = 0;
+
+    QmlProfilerTool *profilerTool = qobject_cast<QmlProfilerTool *>(d->m_profilerTool);
+    QPoint position = ev->globalPos();
+
+    if (profilerTool) {
+        QList <QAction *> commonActions = profilerTool->profilerContextMenuActions();
+        foreach (QAction *act, commonActions) {
+            menu.addAction(act);
+        }
+    }
+
+    if (mouseOnTable(position)) {
+        menu.addSeparator();
+        if (selectedItem().isValid())
+            copyRowAction = menu.addAction(tr("Copy Row"));
+        copyTableAction = menu.addAction(tr("Copy Table"));
+
+        if (isQml()) {
+            // only for qml events view, not for v8
+            showExtendedStatsAction = menu.addAction(tr("Extended Event Statistics"));
+            showExtendedStatsAction->setCheckable(true);
+            showExtendedStatsAction->setChecked(showExtendedStatistics());
+        }
+    }
+
+    if (isQml()) {
+        menu.addSeparator();
+        getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range"));
+        if (!d->m_viewContainer->hasValidSelection())
+            getLocalStatsAction->setEnabled(false);
+        getGlobalStatsAction = menu.addAction(tr("Reset Events Pane"));
+        if (hasGlobalStats())
+            getGlobalStatsAction->setEnabled(false);
+    }
+
+    QAction *selectedAction = menu.exec(position);
+
+    if (selectedAction) {
+        if (selectedAction == copyRowAction)
+            copyRowToClipboard();
+        if (selectedAction == copyTableAction)
+            copyTableToClipboard();
+        if (selectedAction == getLocalStatsAction) {
+            getStatisticsInRange(d->m_viewContainer->selectionStart(),
+                                 d->m_viewContainer->selectionEnd());
+        }
+        if (selectedAction == getGlobalStatsAction) {
+            if (d->m_profilerDataModel) {
+                getStatisticsInRange(d->m_profilerDataModel->traceStartTime(),
+                                     d->m_profilerDataModel->traceEndTime());
+            }
+        }
+        if (selectedAction == showExtendedStatsAction)
+            setShowExtendedStatistics(!showExtendedStatistics());
+    }
 }
 
 bool QmlProfilerEventsWidget::mouseOnTable(const QPoint &position) const
 {
-    QPoint tableTopLeft = m_eventTree->mapToGlobal(QPoint(0,0));
-    QPoint tableBottomRight = m_eventTree->mapToGlobal(QPoint(m_eventTree->width(), m_eventTree->height()));
+    QPoint tableTopLeft = d->m_eventTree->mapToGlobal(QPoint(0,0));
+    QPoint tableBottomRight = d->m_eventTree->mapToGlobal(QPoint(d->m_eventTree->width(), d->m_eventTree->height()));
     return (position.x() >= tableTopLeft.x() && position.x() <= tableBottomRight.x() && position.y() >= tableTopLeft.y() && position.y() <= tableBottomRight.y());
 }
 
 void QmlProfilerEventsWidget::copyTableToClipboard() const
 {
-    m_eventTree->copyTableToClipboard();
+    d->m_eventTree->copyTableToClipboard();
 }
 
 void QmlProfilerEventsWidget::copyRowToClipboard() const
 {
-    m_eventTree->copyRowToClipboard();
+    d->m_eventTree->copyRowToClipboard();
 }
 
 void QmlProfilerEventsWidget::updateSelectedEvent(int eventId) const
 {
-    if (m_eventTree->selectedEventId() != eventId)
-        m_eventTree->selectEvent(eventId);
+    if (d->m_eventTree->selectedEventId() != eventId)
+        d->m_eventTree->selectEvent(eventId);
 }
 
 void QmlProfilerEventsWidget::selectBySourceLocation(const QString &filename, int line, int column)
@@ -207,22 +304,31 @@ void QmlProfilerEventsWidget::selectBySourceLocation(const QString &filename, in
     // Our javascript trace data does not store column information
     // thus we ignore it here
     Q_UNUSED(column);
-    m_eventTree->selectEventByLocation(filename, line);
+    d->m_eventTree->selectEventByLocation(filename, line);
 }
 
 bool QmlProfilerEventsWidget::hasGlobalStats() const
 {
-    return m_globalStatsEnabled;
+    return d->m_globalStatsEnabled;
 }
 
 void QmlProfilerEventsWidget::setShowExtendedStatistics(bool show)
 {
-    m_eventTree->setShowExtendedStatistics(show);
+    d->m_eventTree->setShowExtendedStatistics(show);
 }
 
 bool QmlProfilerEventsWidget::showExtendedStatistics() const
 {
-    return m_eventTree->showExtendedStatistics();
+    return d->m_eventTree->showExtendedStatistics();
+}
+
+bool QmlProfilerEventsWidget::isQml() const
+{
+    return d->m_eventTree->viewType() == QmlProfilerEventsMainView::EventsView;
+}
+bool QmlProfilerEventsWidget::isV8() const
+{
+    return d->m_eventTree->viewType() == QmlProfilerEventsMainView::V8ProfileView;
 }
 
 ////////////////////////////////////////////////////////////////////////////////////
@@ -232,8 +338,8 @@ class QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate
 public:
     QmlProfilerEventsMainViewPrivate(QmlProfilerEventsMainView *qq) : q(qq) {}
 
-    void buildModelFromList(const QmlEventDescriptions &list, QStandardItem *parentItem, const QmlEventDescriptions &visitedFunctionsList = QmlEventDescriptions() );
-    void buildV8ModelFromList( const QV8EventDescriptions &list );
+    void buildModelFromList(const QList<QmlRangeEventData *> &list, QStandardItem *parentItem );
+    void buildV8ModelFromList( const QList<QV8EventData *> &list );
     int getFieldCount();
 
     QString textForItem(QStandardItem *item, bool recursive) const;
@@ -242,7 +348,7 @@ public:
     QmlProfilerEventsMainView *q;
 
     QmlProfilerEventsMainView::ViewTypes m_viewType;
-    QmlProfilerEventList *m_eventStatistics;
+    QmlProfilerDataModel *m_profilerDataModel;
     QStandardItemModel *m_model;
     QList<bool> m_fieldShown;
     QHash<int, int> m_columnIndex; // maps field enum to column index
@@ -254,8 +360,10 @@ public:
 
 ////////////////////////////////////////////////////////////////////////////////////
 
-QmlProfilerEventsMainView::QmlProfilerEventsMainView(QmlProfilerEventList *model, QWidget *parent) :
-    QTreeView(parent), d(new QmlProfilerEventsMainViewPrivate(this))
+QmlProfilerEventsMainView::QmlProfilerEventsMainView(ViewTypes viewType,
+                                                     QWidget *parent,
+                                                     QmlProfilerDataModel *dataModel)
+    : QTreeView(parent), d(new QmlProfilerEventsMainViewPrivate(this))
 {
     setObjectName("QmlProfilerEventsTable");
     header()->setResizeMode(QHeaderView::Interactive);
@@ -268,15 +376,17 @@ QmlProfilerEventsMainView::QmlProfilerEventsMainView(QmlProfilerEventList *model
     setModel(d->m_model);
     connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex)));
 
-    d->m_eventStatistics = 0;
-    setEventStatisticsModel(model);
+    d->m_profilerDataModel = dataModel;
+    connect(d->m_profilerDataModel,SIGNAL(stateChanged()),
+            this,SLOT(profilerDataModelStateChanged()));
+    connect(d->m_profilerDataModel,SIGNAL(detailsChanged(int,QString)),
+            this,SLOT(changeDetailsForEvent(int,QString)));
 
     d->m_firstNumericColumn = 0;
     d->m_preventSelectBounce = false;
     d->m_showExtendedStatistics = false;
 
-    // default view
-    setViewType(EventsView);
+    setViewType(viewType);
 }
 
 QmlProfilerEventsMainView::~QmlProfilerEventsMainView()
@@ -285,24 +395,11 @@ QmlProfilerEventsMainView::~QmlProfilerEventsMainView()
     delete d->m_model;
 }
 
-void QmlProfilerEventsMainView::setEventStatisticsModel( QmlProfilerEventList *model )
-{
-    if (d->m_eventStatistics) {
-        disconnect(d->m_eventStatistics,SIGNAL(stateChanged()),this,SLOT(eventListStateChanged()));
-        disconnect(d->m_eventStatistics,SIGNAL(detailsChanged(int,QString)),this,SLOT(changeDetailsForEvent(int,QString)));
-    }
-    d->m_eventStatistics = model;
-    if (model) {
-        connect(d->m_eventStatistics,SIGNAL(stateChanged()),this,SLOT(eventListStateChanged()));
-        connect(d->m_eventStatistics,SIGNAL(detailsChanged(int,QString)),this,SLOT(changeDetailsForEvent(int,QString)));
-    }
-}
-
-void QmlProfilerEventsMainView::eventListStateChanged()
+void QmlProfilerEventsMainView::profilerDataModelStateChanged()
 {
-    if (d->m_eventStatistics) {
-        QmlProfilerEventList::State newState = d->m_eventStatistics->currentState();
-        if (newState == QmlProfilerEventList::Done)
+    if (d->m_profilerDataModel) {
+        QmlProfilerDataModel::State newState = d->m_profilerDataModel->currentState();
+        if (newState == QmlProfilerDataModel::Done)
             buildModel();
     }
 }
@@ -319,6 +416,11 @@ void QmlProfilerEventsMainView::setFieldViewable(Fields field, bool show)
     }
 }
 
+QmlProfilerEventsMainView::ViewTypes QmlProfilerEventsMainView::viewType() const
+{
+    return d->m_viewType;
+}
+
 void QmlProfilerEventsMainView::setViewType(ViewTypes type)
 {
     d->m_viewType = type;
@@ -465,12 +567,12 @@ int QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::getFieldCount()
 
 void QmlProfilerEventsMainView::buildModel()
 {
-    if (d->m_eventStatistics) {
+    if (d->m_profilerDataModel) {
         clear();
         if (d->m_viewType == V8ProfileView)
-            d->buildV8ModelFromList( d->m_eventStatistics->getV8Events() );
+            d->buildV8ModelFromList( d->m_profilerDataModel->getV8Events() );
         else
-            d->buildModelFromList( d->m_eventStatistics->getEventDescriptions(), d->m_model->invisibleRootItem() );
+            d->buildModelFromList( d->m_profilerDataModel->getEventDescriptions(), d->m_model->invisibleRootItem() );
 
         setShowExtendedStatistics(d->m_showExtendedStatistics);
 
@@ -488,18 +590,15 @@ void QmlProfilerEventsMainView::buildModel()
     }
 }
 
-void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildModelFromList( const QmlEventDescriptions &list, QStandardItem *parentItem, const QmlEventDescriptions &visitedFunctionsList )
+void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildModelFromList( const QList<QmlRangeEventData *> &list, QStandardItem *parentItem)
 {
-    foreach (QmlEventData *binding, list) {
-        if (visitedFunctionsList.contains(binding))
-            continue;
-
+    foreach (QmlRangeEventData *binding, list) {
         if (binding->calls == 0)
             continue;
 
         QList<QStandardItem *> newRow;
         if (m_fieldShown[Name]) {
-            newRow << new EventsViewItem(binding->displayname);
+            newRow << new EventsViewItem(binding->displayName);
         }
 
         if (m_fieldShown[Type]) {
@@ -572,7 +671,7 @@ void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildModelFrom
     }
 }
 
-void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildV8ModelFromList(const QV8EventDescriptions &list)
+void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildV8ModelFromList(const QList<QV8EventData *> &list)
 {
     for (int index = 0; index < list.count(); index++) {
         QV8EventData *v8event = list.at(index);
@@ -649,13 +748,17 @@ QString QmlProfilerEventsMainView::nameForType(int typeNumber)
 
 void QmlProfilerEventsMainView::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd)
 {
-    d->m_eventStatistics->compileStatistics(rangeStart, rangeEnd);
+    if (d->m_profilerDataModel)
+        d->m_profilerDataModel->compileStatistics(rangeStart, rangeEnd);
     buildModel();
 }
 
 bool QmlProfilerEventsMainView::isRangeGlobal(qint64 rangeStart, qint64 rangeEnd) const
 {
-    return d->m_eventStatistics->traceStartTime() == rangeStart && d->m_eventStatistics->traceEndTime() == rangeEnd;
+    if (d->m_profilerDataModel)
+        return d->m_profilerDataModel->traceStartTime() == rangeStart && d->m_profilerDataModel->traceEndTime() == rangeEnd;
+    else
+        return true;
 }
 
 int QmlProfilerEventsMainView::selectedEventId() const
@@ -691,7 +794,7 @@ void QmlProfilerEventsMainView::jumpToItem(const QModelIndex &index)
     // show in callers/callees subwindow
     emit eventSelected(infoItem->data(EventIdRole).toInt());
 
-    // show in timelineview
+    // show in timelinerenderer
     if (d->m_viewType == EventsView) {
         emit showEventInTimeline(infoItem->data(EventIdRole).toInt());
     }
@@ -819,9 +922,11 @@ void QmlProfilerEventsMainView::copyRowToClipboard() const
 
 ////////////////////////////////////////////////////////////////////////////////////
 
-QmlProfilerEventsParentsAndChildrenView::QmlProfilerEventsParentsAndChildrenView(QmlJsDebugClient::QmlProfilerEventList *model, SubViewType subtableType, QWidget *parent):QTreeView(parent)
+QmlProfilerEventsParentsAndChildrenView::QmlProfilerEventsParentsAndChildrenView(
+        SubViewType subtableType, QWidget *parent, QmlProfilerDataModel *model)
+    : QTreeView(parent)
 {
-    m_eventList = model;
+    m_profilerDataModel = model;
     setModel(new QStandardItemModel(this));
     setRootIsDecorated(false);
     setFrameStyle(QFrame::NoFrame);
@@ -843,30 +948,33 @@ void QmlProfilerEventsParentsAndChildrenView::setViewType(SubViewType type)
 
 void QmlProfilerEventsParentsAndChildrenView::displayEvent(int eventId)
 {
+    if (!m_profilerDataModel)
+        return;
+
     bool isV8 = m_subtableType == V8ParentsView || m_subtableType == V8ChildrenView;
     bool isChildren = m_subtableType == ChildrenView || m_subtableType == V8ChildrenView;
 
     if (isV8) {
-        QmlJsDebugClient::QV8EventData *v8event = m_eventList->v8EventDescription(eventId);
+        QV8EventData *v8event = m_profilerDataModel->v8EventDescription(eventId);
         if (v8event) {
             if (isChildren) {
-                QList <QmlJsDebugClient::QV8EventSub *> childrenList = v8event->childrenHash.values();
+                QList <QV8EventSub *> childrenList = v8event->childrenHash.values();
                 rebuildTree((QObject *)&childrenList);
             }
             else {
-                QList <QmlJsDebugClient::QV8EventSub *> parentList = v8event->parentHash.values();
+                QList <QV8EventSub *> parentList = v8event->parentHash.values();
                 rebuildTree((QObject *)&parentList);
             }
         }
     } else {
-        QmlJsDebugClient::QmlEventData *qmlEvent = m_eventList->eventDescription(eventId);
+        QmlRangeEventData *qmlEvent = m_profilerDataModel->eventDescription(eventId);
         if (qmlEvent) {
             if (isChildren) {
-                QList <QmlJsDebugClient::QmlEventSub *> childrenList = qmlEvent->childrenHash.values();
+                QList <QmlRangeEventRelative *> childrenList = qmlEvent->childrenHash.values();
                 rebuildTree((QObject *)&childrenList);
             }
             else {
-                QList <QmlJsDebugClient::QmlEventSub *> parentList = qmlEvent->parentHash.values();
+                QList <QmlRangeEventRelative *> parentList = qmlEvent->parentHash.values();
                 rebuildTree((QObject *)&parentList);
             }
         }
@@ -881,7 +989,7 @@ void QmlProfilerEventsParentsAndChildrenView::displayEvent(int eventId)
         sortByColumn(2);
 }
 
-void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList)
+void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *profilerDataModel)
 {
     Q_ASSERT(treeModel());
     treeModel()->clear();
@@ -889,8 +997,8 @@ void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList)
     QStandardItem *topLevelItem = treeModel()->invisibleRootItem();
     bool isV8 = m_subtableType == V8ParentsView || m_subtableType == V8ChildrenView;
 
-    QList <QmlEventSub *> *qmlList = static_cast< QList <QmlEventSub *> *>(eventList);
-    QList <QV8EventSub*> *v8List = static_cast< QList <QV8EventSub *> *>(eventList);
+    QList <QmlRangeEventRelative *> *qmlList = static_cast< QList <QmlRangeEventRelative *> *>(profilerDataModel);
+    QList <QV8EventSub*> *v8List = static_cast< QList <QV8EventSub *> *>(profilerDataModel);
 
     int listLength;
     if (!isV8)
@@ -901,9 +1009,9 @@ void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList)
     for (int index=0; index < listLength; index++) {
         QList<QStandardItem *> newRow;
         if (!isV8) {
-            QmlEventSub *event = qmlList->at(index);
+            QmlRangeEventRelative *event = qmlList->at(index);
 
-            newRow << new EventsViewItem(event->reference->displayname);
+            newRow << new EventsViewItem(event->reference->displayName);
             newRow << new EventsViewItem(QmlProfilerEventsMainView::nameForType(event->reference->eventType));
             newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event->duration));
             newRow << new EventsViewItem(QString::number(event->calls));
diff --git a/src/plugins/qmlprofiler/qmlprofilereventview.h b/src/plugins/qmlprofiler/qmlprofilereventview.h
index 1c7c87d7f243b44ee9eb597d0646a9ecc07bfe21..409ea4dca08041d6c16d6837b3e1ee6e6a92a9f4 100644
--- a/src/plugins/qmlprofiler/qmlprofilereventview.h
+++ b/src/plugins/qmlprofiler/qmlprofilereventview.h
@@ -34,9 +34,13 @@
 #define QMLPROFILEREVENTVIEW_H
 
 #include <QTreeView>
-#include <qmljsdebugclient/qmlprofilereventtypes.h>
-#include <qmljsdebugclient/qmlprofilereventlist.h>
 #include <QStandardItemModel>
+#include <qmljsdebugclient/qmlprofilereventtypes.h>
+#include "qmlprofilerdatamodel.h"
+
+#include <analyzerbase/ianalyzertool.h>
+
+#include "qmlprofilerviewmanager.h"
 
 namespace QmlProfiler {
 namespace Internal {
@@ -44,9 +48,6 @@ namespace Internal {
 class QmlProfilerEventsMainView;
 class QmlProfilerEventsParentsAndChildrenView;
 
-typedef QHash<QString, QmlJsDebugClient::QmlEventData *> QmlEventHash;
-typedef QList<QmlJsDebugClient::QmlEventData *> QmlEventList;
-
 enum ItemRole {
     EventHashStrRole = Qt::UserRole+1,
     FilenameRole = Qt::UserRole+2,
@@ -59,7 +60,10 @@ class QmlProfilerEventsWidget : public QWidget
 {
     Q_OBJECT
 public:
-    explicit QmlProfilerEventsWidget(QmlJsDebugClient::QmlProfilerEventList *model, QWidget *parent);
+    explicit QmlProfilerEventsWidget(QWidget *parent,
+                                     Analyzer::IAnalyzerTool *profilerTool,
+                                     QmlProfilerViewManager *container,
+                                     QmlProfilerDataModel *profilerDataModel );
     ~QmlProfilerEventsWidget();
 
     void switchToV8View();
@@ -75,9 +79,11 @@ public:
     void setShowExtendedStatistics(bool show);
     bool showExtendedStatistics() const;
 
+    bool isQml() const;
+    bool isV8() const;
+
 signals:
     void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
-    void contextMenuRequested(const QPoint &position);
     void showEventInTimeline(int eventId);
 
 public slots:
@@ -85,18 +91,14 @@ public slots:
     void selectBySourceLocation(const QString &filename, int line, int column);
 
 private slots:
-    void eventListStateChanged();
+    void profilerDataModelStateChanged();
 
 protected:
     void contextMenuEvent(QContextMenuEvent *ev);
 
 private:
-    QmlProfilerEventsMainView *m_eventTree;
-    QmlProfilerEventsParentsAndChildrenView *m_eventChildren;
-    QmlProfilerEventsParentsAndChildrenView *m_eventParents;
-    QmlJsDebugClient::QmlProfilerEventList *m_eventStatistics;
-
-    bool m_globalStatsEnabled;
+    class QmlProfilerEventsWidgetPrivate;
+    QmlProfilerEventsWidgetPrivate *d;
 };
 
 class QmlProfilerEventsMainView : public QTreeView
@@ -129,12 +131,14 @@ public:
         MaxViewTypes
     };
 
-    explicit QmlProfilerEventsMainView(QmlJsDebugClient::QmlProfilerEventList *model, QWidget *parent);
+    explicit QmlProfilerEventsMainView(ViewTypes viewType,
+                                       QWidget *parent,
+                                       QmlProfilerDataModel *dataModel);
     ~QmlProfilerEventsMainView();
 
-    void setEventStatisticsModel(QmlJsDebugClient::QmlProfilerEventList *model);
     void setFieldViewable(Fields field, bool show);
     void setViewType(ViewTypes type);
+    ViewTypes viewType() const;
     void setShowAnonymousEvents( bool showThem );
 
     QModelIndex selectedItem() const;
@@ -157,7 +161,6 @@ signals:
     void showEventInTimeline(int eventId);
 
 public slots:
-    void eventListStateChanged();
     void clear();
     void jumpToItem(const QModelIndex &index);
     void selectEvent(int eventId);
@@ -165,6 +168,9 @@ public slots:
     void buildModel();
     void changeDetailsForEvent(int eventId, const QString &newString);
 
+private slots:
+    void profilerDataModelStateChanged();
+
 private:
     void setHeaderLabels();
 
@@ -186,7 +192,9 @@ public:
         MaxSubtableTypes
     };
 
-    explicit QmlProfilerEventsParentsAndChildrenView(QmlJsDebugClient::QmlProfilerEventList *model, SubViewType subtableType, QWidget *parent);
+    explicit QmlProfilerEventsParentsAndChildrenView(SubViewType subtableType,
+                                                     QWidget *parent,
+                                                     QmlProfilerDataModel *model);
     ~QmlProfilerEventsParentsAndChildrenView();
 
     void setViewType(SubViewType type);
@@ -200,10 +208,10 @@ public slots:
     void clear();
 
 private:
-    void rebuildTree(void *eventList);
+    void rebuildTree(void *profilerDataModel);
     void updateHeader();
     QStandardItemModel *treeModel();
-    QmlJsDebugClient::QmlProfilerEventList *m_eventList;
+    QmlProfilerDataModel *m_profilerDataModel;
 
     SubViewType m_subtableType;
 };
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatemanager.cpp b/src/plugins/qmlprofiler/qmlprofilerstatemanager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..194e2cdf1c6cf8acf7fceb3c40d44c7e391ed6cd
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilerstatemanager.cpp
@@ -0,0 +1,163 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "qmlprofilerstatemanager.h"
+
+#include <QDebug>
+#include <utils/qtcassert.h>
+
+// uncomment for printing the state changes to debug output
+//#define _DEBUG_PROFILERSTATE_
+
+namespace QmlProfiler {
+namespace Internal {
+
+inline QString stringForState(int state) {
+    switch (state) {
+    case QmlProfilerStateManager::Idle: return QString("Idle");
+    case QmlProfilerStateManager::AppStarting: return QString("AppStarting");
+    case QmlProfilerStateManager::AppRunning: return QString("AppRunning");
+    case QmlProfilerStateManager::AppStopRequested: return QString("AppStopRequested");
+    case QmlProfilerStateManager::AppReadyToStop: return QString("AppReadyToStop");
+    case QmlProfilerStateManager::AppStopped: return QString("AppStopped");
+    case QmlProfilerStateManager::AppKilled: return QString("AppKilled");
+    default: break;
+    }
+    return QString();
+}
+
+class QmlProfilerStateManager::QmlProfilerStateManagerPrivate
+{
+public:
+    QmlProfilerStateManagerPrivate(QmlProfilerStateManager *qq) : q(qq) {}
+    ~QmlProfilerStateManagerPrivate() {}
+
+    QmlProfilerStateManager *q;
+
+    QmlProfilerStateManager::QmlProfilerState m_currentState;
+    bool m_clientRecording;
+    bool m_serverRecording;
+};
+QmlProfilerStateManager::QmlProfilerStateManager(QObject *parent) :
+    QObject(parent),d(new QmlProfilerStateManagerPrivate(this))
+{
+    d->m_currentState = Idle;
+    d->m_clientRecording = true;
+    d->m_serverRecording = false;
+}
+
+QmlProfilerStateManager::~QmlProfilerStateManager()
+{
+    delete d;
+}
+
+QmlProfilerStateManager::QmlProfilerState QmlProfilerStateManager::currentState()
+{
+    return d->m_currentState;
+}
+
+bool QmlProfilerStateManager::clientRecording()
+{
+    return d->m_clientRecording;
+}
+
+bool QmlProfilerStateManager::serverRecording()
+{
+    return d->m_serverRecording;
+}
+
+QString QmlProfilerStateManager::currentStateAsString()
+{
+    return stringForState(d->m_currentState);
+}
+
+void QmlProfilerStateManager::setCurrentState(QmlProfilerState newState)
+{
+#ifdef _DEBUG_PROFILERSTATE_
+    qDebug() << "Profiler state change request from" << stringForState(d->m_currentState) << "to" << stringForState(newState);
+#endif
+    QTC_ASSERT(d->m_currentState != newState, /**/);
+    switch (newState) {
+    case Idle:
+        QTC_ASSERT(d->m_currentState == AppStarting || d->m_currentState == AppStopped || d->m_currentState == AppKilled, /**/);
+        break;
+    case AppStarting:
+        QTC_ASSERT(d->m_currentState == Idle, /**/);
+        break;
+    case AppRunning:
+        QTC_ASSERT(d->m_currentState == AppStarting, /**/);
+        break;
+    case AppStopRequested:
+        QTC_ASSERT(d->m_currentState == AppRunning, /**/);
+        break;
+    case AppReadyToStop:
+        QTC_ASSERT(d->m_currentState == AppStopRequested, /**/);
+        break;
+    case AppStopped:
+        QTC_ASSERT(d->m_currentState == AppReadyToStop, /**/);
+        break;
+    case AppKilled:
+        QTC_ASSERT(d->m_currentState == AppRunning, /**/);
+        break;
+    default:
+        qDebug() << tr("Switching to unknown state in %1:%2").arg(QString(__FILE__), QString::number(__LINE__));
+        break;
+    }
+
+    d->m_currentState = newState;
+    emit stateChanged();
+}
+
+void QmlProfilerStateManager::setClientRecording(bool recording)
+{
+#ifdef _DEBUG_PROFILERSTATE_
+    qDebug() << "Setting client recording flag from" << d->m_serverRecording << "to" << recording;
+#endif
+    if (d->m_clientRecording != recording) {
+        d->m_clientRecording = recording;
+        emit clientRecordingChanged();
+    }
+}
+
+void QmlProfilerStateManager::setServerRecording(bool recording)
+{
+#ifdef _DEBUG_PROFILERSTATE_
+    qDebug() << "Setting server recording flag from" << d->m_serverRecording << "to" << recording;
+#endif
+    if (d->m_serverRecording != recording) {
+        d->m_serverRecording = recording;
+        emit serverRecordingChanged();
+    }
+}
+
+}
+}
diff --git a/src/tools/qmlprofilertool/commandlistener.h b/src/plugins/qmlprofiler/qmlprofilerstatemanager.h
similarity index 58%
rename from src/tools/qmlprofilertool/commandlistener.h
rename to src/plugins/qmlprofiler/qmlprofilerstatemanager.h
index 4b8df747ffe2eef48db9e447d47895745309b313..188b0b5be34bf38cc6b83c0cbdf20e81c2581f3d 100644
--- a/src/tools/qmlprofilertool/commandlistener.h
+++ b/src/plugins/qmlprofiler/qmlprofilerstatemanager.h
@@ -30,25 +30,53 @@
 **
 **************************************************************************/
 
-#ifndef COMMANDLISTENER_H
-#define COMMANDLISTENER_H
+#ifndef QMLPROFILERSTATEMANAGER_H
+#define QMLPROFILERSTATEMANAGER_H
 
-#include <QThread>
+#include <QObject>
 
-class CommandListener : public QThread
+namespace QmlProfiler {
+namespace Internal {
+
+class QmlProfilerStateManager : public QObject
 {
     Q_OBJECT
 public:
-    CommandListener(QObject *parent = 0);
+    enum QmlProfilerState {
+        Idle,
+        AppStarting,
+        AppRunning,
+        AppStopRequested,
+        AppReadyToStop,
+        AppStopped,
+        AppKilled
+    };
+
+    explicit QmlProfilerStateManager(QObject *parent = 0);
+    ~QmlProfilerStateManager();
+
+    QmlProfilerState currentState();
+    bool clientRecording();
+    bool serverRecording();
 
-    void run();
+    QString currentStateAsString();
 
-    void requestStop() { m_stopRequested = true; }
 signals:
-    void command(const QString &command);
+    void stateChanged();
+    void clientRecordingChanged();
+    void serverRecordingChanged();
+
+public slots:
+    void setCurrentState(QmlProfilerState newState);
+    void setClientRecording(bool recording);
+    void setServerRecording(bool recording);
 
 private:
-    bool m_stopRequested;
+    class QmlProfilerStateManagerPrivate;
+    QmlProfilerStateManagerPrivate *d;
 };
 
-#endif // COMMANDLISTENER_H
+}
+}
+
+#endif // QMLPROFILERSTATEMANAGER_H
diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp
index 76359684c9e3531b3bb099768845fbeeb986012a..46bf8b6085b82d69e9c939cbd63d3e805fb73596 100644
--- a/src/plugins/qmlprofiler/qmlprofilertool.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp
@@ -31,24 +31,20 @@
 **************************************************************************/
 
 #include "qmlprofilertool.h"
+#include "qmlprofilerstatemanager.h"
 #include "qmlprofilerengine.h"
-#include "qmlprofilerplugin.h"
 #include "qmlprofilerconstants.h"
 #include "qmlprofilerattachdialog.h"
-#include "qmlprofilereventview.h"
-
-#include "tracewindow.h"
-#include "timelineview.h"
-
-#include <qmljsdebugclient/qmlprofilereventlist.h>
-#include <qmljsdebugclient/qdeclarativedebugclient.h>
+#include "qmlprofilerviewmanager.h"
+#include "qmlprofilerclientmanager.h"
+#include "qmlprofilerdatamodel.h"
+#include "qmlprofilerdetailsrewriter.h"
+#include "timelinerenderer.h"
 
 #include <analyzerbase/analyzermanager.h>
-#include <analyzerbase/analyzerconstants.h>
 #include <analyzerbase/analyzerruncontrol.h>
 
-#include "canvas/qdeclarativecanvas_p.h"
-#include "canvas/qdeclarativecanvastimer_p.h"
+#include "canvas/qdeclarativecontext2d_p.h"
 #include "canvas/qmlprofilercanvas.h"
 
 #include <qmlprojectmanager/qmlprojectrunconfiguration.h>
@@ -56,7 +52,6 @@
 #include <utils/fileinprojectfinder.h>
 #include <utils/qtcassert.h>
 #include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/projectexplorerconstants.h>
 #include <projectexplorer/project.h>
 #include <projectexplorer/target.h>
 #include <projectexplorer/session.h>
@@ -65,7 +60,6 @@
 #include <remotelinux/remotelinuxrunconfiguration.h>
 #include <remotelinux/linuxdeviceconfiguration.h>
 
-#include <texteditor/itexteditor.h>
 #include <coreplugin/coreconstants.h>
 #include <coreplugin/editormanager/editormanager.h>
 #include <coreplugin/icore.h>
@@ -82,23 +76,22 @@
 #include <qt4projectmanager/qt-s60/s60devicerunconfiguration.h>
 #include <qt4projectmanager/qt-s60/s60deployconfiguration.h>
 
-#include <QFile>
-
 #include <QApplication>
 #include <QHBoxLayout>
 #include <QLabel>
-#include <QTabWidget>
 #include <QToolButton>
 #include <QMessageBox>
-#include <QDockWidget>
 #include <QFileDialog>
 #include <QMenu>
+#include <QTimer>
+#include <QTime>
 
 using namespace Core;
 using namespace Core::Constants;
 using namespace Analyzer;
 using namespace Analyzer::Constants;
 using namespace QmlProfiler::Internal;
+using namespace QmlProfiler::Constants;
 using namespace QmlJsDebugClient;
 using namespace ProjectExplorer;
 using namespace QmlProjectManager;
@@ -112,59 +105,67 @@ public:
 
     QmlProfilerTool *q;
 
-    QDeclarativeDebugConnection *m_client;
-    QTimer m_connectionTimer;
-    int m_connectionAttempts;
-    TraceWindow *m_traceWindow;
-    QmlProfilerEventsWidget *m_eventsView;
-    QmlProfilerEventsWidget *m_v8profilerView;
+    QmlProfilerStateManager *m_profilerState;
+    QmlProfilerClientManager *m_profilerConnections;
+    QmlProfilerDataModel *m_profilerDataModel;
+    QmlProfilerDetailsRewriter *m_detailsRewriter;
+
+    QmlProfilerViewManager *m_viewContainer;
     Utils::FileInProjectFinder m_projectFinder;
     RunConfiguration *m_runConfiguration;
-    bool m_isAttached;
     QToolButton *m_recordButton;
     QToolButton *m_clearButton;
-    bool m_recordingEnabled;
-    bool m_appIsRunning;
-    bool m_qmlActive;
-    bool m_v8Active;
-    QTime m_appTimer;
-    qint64 m_appRunningTime;
-
-    enum ConnectMode {
-        TcpConnection, OstConnection
-    };
-
-    ConnectMode m_connectMode;
-    QString m_tcpHost;
-    quint16 m_tcpPort;
-    QString m_ostDevice;
-    QString m_sysroot;
+
+    // elapsed time display
+    QTimer m_recordingTimer;
+    QTime m_recordingElapsedTime;
+    QLabel *m_timeLabel;
+
+    // save and load actions
     QAction *m_saveQmlTrace;
+    QAction *m_loadQmlTrace;
 };
 
 QmlProfilerTool::QmlProfilerTool(QObject *parent)
     : IAnalyzerTool(parent), d(new QmlProfilerToolPrivate(this))
 {
     setObjectName("QmlProfilerTool");
-    d->m_client = 0;
-    d->m_connectionAttempts = 0;
-    d->m_traceWindow = 0;
-    d->m_runConfiguration = 0;
-    d->m_isAttached = false;
-    d->m_recordingEnabled = true;
-    d->m_appIsRunning = false;
-    d->m_appTimer.start();
-    d->m_appRunningTime = 0;
 
-    d->m_connectionTimer.setInterval(200);
-    connect(&d->m_connectionTimer, SIGNAL(timeout()), SLOT(tryToConnect()));
+    d->m_profilerState = 0;
+    d->m_viewContainer = 0;
+    d->m_runConfiguration = 0;
 
-    qmlRegisterType<Canvas>("Monitor", 1, 0, "Canvas");
     qmlRegisterType<QmlProfilerCanvas>("Monitor", 1, 0, "Canvas2D");
     qmlRegisterType<Context2D>();
-    qmlRegisterType<CanvasImage>();
     qmlRegisterType<CanvasGradient>();
-    qmlRegisterType<TimelineView>("Monitor", 1, 0,"TimelineView");
+    qmlRegisterType<TimelineRenderer>("Monitor", 1, 0,"TimelineRenderer");
+
+    d->m_profilerState = new QmlProfilerStateManager(this);
+    connect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged()));
+    connect(d->m_profilerState, SIGNAL(clientRecordingChanged()), this, SLOT(clientRecordingChanged()));
+    connect(d->m_profilerState, SIGNAL(serverRecordingChanged()), this, SLOT(serverRecordingChanged()));
+
+    d->m_profilerConnections = new QmlProfilerClientManager(this);
+    d->m_profilerConnections->registerProfilerStateManager(d->m_profilerState);
+
+    d->m_profilerDataModel = new QmlProfilerDataModel(this);
+    connect(d->m_profilerDataModel, SIGNAL(stateChanged()), this, SLOT(profilerDataModelStateChanged()));
+    connect(d->m_profilerDataModel, SIGNAL(error(QString)), this, SLOT(showErrorDialog(QString)));
+    connect(d->m_profilerConnections, SIGNAL(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)), d->m_profilerDataModel, SLOT(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
+    connect(d->m_profilerConnections, SIGNAL(addV8Event(int,QString,QString,int,double,double)), d->m_profilerDataModel, SLOT(addV8Event(int,QString,QString,int,double,double)));
+    connect(d->m_profilerConnections, SIGNAL(addFrameEvent(qint64,int,int)), d->m_profilerDataModel, SLOT(addFrameEvent(qint64,int,int)));
+    connect(d->m_profilerConnections, SIGNAL(traceStarted(qint64)), d->m_profilerDataModel, SLOT(setTraceStartTime(qint64)));
+    connect(d->m_profilerConnections, SIGNAL(traceFinished(qint64)), d->m_profilerDataModel, SLOT(setTraceEndTime(qint64)));
+    connect(d->m_profilerConnections, SIGNAL(dataReadyForProcessing()), d->m_profilerDataModel, SLOT(complete()));
+
+
+    d->m_detailsRewriter = new QmlProfilerDetailsRewriter(this);
+    connect(d->m_profilerDataModel, SIGNAL(requestDetailsForLocation(int,QmlJsDebugClient::QmlEventLocation)),
+            d->m_detailsRewriter, SLOT(requestDetailsForLocation(int,QmlJsDebugClient::QmlEventLocation)));
+    connect(d->m_detailsRewriter, SIGNAL(rewriteDetailsString(int,QmlJsDebugClient::QmlEventLocation,QString)),
+            d->m_profilerDataModel, SLOT(rewriteDetailsString(int,QmlJsDebugClient::QmlEventLocation,QString)));
+    connect(d->m_detailsRewriter, SIGNAL(eventDetailsChanged()), d->m_profilerDataModel, SLOT(finishedRewritingDetails()));
+    connect(d->m_profilerDataModel, SIGNAL(reloadDocumentsForDetails()), d->m_detailsRewriter, SLOT(reloadDocuments()));
 
     Command *command = 0;
     const Context globalContext(C_GLOBAL);
@@ -176,7 +177,7 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
     menu->addMenu(options, G_ANALYZER_OPTIONS);
     options->menu()->setEnabled(true);
 
-    QAction *act = new QAction(tr("Load QML Trace"), options);
+    QAction *act = d->m_loadQmlTrace = new QAction(tr("Load QML Trace"), options);
     command = am->registerAction(act, "Analyzer.Menu.StartAnalyzer.QMLProfilerOptions.LoadQMLTrace", globalContext);
     connect(act, SIGNAL(triggered()), this, SLOT(showLoadDialog()));
     options->addAction(command);
@@ -186,11 +187,13 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
     command = am->registerAction(act, "Analyzer.Menu.StartAnalyzer.QMLProfilerOptions.SaveQMLTrace", globalContext);
     connect(act, SIGNAL(triggered()), this, SLOT(showSaveDialog()));
     options->addAction(command);
+
+    d->m_recordingTimer.setInterval(100);
+    connect(&d->m_recordingTimer, SIGNAL(timeout()), this, SLOT(updateTimeDisplay()));
 }
 
 QmlProfilerTool::~QmlProfilerTool()
 {
-    delete d->m_client;
     delete d;
 }
 
@@ -220,86 +223,14 @@ IAnalyzerTool::ToolMode QmlProfilerTool::toolMode() const
     return AnyMode;
 }
 
-void QmlProfilerTool::showContextMenu(const QPoint &position)
-{
-    QmlProfilerEventsWidget *eventView = qobject_cast<QmlProfilerEventsWidget *>(sender());
-    TraceWindow *traceView = qobject_cast<TraceWindow *>(sender());
-
-    QMenu menu;
-    QAction *loadAction = menu.addAction(tr("Load QML Trace"));
-    QAction *saveAction = menu.addAction(tr("Save QML Trace"));
-    QAction *copyRowAction = 0;
-    QAction *copyTableAction = 0;
-    QAction *showExtendedStatsAction = 0;
-    QAction *viewAllAction = 0;
-    QAction *getLocalStatsAction = 0;
-    QAction *getGlobalStatsAction = 0;
-
-    if (eventView && eventView->mouseOnTable(position)) {
-        menu.addSeparator();
-        if (eventView->selectedItem().isValid())
-            copyRowAction = menu.addAction(tr("Copy Row"));
-        copyTableAction = menu.addAction(tr("Copy Table"));
-
-        if (eventView == d->m_eventsView) {
-            // only for qml events view, not for v8
-            showExtendedStatsAction = menu.addAction(tr("Extended Event Statistics"));
-            showExtendedStatsAction->setCheckable(true);
-            showExtendedStatsAction->setChecked(eventView->showExtendedStatistics());
-        }
-    }
-
-    if (sender() == d->m_traceWindow || sender() == d->m_eventsView) {
-        menu.addSeparator();
-        getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range"));
-        if (!d->m_traceWindow->hasValidSelection())
-            getLocalStatsAction->setEnabled(false);
-        getGlobalStatsAction = menu.addAction(tr("Reset Events Pane"));
-        if (d->m_eventsView->hasGlobalStats())
-            getGlobalStatsAction->setEnabled(false);
-    }
-
-    if (traceView) {
-        if (traceView->getEventList()->count() > 0) {
-            menu.addSeparator();
-            viewAllAction = menu.addAction(tr("Reset Zoom"));
-        }
-    }
-
-    QAction *selectedAction = menu.exec(position);
-
-    if (selectedAction) {
-        if (selectedAction == loadAction)
-            showLoadDialog();
-        if (selectedAction == saveAction)
-            showSaveDialog();
-        if (selectedAction == copyRowAction)
-            eventView->copyRowToClipboard();
-        if (selectedAction == copyTableAction)
-            eventView->copyTableToClipboard();
-        if (selectedAction == viewAllAction)
-            traceView->viewAll();
-        if (selectedAction == getLocalStatsAction) {
-            d->m_eventsView->getStatisticsInRange(
-                        d->m_traceWindow->selectionStart(),
-                        d->m_traceWindow->selectionEnd());
-        }
-        if (selectedAction == getGlobalStatsAction) {
-            d->m_eventsView->getStatisticsInRange(
-                        d->m_traceWindow->getEventList()->traceStartTime(),
-                        d->m_traceWindow->getEventList()->traceEndTime());
-        }
-        if (selectedAction == showExtendedStatsAction)
-            eventView->setShowExtendedStatistics(!eventView->showExtendedStatistics());
-    }
-}
-
 IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp,
     RunConfiguration *runConfiguration)
 {
     QmlProfilerEngine *engine = new QmlProfilerEngine(this, sp, runConfiguration);
 
-    d->m_connectMode = QmlProfilerToolPrivate::TcpConnection;
+    engine->registerProfilerStateManager(d->m_profilerState);
+
+    bool isTcpConnection = true;
 
     if (runConfiguration) {
         // Check minimum Qt Version. We cannot really be sure what the Qt version
@@ -324,16 +255,15 @@ IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp
                     runConfiguration->target()->activeDeployConfiguration())) {
             if (deployConfig->communicationChannel()
                     == Qt4ProjectManager::S60DeployConfiguration::CommunicationCodaSerialConnection) {
-                d->m_connectMode = QmlProfilerToolPrivate::OstConnection;
-                d->m_ostDevice = deployConfig->serialPortName();
+                d->m_profilerConnections->setOstConnection(deployConfig->serialPortName());
+                isTcpConnection = false;
             }
         }
     }
 
     // FIXME: Check that there's something sensible in sp.connParams
-    if (d->m_connectMode == QmlProfilerToolPrivate::TcpConnection) {
-        d->m_tcpHost = sp.connParams.host;
-        d->m_tcpPort = sp.connParams.port;
+    if (isTcpConnection) {
+        d->m_profilerConnections->setTcpConnection(sp.connParams.host, sp.connParams.port);
     }
 
     d->m_runConfiguration = runConfiguration;
@@ -364,20 +294,9 @@ IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp
     d->m_projectFinder.setProjectFiles(sourceFiles);
     d->m_projectFinder.setSysroot(sp.sysroot);
 
-    connect(engine, SIGNAL(processRunning(quint16)), this, SLOT(connectClient(quint16)));
-    connect(engine, SIGNAL(finished()), this, SLOT(disconnectClient()));
-    connect(engine, SIGNAL(finished()), this, SLOT(updateTimers()));
-    connect(engine, SIGNAL(stopRecording()), this, SLOT(stopRecording()));
-    connect(engine, SIGNAL(recordingChanged(bool)), this, SLOT(setRecording(bool)));
-    connect(engine, SIGNAL(timeUpdate()), this, SLOT(updateTimers()));
-    connect(d->m_traceWindow, SIGNAL(viewUpdated()), engine, SLOT(dataReceived()));
-    connect(this, SIGNAL(connectionFailed()), engine, SLOT(finishProcess()));
-    connect(this, SIGNAL(fetchingData(bool)), engine, SLOT(setFetchingData(bool)));
-    connect(engine, SIGNAL(starting(const Analyzer::IAnalyzerEngine*)), this, SLOT(setAppIsRunning()));
-    connect(engine, SIGNAL(finished()), this, SLOT(setAppIsStopped()));
-    connect(this, SIGNAL(cancelRun()), engine, SLOT(finishProcess()));
-    connect(engine, SIGNAL(applicationDied()), d->m_traceWindow, SLOT(applicationDied()));
-    emit fetchingData(d->m_recordButton->isChecked());
+    connect(engine, SIGNAL(processRunning(quint16)), d->m_profilerConnections, SLOT(connectClient(quint16)));
+    connect(engine, SIGNAL(finished()), d->m_profilerConnections, SLOT(disconnectClient()));
+    connect(d->m_profilerConnections, SIGNAL(connectionFailed()), engine, SLOT(cancelProcess()));
 
     return engine;
 }
@@ -444,53 +363,15 @@ AnalyzerStartParameters QmlProfilerTool::createStartParameters(RunConfiguration
 
 QWidget *QmlProfilerTool::createWidgets()
 {
-    QTC_ASSERT(!d->m_traceWindow, return 0);
-
-    //
-    // DockWidgets
-    //
-
-    Utils::FancyMainWindow *mw = AnalyzerManager::mainWindow();
-
-    d->m_traceWindow = new TraceWindow(mw);
-    d->m_traceWindow->reset(d->m_client);
-
-    connect(d->m_traceWindow, SIGNAL(clearViewsFromTool()), this, SLOT(clearDisplay()));
-    connect(d->m_traceWindow, SIGNAL(gotoSourceLocation(QString,int,int)),this, SLOT(gotoSourceLocation(QString,int,int)));
-    connect(d->m_traceWindow, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
-    connect(d->m_traceWindow->getEventList(), SIGNAL(error(QString)), this, SLOT(showErrorDialog(QString)));
-    connect(d->m_traceWindow->getEventList(), SIGNAL(stateChanged()), this, SLOT(eventListStateChanged()));
-    connect(d->m_traceWindow, SIGNAL(profilerStateChanged(bool,bool)), this, SLOT(profilerStateChanged(bool,bool)));
-    connect(d->m_traceWindow, SIGNAL(recordingChanged(bool)), this, SLOT(setRecording(bool)));
-
-    d->m_eventsView = new QmlProfilerEventsWidget(d->m_traceWindow->getEventList(), mw);
-    connect(d->m_eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), this, SLOT(gotoSourceLocation(QString,int,int)));
-    connect(d->m_eventsView, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
-    connect(d->m_eventsView, SIGNAL(showEventInTimeline(int)), d->m_traceWindow, SLOT(selectNextEvent(int)));
-    connect(d->m_traceWindow, SIGNAL(selectedEventIdChanged(int)), d->m_eventsView, SLOT(updateSelectedEvent(int)));
+    QTC_ASSERT(!d->m_viewContainer, return 0);
 
-    d->m_v8profilerView = new QmlProfilerEventsWidget(d->m_traceWindow->getEventList(), mw);
-    d->m_v8profilerView->switchToV8View();
-    connect(d->m_v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)), this, SLOT(gotoSourceLocation(QString,int,int)));
-    connect(d->m_v8profilerView, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
 
-    connect(d->m_v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)), d->m_eventsView, SLOT(selectBySourceLocation(QString,int,int)));
-    connect(d->m_eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), d->m_v8profilerView, SLOT(selectBySourceLocation(QString,int,int)));
-
-    QDockWidget *eventsDock = AnalyzerManager::createDockWidget
-            (this, tr("Events"), d->m_eventsView, Qt::BottomDockWidgetArea);
-    QDockWidget *timelineDock = AnalyzerManager::createDockWidget
-            (this, tr("Timeline"), d->m_traceWindow, Qt::BottomDockWidgetArea);
-    QDockWidget *v8profilerDock = AnalyzerManager::createDockWidget
-            (this, tr("JavaScript"), d->m_v8profilerView, Qt::BottomDockWidgetArea);
-
-    eventsDock->show();
-    timelineDock->show();
-    v8profilerDock->show();
-
-    mw->splitDockWidget(mw->toolBarDockWidget(), eventsDock, Qt::Vertical);
-    mw->tabifyDockWidget(eventsDock, timelineDock);
-    mw->tabifyDockWidget(timelineDock, v8profilerDock);
+    d->m_viewContainer = new QmlProfilerViewManager(this,
+                                                    this,
+                                                    d->m_profilerDataModel,
+                                                    d->m_profilerState);
+    connect(d->m_viewContainer, SIGNAL(gotoSourceLocation(QString,int,int)),
+            this, SLOT(gotoSourceLocation(QString,int,int)));
 
     //
     // Toolbar
@@ -507,118 +388,53 @@ QWidget *QmlProfilerTool::createWidgets()
 
     connect(d->m_recordButton,SIGNAL(clicked(bool)), this, SLOT(recordingButtonChanged(bool)));
     d->m_recordButton->setChecked(true);
-    setRecording(d->m_recordingEnabled);
+    setRecording(d->m_profilerState->clientRecording());
     layout->addWidget(d->m_recordButton);
 
     d->m_clearButton = new QToolButton(toolbarWidget);
     d->m_clearButton->setIcon(QIcon(QLatin1String(":/qmlprofiler/clean_pane_small.png")));
     d->m_clearButton->setToolTip(tr("Discard data"));
-    connect(d->m_clearButton,SIGNAL(clicked()), this, SLOT(clearDisplay()));
+
+    connect(d->m_clearButton,SIGNAL(clicked()), this, SLOT(clearData()));
+
     layout->addWidget(d->m_clearButton);
 
-    QLabel *timeLabel = new QLabel();
-    QPalette palette = timeLabel->palette();
+    d->m_timeLabel = new QLabel();
+    QPalette palette = d->m_timeLabel->palette();
     palette.setColor(QPalette::WindowText, Qt::white);
-    timeLabel->setPalette(palette);
-    timeLabel->setIndent(10);
-    connect(d->m_traceWindow, SIGNAL(viewUpdated()), this, SLOT(updateTimers()));
-    connect(this, SIGNAL(setTimeLabel(QString)), timeLabel, SLOT(setText(QString)));
-    updateTimers();
-    layout->addWidget(timeLabel);
+    d->m_timeLabel->setPalette(palette);
+    d->m_timeLabel->setIndent(10);
+    updateTimeDisplay();
+    layout->addWidget(d->m_timeLabel);
 
     toolbarWidget->setLayout(layout);
 
     return toolbarWidget;
 }
 
-void QmlProfilerTool::connectClient(quint16 port)
-{
-    if (d->m_client)
-        delete d->m_client;
-    d->m_client = new QDeclarativeDebugConnection;
-    d->m_traceWindow->reset(d->m_client);
-    connect(d->m_client, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
-            this, SLOT(connectionStateChanged()));
-    d->m_connectionTimer.start();
-    d->m_appTimer.start();
-    d->m_tcpPort = port;
-}
-
-void QmlProfilerTool::connectToClient()
-{
-    if (!d->m_client || d->m_client->state() != QAbstractSocket::UnconnectedState)
-        return;
-
-    if (d->m_connectMode == QmlProfilerToolPrivate::TcpConnection) {
-        logStatus(QString("QML Profiler: Connecting to %1:%2...").arg(d->m_tcpHost, QString::number(d->m_tcpPort)));
-        d->m_client->connectToHost(d->m_tcpHost, d->m_tcpPort);
-    } else {
-        logStatus(QString("QML Profiler: Connecting to %1...").arg(d->m_tcpHost));
-        d->m_client->connectToOst(d->m_ostDevice);
-    }
-}
-
-void QmlProfilerTool::disconnectClient()
-{
-    // this might be actually be called indirectly by QDDConnectionPrivate::readyRead(), therefore allow
-    // method to complete before deleting object
-    if (d->m_client) {
-        d->m_client->deleteLater();
-        d->m_client = 0;
-    }
-}
-
-void QmlProfilerTool::startRecording()
-{
-    if (d->m_client && d->m_client->isConnected()) {
-        clearDisplay();
-        d->m_traceWindow->setRecording(true);
-    }
-    emit fetchingData(true);
-}
-
-void QmlProfilerTool::stopRecording()
-{
-    d->m_traceWindow->setRecording(false);
-    emit fetchingData(false);
-
-    // manage early stop
-    if (d->m_client && !d->m_client->isConnected() && d->m_appIsRunning)
-        emit cancelRun();
-}
-
 void QmlProfilerTool::recordingButtonChanged(bool recording)
 {
-    if (recording)
-        startRecording();
-    else
-        stopRecording();
-
-    setRecording(recording);
+    d->m_profilerState->setClientRecording(recording);
 }
 
 void QmlProfilerTool::setRecording(bool recording)
 {
-    // update record button
-    d->m_recordingEnabled = recording;
+    // update display
     d->m_recordButton->setToolTip( recording ? tr("Disable profiling") : tr("Enable profiling"));
     d->m_recordButton->setIcon(QIcon(recording ? QLatin1String(":/qmlprofiler/recordOn.png") :
                                                  QLatin1String(":/qmlprofiler/recordOff.png")));
 
     d->m_recordButton->setChecked(recording);
-    updateTimers();
-}
 
-void QmlProfilerTool::setAppIsRunning()
-{
-    d->m_appIsRunning = true;
-    updateTimers();
-}
-
-void QmlProfilerTool::setAppIsStopped()
-{
-    d->m_appIsRunning = false;
-    updateTimers();
+    // manage timer
+    if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) {
+        if (recording) {
+            d->m_recordingTimer.start();
+            d->m_recordingElapsedTime.start();
+        } else {
+            d->m_recordingTimer.stop();
+        }
+    }
 }
 
 void QmlProfilerTool::gotoSourceLocation(const QString &fileUrl, int lineNumber, int columnNumber)
@@ -643,33 +459,30 @@ void QmlProfilerTool::gotoSourceLocation(const QString &fileUrl, int lineNumber,
     }
 }
 
-inline QString stringifyTime(double seconds)
+void QmlProfilerTool::updateTimeDisplay()
 {
+    double seconds = 0;
+    if (d->m_profilerState->serverRecording() &&
+        d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) {
+            seconds = d->m_recordingElapsedTime.elapsed() / 1000.0;
+    } else if (d->m_profilerDataModel->currentState() != QmlProfilerDataModel::Empty ) {
+        seconds = (d->m_profilerDataModel->traceEndTime() - d->m_profilerDataModel->traceStartTime()) / 1.0e9;
+    }
     QString timeString = QString::number(seconds,'f',1);
-    return QmlProfilerTool::tr("%1 s").arg(timeString, 6);
+    QString profilerTimeStr = QmlProfilerTool::tr("%1 s").arg(timeString, 6);
+    d->m_timeLabel->setText(tr("Elapsed: %1").arg(profilerTimeStr));
 }
 
-void QmlProfilerTool::updateTimers()
+void QmlProfilerTool::clearData()
 {
-    // prof time
-    QString profilerTimeStr = stringifyTime(d->m_traceWindow->profiledTime());
-    emit setTimeLabel(tr("Elapsed: %1").arg(profilerTimeStr));
-}
-
-void QmlProfilerTool::profilerStateChanged(bool qmlActive, bool v8active)
-{
-    d->m_v8Active = v8active;
-    d->m_qmlActive = qmlActive;
-    updateTimers();
+    d->m_profilerDataModel->clear();
 }
 
 void QmlProfilerTool::clearDisplay()
 {
-    d->m_appRunningTime = 0;
-    d->m_traceWindow->clearDisplay();
-    d->m_eventsView->clear();
-    d->m_v8profilerView->clear();
-    updateTimers();
+    d->m_profilerConnections->clearBufferedData();
+    d->m_viewContainer->clear();
+    updateTimeDisplay();
 }
 
 static void startRemoteTool(IAnalyzerTool *tool, StartMode mode)
@@ -718,84 +531,6 @@ static void startRemoteTool(IAnalyzerTool *tool, StartMode mode)
     ProjectExplorerPlugin::instance()->startRunControl(rc, tool->runMode());
 }
 
-void QmlProfilerTool::tryToConnect()
-{
-    ++d->m_connectionAttempts;
-
-    if (d->m_client && d->m_client->isConnected()) {
-        d->m_connectionTimer.stop();
-        d->m_connectionAttempts = 0;
-    } else if (d->m_connectionAttempts == 50) {
-        d->m_connectionTimer.stop();
-        d->m_connectionAttempts = 0;
-
-        QMessageBox *infoBox = new QMessageBox(Core::ICore::mainWindow());
-        infoBox->setIcon(QMessageBox::Critical);
-        infoBox->setWindowTitle(tr("Qt Creator"));
-        infoBox->setText(tr("Could not connect to the in-process QML profiler.\n"
-                            "Do you want to retry?"));
-        infoBox->setStandardButtons(QMessageBox::Retry | QMessageBox::Cancel | QMessageBox::Help);
-        infoBox->setDefaultButton(QMessageBox::Retry);
-        infoBox->setModal(true);
-
-        connect(infoBox, SIGNAL(finished(int)),
-                this, SLOT(retryMessageBoxFinished(int)));
-
-        infoBox->show();
-    } else {
-        connectToClient();
-    }
-}
-
-void QmlProfilerTool::connectionStateChanged()
-{
-    if (!d->m_client)
-        return;
-    switch (d->m_client->state()) {
-    case QAbstractSocket::UnconnectedState:
-    {
-        if (QmlProfilerPlugin::debugOutput)
-            qWarning("QML Profiler: disconnected");
-        break;
-    }
-    case QAbstractSocket::HostLookupState:
-        break;
-    case QAbstractSocket::ConnectingState: {
-        if (QmlProfilerPlugin::debugOutput)
-            qWarning("QML Profiler: Connecting to debug server ...");
-        break;
-    }
-    case QAbstractSocket::ConnectedState:
-    {
-        if (QmlProfilerPlugin::debugOutput)
-            qWarning("QML Profiler: connected and running");
-        updateRecordingState();
-        break;
-    }
-    case QAbstractSocket::ClosingState:
-        if (QmlProfilerPlugin::debugOutput)
-            qWarning("QML Profiler: closing ...");
-        break;
-    case QAbstractSocket::BoundState:
-    case QAbstractSocket::ListeningState:
-        break;
-    }
-}
-
-void QmlProfilerTool::updateRecordingState()
-{
-    if (d->m_client->isConnected()) {
-        d->m_traceWindow->setRecording(d->m_recordingEnabled);
-    } else {
-        d->m_traceWindow->setRecording(false);
-    }
-
-    if (d->m_traceWindow->isRecording())
-        clearDisplay();
-
-    updateTimers();
-}
-
 void QmlProfilerTool::startTool(StartMode mode)
 {
     using namespace ProjectExplorer;
@@ -821,14 +556,25 @@ void QmlProfilerTool::logStatus(const QString &msg)
 
 void QmlProfilerTool::logError(const QString &msg)
 {
-    // TODO: Rather show errors in the application ouput
     MessageManager *messageManager = MessageManager::instance();
     messageManager->printToOutputPane(msg, true);
 }
 
+void QmlProfilerTool::showErrorDialog(const QString &error)
+{
+    QMessageBox *errorDialog = new QMessageBox(Core::ICore::mainWindow());
+    errorDialog->setIcon(QMessageBox::Warning);
+    errorDialog->setWindowTitle(tr("QML Profiler"));
+    errorDialog->setText(error);
+    errorDialog->setStandardButtons(QMessageBox::Ok);
+    errorDialog->setDefaultButton(QMessageBox::Ok);
+    errorDialog->setModal(false);
+    errorDialog->show();
+}
+
 void QmlProfilerTool::showSaveOption()
 {
-    d->m_saveQmlTrace->setEnabled(d->m_traceWindow->getEventList()->count());
+    d->m_saveQmlTrace->setEnabled(!d->m_profilerDataModel->isEmpty());
 }
 
 void QmlProfilerTool::showSaveDialog()
@@ -837,7 +583,7 @@ void QmlProfilerTool::showSaveDialog()
     if (!filename.isEmpty()) {
         if (!filename.endsWith(QLatin1String(TraceFileExtension)))
             filename += QLatin1String(TraceFileExtension);
-        d->m_traceWindow->getEventList()->save(filename);
+        d->m_profilerDataModel->save(filename);
     }
 }
 
@@ -853,53 +599,98 @@ void QmlProfilerTool::showLoadDialog()
 
     if (!filename.isEmpty()) {
         // delayed load (prevent graphical artifacts due to long load time)
-        d->m_traceWindow->getEventList()->setFilename(filename);
-        QTimer::singleShot(100, d->m_traceWindow->getEventList(), SLOT(load()));
+        d->m_profilerDataModel->setFilename(filename);
+        QTimer::singleShot(100, d->m_profilerDataModel, SLOT(load()));
     }
 }
 
-void QmlProfilerTool::showErrorDialog(const QString &error)
+void QmlProfilerTool::profilerDataModelStateChanged()
 {
-    QMessageBox *errorDialog = new QMessageBox(Core::ICore::mainWindow());
-    errorDialog->setIcon(QMessageBox::Warning);
-    errorDialog->setWindowTitle(tr("QML Profiler"));
-    errorDialog->setText(error);
-    errorDialog->setStandardButtons(QMessageBox::Ok);
-    errorDialog->setDefaultButton(QMessageBox::Ok);
-    errorDialog->setModal(false);
-    errorDialog->show();
+    switch (d->m_profilerDataModel->currentState()) {
+    case QmlProfilerDataModel::Empty :
+        clearDisplay();
+        break;
+    case QmlProfilerDataModel::AcquiringData :
+    case QmlProfilerDataModel::ProcessingData :
+        // nothing to be done for these two
+        break;
+    case QmlProfilerDataModel::Done :
+        if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppStopRequested)
+            d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppReadyToStop);
+        showSaveOption();
+        updateTimeDisplay();
+    break;
+    default:
+        break;
+    }
+}
+
+QList <QAction *> QmlProfilerTool::profilerContextMenuActions() const
+{
+    QList <QAction *> commonActions;
+    commonActions << d->m_loadQmlTrace << d->m_saveQmlTrace;
+    return commonActions;
+}
+
+void QmlProfilerTool::showNonmodalWarning(const QString &warningMsg)
+{
+    QMessageBox *noExecWarning = new QMessageBox(Core::ICore::mainWindow());
+    noExecWarning->setIcon(QMessageBox::Warning);
+    noExecWarning->setWindowTitle(tr("QML Profiler"));
+    noExecWarning->setText(warningMsg);
+    noExecWarning->setStandardButtons(QMessageBox::Ok);
+    noExecWarning->setDefaultButton(QMessageBox::Ok);
+    noExecWarning->setModal(false);
+    noExecWarning->show();
+}
+
+QMessageBox *QmlProfilerTool::requestMessageBox()
+{
+    return new QMessageBox(Core::ICore::mainWindow());
+}
+
+void QmlProfilerTool::handleHelpRequest(const QString &link)
+{
+    HelpManager *helpManager = HelpManager::instance();
+    helpManager->handleHelpRequest(link);
 }
 
-void QmlProfilerTool::retryMessageBoxFinished(int result)
+void QmlProfilerTool::profilerStateChanged()
 {
-    switch (result) {
-    case QMessageBox::Retry: {
-        d->m_connectionAttempts = 0;
-        d->m_connectionTimer.start();
+    switch (d->m_profilerState->currentState()) {
+    case QmlProfilerStateManager::AppKilled : {
+        if (d->m_profilerDataModel->currentState() == QmlProfilerDataModel::AcquiringData) {
+            showNonmodalWarning(tr("Application finished before loading profiled data.\n Please use the stop button instead."));
+        }
         break;
     }
-    case QMessageBox::Help: {
-        HelpManager *helpManager = HelpManager::instance();
-        helpManager->handleHelpRequest("qthelp://com.nokia.qtcreator/doc/creator-debugging-qml.html");
-        // fall through
-    }
-    default: {
-        if (d->m_client) {
-            logStatus("QML Profiler: Failed to connect! " + d->m_client->errorString());
-        } else {
-            logStatus("QML Profiler: Failed to connect!");
-        }
-
-        emit connectionFailed();
+    case QmlProfilerStateManager::Idle :
+        // when the app finishes, set recording display to client status
+        setRecording(d->m_profilerState->clientRecording());
+        break;
+    default:
+        // no special action needed for other states
         break;
     }
+}
+
+void QmlProfilerTool::clientRecordingChanged()
+{
+    // if application is running, display server record changes
+    // if application is stopped, display client record changes
+    if (d->m_profilerState->currentState() != QmlProfilerStateManager::AppRunning) {
+        setRecording(d->m_profilerState->clientRecording());
     }
 }
 
-void QmlProfilerTool::eventListStateChanged()
+void QmlProfilerTool::serverRecordingChanged()
 {
-    if (d->m_traceWindow->getEventList()->currentState() == QmlProfilerEventList::Done) {
-        showSaveOption();
-        updateTimers();
+    if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) {
+        setRecording(d->m_profilerState->serverRecording());
+        // clear the old data each time we start a new profiling session
+        if (d->m_profilerState->serverRecording()) {
+            clearData();
+        }
     }
 }
+
diff --git a/src/plugins/qmlprofiler/qmlprofilertool.h b/src/plugins/qmlprofiler/qmlprofilertool.h
index 32f46105f064e249b9d833d73ba359b9b78644c1..bb3f2b1cec600fb63145335d7b3718b4e18be123 100644
--- a/src/plugins/qmlprofiler/qmlprofilertool.h
+++ b/src/plugins/qmlprofiler/qmlprofilertool.h
@@ -36,13 +36,11 @@
 #include <analyzerbase/ianalyzertool.h>
 #include <analyzerbase/ianalyzerengine.h>
 
-#include <QPoint>
+class QMessageBox;
 
 namespace QmlProfiler {
 namespace Internal {
 
-#define TraceFileExtension ".qtd"
-
 class QmlProfilerTool : public Analyzer::IAnalyzerTool
 {
     Q_OBJECT
@@ -72,49 +70,37 @@ public:
     QWidget *createWidgets();
     void startTool(Analyzer::StartMode mode);
 
+    QList <QAction *> profilerContextMenuActions() const;
+
+    // display dialogs / log output
+    static QMessageBox *requestMessageBox();
+    static void handleHelpRequest(const QString &link);
+    static void logStatus(const QString &msg);
+    static void logError(const QString &msg);
+    static void showNonmodalWarning(const QString &warningMsg);
+
 public slots:
-    void connectClient(quint16 port);
-    void disconnectClient();
+    void profilerStateChanged();
+    void clientRecordingChanged();
+    void serverRecordingChanged();
 
-    void startRecording();
-    void stopRecording();
     void recordingButtonChanged(bool recording);
     void setRecording(bool recording);
 
-    void setAppIsRunning();
-    void setAppIsStopped();
-
     void gotoSourceLocation(const QString &fileUrl, int lineNumber, int columnNumber);
-    void updateTimers();
-    void profilerStateChanged(bool qmlActive, bool v8active);
-
-    void clearDisplay();
-
-    void showContextMenu(const QPoint &position);
-
-signals:
-    void setTimeLabel(const QString &);
-    void setStatusLabel(const QString &);
-    void fetchingData(bool);
-    void connectionFailed();
-    void cancelRun();
 
 private slots:
-    void tryToConnect();
-    void connectionStateChanged();
+    void clearData();
+    void showErrorDialog(const QString &error);
+    void profilerDataModelStateChanged();
+    void updateTimeDisplay();
+
     void showSaveOption();
     void showSaveDialog();
     void showLoadDialog();
-    void showErrorDialog(const QString &error);
-    void retryMessageBoxFinished(int result);
-    void eventListStateChanged();
 
 private:
-    void connectToClient();
-    void updateRecordingState();
-    void ensureWidgets();
-    void logStatus(const QString &msg);
-    void logError(const QString &msg);
+    void clearDisplay();
 
     class QmlProfilerToolPrivate;
     QmlProfilerToolPrivate *d;
diff --git a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ab02f45b08ea9e8ec083d17f153ee2a1f11fb577
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp
@@ -0,0 +1,601 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "qmlprofilertraceview.h"
+#include "qmlprofilertool.h"
+#include "qmlprofilerstatemanager.h"
+#include "qmlprofilerdatamodel.h"
+
+// Needed for the load&save actions in the context menu
+#include <analyzerbase/ianalyzertool.h>
+
+// Comunication with the other views (limit events to range)
+#include "qmlprofilerviewmanager.h"
+
+#include <utils/styledbar.h>
+
+#include <QDeclarativeContext>
+#include <QToolButton>
+#include <QEvent>
+#include <QVBoxLayout>
+#include <QGraphicsObject>
+#include <QScrollBar>
+#include <QSlider>
+#include <QMenu>
+
+#include <math.h>
+
+using namespace QmlJsDebugClient;
+
+namespace QmlProfiler {
+namespace Internal {
+
+const int sliderTicks = 10000;
+const qreal sliderExp = 3;
+
+
+/////////////////////////////////////////////////////////
+bool MouseWheelResizer::eventFilter(QObject *obj, QEvent *event)
+{
+    if (event->type() == QEvent::Wheel) {
+        QWheelEvent *ev = static_cast<QWheelEvent *>(event);
+        if (ev->modifiers() & Qt::ControlModifier) {
+            emit mouseWheelMoved(ev->pos().x(), ev->pos().y(), ev->delta());
+            return true;
+        }
+    }
+    return QObject::eventFilter(obj, event);
+}
+
+/////////////////////////////////////////////////////////
+void ZoomControl::setRange(qint64 startTime, qint64 endTime)
+{
+    if (m_startTime != startTime || m_endTime != endTime) {
+        m_startTime = startTime;
+        m_endTime = endTime;
+        emit rangeChanged();
+    }
+}
+
+/////////////////////////////////////////////////////////
+ScrollableDeclarativeView::ScrollableDeclarativeView(QWidget *parent)
+    : QDeclarativeView(parent)
+{
+}
+
+ScrollableDeclarativeView::~ScrollableDeclarativeView()
+{
+}
+
+void ScrollableDeclarativeView::scrollContentsBy(int dx, int dy)
+{
+    // special workaround to track the scrollbar
+    if (rootObject()) {
+        int scrollY = rootObject()->property("scrollY").toInt();
+        rootObject()->setProperty("scrollY", QVariant(scrollY - dy));
+    }
+    QDeclarativeView::scrollContentsBy(dx,dy);
+}
+
+/////////////////////////////////////////////////////////
+class QmlProfilerTraceView::QmlProfilerTraceViewPrivate
+{
+public:
+    QmlProfilerTraceViewPrivate(QmlProfilerTraceView *qq) : q(qq) {}
+    QmlProfilerTraceView *q;
+
+    QmlProfilerStateManager *m_profilerState;
+    Analyzer::IAnalyzerTool *m_profilerTool;
+    QmlProfilerViewManager *m_viewContainer;
+
+    QSize m_sizeHint;
+
+    ScrollableDeclarativeView *m_mainView;
+    QDeclarativeView *m_timebar;
+    QDeclarativeView *m_overview;
+    QmlProfilerDataModel *m_profilerDataModel;
+
+    ZoomControl *m_zoomControl;
+
+    QToolButton *m_buttonRange;
+    QToolButton *m_buttonLock;
+    QWidget *m_zoomToolbar;
+    int m_currentZoomLevel;
+};
+
+QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerTool *profilerTool, QmlProfilerViewManager *container, QmlProfilerDataModel *model, QmlProfilerStateManager *profilerState)
+    : QWidget(parent), d(new QmlProfilerTraceViewPrivate(this))
+{
+    setObjectName("QML Profiler");
+
+    d->m_zoomControl = new ZoomControl(this);
+    connect(d->m_zoomControl, SIGNAL(rangeChanged()), this, SLOT(updateRange()));
+
+    QVBoxLayout *groupLayout = new QVBoxLayout;
+    groupLayout->setContentsMargins(0, 0, 0, 0);
+    groupLayout->setSpacing(0);
+
+    d->m_mainView = new ScrollableDeclarativeView(this);
+    d->m_mainView->setResizeMode(QDeclarativeView::SizeViewToRootObject);
+    d->m_mainView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    d->m_mainView->setBackgroundBrush(QBrush(Qt::white));
+    d->m_mainView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
+    d->m_mainView->setFocus();
+
+    MouseWheelResizer *resizer = new MouseWheelResizer(this);
+    connect(resizer,SIGNAL(mouseWheelMoved(int,int,int)), this, SLOT(mouseWheelMoved(int,int,int)));
+    d->m_mainView->viewport()->installEventFilter(resizer);
+
+    QHBoxLayout *toolsLayout = new QHBoxLayout;
+
+    d->m_timebar = new QDeclarativeView(this);
+    d->m_timebar->setResizeMode(QDeclarativeView::SizeRootObjectToView);
+    d->m_timebar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+    d->m_timebar->setFixedHeight(24);
+
+    d->m_overview = new QDeclarativeView(this);
+    d->m_overview->setResizeMode(QDeclarativeView::SizeRootObjectToView);
+    d->m_overview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+    d->m_overview->setMaximumHeight(50);
+
+    d->m_zoomToolbar = createZoomToolbar();
+    d->m_zoomToolbar->move(0, d->m_timebar->height());
+    d->m_zoomToolbar->setVisible(false);
+
+    toolsLayout->addWidget(createToolbar());
+    toolsLayout->addWidget(d->m_timebar);
+    emit enableToolbar(false);
+
+    groupLayout->addLayout(toolsLayout);
+    groupLayout->addWidget(d->m_mainView);
+    groupLayout->addWidget(d->m_overview);
+
+    setLayout(groupLayout);
+
+    d->m_profilerTool = profilerTool;
+    d->m_viewContainer = container;
+    d->m_profilerDataModel = model;
+    connect(d->m_profilerDataModel, SIGNAL(stateChanged()),
+            this, SLOT(profilerDataModelStateChanged()));
+    d->m_mainView->rootContext()->setContextProperty("qmlProfilerDataModel",
+                                                     d->m_profilerDataModel);
+    d->m_overview->rootContext()->setContextProperty("qmlProfilerDataModel",
+                                                     d->m_profilerDataModel);
+
+    d->m_profilerState = profilerState;
+    connect(d->m_profilerState, SIGNAL(stateChanged()),
+            this, SLOT(profilerStateChanged()));
+    connect(d->m_profilerState, SIGNAL(clientRecordingChanged()),
+            this, SLOT(clientRecordingChanged()));
+    connect(d->m_profilerState, SIGNAL(serverRecordingChanged()),
+            this, SLOT(serverRecordingChanged()));
+
+    // Minimum height: 5 rows of 20 pixels + scrollbar of 50 pixels + 20 pixels margin
+    setMinimumHeight(170);
+    d->m_currentZoomLevel = 0;
+}
+
+QmlProfilerTraceView::~QmlProfilerTraceView()
+{
+    delete d;
+}
+
+/////////////////////////////////////////////////////////
+// Initialize widgets
+void QmlProfilerTraceView::reset()
+{
+    d->m_mainView->rootContext()->setContextProperty("zoomControl", d->m_zoomControl);
+    d->m_timebar->rootContext()->setContextProperty("zoomControl", d->m_zoomControl);
+    d->m_overview->rootContext()->setContextProperty("zoomControl", d->m_zoomControl);
+
+    d->m_timebar->setSource(QUrl("qrc:/qmlprofiler/TimeDisplay.qml"));
+    d->m_overview->setSource(QUrl("qrc:/qmlprofiler/Overview.qml"));
+
+    d->m_mainView->setSource(QUrl("qrc:/qmlprofiler/MainView.qml"));
+    d->m_mainView->rootObject()->setProperty("width", QVariant(width()));
+    d->m_mainView->rootObject()->setProperty("candidateHeight", QVariant(height() - d->m_timebar->height() - d->m_overview->height()));
+
+    connect(d->m_mainView->rootObject(), SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition()));
+    connect(d->m_mainView->rootObject(), SIGNAL(updateRangeButton()), this, SLOT(updateRangeButton()));
+    connect(d->m_mainView->rootObject(), SIGNAL(updateLockButton()), this, SLOT(updateLockButton()));
+    connect(this, SIGNAL(jumpToPrev()), d->m_mainView->rootObject(), SLOT(prevEvent()));
+    connect(this, SIGNAL(jumpToNext()), d->m_mainView->rootObject(), SLOT(nextEvent()));
+    connect(d->m_mainView->rootObject(), SIGNAL(selectedEventChanged(int)), this, SIGNAL(selectedEventChanged(int)));
+    connect(d->m_mainView->rootObject(), SIGNAL(changeToolTip(QString)), this, SLOT(updateToolTip(QString)));
+    connect(d->m_mainView->rootObject(), SIGNAL(updateVerticalScroll(int)), this, SLOT(updateVerticalScroll(int)));
+}
+
+QWidget *QmlProfilerTraceView::createToolbar()
+{
+    Utils::StyledBar *bar = new Utils::StyledBar(this);
+    bar->setSingleRow(true);
+    bar->setFixedWidth(150);
+    bar->setFixedHeight(24);
+
+    QHBoxLayout *toolBarLayout = new QHBoxLayout(bar);
+    toolBarLayout->setMargin(0);
+    toolBarLayout->setSpacing(0);
+
+    QToolButton *buttonPrev= new QToolButton;
+    buttonPrev->setIcon(QIcon(":/qmlprofiler/ico_prev.png"));
+    buttonPrev->setToolTip(tr("Jump to previous event"));
+    connect(buttonPrev, SIGNAL(clicked()), this, SIGNAL(jumpToPrev()));
+    connect(this, SIGNAL(enableToolbar(bool)), buttonPrev, SLOT(setEnabled(bool)));
+
+    QToolButton *buttonNext= new QToolButton;
+    buttonNext->setIcon(QIcon(":/qmlprofiler/ico_next.png"));
+    buttonNext->setToolTip(tr("Jump to next event"));
+    connect(buttonNext, SIGNAL(clicked()), this, SIGNAL(jumpToNext()));
+    connect(this, SIGNAL(enableToolbar(bool)), buttonNext, SLOT(setEnabled(bool)));
+
+    QToolButton *buttonZoomControls = new QToolButton;
+    buttonZoomControls->setIcon(QIcon(":/qmlprofiler/ico_zoom.png"));
+    buttonZoomControls->setToolTip(tr("Show zoom slider"));
+    buttonZoomControls->setCheckable(true);
+    buttonZoomControls->setChecked(false);
+    connect(buttonZoomControls, SIGNAL(toggled(bool)), d->m_zoomToolbar, SLOT(setVisible(bool)));
+    connect(this, SIGNAL(enableToolbar(bool)), buttonZoomControls, SLOT(setEnabled(bool)));
+
+    d->m_buttonRange = new QToolButton;
+    d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png"));
+    d->m_buttonRange->setToolTip(tr("Select range"));
+    d->m_buttonRange->setCheckable(true);
+    d->m_buttonRange->setChecked(false);
+    connect(d->m_buttonRange, SIGNAL(clicked(bool)), this, SLOT(toggleRangeMode(bool)));
+    connect(this, SIGNAL(enableToolbar(bool)), d->m_buttonRange, SLOT(setEnabled(bool)));
+    connect(this, SIGNAL(rangeModeChanged(bool)), d->m_buttonRange, SLOT(setChecked(bool)));
+
+    d->m_buttonLock = new QToolButton;
+    d->m_buttonLock->setIcon(QIcon(":/qmlprofiler/ico_selectionmode.png"));
+    d->m_buttonLock->setToolTip(tr("View event information on mouseover"));
+    d->m_buttonLock->setCheckable(true);
+    d->m_buttonLock->setChecked(false);
+    connect(d->m_buttonLock, SIGNAL(clicked(bool)), this, SLOT(toggleLockMode(bool)));
+    connect(this, SIGNAL(enableToolbar(bool)), d->m_buttonLock, SLOT(setEnabled(bool)));
+    connect(this, SIGNAL(lockModeChanged(bool)), d->m_buttonLock, SLOT(setChecked(bool)));
+
+    toolBarLayout->addWidget(buttonPrev);
+    toolBarLayout->addWidget(buttonNext);
+    toolBarLayout->addWidget(new Utils::StyledSeparator());
+    toolBarLayout->addWidget(buttonZoomControls);
+    toolBarLayout->addWidget(new Utils::StyledSeparator());
+    toolBarLayout->addWidget(d->m_buttonRange);
+    toolBarLayout->addWidget(d->m_buttonLock);
+
+    return bar;
+}
+
+
+QWidget *QmlProfilerTraceView::createZoomToolbar()
+{
+    Utils::StyledBar *bar = new Utils::StyledBar(this);
+    bar->setSingleRow(true);
+    bar->setFixedWidth(150);
+    bar->setFixedHeight(24);
+
+    QHBoxLayout *toolBarLayout = new QHBoxLayout(bar);
+    toolBarLayout->setMargin(0);
+    toolBarLayout->setSpacing(0);
+
+    QSlider *zoomSlider = new QSlider(Qt::Horizontal);
+    zoomSlider->setFocusPolicy(Qt::NoFocus);
+    zoomSlider->setRange(1, sliderTicks);
+    zoomSlider->setInvertedAppearance(true);
+    zoomSlider->setPageStep(sliderTicks/100);
+    connect(this, SIGNAL(enableToolbar(bool)), zoomSlider, SLOT(setEnabled(bool)));
+    connect(zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setZoomLevel(int)));
+    connect(this, SIGNAL(zoomLevelChanged(int)), zoomSlider, SLOT(setValue(int)));
+    zoomSlider->setStyleSheet("\
+        QSlider:horizontal {\
+            background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #444444, stop: 1 #5a5a5a);\
+            border: 1px #313131;\
+            height: 20px;\
+            margin: 0px 0px 0px 0px;\
+        }\
+        QSlider::add-page:horizontal {\
+            background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\
+            border: 1px #313131;\
+        }\
+        QSlider::sub-page:horizontal {\
+            background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\
+            border: 1px #313131;\
+        }\
+        ");
+
+    toolBarLayout->addWidget(zoomSlider);
+
+    return bar;
+}
+
+/////////////////////////////////////////////////////////
+bool QmlProfilerTraceView::hasValidSelection() const
+{
+    if (d->m_mainView->rootObject()) {
+        return d->m_mainView->rootObject()->property("selectionRangeReady").toBool();
+    }
+    return false;
+}
+
+qint64 QmlProfilerTraceView::selectionStart() const
+{
+    if (d->m_mainView->rootObject()) {
+        return d->m_mainView->rootObject()->property("selectionRangeStart").toLongLong();
+    }
+    return 0;
+}
+
+qint64 QmlProfilerTraceView::selectionEnd() const
+{
+    if (d->m_mainView->rootObject()) {
+        return d->m_mainView->rootObject()->property("selectionRangeEnd").toLongLong();
+    }
+    return 0;
+}
+
+void QmlProfilerTraceView::clearDisplay()
+{
+    d->m_zoomControl->setRange(0,0);
+
+    updateVerticalScroll(0);
+    d->m_mainView->rootObject()->setProperty("scrollY", QVariant(0));
+
+    QMetaObject::invokeMethod(d->m_mainView->rootObject(), "clearAll");
+    QMetaObject::invokeMethod(d->m_overview->rootObject(), "clearDisplay");
+}
+
+void QmlProfilerTraceView::selectNextEventWithId(int eventId)
+{
+    if (d->m_mainView->rootObject())
+        QMetaObject::invokeMethod(d->m_mainView->rootObject(), "selectNextWithId",
+                                  Q_ARG(QVariant,QVariant(eventId)));
+}
+
+/////////////////////////////////////////////////////////
+// Goto source location
+void QmlProfilerTraceView::updateCursorPosition()
+{
+    emit gotoSourceLocation(d->m_mainView->rootObject()->property("fileName").toString(),
+                            d->m_mainView->rootObject()->property("lineNumber").toInt(),
+                            d->m_mainView->rootObject()->property("columnNumber").toInt());
+}
+
+/////////////////////////////////////////////////////////
+// Toolbar buttons
+void QmlProfilerTraceView::toggleRangeMode(bool active)
+{
+    bool rangeMode = d->m_mainView->rootObject()->property("selectionRangeMode").toBool();
+    if (active != rangeMode) {
+        if (active)
+            d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselected.png"));
+        else
+            d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png"));
+        d->m_mainView->rootObject()->setProperty("selectionRangeMode", QVariant(active));
+    }
+}
+
+void QmlProfilerTraceView::updateRangeButton()
+{
+    bool rangeMode = d->m_mainView->rootObject()->property("selectionRangeMode").toBool();
+    if (rangeMode)
+        d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselected.png"));
+    else
+        d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png"));
+    emit rangeModeChanged(rangeMode);
+}
+
+void QmlProfilerTraceView::toggleLockMode(bool active)
+{
+    bool lockMode = !d->m_mainView->rootObject()->property("selectionLocked").toBool();
+    if (active != lockMode) {
+        d->m_mainView->rootObject()->setProperty("selectionLocked", QVariant(!active));
+        d->m_mainView->rootObject()->setProperty("selectedItem", QVariant(-1));
+    }
+}
+
+void QmlProfilerTraceView::updateLockButton()
+{
+    bool lockMode = !d->m_mainView->rootObject()->property("selectionLocked").toBool();
+    emit lockModeChanged(lockMode);
+}
+
+////////////////////////////////////////////////////////
+// Zoom control
+void QmlProfilerTraceView::setZoomLevel(int zoomLevel)
+{
+    if (d->m_currentZoomLevel != zoomLevel && d->m_mainView->rootObject()) {
+        QVariant newFactor = pow(qreal(zoomLevel) / qreal(sliderTicks), sliderExp);
+        d->m_currentZoomLevel = zoomLevel;
+        QMetaObject::invokeMethod(d->m_mainView->rootObject(), "updateWindowLength", Q_ARG(QVariant, newFactor));
+    }
+}
+
+void QmlProfilerTraceView::updateRange()
+{
+    if (!d->m_profilerDataModel)
+        return;
+    qreal duration = d->m_zoomControl->endTime() - d->m_zoomControl->startTime();
+    if (duration <= 0)
+        return;
+    if (d->m_profilerDataModel->traceDuration() <= 0)
+        return;
+    int newLevel = pow(duration / d->m_profilerDataModel->traceDuration(), 1/sliderExp) * sliderTicks;
+    if (d->m_currentZoomLevel != newLevel) {
+        d->m_currentZoomLevel = newLevel;
+        emit zoomLevelChanged(newLevel);
+    }
+}
+
+void QmlProfilerTraceView::mouseWheelMoved(int mouseX, int mouseY, int wheelDelta)
+{
+    Q_UNUSED(mouseY);
+    if (d->m_mainView->rootObject()) {
+        QMetaObject::invokeMethod(d->m_mainView->rootObject(), "wheelZoom",
+                                  Q_ARG(QVariant, QVariant(mouseX)),
+                                  Q_ARG(QVariant, QVariant(wheelDelta)));
+    }
+}
+////////////////////////////////////////////////////////
+void QmlProfilerTraceView::updateToolTip(const QString &text)
+{
+    setToolTip(text);
+}
+
+void QmlProfilerTraceView::updateVerticalScroll(int newPosition)
+{
+    d->m_mainView->verticalScrollBar()->setValue(newPosition);
+}
+
+void QmlProfilerTraceView::resizeEvent(QResizeEvent *event)
+{
+    if (d->m_mainView->rootObject()) {
+        d->m_mainView->rootObject()->setProperty("width", QVariant(event->size().width()));
+        int newHeight = event->size().height() - d->m_timebar->height() - d->m_overview->height();
+        d->m_mainView->rootObject()->setProperty("candidateHeight", QVariant(newHeight));
+    }
+}
+
+////////////////////////////////////////////////////////////////
+// Context menu
+void QmlProfilerTraceView::contextMenuEvent(QContextMenuEvent *ev)
+{
+    QMenu menu;
+    QAction *viewAllAction = 0;
+    QAction *getLocalStatsAction = 0;
+    QAction *getGlobalStatsAction = 0;
+
+    QmlProfilerTool *profilerTool = qobject_cast<QmlProfilerTool *>(d->m_profilerTool);
+    QPoint position = ev->globalPos();
+
+    if (profilerTool) {
+        QList <QAction *> commonActions = profilerTool->profilerContextMenuActions();
+        foreach (QAction *act, commonActions) {
+            menu.addAction(act);
+        }
+    }
+
+    menu.addSeparator();
+    getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range"));
+    if (!d->m_viewContainer->hasValidSelection())
+        getLocalStatsAction->setEnabled(false);
+    getGlobalStatsAction = menu.addAction(tr("Reset Events Pane"));
+    if (d->m_viewContainer->hasGlobalStats())
+        getGlobalStatsAction->setEnabled(false);
+
+
+    if (d->m_profilerDataModel->count() > 0) {
+        menu.addSeparator();
+        viewAllAction = menu.addAction(tr("Reset Zoom"));
+    }
+
+
+    QAction *selectedAction = menu.exec(position);
+
+    if (selectedAction) {
+        if (selectedAction == viewAllAction) {
+            d->m_zoomControl->setRange(
+                        d->m_profilerDataModel->traceStartTime(),
+                        d->m_profilerDataModel->traceEndTime());
+        }
+        if (selectedAction == getLocalStatsAction) {
+            d->m_viewContainer->getStatisticsInRange(
+                        d->m_viewContainer->selectionStart(),
+                        d->m_viewContainer->selectionEnd());
+        }
+        if (selectedAction == getGlobalStatsAction) {
+            d->m_viewContainer->getStatisticsInRange(
+                        d->m_profilerDataModel->traceStartTime(),
+                        d->m_profilerDataModel->traceEndTime());
+        }
+    }
+}
+
+/////////////////////////////////////////////////
+// Tell QML the state of the profiler
+void QmlProfilerTraceView::setRecording(bool recording)
+{
+    if (d->m_mainView->rootObject())
+        d->m_mainView->rootObject()->setProperty("recordingEnabled", QVariant(recording));
+}
+
+void QmlProfilerTraceView::setAppKilled()
+{
+    if (d->m_mainView->rootObject())
+        d->m_mainView->rootObject()->setProperty("appKilled",QVariant(true));
+}
+////////////////////////////////////////////////////////////////
+// Profiler State
+void QmlProfilerTraceView::profilerDataModelStateChanged()
+{
+    switch (d->m_profilerDataModel->currentState()) {
+    case QmlProfilerDataModel::Empty :
+        emit enableToolbar(false);
+        break;
+    case QmlProfilerDataModel::AcquiringData :
+        // nothing to be done
+        break;
+    case QmlProfilerDataModel::ProcessingData :
+        // nothing to be done
+        break;
+    case QmlProfilerDataModel::Done :
+        emit enableToolbar(true);
+    break;
+    default:
+        break;
+    }
+}
+
+void QmlProfilerTraceView::profilerStateChanged()
+{
+    switch (d->m_profilerState->currentState()) {
+    case QmlProfilerStateManager::AppKilled : {
+        if (d->m_profilerDataModel->currentState() == QmlProfilerDataModel::AcquiringData)
+            setAppKilled();
+        break;
+    }
+    default:
+        // no special action needed for other states
+        break;
+    }
+}
+
+void QmlProfilerTraceView::clientRecordingChanged()
+{
+    // nothing yet
+}
+
+void QmlProfilerTraceView::serverRecordingChanged()
+{
+    setRecording(d->m_profilerState->serverRecording());
+}
+
+} // namespace Internal
+} // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/tracewindow.h b/src/plugins/qmlprofiler/qmlprofilertraceview.h
similarity index 56%
rename from src/plugins/qmlprofiler/tracewindow.h
rename to src/plugins/qmlprofiler/qmlprofilertraceview.h
index 2959720db6437df0c653caf010c1acc8c4ffb2c6..6b61380882e28df551f529bc9d6a283c38507741 100644
--- a/src/plugins/qmlprofiler/tracewindow.h
+++ b/src/plugins/qmlprofiler/qmlprofilertraceview.h
@@ -30,24 +30,23 @@
 **
 **************************************************************************/
 
-#ifndef TRACEWINDOW_H
-#define TRACEWINDOW_H
+#ifndef QMLPROFILERTRACEVIEW_H
+#define QMLPROFILERTRACEVIEW_H
 
-#include <qmljsdebugclient/qmlprofilertraceclient.h>
-#include <qmljsdebugclient/qmlprofilereventlist.h>
-#include "qmlprofilerdetailsrewriter.h"
-#include <qmljsdebugclient/qv8profilerclient.h>
-
-#include <QPointer>
-#include <QWidget>
-#include <QToolButton>
-
-#include <QEvent>
 #include <QDeclarativeView>
 
+namespace Analyzer {
+class IAnalyzerTool;
+}
+
 namespace QmlProfiler {
 namespace Internal {
 
+class QmlProfilerStateManager;
+class QmlProfilerViewManager;
+class QmlProfilerDataModel;
+
+// capture mouse wheel events
 class MouseWheelResizer : public QObject {
     Q_OBJECT
 public:
@@ -87,117 +86,73 @@ protected:
     void scrollContentsBy(int dx, int dy);
 };
 
-class TraceWindow : public QWidget
+class QmlProfilerTraceView : public QWidget
 {
     Q_OBJECT
 
 public:
-    TraceWindow(QWidget *parent = 0);
-    ~TraceWindow();
-
-    void reset(QmlJsDebugClient::QDeclarativeDebugConnection *conn);
+    explicit QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerTool *profilerTool, QmlProfilerViewManager *container, QmlProfilerDataModel *model, QmlProfilerStateManager *profilerState);
+    ~QmlProfilerTraceView();
 
-    QmlJsDebugClient::QmlProfilerEventList *getEventList() const;
-    ZoomControl *rangeTimes() const;
-
-    void setRecording(bool recording);
-    bool isRecording() const;
-    void viewAll();
+    void reset();
 
     bool hasValidSelection() const;
     qint64 selectionStart() const;
     qint64 selectionEnd() const;
-    double profiledTime() const;
 
 public slots:
     void clearDisplay();
-    void selectNextEvent(int eventId);
-    void applicationDied();
+    void selectNextEventWithId(int eventId);
 
 private slots:
     void updateCursorPosition();
-    void updateTimer();
-    void updateToolbar();
     void toggleRangeMode(bool);
-    void toggleLockMode(bool);
     void updateRangeButton();
+    void toggleLockMode(bool);
     void updateLockButton();
+
     void setZoomLevel(int zoomLevel);
     void updateRange();
-    void mouseWheelMoved(int x, int y, int delta);
+    void mouseWheelMoved(int mouseX, int mouseY, int wheelDelta);
 
-    void qmlComplete();
-    void v8Complete();
-    void updateProfilerState();
     void updateToolTip(const QString &text);
     void updateVerticalScroll(int newPosition);
-    void eventListStateChanged();
-    void manageTraceStart(qint64 traceStart);
-    void firstDataReceived();
-    void correctTimer();
+    void profilerDataModelStateChanged();
+
+protected:
+    virtual void resizeEvent(QResizeEvent *event);
+
+private slots:
+    void profilerStateChanged();
+    void clientRecordingChanged();
+    void serverRecordingChanged();
 
 signals:
-    void viewUpdated();
-    void profilerStateChanged(bool qmlActive, bool v8active);
     void gotoSourceLocation(const QString &fileUrl, int lineNumber, int columNumber);
-    void range(int type, qint64 startTime, qint64 length, const QStringList &data, const QmlJsDebugClient::QmlEventLocation &location);
-    void v8range(int depth,const QString &function,const QString &filename,
-               int lineNumber, double totalTime, double selfTime);
-    void traceFinished(qint64);
-    void traceStarted(qint64);
-    void frameEvent(qint64, int, int);
-    void recordingChanged(bool);
-
-    void internalClearDisplay();
-    void clearViewsFromTool();
+    void selectedEventChanged(int eventId);
+
     void jumpToPrev();
     void jumpToNext();
     void rangeModeChanged(bool);
     void lockModeChanged(bool);
     void enableToolbar(bool);
     void zoomLevelChanged(int);
-    void updateViewZoom(QVariant zoomLevel);
-    void wheelZoom(QVariant wheelCenter, QVariant wheelDelta);
-    void globalZoom();
-
-    void contextMenuRequested(const QPoint& position);
-    void selectNextEventInDisplay(QVariant eventId);
-    void selectedEventIdChanged(int eventId);
 
 private:
     void contextMenuEvent(QContextMenuEvent *);
     QWidget *createToolbar();
     QWidget *createZoomToolbar();
-    void connectClientSignals();
-    void disconnectClientSignals();
 
-protected:
-    virtual void resizeEvent(QResizeEvent *event);
+    void setRecording(bool recording);
+    void setAppKilled();
 
 private:
-    QWeakPointer<QmlJsDebugClient::QmlProfilerTraceClient> m_plugin;
-    QWeakPointer<QmlJsDebugClient::QV8ProfilerClient> m_v8plugin;
-    QSize m_sizeHint;
-
-    ScrollableDeclarativeView *m_mainView;
-    QDeclarativeView *m_timebar;
-    QDeclarativeView *m_overview;
-    QmlJsDebugClient::QmlProfilerEventList *m_eventList;
-    QmlProfilerDetailsRewriter *m_rewriter;
-    bool m_qmlDataReady;
-    bool m_v8DataReady;
-    double m_profiledTime;
-
-    QWeakPointer<ZoomControl> m_zoomControl;
-
-    QToolButton *m_buttonRange;
-    QToolButton *m_buttonLock;
-    QWidget *m_zoomToolbar;
-    int m_currentZoomLevel;
+    class QmlProfilerTraceViewPrivate;
+    QmlProfilerTraceViewPrivate *d;
 };
 
 } // namespace Internal
 } // namespace QmlProfiler
 
-#endif // TRACEWINDOW_H
+#endif // QMLPROFILERTRACEVIEW_H
 
diff --git a/src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp b/src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a12a6ccda5f8643a6b8a9f79aab92669c10e2f6c
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp
@@ -0,0 +1,172 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "qmlprofilerviewmanager.h"
+
+#include "qmlprofilertraceview.h"
+#include "qmlprofilereventview.h"
+#include "qmlprofilertool.h"
+#include "qmlprofilerstatemanager.h"
+#include "qmlprofilerdatamodel.h"
+
+#include <utils/qtcassert.h>
+#include <utils/fancymainwindow.h>
+#include <analyzerbase/analyzermanager.h>
+
+
+#include <QDockWidget>
+
+using namespace Analyzer;
+
+namespace QmlProfiler {
+namespace Internal {
+
+class QmlProfilerViewManager::QmlProfilerViewManagerPrivate {
+public:
+    QmlProfilerViewManagerPrivate(QmlProfilerViewManager *qq) { Q_UNUSED(qq); }
+
+    QmlProfilerTraceView *traceView;
+    QmlProfilerEventsWidget *eventsView;
+    QmlProfilerEventsWidget *v8profilerView;
+    QmlProfilerStateManager *profilerState;
+    QmlProfilerDataModel *profilerDataModel;
+    QmlProfilerTool *profilerTool;
+};
+
+QmlProfilerViewManager::QmlProfilerViewManager(QObject *parent,
+                                               QmlProfilerTool *profilerTool,
+                                               QmlProfilerDataModel *model,
+                                               QmlProfilerStateManager *profilerState)
+    : QObject(parent), d(new QmlProfilerViewManagerPrivate(this))
+{
+    setObjectName("QML Profiler View Manager");
+    d->traceView = 0;
+    d->eventsView = 0;
+    d->v8profilerView = 0;
+    d->profilerState = profilerState;
+    d->profilerDataModel = model;
+    d->profilerTool = profilerTool;
+    createViews();
+}
+
+QmlProfilerViewManager::~QmlProfilerViewManager()
+{
+    delete d;
+}
+
+////////////////////////////////////////////////////////////
+// Views
+void QmlProfilerViewManager::createViews()
+{
+    QTC_ASSERT(d->profilerDataModel, return);
+    QTC_ASSERT(d->profilerState, return);
+
+    Utils::FancyMainWindow *mw = AnalyzerManager::mainWindow();
+
+    d->traceView = new QmlProfilerTraceView(mw,
+                                            d->profilerTool,
+                                            this,
+                                            d->profilerDataModel,
+                                            d->profilerState);
+    connect(d->traceView, SIGNAL(gotoSourceLocation(QString,int,int)),
+            this, SIGNAL(gotoSourceLocation(QString,int,int)));
+
+    d->traceView->reset();
+
+    d->eventsView = new QmlProfilerEventsWidget(mw, d->profilerTool, this, d->profilerDataModel);
+    connect(d->eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), this,
+            SIGNAL(gotoSourceLocation(QString,int,int)));
+    connect(d->eventsView, SIGNAL(showEventInTimeline(int)), d->traceView,
+            SLOT(selectNextEventWithId(int)));
+    connect(d->traceView, SIGNAL(selectedEventChanged(int)), d->eventsView,
+            SLOT(updateSelectedEvent(int)));
+
+    d->v8profilerView = new QmlProfilerEventsWidget(mw, d->profilerTool,
+                                                    this, d->profilerDataModel);
+    d->v8profilerView->switchToV8View();
+    connect(d->v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)),
+            this, SIGNAL(gotoSourceLocation(QString,int,int)));
+    connect(d->v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)),
+            d->eventsView, SLOT(selectBySourceLocation(QString,int,int)));
+    connect(d->eventsView, SIGNAL(gotoSourceLocation(QString,int,int)),
+            d->v8profilerView, SLOT(selectBySourceLocation(QString,int,int)));
+
+    QDockWidget *eventsDock = AnalyzerManager::createDockWidget
+            (d->profilerTool, tr("Events"), d->eventsView, Qt::BottomDockWidgetArea);
+    QDockWidget *timelineDock = AnalyzerManager::createDockWidget
+            (d->profilerTool, tr("Timeline"), d->traceView, Qt::BottomDockWidgetArea);
+    QDockWidget *v8profilerDock = AnalyzerManager::createDockWidget
+            (d->profilerTool, tr("JavaScript"), d->v8profilerView, Qt::BottomDockWidgetArea);
+
+    eventsDock->show();
+    timelineDock->show();
+    v8profilerDock->show();
+
+    mw->splitDockWidget(mw->toolBarDockWidget(), eventsDock, Qt::Vertical);
+    mw->tabifyDockWidget(eventsDock, timelineDock);
+    mw->tabifyDockWidget(timelineDock, v8profilerDock);
+}
+
+bool QmlProfilerViewManager::hasValidSelection() const
+{
+    return d->traceView->hasValidSelection();
+}
+
+qint64 QmlProfilerViewManager::selectionStart() const
+{
+    return d->traceView->selectionStart();
+}
+
+qint64 QmlProfilerViewManager::selectionEnd() const
+{
+    return d->traceView->selectionEnd();
+}
+
+bool QmlProfilerViewManager::hasGlobalStats() const
+{
+    return d->eventsView->hasGlobalStats();
+}
+
+void QmlProfilerViewManager::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd)
+{
+    d->eventsView->getStatisticsInRange(rangeStart, rangeEnd);
+}
+
+void QmlProfilerViewManager::clear()
+{
+    d->traceView->clearDisplay();
+    d->eventsView->clear();
+    d->v8profilerView->clear();
+}
+
+} // namespace Internal
+} // namespace QmlProfiler
diff --git a/src/tools/qmlprofilertool/main.cpp b/src/plugins/qmlprofiler/qmlprofilerviewmanager.h
similarity index 53%
rename from src/tools/qmlprofilertool/main.cpp
rename to src/plugins/qmlprofiler/qmlprofilerviewmanager.h
index bb5c2bd32880187e3f9ce2561578c8d587b64521..4e492918eeedc1348d01240bb1d9f9b41cace3c7 100644
--- a/src/tools/qmlprofilertool/main.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerviewmanager.h
@@ -30,26 +30,50 @@
 **
 **************************************************************************/
 
-#include "qmlprofilerapplication.h"
-#include "commandlistener.h"
+#ifndef QMLPROFILERVIEWMANAGER_H
+#define QMLPROFILERVIEWMANAGER_H
 
-int main(int argc, char *argv[])
+#include <QObject>
+
+namespace QmlProfiler {
+namespace Internal {
+
+class QmlProfilerTool;
+class QmlProfilerDataModel;
+class QmlProfilerStateManager;
+
+class QmlProfilerViewManager : public QObject
 {
-    QmlProfilerApplication app(argc, argv);
+    Q_OBJECT
+public:
+    explicit QmlProfilerViewManager(QObject *parent,
+                                    QmlProfilerTool *profilerTool,
+                                    QmlProfilerDataModel *model,
+                                    QmlProfilerStateManager *profilerState);
+    ~QmlProfilerViewManager();
+
+    void createViews();
+
+    // used by the options "limit events to range"
+    bool hasValidSelection() const;
+    qint64 selectionStart() const;
+    qint64 selectionEnd() const;
+    bool hasGlobalStats() const;
+    void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd);
+
+public slots:
+    void clear();
 
-    if (!app.parseArguments()) {
-        app.printUsage();
-        return 1;
-    }
+signals:
+    void gotoSourceLocation(QString,int,int);
 
-    CommandListener listener;
-    QObject::connect(&listener, SIGNAL(command(QString)), &app, SLOT(userCommand(QString)));
-    listener.start();
+private:
+    class QmlProfilerViewManagerPrivate;
+    QmlProfilerViewManagerPrivate *d;
+};
 
-    int exitValue = app.exec();
-    // wait for listener to exit
-    listener.wait();
 
+} // namespace Internal
+} // namespace QmlProfiler
 
-    return exitValue;
-}
+#endif // QMLPROFILERVIEWMANAGER_H
diff --git a/src/plugins/qmlprofiler/qv8profilerdatamodel.cpp b/src/plugins/qmlprofiler/qv8profilerdatamodel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d58f198be6bbc841e048c34d61b418b431148878
--- /dev/null
+++ b/src/plugins/qmlprofiler/qv8profilerdatamodel.cpp
@@ -0,0 +1,445 @@
+#include "qv8profilerdatamodel.h"
+#include "qmlprofilerdatamodel.h"
+
+#include <QStringList>
+
+using namespace QmlJsDebugClient;
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QV8EventData, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QV8EventSub, Q_MOVABLE_TYPE);
+QT_END_NAMESPACE
+
+namespace QmlProfiler {
+namespace Internal {
+
+QV8EventData &QV8EventData::operator=(const QV8EventData &ref)
+{
+    if (this == &ref)
+        return *this;
+
+    displayName = ref.displayName;
+    eventHashStr = ref.eventHashStr;
+    filename = ref.filename;
+    functionName = ref.functionName;
+    line = ref.line;
+    totalTime = ref.totalTime;
+    totalPercent = ref.totalPercent;
+    selfTime = ref.selfTime;
+    selfPercent = ref.selfPercent;
+    eventId = ref.eventId;
+
+    qDeleteAll(parentHash.values());
+    parentHash.clear();
+    foreach (const QString &key, ref.parentHash.keys()) {
+        parentHash.insert(key, new QV8EventSub(ref.parentHash.value(key)));
+    }
+
+    qDeleteAll(childrenHash.values());
+    childrenHash.clear();
+    foreach (const QString &key, ref.childrenHash.keys()) {
+        childrenHash.insert(key, new QV8EventSub(ref.childrenHash.value(key)));
+    }
+    return *this;
+}
+
+QV8EventData::QV8EventData()
+{
+    line = -1;
+    eventId = -1;
+    totalTime = 0;
+    selfTime = 0;
+    totalPercent = 0;
+    selfPercent = 0;
+}
+
+QV8EventData::~QV8EventData()
+{
+    qDeleteAll(parentHash.values());
+    parentHash.clear();
+    qDeleteAll(childrenHash.values());
+    childrenHash.clear();
+}
+
+class QV8ProfilerDataModel::QV8ProfilerDataModelPrivate
+{
+public:
+    QV8ProfilerDataModelPrivate(QV8ProfilerDataModel *qq) {Q_UNUSED(qq);}
+
+    QmlProfilerDataModel *qmlProfilerDataModel;
+
+    void clearV8RootEvent();
+    void collectV8Statistics();
+
+    QHash<QString, QV8EventData *> v8EventHash;
+    QHash<int, QV8EventData *> v8parents;
+    QV8EventData v8RootEvent;
+    qint64 v8MeasuredTime;
+};
+
+QV8ProfilerDataModel::QV8ProfilerDataModel(QObject *parent,
+                                           QmlProfilerDataModel *profilerDataModel)
+    : QObject(parent), d(new QV8ProfilerDataModelPrivate(this))
+{
+    d->v8MeasuredTime = 0;
+    d->clearV8RootEvent();
+    d->qmlProfilerDataModel = profilerDataModel;
+}
+
+QV8ProfilerDataModel::~QV8ProfilerDataModel()
+{
+    delete d;
+}
+
+void QV8ProfilerDataModel::clear()
+{
+    qDeleteAll(d->v8EventHash.values());
+    d->v8EventHash.clear();
+    d->v8parents.clear();
+    d->clearV8RootEvent();
+    d->v8MeasuredTime = 0;
+}
+
+bool QV8ProfilerDataModel::isEmpty() const
+{
+    return d->v8EventHash.isEmpty();
+}
+
+QV8EventData *QV8ProfilerDataModel::v8EventDescription(int eventId) const
+{
+    foreach (QV8EventData *event, d->v8EventHash.values()) {
+        if (event->eventId == eventId)
+            return event;
+    }
+    return 0;
+}
+
+qint64 QV8ProfilerDataModel::v8MeasuredTime() const
+{
+    return d->v8MeasuredTime;
+}
+
+QList<QV8EventData *> QV8ProfilerDataModel::getV8Events() const
+{
+    return d->v8EventHash.values();
+}
+
+void QV8ProfilerDataModel::addV8Event(int depth,
+                                      const QString &function,
+                                      const QString &filename,
+                                      int lineNumber,
+                                      double totalTime,
+                                      double selfTime)
+{
+    QString displayName = filename.mid(filename.lastIndexOf(QLatin1Char('/')) + 1) +
+            QLatin1Char(':') + QString::number(lineNumber);
+    QString hashStr = QmlProfilerDataModel::getHashStringForV8Event(displayName, function);
+
+    d->qmlProfilerDataModel->setState(QmlProfilerDataModel::AcquiringData);
+
+    // time is given in milliseconds, but internally we store it in microseconds
+    totalTime *= 1e6;
+    selfTime *= 1e6;
+
+    // accumulate information
+    QV8EventData *eventData = d->v8EventHash[hashStr];
+    if (!eventData) {
+        eventData = new QV8EventData;
+        eventData->displayName = displayName;
+        eventData->eventHashStr = hashStr;
+        eventData->filename = filename;
+        eventData->functionName = function;
+        eventData->line = lineNumber;
+        eventData->totalTime = totalTime;
+        eventData->selfTime = selfTime;
+        d->v8EventHash[hashStr] = eventData;
+    } else {
+        eventData->totalTime += totalTime;
+        eventData->selfTime += selfTime;
+    }
+    d->v8parents[depth] = eventData;
+
+    QV8EventData *parentEvent = 0;
+    if (depth == 0) {
+        parentEvent = &d->v8RootEvent;
+        d->v8MeasuredTime += totalTime;
+    }
+    if (depth > 0 && d->v8parents.contains(depth-1)) {
+        parentEvent = d->v8parents.value(depth-1);
+    }
+
+    if (parentEvent != 0) {
+        if (!eventData->parentHash.contains(parentEvent->eventHashStr)) {
+            QV8EventSub *newParentSub = new QV8EventSub(parentEvent);
+            newParentSub->totalTime = totalTime;
+
+            eventData->parentHash.insert(parentEvent->eventHashStr, newParentSub);
+        } else {
+            QV8EventSub *newParentSub = eventData->parentHash.value(parentEvent->eventHashStr);
+            newParentSub->totalTime += totalTime;
+        }
+
+        if (!parentEvent->childrenHash.contains(eventData->eventHashStr)) {
+            QV8EventSub *newChildSub = new QV8EventSub(eventData);
+            newChildSub->totalTime = totalTime;
+
+            parentEvent->childrenHash.insert(eventData->eventHashStr, newChildSub);
+        } else {
+            QV8EventSub *newChildSub = parentEvent->childrenHash.value(eventData->eventHashStr);
+            newChildSub->totalTime += totalTime;
+        }
+    }
+}
+
+void QV8ProfilerDataModel::collectV8Statistics()
+{
+    d->collectV8Statistics();
+}
+
+void QV8ProfilerDataModel::QV8ProfilerDataModelPrivate::collectV8Statistics()
+{
+    if (!v8EventHash.isEmpty()) {
+        double totalTimes = v8MeasuredTime;
+        double selfTimes = 0;
+        foreach (QV8EventData *v8event, v8EventHash.values()) {
+            selfTimes += v8event->selfTime;
+        }
+
+        // prevent divisions by 0
+        if (totalTimes == 0)
+            totalTimes = 1;
+        if (selfTimes == 0)
+            selfTimes = 1;
+
+        // insert root event in eventlist
+        // the +1 ns is to get it on top of the sorted list
+        v8RootEvent.totalTime = v8MeasuredTime + 1;
+        v8RootEvent.selfTime = 0;
+
+        QString rootEventHash = QmlProfilerDataModel::getHashStringForV8Event(
+                    QmlProfilerDataModel::rootEventName(),
+                    QmlProfilerDataModel::rootEventDescription());
+        QV8EventData *v8RootEventPointer = v8EventHash[rootEventHash];
+        if (v8RootEventPointer) {
+            v8RootEvent = *v8RootEventPointer;
+        } else {
+            v8EventHash[rootEventHash] = new QV8EventData;
+            *v8EventHash[rootEventHash] = v8RootEvent;
+        }
+
+        foreach (QV8EventData *v8event, v8EventHash.values()) {
+            v8event->totalPercent = v8event->totalTime * 100.0 / totalTimes;
+            v8event->selfPercent = v8event->selfTime * 100.0 / selfTimes;
+        }
+
+        int index = 0;
+        foreach (QV8EventData *v8event, v8EventHash.values()) {
+            v8event->eventId = index++;
+        }
+        v8RootEvent.eventId = v8EventHash[rootEventHash]->eventId;
+    }
+}
+
+void QV8ProfilerDataModel::QV8ProfilerDataModelPrivate::clearV8RootEvent()
+{
+    v8RootEvent.displayName = QmlProfilerDataModel::rootEventName();
+    v8RootEvent.eventHashStr = QmlProfilerDataModel::rootEventName();
+    v8RootEvent.functionName = QmlProfilerDataModel::rootEventDescription();
+    v8RootEvent.line = -1;
+    v8RootEvent.totalTime = 0;
+    v8RootEvent.totalPercent = 0;
+    v8RootEvent.selfTime = 0;
+    v8RootEvent.selfPercent = 0;
+    v8RootEvent.eventId = -1;
+
+    qDeleteAll(v8RootEvent.parentHash.values());
+    qDeleteAll(v8RootEvent.childrenHash.values());
+    v8RootEvent.parentHash.clear();
+    v8RootEvent.childrenHash.clear();
+}
+
+void QV8ProfilerDataModel::save(QXmlStreamWriter &stream)
+{
+    stream.writeStartElement("v8profile"); // v8 profiler output
+    stream.writeAttribute("totalTime", QString::number(d->v8MeasuredTime));
+    foreach (QV8EventData *v8event, d->v8EventHash.values()) {
+        stream.writeStartElement("event");
+        stream.writeAttribute("index",
+                              QString::number(
+                                  d->v8EventHash.keys().indexOf(
+                                      v8event->eventHashStr)));
+        stream.writeTextElement("displayname", v8event->displayName);
+        stream.writeTextElement("functionname", v8event->functionName);
+        if (!v8event->filename.isEmpty()) {
+            stream.writeTextElement("filename", v8event->filename);
+            stream.writeTextElement("line", QString::number(v8event->line));
+        }
+        stream.writeTextElement("totalTime", QString::number(v8event->totalTime));
+        stream.writeTextElement("selfTime", QString::number(v8event->selfTime));
+        if (!v8event->childrenHash.isEmpty()) {
+            stream.writeStartElement("childrenEvents");
+            QStringList childrenIndexes;
+            QStringList childrenTimes;
+            QStringList parentTimes;
+            foreach (QV8EventSub *v8child, v8event->childrenHash.values()) {
+                childrenIndexes << QString::number(v8child->reference->eventId);
+                childrenTimes << QString::number(v8child->totalTime);
+                parentTimes << QString::number(v8child->totalTime);
+            }
+
+            stream.writeAttribute("list", childrenIndexes.join(QString(", ")));
+            stream.writeAttribute("childrenTimes", childrenTimes.join(QString(", ")));
+            stream.writeAttribute("parentTimes", parentTimes.join(QString(", ")));
+            stream.writeEndElement();
+        }
+        stream.writeEndElement();
+    }
+    stream.writeEndElement(); // v8 profiler output
+}
+
+void QV8ProfilerDataModel::load(QXmlStreamReader &stream)
+{
+    QHash <int, QV8EventData *> v8eventBuffer;
+    QHash <int, QString> childrenIndexes;
+    QHash <int, QString> childrenTimes;
+    QHash <int, QString> parentTimes;
+    QV8EventData *v8event = 0;
+
+    // time computation
+    d->v8MeasuredTime = 0;
+    double cumulatedV8Time = 0;
+
+    // get the v8 time
+    QXmlStreamAttributes attributes = stream.attributes();
+    if (attributes.hasAttribute("totalTime"))
+        d->v8MeasuredTime = attributes.value("totalTime").toString().toDouble();
+
+    while (!stream.atEnd() && !stream.hasError()) {
+        QXmlStreamReader::TokenType token = stream.readNext();
+        QString elementName = stream.name().toString();
+        switch (token) {
+        case QXmlStreamReader::StartDocument :  continue;
+        case QXmlStreamReader::StartElement : {
+                if (elementName == "event") {
+                    QXmlStreamAttributes attributes = stream.attributes();
+                    if (attributes.hasAttribute("index")) {
+                        int ndx = attributes.value("index").toString().toInt();
+                        if (!v8eventBuffer.value(ndx))
+                            v8eventBuffer[ndx] = new QV8EventData;
+                        v8event = v8eventBuffer[ndx];
+                    } else {
+                        v8event = 0;
+                    }
+                    break;
+                }
+
+                if (!v8event)
+                    break;
+
+                if (elementName == "childrenEvents") {
+                    QXmlStreamAttributes attributes = stream.attributes();
+                    int eventIndex = v8eventBuffer.key(v8event);
+                    if (attributes.hasAttribute("list")) {
+                        // store for later parsing (we haven't read all the events yet)
+                        childrenIndexes[eventIndex] = attributes.value("list").toString();
+                    }
+                    if (attributes.hasAttribute("childrenTimes")) {
+                        childrenTimes[eventIndex] =
+                                attributes.value("childrenTimes").toString();
+                    }
+                    if (attributes.hasAttribute("parentTimes")) {
+                        parentTimes[eventIndex] = attributes.value("parentTimes").toString();
+                    }
+                }
+
+                stream.readNext();
+                if (stream.tokenType() != QXmlStreamReader::Characters)
+                    break;
+                QString readData = stream.text().toString();
+
+                if (elementName == "displayname") {
+                    v8event->displayName = readData;
+                    break;
+                }
+
+                if (elementName == "functionname") {
+                    v8event->functionName = readData;
+                    break;
+                }
+
+                if (elementName == "filename") {
+                    v8event->filename = readData;
+                    break;
+                }
+
+                if (elementName == "line") {
+                    v8event->line = readData.toInt();
+                    break;
+                }
+
+                if (elementName == "totalTime") {
+                    v8event->totalTime = readData.toDouble();
+                    cumulatedV8Time += v8event->totalTime;
+                    break;
+                }
+
+                if (elementName == "selfTime") {
+                    v8event->selfTime = readData.toDouble();
+                    break;
+                }
+            break;
+        }
+        case QXmlStreamReader::EndElement : {
+            if (elementName == "v8profile") {
+                // done reading the v8 profile data
+                break;
+            }
+        }
+        default: break;
+        }
+}
+
+    // backwards compatibility
+    if (d->v8MeasuredTime == 0)
+        d->v8MeasuredTime = cumulatedV8Time;
+
+    // find v8events' children and parents
+    foreach (int parentIndex, childrenIndexes.keys()) {
+        QStringList childrenStrings = childrenIndexes.value(parentIndex).split(",");
+        QStringList childrenTimesStrings = childrenTimes.value(parentIndex).split(", ");
+        QStringList parentTimesStrings = parentTimes.value(parentIndex).split(", ");
+        for (int ndx = 0; ndx < childrenStrings.count(); ndx++) {
+            int childIndex = childrenStrings[ndx].toInt();
+            if (v8eventBuffer.value(childIndex)) {
+                QV8EventSub *newChild = new QV8EventSub(v8eventBuffer[childIndex]);
+                QV8EventSub *newParent = new QV8EventSub(v8eventBuffer[parentIndex]);
+                if (childrenTimesStrings.count() > ndx) {
+                    newChild->totalTime = childrenTimesStrings[ndx].toDouble();
+                }
+                if (parentTimesStrings.count() > ndx) {
+                    newParent->totalTime = parentTimesStrings[ndx].toDouble();
+                }
+                v8eventBuffer[parentIndex]->childrenHash.insert(
+                            newChild->reference->displayName,
+                            newChild);
+                v8eventBuffer[childIndex]->parentHash.insert(
+                            newParent->reference->displayName,
+                            newParent);
+            }
+        }
+    }
+
+    // store v8 events
+    foreach (QV8EventData *storedV8Event, v8eventBuffer.values()) {
+        storedV8Event->eventHashStr =
+                QmlProfilerDataModel::getHashStringForV8Event(
+                    storedV8Event->displayName, storedV8Event->functionName);
+        d->v8EventHash[storedV8Event->eventHashStr] = storedV8Event;
+    }
+
+    d->collectV8Statistics();
+
+}
+
+} // namespace Internal
+} // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/qv8profilerdatamodel.h b/src/plugins/qmlprofiler/qv8profilerdatamodel.h
new file mode 100644
index 0000000000000000000000000000000000000000..6441a24702aea2db5839fe1a3672daac1ec48495
--- /dev/null
+++ b/src/plugins/qmlprofiler/qv8profilerdatamodel.h
@@ -0,0 +1,79 @@
+#ifndef QV8PROFILERDATAMODEL_H
+#define QV8PROFILERDATAMODEL_H
+
+#include <QObject>
+#include <QHash>
+
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+
+namespace QmlProfiler {
+namespace Internal {
+
+class QmlProfilerDataModel;
+struct QV8EventSub;
+
+struct QV8EventData
+{
+    QV8EventData();
+    ~QV8EventData();
+
+    QString displayName;
+    QString eventHashStr;
+    QString filename;
+    QString functionName;
+    int line;
+    double totalTime; // given in milliseconds
+    double totalPercent;
+    double selfTime;
+    double selfPercent;
+    QHash <QString, QV8EventSub *> parentHash;
+    QHash <QString, QV8EventSub *> childrenHash;
+    int eventId;
+
+    QV8EventData &operator=(const QV8EventData &ref);
+};
+
+struct QV8EventSub {
+    QV8EventSub(QV8EventData *from) : reference(from), totalTime(0) {}
+    QV8EventSub(QV8EventSub *from) : reference(from->reference), totalTime(from->totalTime) {}
+
+    QV8EventData *reference;
+    qint64 totalTime;
+};
+
+class QV8ProfilerDataModel : public QObject
+{
+    Q_OBJECT
+public:
+    explicit QV8ProfilerDataModel(QObject *parent, QmlProfilerDataModel *profilerDataModel);
+    ~QV8ProfilerDataModel();
+
+    void clear();
+    bool isEmpty() const;
+    QList<QV8EventData *> getV8Events() const;
+    QV8EventData *v8EventDescription(int eventId) const;
+
+    qint64 v8MeasuredTime() const;
+    void collectV8Statistics();
+
+    void save(QXmlStreamWriter &stream);
+    void load(QXmlStreamReader &stream);
+
+public slots:
+    void addV8Event(int depth,
+                    const QString &function,
+                    const QString &filename,
+                    int lineNumber,
+                    double totalTime,
+                    double selfTime);
+
+private:
+    class QV8ProfilerDataModelPrivate;
+    QV8ProfilerDataModelPrivate *d;
+};
+
+} // namespace Internal
+} // namespace QmlProfiler
+
+#endif // QV8PROFILERDATAMODEL_H
diff --git a/src/plugins/qmlprofiler/timelineview.cpp b/src/plugins/qmlprofiler/timelinerenderer.cpp
similarity index 60%
rename from src/plugins/qmlprofiler/timelineview.cpp
rename to src/plugins/qmlprofiler/timelinerenderer.cpp
index 1e10eb0075e8474b6c43b5d6438ee392bac0db45..a078d31f8402ee0c4995c9659f42432fac48e706 100644
--- a/src/plugins/qmlprofiler/timelineview.cpp
+++ b/src/plugins/qmlprofiler/timelinerenderer.cpp
@@ -30,7 +30,7 @@
 **
 **************************************************************************/
 
-#include "timelineview.h"
+#include "timelinerenderer.h"
 
 #include <qdeclarativecontext.h>
 #include <qdeclarativeproperty.h>
@@ -45,9 +45,9 @@ using namespace QmlProfiler::Internal;
 
 const int DefaultRowHeight = 30;
 
-TimelineView::TimelineView(QDeclarativeItem *parent) :
+TimelineRenderer::TimelineRenderer(QDeclarativeItem *parent) :
     QDeclarativeItem(parent), m_startTime(0), m_endTime(0), m_spacing(0),
-    m_lastStartTime(0), m_lastEndTime(0), m_eventList(0)
+    m_lastStartTime(0), m_lastEndTime(0), m_profilerDataModel(0)
 {
     clearData();
     setFlag(QGraphicsItem::ItemHasNoContents, false);
@@ -57,12 +57,12 @@ TimelineView::TimelineView(QDeclarativeItem *parent) :
         m_rowsExpanded << false;
 }
 
-void TimelineView::componentComplete()
+void TimelineRenderer::componentComplete()
 {
     const QMetaObject *metaObject = this->metaObject();
     int propertyCount = metaObject->propertyCount();
     int requestPaintMethod = metaObject->indexOfMethod("requestPaint()");
-    for (int ii = TimelineView::staticMetaObject.propertyCount(); ii < propertyCount; ++ii) {
+    for (int ii = TimelineRenderer::staticMetaObject.propertyCount(); ii < propertyCount; ++ii) {
         QMetaProperty p = metaObject->property(ii);
         if (p.hasNotifySignal())
             QMetaObject::connect(this, p.notifySignalIndex(), this, requestPaintMethod, 0, 0);
@@ -70,12 +70,12 @@ void TimelineView::componentComplete()
     QDeclarativeItem::componentComplete();
 }
 
-void TimelineView::requestPaint()
+void TimelineRenderer::requestPaint()
 {
     update();
 }
 
-void TimelineView::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+void TimelineRenderer::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
 {
     qint64 windowDuration = m_endTime - m_startTime;
     if (windowDuration <= 0)
@@ -86,7 +86,8 @@ void TimelineView::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget
     m_rowWidths.clear();
     // The "1+" is because the reference screenshot features an empty row per type, in order to leave space for the title
     for (int i=0; i<QmlJsDebugClient::MaximumQmlEventType; i++) {
-        m_rowWidths << 1 + (m_rowsExpanded[i] ? m_eventList->uniqueEventsOfType(i) : m_eventList->maxNestingForType(i));
+        m_rowWidths << 1 + (m_rowsExpanded[i] ? m_profilerDataModel->uniqueEventsOfType(i) :
+                                                m_profilerDataModel->maxNestingForType(i));
     }
 
     // event rows
@@ -105,8 +106,8 @@ void TimelineView::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget
         for (int j=0; j<m_rowWidths[i]; j++)
             m_rowLastX << -m_startTime * m_spacing;
 
-    int firstIndex = m_eventList->findFirstIndex(m_startTime);
-    int lastIndex = m_eventList->findLastIndex(m_endTime);
+    int firstIndex = m_profilerDataModel->findFirstIndex(m_startTime);
+    int lastIndex = m_profilerDataModel->findLastIndex(m_endTime);
 
     drawItemsToPainter(p, firstIndex, lastIndex);
     drawSelectionBoxes(p, firstIndex, lastIndex);
@@ -116,25 +117,27 @@ void TimelineView::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget
     m_lastEndTime = m_endTime;
 }
 
-QColor TimelineView::colorForItem(int itemIndex)
+QColor TimelineRenderer::colorForItem(int itemIndex)
 {
-    int ndx = m_eventList->getEventId(itemIndex);
+    int ndx = m_profilerDataModel->getEventId(itemIndex);
     return QColor::fromHsl((ndx*25)%360, 76, 166);
 }
 
-void TimelineView::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex)
+void TimelineRenderer::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex)
 {
     int x, y, width, height, rowNumber, eventType;
     for (int i = fromIndex; i <= toIndex; i++) {
-        x = (m_eventList->getStartTime(i) - m_startTime) * m_spacing;
+        x = (m_profilerDataModel->getStartTime(i) - m_startTime) * m_spacing;
 
-        eventType = m_eventList->getType(i);
+        eventType = m_profilerDataModel->getType(i);
         if (m_rowsExpanded[eventType])
-            y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->eventPosInType(i) + 1);
+            y = m_rowStarts[eventType] + DefaultRowHeight *
+                    (m_profilerDataModel->eventPosInType(i) + 1);
         else
-            y = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->getNestingLevel(i);
+            y = m_rowStarts[eventType] + DefaultRowHeight *
+                    m_profilerDataModel->getNestingLevel(i);
 
-        width = m_eventList->getDuration(i)*m_spacing;
+        width = m_profilerDataModel->getDuration(i)*m_spacing;
         if (width<1)
             width = 1;
 
@@ -144,17 +147,19 @@ void TimelineView::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex)
         m_rowLastX[rowNumber] = x+width;
 
         // special: animations
-        if (eventType == 0 && m_eventList->getAnimationCount(i) >= 0) {
-            double scale = m_eventList->getMaximumAnimationCount() - m_eventList->getMinimumAnimationCount();
+        if (eventType == 0 && m_profilerDataModel->getAnimationCount(i) >= 0) {
+            double scale = m_profilerDataModel->getMaximumAnimationCount() -
+                    m_profilerDataModel->getMinimumAnimationCount();
             double fraction;
             if (scale > 1)
-                fraction = (double)(m_eventList->getAnimationCount(i) - m_eventList->getMinimumAnimationCount()) / scale;
+                fraction = (double)(m_profilerDataModel->getAnimationCount(i) -
+                                    m_profilerDataModel->getMinimumAnimationCount()) / scale;
             else
                 fraction = 1.0;
             height = DefaultRowHeight * (fraction * 0.85 + 0.15);
             y += DefaultRowHeight - height;
 
-            double fpsFraction = m_eventList->getFramerate(i) / 60.0;
+            double fpsFraction = m_profilerDataModel->getFramerate(i) / 60.0;
             if (fpsFraction > 1.0)
                 fpsFraction = 1.0;
             p->setBrush(QColor::fromHsl((fpsFraction*96)+10, 76, 166));
@@ -167,12 +172,12 @@ void TimelineView::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex)
     }
 }
 
-void TimelineView::drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex)
+void TimelineRenderer::drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex)
 {
     if (m_selectedItem == -1)
         return;
 
-    int id = m_eventList->getEventId(m_selectedItem);
+    int id = m_profilerDataModel->getEventId(m_selectedItem);
 
     p->setBrush(Qt::transparent);
     QColor selectionColor = Qt::blue;
@@ -188,17 +193,19 @@ void TimelineView::drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex)
 
     QRect selectedItemRect(0,0,0,0);
     for (int i = fromIndex; i <= toIndex; i++) {
-        if (m_eventList->getEventId(i) != id)
+        if (m_profilerDataModel->getEventId(i) != id)
             continue;
 
-        x = (m_eventList->getStartTime(i) - m_startTime) * m_spacing;
-        eventType = m_eventList->getType(i);
+        x = (m_profilerDataModel->getStartTime(i) - m_startTime) * m_spacing;
+        eventType = m_profilerDataModel->getType(i);
         if (m_rowsExpanded[eventType])
-            y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->eventPosInType(i) + 1);
+            y = m_rowStarts[eventType] + DefaultRowHeight *
+                    (m_profilerDataModel->eventPosInType(i) + 1);
         else
-            y = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->getNestingLevel(i);
+            y = m_rowStarts[eventType] + DefaultRowHeight *
+                    m_profilerDataModel->getNestingLevel(i);
 
-        width = m_eventList->getDuration(i)*m_spacing;
+        width = m_profilerDataModel->getDuration(i)*m_spacing;
         if (width<1)
             width = 1;
 
@@ -215,7 +222,7 @@ void TimelineView::drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex)
     }
 }
 
-void TimelineView::drawBindingLoopMarkers(QPainter *p, int fromIndex, int toIndex)
+void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int fromIndex, int toIndex)
 {
     int destindex;
     int xfrom, xto, eventType;
@@ -228,35 +235,38 @@ void TimelineView::drawBindingLoopMarkers(QPainter *p, int fromIndex, int toInde
 
     p->save();
     for (int i = fromIndex; i <= toIndex; i++) {
-        destindex = m_eventList->getBindingLoopDest(i);
+        destindex = m_profilerDataModel->getBindingLoopDest(i);
         if (destindex >= 0) {
             // from
-            xfrom = (m_eventList->getStartTime(i) + m_eventList->getDuration(i)/2 -
+            xfrom = (m_profilerDataModel->getStartTime(i) +
+                     m_profilerDataModel->getDuration(i)/2 -
                      m_startTime) * m_spacing;
-            eventType = m_eventList->getType(i);
+            eventType = m_profilerDataModel->getType(i);
             if (m_rowsExpanded[eventType])
                 yfrom = m_rowStarts[eventType] + DefaultRowHeight*
-                        (m_eventList->eventPosInType(i) + 1);
+                        (m_profilerDataModel->eventPosInType(i) + 1);
             else
-                yfrom = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->getNestingLevel(i);
+                yfrom = m_rowStarts[eventType] + DefaultRowHeight *
+                        m_profilerDataModel->getNestingLevel(i);
 
             yfrom += DefaultRowHeight / 2;
 
             // to
-            xto = (m_eventList->getStartTime(destindex) + m_eventList->getDuration(destindex)/2 -
+            xto = (m_profilerDataModel->getStartTime(destindex) +
+                   m_profilerDataModel->getDuration(destindex)/2 -
                    m_startTime) * m_spacing;
-            eventType = m_eventList->getType(destindex);
+            eventType = m_profilerDataModel->getType(destindex);
             if (m_rowsExpanded[eventType])
-                yto = m_rowStarts[eventType] + DefaultRowHeight*
-                        (m_eventList->eventPosInType(destindex) + 1);
+                yto = m_rowStarts[eventType] + DefaultRowHeight *
+                        (m_profilerDataModel->eventPosInType(destindex) + 1);
             else
                 yto = m_rowStarts[eventType] + DefaultRowHeight *
-                        m_eventList->getNestingLevel(destindex);
+                        m_profilerDataModel->getNestingLevel(destindex);
 
             yto += DefaultRowHeight / 2;
 
             // radius
-            int eventWidth = m_eventList->getDuration(i) * m_spacing;
+            int eventWidth = m_profilerDataModel->getDuration(i) * m_spacing;
             radius = 5;
             if (radius * 2 > eventWidth)
                 radius = eventWidth / 2;
@@ -283,7 +293,7 @@ void TimelineView::drawBindingLoopMarkers(QPainter *p, int fromIndex, int toInde
     p->restore();
 }
 
-void TimelineView::mousePressEvent(QGraphicsSceneMouseEvent *event)
+void TimelineRenderer::mousePressEvent(QGraphicsSceneMouseEvent *event)
 {
     // special case: if there is a drag area below me, don't accept the
     // events unless I'm actually clicking inside an item
@@ -294,19 +304,19 @@ void TimelineView::mousePressEvent(QGraphicsSceneMouseEvent *event)
 
 }
 
-void TimelineView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+void TimelineRenderer::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
 {
     Q_UNUSED(event);
     manageClicked();
 }
 
-void TimelineView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+void TimelineRenderer::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
 {
     event->setAccepted(false);
 }
 
 
-void TimelineView::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
+void TimelineRenderer::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
 {
     Q_UNUSED(event);
     manageHovered(event->pos().x(), event->pos().y());
@@ -314,7 +324,7 @@ void TimelineView::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
         event->setAccepted(false);
 }
 
-void TimelineView::manageClicked()
+void TimelineRenderer::manageClicked()
 {
     if (m_currentSelection.eventIndex != -1) {
         if (m_currentSelection.eventIndex == m_selectedItem)
@@ -328,7 +338,7 @@ void TimelineView::manageClicked()
     setSelectedItem(m_currentSelection.eventIndex);
 }
 
-void TimelineView::manageHovered(int x, int y)
+void TimelineRenderer::manageHovered(int x, int y)
 {
     if (m_endTime - m_startTime <=0 || m_lastEndTime - m_lastStartTime <= 0)
         return;
@@ -337,13 +347,16 @@ void TimelineView::manageHovered(int x, int y)
     int row = y / DefaultRowHeight;
 
     // already covered? nothing to do
-    if (m_currentSelection.eventIndex != -1 && time >= m_currentSelection.startTime && time <= m_currentSelection.endTime && row == m_currentSelection.row) {
+    if (m_currentSelection.eventIndex != -1 &&
+            time >= m_currentSelection.startTime &&
+            time <= m_currentSelection.endTime &&
+            row == m_currentSelection.row) {
         return;
     }
 
     // find if there's items in the time range
-    int eventFrom = m_eventList->findFirstIndex(time);
-    int eventTo = m_eventList->findLastIndex(time);
+    int eventFrom = m_profilerDataModel->findFirstIndex(time);
+    int eventTo = m_profilerDataModel->findLastIndex(time);
     if (eventTo < eventFrom) {
         m_currentSelection.eventIndex = -1;
         return;
@@ -352,19 +365,21 @@ void TimelineView::manageHovered(int x, int y)
     // find if we are in the right column
     int itemRow, eventType;
     for (int i=eventTo; i>=eventFrom; --i) {
-        if (ceil(m_eventList->getEndTime(i)*m_spacing) < floor(time*m_spacing))
+        if (ceil(m_profilerDataModel->getEndTime(i)*m_spacing) < floor(time*m_spacing))
             continue;
 
-        eventType = m_eventList->getType(i);
+        eventType = m_profilerDataModel->getType(i);
         if (m_rowsExpanded[eventType])
-            itemRow = m_rowStarts[eventType]/DefaultRowHeight + m_eventList->eventPosInType(i) + 1;
+            itemRow = m_rowStarts[eventType]/DefaultRowHeight +
+                    m_profilerDataModel->eventPosInType(i) + 1;
         else
-            itemRow = m_rowStarts[eventType]/DefaultRowHeight + m_eventList->getNestingLevel(i);
+            itemRow = m_rowStarts[eventType]/DefaultRowHeight +
+                    m_profilerDataModel->getNestingLevel(i);
         if (itemRow == row) {
             // match
             m_currentSelection.eventIndex = i;
-            m_currentSelection.startTime = m_eventList->getStartTime(i);
-            m_currentSelection.endTime = m_eventList->getEndTime(i);
+            m_currentSelection.startTime = m_profilerDataModel->getStartTime(i);
+            m_currentSelection.endTime = m_profilerDataModel->getEndTime(i);
             m_currentSelection.row = row;
             if (!m_selectionLocked)
                 setSelectedItem(i);
@@ -376,7 +391,7 @@ void TimelineView::manageHovered(int x, int y)
     return;
 }
 
-void TimelineView::clearData()
+void TimelineRenderer::clearData()
 {
     m_startTime = 0;
     m_endTime = 0;
@@ -390,122 +405,125 @@ void TimelineView::clearData()
     m_selectionLocked = true;
 }
 
-qint64 TimelineView::getDuration(int index) const
+qint64 TimelineRenderer::getDuration(int index) const
 {
-    Q_ASSERT(m_eventList);
-    return m_eventList->getEndTime(index) - m_eventList->getStartTime(index);
+    Q_ASSERT(m_profilerDataModel);
+    return m_profilerDataModel->getEndTime(index) -
+            m_profilerDataModel->getStartTime(index);
 }
 
-QString TimelineView::getFilename(int index) const
+QString TimelineRenderer::getFilename(int index) const
 {
-    Q_ASSERT(m_eventList);
-    return m_eventList->getFilename(index);
+    Q_ASSERT(m_profilerDataModel);
+    return m_profilerDataModel->getFilename(index);
 }
 
-int TimelineView::getLine(int index) const
+int TimelineRenderer::getLine(int index) const
 {
-    Q_ASSERT(m_eventList);
-    return m_eventList->getLine(index);
+    Q_ASSERT(m_profilerDataModel);
+    return m_profilerDataModel->getLine(index);
 }
 
-QString TimelineView::getDetails(int index) const
+QString TimelineRenderer::getDetails(int index) const
 {
-    Q_ASSERT(m_eventList);
-    return m_eventList->getDetails(index);
+    Q_ASSERT(m_profilerDataModel);
+    return m_profilerDataModel->getDetails(index);
 }
 
-int TimelineView::getYPosition(int index) const
+int TimelineRenderer::getYPosition(int index) const
 {
-    Q_ASSERT(m_eventList);
-    if (index >= m_eventList->count() || m_rowStarts.isEmpty())
+    Q_ASSERT(m_profilerDataModel);
+    if (index >= m_profilerDataModel->count() || m_rowStarts.isEmpty())
         return 0;
-    int y, eventType = m_eventList->getType(index);
+    int y, eventType = m_profilerDataModel->getType(index);
     if (m_rowsExpanded[eventType])
-        y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->eventPosInType(index) + 1);
+        y = m_rowStarts[eventType] + DefaultRowHeight *
+                (m_profilerDataModel->eventPosInType(index) + 1);
     else
-        y = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->getNestingLevel(index);
+        y = m_rowStarts[eventType] + DefaultRowHeight *
+                m_profilerDataModel->getNestingLevel(index);
     return y;
 }
 
-void TimelineView::setRowExpanded(int rowIndex, bool expanded)
+void TimelineRenderer::setRowExpanded(int rowIndex, bool expanded)
 {
     m_rowsExpanded[rowIndex] = expanded;
     update();
 }
 
-void TimelineView::selectNext()
+void TimelineRenderer::selectNext()
 {
-    if (m_eventList->count() == 0)
+    if (m_profilerDataModel->count() == 0)
         return;
 
     // select next in view or after
     int newIndex = m_selectedItem+1;
-    if (newIndex >= m_eventList->count())
+    if (newIndex >= m_profilerDataModel->count())
         newIndex = 0;
-    if (m_eventList->getEndTime(newIndex) < m_startTime)
-        newIndex = m_eventList->findFirstIndexNoParents(m_startTime);
+    if (m_profilerDataModel->getEndTime(newIndex) < m_startTime)
+        newIndex = m_profilerDataModel->findFirstIndexNoParents(m_startTime);
     setSelectedItem(newIndex);
 }
 
-void TimelineView::selectPrev()
+void TimelineRenderer::selectPrev()
 {
-    if (m_eventList->count() == 0)
+    if (m_profilerDataModel->count() == 0)
         return;
 
     // select last in view or before
     int newIndex = m_selectedItem-1;
     if (newIndex < 0)
-        newIndex = m_eventList->count()-1;
-    if (m_eventList->getStartTime(newIndex) > m_endTime)
-        newIndex = m_eventList->findLastIndex(m_endTime);
+        newIndex = m_profilerDataModel->count()-1;
+    if (m_profilerDataModel->getStartTime(newIndex) > m_endTime)
+        newIndex = m_profilerDataModel->findLastIndex(m_endTime);
     setSelectedItem(newIndex);
 }
 
-int TimelineView::nextItemFromId(int eventId) const
+int TimelineRenderer::nextItemFromId(int eventId) const
 {
     int ndx = -1;
     if (m_selectedItem == -1)
-        ndx = m_eventList->findFirstIndexNoParents(m_startTime);
+        ndx = m_profilerDataModel->findFirstIndexNoParents(m_startTime);
     else
         ndx = m_selectedItem + 1;
-    if (ndx >= m_eventList->count())
+    if (ndx >= m_profilerDataModel->count())
         ndx = 0;
     int startIndex = ndx;
     do {
-        if (m_eventList->getEventId(ndx) == eventId)
+        if (m_profilerDataModel->getEventId(ndx) == eventId)
             return ndx;
-        ndx = (ndx + 1) % m_eventList->count();
+        ndx = (ndx + 1) % m_profilerDataModel->count();
     } while (ndx != startIndex);
     return -1;
 }
 
-int TimelineView::prevItemFromId(int eventId) const
+int TimelineRenderer::prevItemFromId(int eventId) const
 {
     int ndx = -1;
     if (m_selectedItem == -1)
-        ndx = m_eventList->findFirstIndexNoParents(m_startTime);
+        ndx = m_profilerDataModel->findFirstIndexNoParents(m_startTime);
     else
         ndx = m_selectedItem - 1;
     if (ndx < 0)
-        ndx = m_eventList->count() - 1;
+        ndx = m_profilerDataModel->count() - 1;
     int startIndex = ndx;
     do {
-        if (m_eventList->getEventId(ndx) == eventId)
+        if (m_profilerDataModel->getEventId(ndx) == eventId)
             return ndx;
         if (--ndx < 0)
-            ndx = m_eventList->count()-1;
+            ndx = m_profilerDataModel->count()-1;
     } while (ndx != startIndex);
     return -1;
 }
 
-void TimelineView::selectNextFromId(int eventId)
+void TimelineRenderer::selectNextFromId(int eventId)
 {
     int eventIndex = nextItemFromId(eventId);
     if (eventIndex != -1)
         setSelectedItem(eventIndex);
 }
 
-void TimelineView::selectPrevFromId(int eventId)
+void TimelineRenderer::selectPrevFromId(int eventId)
 {
     int eventIndex = prevItemFromId(eventId);
     if (eventIndex != -1)
diff --git a/src/plugins/qmlprofiler/timelineview.h b/src/plugins/qmlprofiler/timelinerenderer.h
similarity index 87%
rename from src/plugins/qmlprofiler/timelineview.h
rename to src/plugins/qmlprofiler/timelinerenderer.h
index 357662ea3e0ab0f783bd9d5d852731497d53a5dc..6b776b4c047110002e6f2fb521145743b66ede4a 100644
--- a/src/plugins/qmlprofiler/timelineview.h
+++ b/src/plugins/qmlprofiler/timelinerenderer.h
@@ -30,29 +30,29 @@
 **
 **************************************************************************/
 
-#ifndef TIMELINEVIEW_H
-#define TIMELINEVIEW_H
+#ifndef TIMELINERENDERER_H
+#define TIMELINERENDERER_H
 
 #include <QDeclarativeItem>
 #include <QScriptValue>
-#include <qmljsdebugclient/qmlprofilereventlist.h>
+#include "qmlprofilerdatamodel.h"
 
 namespace QmlProfiler {
 namespace Internal {
 
-class TimelineView : public QDeclarativeItem
+class TimelineRenderer : public QDeclarativeItem
 {
     Q_OBJECT
     Q_PROPERTY(qint64 startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
     Q_PROPERTY(qint64 endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged)
-    Q_PROPERTY(QObject* eventList READ eventList WRITE setEventList NOTIFY eventListChanged)
+    Q_PROPERTY(QObject* profilerDataModel READ profilerDataModel WRITE setProfilerDataModel NOTIFY profilerDataModelChanged)
     Q_PROPERTY(bool selectionLocked READ selectionLocked WRITE setSelectionLocked NOTIFY selectionLockedChanged)
     Q_PROPERTY(int selectedItem READ selectedItem WRITE setSelectedItem NOTIFY selectedItemChanged)
     Q_PROPERTY(int startDragArea READ startDragArea WRITE setStartDragArea NOTIFY startDragAreaChanged)
     Q_PROPERTY(int endDragArea READ endDragArea WRITE setEndDragArea NOTIFY endDragAreaChanged)
 
 public:
-    explicit TimelineView(QDeclarativeItem *parent = 0);
+    explicit TimelineRenderer(QDeclarativeItem *parent = 0);
 
     qint64 startTime() const
     {
@@ -84,11 +84,11 @@ public:
         return m_endDragArea;
     }
 
-    QmlJsDebugClient::QmlProfilerEventList *eventList() const { return m_eventList; }
-    void setEventList(QObject *eventList)
+    QmlProfilerDataModel *profilerDataModel() const { return m_profilerDataModel; }
+    void setProfilerDataModel(QObject *profilerDataModel)
     {
-        m_eventList = qobject_cast<QmlJsDebugClient::QmlProfilerEventList *>(eventList);
-        emit eventListChanged(m_eventList);
+        m_profilerDataModel = qobject_cast<QmlProfilerDataModel *>(profilerDataModel);
+        emit profilerDataModelChanged(m_profilerDataModel);
     }
 
     Q_INVOKABLE qint64 getDuration(int index) const;
@@ -109,7 +109,7 @@ public:
 signals:
     void startTimeChanged(qint64 arg);
     void endTimeChanged(qint64 arg);
-    void eventListChanged(QmlJsDebugClient::QmlProfilerEventList *list);
+    void profilerDataModelChanged(QmlProfilerDataModel *list);
     void selectionLockedChanged(bool locked);
     void selectedItemChanged(int itemIndex);
     void startDragAreaChanged(int startDragArea);
@@ -195,7 +195,7 @@ private:
     qint64 m_lastStartTime;
     qint64 m_lastEndTime;
 
-    QmlJsDebugClient::QmlProfilerEventList *m_eventList;
+    QmlProfilerDataModel *m_profilerDataModel;
 
     QList<int> m_rowLastX;
     QList<int> m_rowStarts;
@@ -218,6 +218,6 @@ private:
 } // namespace Internal
 } // namespace QmlProfiler
 
-QML_DECLARE_TYPE(QmlProfiler::Internal::TimelineView)
+QML_DECLARE_TYPE(QmlProfiler::Internal::TimelineRenderer)
 
-#endif // TIMELINEVIEW_H
+#endif // TIMELINERENDERER_H
diff --git a/src/plugins/qmlprofiler/tracewindow.cpp b/src/plugins/qmlprofiler/tracewindow.cpp
deleted file mode 100644
index 6a4f3817fb4bbac5b0e3fba0946954ef25102abb..0000000000000000000000000000000000000000
--- a/src/plugins/qmlprofiler/tracewindow.cpp
+++ /dev/null
@@ -1,649 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-**
-** GNU Lesser General Public License Usage
-**
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this file.
-** Please review the following information to ensure the GNU Lesser General
-** Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**************************************************************************/
-
-#include "tracewindow.h"
-
-#include "qmlprofilerplugin.h"
-
-#include <qmljsdebugclient/qmlprofilereventlist.h>
-#include <qmljsdebugclient/qmlprofilertraceclient.h>
-#include <utils/styledbar.h>
-
-#include <QDeclarativeView>
-#include <QDeclarativeContext>
-#include <QVBoxLayout>
-#include <QGraphicsObject>
-#include <QContextMenuEvent>
-#include <QScrollBar>
-#include <QSlider>
-#include <QWidget>
-
-#include <math.h>
-
-using namespace QmlJsDebugClient;
-
-namespace QmlProfiler {
-namespace Internal {
-
-const int sliderTicks = 10000;
-const qreal sliderExp = 3;
-
-void ZoomControl::setRange(qint64 startTime, qint64 endTime)
-{
-    if (m_startTime != startTime || m_endTime != endTime) {
-        m_startTime = startTime;
-        m_endTime = endTime;
-        emit rangeChanged();
-    }
-}
-
-ScrollableDeclarativeView::ScrollableDeclarativeView(QWidget *parent)
-    : QDeclarativeView(parent)
-{
-}
-
-ScrollableDeclarativeView::~ScrollableDeclarativeView()
-{
-}
-
-void ScrollableDeclarativeView::scrollContentsBy(int dx, int dy)
-{
-    // special workaround to track the scrollbar
-    if (rootObject()) {
-        int scrollY = rootObject()->property("scrollY").toInt();
-        rootObject()->setProperty("scrollY", QVariant(scrollY - dy));
-    }
-    QDeclarativeView::scrollContentsBy(dx,dy);
-}
-
-TraceWindow::TraceWindow(QWidget *parent)
-    : QWidget(parent)
-{
-    setObjectName("QML Profiler");
-
-    m_zoomControl = new ZoomControl(this);
-    connect(m_zoomControl.data(), SIGNAL(rangeChanged()), this, SLOT(updateRange()));
-
-    QVBoxLayout *groupLayout = new QVBoxLayout;
-    groupLayout->setContentsMargins(0, 0, 0, 0);
-    groupLayout->setSpacing(0);
-
-    m_mainView = new ScrollableDeclarativeView(this);
-    m_mainView->setResizeMode(QDeclarativeView::SizeViewToRootObject);
-    m_mainView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
-    m_mainView->setBackgroundBrush(QBrush(Qt::white));
-    m_mainView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
-    m_mainView->setFocus();
-
-    MouseWheelResizer *resizer = new MouseWheelResizer(this);
-    connect(resizer,SIGNAL(mouseWheelMoved(int,int,int)), this, SLOT(mouseWheelMoved(int,int,int)));
-    m_mainView->viewport()->installEventFilter(resizer);
-
-    QHBoxLayout *toolsLayout = new QHBoxLayout;
-
-    m_timebar = new QDeclarativeView(this);
-    m_timebar->setResizeMode(QDeclarativeView::SizeRootObjectToView);
-    m_timebar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
-    m_timebar->setFixedHeight(24);
-
-    m_overview = new QDeclarativeView(this);
-    m_overview->setResizeMode(QDeclarativeView::SizeRootObjectToView);
-    m_overview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
-    m_overview->setMaximumHeight(50);
-
-    m_zoomToolbar = createZoomToolbar();
-    m_zoomToolbar->move(0, m_timebar->height());
-    m_zoomToolbar->setVisible(false);
-
-    toolsLayout->addWidget(createToolbar());
-    toolsLayout->addWidget(m_timebar);
-
-    groupLayout->addLayout(toolsLayout);
-    groupLayout->addWidget(m_mainView);
-    groupLayout->addWidget(m_overview);
-
-    setLayout(groupLayout);
-
-    m_eventList = new QmlProfilerEventList(this);
-    connect(this,SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)), m_eventList, SLOT(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
-    connect(this, SIGNAL(traceFinished(qint64)), m_eventList, SLOT(setTraceEndTime(qint64)));
-    connect(this, SIGNAL(traceStarted(qint64)), m_eventList, SLOT(setTraceStartTime(qint64)));
-    connect(this, SIGNAL(frameEvent(qint64,int,int)), m_eventList, SLOT(addFrameEvent(qint64,int,int)));
-    connect(m_eventList, SIGNAL(stateChanged()), this, SLOT(eventListStateChanged()));
-    m_mainView->rootContext()->setContextProperty("qmlEventList", m_eventList);
-    m_overview->rootContext()->setContextProperty("qmlEventList", m_eventList);
-
-    m_rewriter = new QmlProfilerDetailsRewriter(this);
-    connect(m_eventList, SIGNAL(requestDetailsForLocation(int,QmlJsDebugClient::QmlEventLocation)), m_rewriter, SLOT(requestDetailsForLocation(int,QmlJsDebugClient::QmlEventLocation)));
-    connect(m_rewriter, SIGNAL(rewriteDetailsString(int,QmlJsDebugClient::QmlEventLocation,QString)), m_eventList, SLOT(rewriteDetailsString(int,QmlJsDebugClient::QmlEventLocation,QString)));
-    connect(m_rewriter, SIGNAL(eventDetailsChanged()), m_eventList, SLOT(finishedRewritingDetails()));
-    connect(m_eventList, SIGNAL(reloadDocumentsForDetails()), m_rewriter, SLOT(reloadDocuments()));
-
-    connect(this, SIGNAL(v8range(int,QString,QString,int,double,double)), m_eventList, SLOT(addV8Event(int,QString,QString,int,double,double)));
-
-    // Minimum height: 5 rows of 20 pixels + scrollbar of 50 pixels + 20 pixels margin
-    setMinimumHeight(170);
-    m_currentZoomLevel = 0;
-    m_profiledTime = 0;
-}
-
-TraceWindow::~TraceWindow()
-{
-    disconnectClientSignals();
-    delete m_plugin.data();
-    delete m_v8plugin.data();
-}
-
-QWidget *TraceWindow::createToolbar()
-{
-    Utils::StyledBar *bar = new Utils::StyledBar(this);
-    bar->setSingleRow(true);
-    bar->setFixedWidth(150);
-    bar->setFixedHeight(24);
-
-    QHBoxLayout *toolBarLayout = new QHBoxLayout(bar);
-    toolBarLayout->setMargin(0);
-    toolBarLayout->setSpacing(0);
-
-    QToolButton *buttonPrev= new QToolButton;
-    buttonPrev->setIcon(QIcon(":/qmlprofiler/ico_prev.png"));
-    buttonPrev->setToolTip(tr("Jump to previous event"));
-    connect(buttonPrev, SIGNAL(clicked()), this, SIGNAL(jumpToPrev()));
-    connect(this, SIGNAL(enableToolbar(bool)), buttonPrev, SLOT(setEnabled(bool)));
-
-    QToolButton *buttonNext= new QToolButton;
-    buttonNext->setIcon(QIcon(":/qmlprofiler/ico_next.png"));
-    buttonNext->setToolTip(tr("Jump to next event"));
-    connect(buttonNext, SIGNAL(clicked()), this, SIGNAL(jumpToNext()));
-    connect(this, SIGNAL(enableToolbar(bool)), buttonNext, SLOT(setEnabled(bool)));
-
-    QToolButton *buttonZoomControls = new QToolButton;
-    buttonZoomControls->setIcon(QIcon(":/qmlprofiler/ico_zoom.png"));
-    buttonZoomControls->setToolTip(tr("Show zoom slider"));
-    buttonZoomControls->setCheckable(true);
-    buttonZoomControls->setChecked(false);
-    connect(buttonZoomControls, SIGNAL(toggled(bool)), m_zoomToolbar, SLOT(setVisible(bool)));
-    connect(this, SIGNAL(enableToolbar(bool)), buttonZoomControls, SLOT(setEnabled(bool)));
-
-    m_buttonRange = new QToolButton;
-    m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png"));
-    m_buttonRange->setToolTip(tr("Select range"));
-    m_buttonRange->setCheckable(true);
-    m_buttonRange->setChecked(false);
-    connect(m_buttonRange, SIGNAL(clicked(bool)), this, SLOT(toggleRangeMode(bool)));
-    connect(this, SIGNAL(enableToolbar(bool)), m_buttonRange, SLOT(setEnabled(bool)));
-    connect(this, SIGNAL(rangeModeChanged(bool)), m_buttonRange, SLOT(setChecked(bool)));
-
-    m_buttonLock = new QToolButton;
-    m_buttonLock->setIcon(QIcon(":/qmlprofiler/ico_selectionmode.png"));
-    m_buttonLock->setToolTip(tr("View event information on mouseover"));
-    m_buttonLock->setCheckable(true);
-    m_buttonLock->setChecked(false);
-    connect(m_buttonLock, SIGNAL(clicked(bool)), this, SLOT(toggleLockMode(bool)));
-    connect(this, SIGNAL(enableToolbar(bool)), m_buttonLock, SLOT(setEnabled(bool)));
-    connect(this, SIGNAL(lockModeChanged(bool)), m_buttonLock, SLOT(setChecked(bool)));
-
-    toolBarLayout->addWidget(buttonPrev);
-    toolBarLayout->addWidget(buttonNext);
-    toolBarLayout->addWidget(new Utils::StyledSeparator());
-    toolBarLayout->addWidget(buttonZoomControls);
-    toolBarLayout->addWidget(new Utils::StyledSeparator());
-    toolBarLayout->addWidget(m_buttonRange);
-    toolBarLayout->addWidget(m_buttonLock);
-
-    return bar;
-}
-
-
-QWidget *TraceWindow::createZoomToolbar()
-{
-    Utils::StyledBar *bar = new Utils::StyledBar(this);
-    bar->setSingleRow(true);
-    bar->setFixedWidth(150);
-    bar->setFixedHeight(24);
-
-    QHBoxLayout *toolBarLayout = new QHBoxLayout(bar);
-    toolBarLayout->setMargin(0);
-    toolBarLayout->setSpacing(0);
-
-    QSlider *zoomSlider = new QSlider(Qt::Horizontal);
-    zoomSlider->setFocusPolicy(Qt::NoFocus);
-    zoomSlider->setRange(1, sliderTicks);
-    zoomSlider->setInvertedAppearance(true);
-    zoomSlider->setPageStep(sliderTicks/100);
-    connect(this, SIGNAL(enableToolbar(bool)), zoomSlider, SLOT(setEnabled(bool)));
-    connect(zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setZoomLevel(int)));
-    connect(this, SIGNAL(zoomLevelChanged(int)), zoomSlider, SLOT(setValue(int)));
-    zoomSlider->setStyleSheet("\
-        QSlider:horizontal {\
-            background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #444444, stop: 1 #5a5a5a);\
-            border: 1px #313131;\
-            height: 20px;\
-            margin: 0px 0px 0px 0px;\
-        }\
-        QSlider::add-page:horizontal {\
-            background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\
-            border: 1px #313131;\
-        }\
-        QSlider::sub-page:horizontal {\
-            background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\
-            border: 1px #313131;\
-        }\
-        ");
-
-    toolBarLayout->addWidget(zoomSlider);
-
-    return bar;
-}
-
-void TraceWindow::reset(QDeclarativeDebugConnection *conn)
-{
-    disconnectClientSignals();
-
-    delete m_plugin.data();
-    m_plugin = new QmlProfilerTraceClient(conn);
-    delete m_v8plugin.data();
-    m_v8plugin = new QV8ProfilerClient(conn);
-
-    connectClientSignals();
-
-    m_mainView->rootContext()->setContextProperty("connection", m_plugin.data());
-    m_mainView->rootContext()->setContextProperty("zoomControl", m_zoomControl.data());
-    m_timebar->rootContext()->setContextProperty("zoomControl", m_zoomControl.data());
-    m_overview->rootContext()->setContextProperty("zoomControl", m_zoomControl.data());
-
-    m_timebar->setSource(QUrl("qrc:/qmlprofiler/TimeDisplay.qml"));
-    m_overview->setSource(QUrl("qrc:/qmlprofiler/Overview.qml"));
-
-    m_mainView->setSource(QUrl("qrc:/qmlprofiler/MainView.qml"));
-    m_mainView->rootObject()->setProperty("width", QVariant(width()));
-    m_mainView->rootObject()->setProperty("candidateHeight", QVariant(height() - m_timebar->height() - m_overview->height()));
-
-    updateToolbar();
-
-    connect(m_mainView->rootObject(), SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition()));
-    connect(m_mainView->rootObject(), SIGNAL(updateTimer()), this, SLOT(updateTimer()));
-    connect(m_mainView->rootObject(), SIGNAL(updateRangeButton()), this, SLOT(updateRangeButton()));
-    connect(m_mainView->rootObject(), SIGNAL(updateLockButton()), this, SLOT(updateLockButton()));
-    connect(m_eventList, SIGNAL(countChanged()), this, SLOT(updateToolbar()));
-    connect(this, SIGNAL(jumpToPrev()), m_mainView->rootObject(), SLOT(prevEvent()));
-    connect(this, SIGNAL(jumpToNext()), m_mainView->rootObject(), SLOT(nextEvent()));
-    connect(this, SIGNAL(updateViewZoom(QVariant)), m_mainView->rootObject(), SLOT(updateWindowLength(QVariant)));
-    connect(this, SIGNAL(wheelZoom(QVariant,QVariant)), m_mainView->rootObject(), SLOT(wheelZoom(QVariant,QVariant)));
-    connect(this, SIGNAL(globalZoom()), m_mainView->rootObject(), SLOT(globalZoom()));
-    connect(this, SIGNAL(selectNextEventInDisplay(QVariant)), m_mainView->rootObject(), SLOT(selectNextWithId(QVariant)));
-    connect(m_mainView->rootObject(), SIGNAL(selectedEventIdChanged(int)), this, SIGNAL(selectedEventIdChanged(int)));
-    connect(m_mainView->rootObject(), SIGNAL(changeToolTip(QString)), this, SLOT(updateToolTip(QString)));
-    connect(m_mainView->rootObject(), SIGNAL(updateVerticalScroll(int)), this, SLOT(updateVerticalScroll(int)));
-
-    connect(this, SIGNAL(internalClearDisplay()), m_mainView->rootObject(), SLOT(clearAll()));
-    connect(this,SIGNAL(internalClearDisplay()), m_overview->rootObject(), SLOT(clearDisplay()));
-
-    m_v8DataReady = false;
-    m_qmlDataReady = false;
-}
-
-void TraceWindow::connectClientSignals()
-{
-    if (m_plugin) {
-        connect(m_plugin.data(), SIGNAL(complete()), this, SLOT(qmlComplete()));
-        connect(m_plugin.data(), SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)),
-                this, SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
-        connect(m_plugin.data(), SIGNAL(traceFinished(qint64)), this, SIGNAL(traceFinished(qint64)));
-        connect(m_plugin.data(), SIGNAL(traceStarted(qint64)), this, SLOT(manageTraceStart(qint64)));
-        connect(m_plugin.data(), SIGNAL(frame(qint64,int,int)), this, SIGNAL(frameEvent(qint64,int,int)));
-        connect(m_plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState()));
-        connect(m_plugin.data(), SIGNAL(enabledChanged()), m_plugin.data(), SLOT(sendRecordingStatus()));
-        connect(m_plugin.data(), SIGNAL(recordingChanged(bool)), this, SIGNAL(recordingChanged(bool)));
-    }
-    if (m_v8plugin) {
-        connect(m_v8plugin.data(), SIGNAL(complete()), this, SLOT(v8Complete()));
-        connect(m_v8plugin.data(), SIGNAL(v8range(int,QString,QString,int,double,double)), this, SIGNAL(v8range(int,QString,QString,int,double,double)));
-        connect(m_v8plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState()));
-        connect(m_v8plugin.data(), SIGNAL(enabledChanged()), m_v8plugin.data(), SLOT(sendRecordingStatus()));
-    }
-}
-
-void TraceWindow::disconnectClientSignals()
-{
-    if (m_plugin) {
-        disconnect(m_plugin.data(), SIGNAL(complete()), this, SLOT(qmlComplete()));
-        disconnect(m_plugin.data(), SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)),
-                this, SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
-        disconnect(m_plugin.data(), SIGNAL(traceFinished(qint64)), this, SIGNAL(traceFinished(qint64)));
-        disconnect(m_plugin.data(), SIGNAL(traceStarted(qint64)), this, SLOT(manageTraceStart(qint64)));
-        disconnect(m_plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState()));
-        disconnect(m_plugin.data(), SIGNAL(enabledChanged()), m_plugin.data(), SLOT(sendRecordingStatus()));
-        disconnect(m_plugin.data(), SIGNAL(recordingChanged(bool)), this, SIGNAL(recordingChanged(bool)));
-    }
-    if (m_v8plugin) {
-        disconnect(m_v8plugin.data(), SIGNAL(complete()), this, SLOT(v8Complete()));
-        disconnect(m_v8plugin.data(), SIGNAL(v8range(int,QString,QString,int,double,double)), this, SIGNAL(v8range(int,QString,QString,int,double,double)));
-        disconnect(m_v8plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState()));
-        disconnect(m_v8plugin.data(), SIGNAL(enabledChanged()), m_v8plugin.data(), SLOT(sendRecordingStatus()));
-    }
-}
-
-QmlProfilerEventList *TraceWindow::getEventList() const
-{
-    return m_eventList;
-}
-
-ZoomControl *TraceWindow::rangeTimes() const
-{
-    return m_zoomControl.data();
-}
-
-void TraceWindow::contextMenuEvent(QContextMenuEvent *ev)
-{
-    emit contextMenuRequested(ev->globalPos());
-}
-
-void TraceWindow::updateCursorPosition()
-{
-    emit gotoSourceLocation(m_mainView->rootObject()->property("fileName").toString(),
-                            m_mainView->rootObject()->property("lineNumber").toInt(),
-                            m_mainView->rootObject()->property("columnNumber").toInt());
-}
-
-void TraceWindow::updateTimer()
-{
-    m_profiledTime = m_mainView->rootObject()->property("elapsedTime").toDouble();
-}
-
-void TraceWindow::correctTimer()
-{
-    // once the data is post-processed, use the eventlist time instead of the qml timer
-    m_profiledTime = (m_eventList->traceEndTime() - m_eventList->traceStartTime()) / 1.0e9;
-    if (m_profiledTime < 0)
-        m_profiledTime = 0;
-    emit viewUpdated();
-}
-
-double TraceWindow::profiledTime() const
-{
-    return m_profiledTime;
-}
-
-void TraceWindow::clearDisplay()
-{
-    m_eventList->clear();
-
-    if (m_plugin)
-        m_plugin.data()->clearData();
-    if (m_v8plugin)
-        m_v8plugin.data()->clearData();
-
-    m_zoomControl.data()->setRange(0,0);
-    m_profiledTime = 0;
-
-    updateVerticalScroll(0);
-    m_mainView->rootObject()->setProperty("scrollY", QVariant(0));
-
-    emit internalClearDisplay();
-}
-
-void TraceWindow::updateToolbar()
-{
-    emit enableToolbar(m_eventList && m_eventList->count()>0);
-}
-
-void TraceWindow::toggleRangeMode(bool active)
-{
-    bool rangeMode = m_mainView->rootObject()->property("selectionRangeMode").toBool();
-    if (active != rangeMode) {
-        if (active)
-            m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselected.png"));
-        else
-            m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png"));
-        m_mainView->rootObject()->setProperty("selectionRangeMode", QVariant(active));
-    }
-}
-
-void TraceWindow::updateRangeButton()
-{
-    bool rangeMode = m_mainView->rootObject()->property("selectionRangeMode").toBool();
-    if (rangeMode)
-        m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselected.png"));
-    else
-        m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png"));
-    emit rangeModeChanged(rangeMode);
-}
-
-void TraceWindow::toggleLockMode(bool active)
-{
-    bool lockMode = !m_mainView->rootObject()->property("selectionLocked").toBool();
-    if (active != lockMode) {
-        m_mainView->rootObject()->setProperty("selectionLocked", QVariant(!active));
-        m_mainView->rootObject()->setProperty("selectedItem", QVariant(-1));
-    }
-}
-
-void TraceWindow::updateLockButton()
-{
-    bool lockMode = !m_mainView->rootObject()->property("selectionLocked").toBool();
-    emit lockModeChanged(lockMode);
-}
-
-void TraceWindow::setRecording(bool recording)
-{
-    if (recording) {
-        m_v8DataReady = false;
-        m_qmlDataReady = false;
-    }
-    if (m_plugin)
-        m_plugin.data()->setRecording(recording);
-    if (m_v8plugin)
-        m_v8plugin.data()->setRecording(recording);
-}
-
-bool TraceWindow::isRecording() const
-{
-    return m_plugin.data()->isRecording();
-}
-
-void TraceWindow::qmlComplete()
-{
-    m_qmlDataReady = true;
-    if (!m_v8plugin || m_v8plugin.data()->status() != QDeclarativeDebugClient::Enabled || m_v8DataReady) {
-        m_eventList->complete();
-        // once complete is sent, reset the flags
-        m_qmlDataReady = false;
-        m_v8DataReady = false;
-    }
-}
-
-void TraceWindow::v8Complete()
-{
-    m_v8DataReady = true;
-    if (!m_plugin || m_plugin.data()->status() != QDeclarativeDebugClient::Enabled || m_qmlDataReady) {
-        m_eventList->complete();
-        // once complete is sent, reset the flags
-        m_v8DataReady = false;
-        m_qmlDataReady = false;
-    }
-}
-
-void TraceWindow::resizeEvent(QResizeEvent *event)
-{
-    if (m_mainView->rootObject()) {
-        m_mainView->rootObject()->setProperty("width", QVariant(event->size().width()));
-        int newHeight = event->size().height() - m_timebar->height() - m_overview->height();
-        m_mainView->rootObject()->setProperty("candidateHeight", QVariant(newHeight));
-    }
-}
-
-bool MouseWheelResizer::eventFilter(QObject *obj, QEvent *event)
-{
-    if (event->type() == QEvent::Wheel) {
-        QWheelEvent *ev = static_cast<QWheelEvent *>(event);
-        if (ev->modifiers() & Qt::ControlModifier) {
-            emit mouseWheelMoved(ev->pos().x(), ev->pos().y(), ev->delta());
-            return true;
-        }
-    }
-    return QObject::eventFilter(obj, event);
-}
-
-void TraceWindow::mouseWheelMoved(int x, int y, int delta)
-{
-    Q_UNUSED(y);
-    if (m_mainView->rootObject()) {
-        emit wheelZoom(QVariant(x), QVariant(delta));
-    }
-}
-
-void TraceWindow::viewAll()
-{
-    emit globalZoom();
-}
-
-bool TraceWindow::hasValidSelection() const
-{
-    if (m_mainView->rootObject()) {
-        return m_mainView->rootObject()->property("selectionRangeReady").toBool();
-    }
-    return false;
-}
-
-qint64 TraceWindow::selectionStart() const
-{
-    if (m_mainView->rootObject()) {
-        return m_mainView->rootObject()->property("selectionRangeStart").toLongLong();
-    }
-    return 0;
-}
-
-qint64 TraceWindow::selectionEnd() const
-{
-    if (m_mainView->rootObject()) {
-        return m_mainView->rootObject()->property("selectionRangeEnd").toLongLong();
-    }
-    return 0;
-}
-
-void TraceWindow::setZoomLevel(int zoomLevel)
-{
-    if (m_currentZoomLevel != zoomLevel && m_mainView->rootObject()) {
-        qreal newFactor = pow(qreal(zoomLevel) / qreal(sliderTicks), sliderExp);
-        m_currentZoomLevel = zoomLevel;
-        emit updateViewZoom(QVariant(newFactor));
-    }
-}
-
-void TraceWindow::updateRange()
-{
-    if (!m_eventList)
-        return;
-    qreal duration = m_zoomControl.data()->endTime() - m_zoomControl.data()->startTime();
-    if (duration <= 0)
-        return;
-    if (m_eventList->traceDuration() <= 0)
-        return;
-    int newLevel = pow(duration / m_eventList->traceDuration(), 1/sliderExp) * sliderTicks;
-    if (m_currentZoomLevel != newLevel) {
-        m_currentZoomLevel = newLevel;
-        emit zoomLevelChanged(newLevel);
-    }
-}
-
-void TraceWindow::selectNextEvent(int eventId)
-{
-    emit selectNextEventInDisplay(QVariant(eventId));
-}
-
-void TraceWindow::updateProfilerState()
-{
-    bool qmlActive = false;
-    bool v8Active = false;
-    if (m_plugin)
-        qmlActive = m_plugin.data()->isEnabled();
-    if (m_v8plugin)
-        v8Active = m_v8plugin.data()->isEnabled();
-
-    emit profilerStateChanged(qmlActive, v8Active);
-}
-
-void TraceWindow::updateToolTip(const QString &text)
-{
-    setToolTip(text);
-}
-
-void TraceWindow::updateVerticalScroll(int newPosition)
-{
-    m_mainView->verticalScrollBar()->setValue(newPosition);
-}
-
-void TraceWindow::eventListStateChanged()
-{
-    switch (m_eventList->currentState()) {
-    case QmlProfilerEventList::Empty :
-        clearDisplay();
-        break;
-    case QmlProfilerEventList::AcquiringData :
-        firstDataReceived();
-        break;
-    case QmlProfilerEventList::ProcessingData :
-        // nothing to be done
-        break;
-    case QmlProfilerEventList::Done :
-        correctTimer();
-    break;
-    default:
-        break;
-    }
-}
-
-void TraceWindow::manageTraceStart(qint64 traceStart)
-{
-    // new trace started
-    emit clearViewsFromTool();
-
-    emit traceStarted(traceStart);
-}
-
-void TraceWindow::firstDataReceived()
-{
-    if (m_plugin && m_plugin.data()->isRecording()) {
-        // serverside recording disabled
-        m_plugin.data()->setRecordingFromServer(false);
-    }
-}
-
-void TraceWindow::applicationDied()
-{
-    if (m_mainView->rootObject())
-        m_mainView->rootObject()->setProperty("applicationDied",QVariant(true));
-}
-
-} // namespace Internal
-} // namespace QmlProfiler
diff --git a/src/tools/qmlprofilertool/commandlistener.cpp b/src/tools/qmlprofilertool/commandlistener.cpp
deleted file mode 100644
index 57754a6dd00d654a5d161a8efe50f2b5c33b809b..0000000000000000000000000000000000000000
--- a/src/tools/qmlprofilertool/commandlistener.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-**
-** GNU Lesser General Public License Usage
-**
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this file.
-** Please review the following information to ensure the GNU Lesser General
-** Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**************************************************************************/
-
-#include "commandlistener.h"
-#include "constants.h"
-#include <QTextStream>
-
-CommandListener::CommandListener(QObject *parent)
-    : QThread(parent)
-    , m_stopRequested(false)
-{
-}
-
-void CommandListener::run()
-{
-    QString line;
-    QTextStream in(stdin, QIODevice::ReadOnly);
-    do {
-        line = in.readLine();
-        line = line.trimmed();
-        if (!line.isEmpty()) {
-            emit command(line);
-            if (line == QLatin1String(Constants::CMD_QUIT)
-                    || line == QLatin1String(Constants::CMD_QUIT2))
-                return;
-        }
-    } while (!m_stopRequested && !line.isNull());
-}
diff --git a/src/tools/qmlprofilertool/constants.h b/src/tools/qmlprofilertool/constants.h
deleted file mode 100644
index 24d2702751cd811bf445c74f9a711e7a744ac1e0..0000000000000000000000000000000000000000
--- a/src/tools/qmlprofilertool/constants.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-**
-** GNU Lesser General Public License Usage
-**
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this file.
-** Please review the following information to ensure the GNU Lesser General
-** Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**************************************************************************/
-
-#ifndef CONSTANTS_H
-#define CONSTANTS_H
-
-namespace Constants {
-
-const char CMD_HELP[] ="help";
-const char CMD_HELP2[] = "h";
-const char CMD_HELP3[] = "?";
-
-const char CMD_RECORD[] ="record";
-const char CMD_RECORD2[] ="r";
-
-const char CMD_QUIT[] ="quit";
-const char CMD_QUIT2[] = "q";
-
-} // Contants
-
-#endif // CONSTANTS_H
diff --git a/src/tools/qmlprofilertool/qmlprofilerapplication.h b/src/tools/qmlprofilertool/qmlprofilerapplication.h
deleted file mode 100644
index 9414895631fd77b99e9041860dbad581446670b0..0000000000000000000000000000000000000000
--- a/src/tools/qmlprofilertool/qmlprofilerapplication.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-**
-** GNU Lesser General Public License Usage
-**
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this file.
-** Please review the following information to ensure the GNU Lesser General
-** Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**************************************************************************/
-
-#ifndef QMLPROFILERAPPLICATION_H
-#define QMLPROFILERAPPLICATION_H
-
-#include <QCoreApplication>
-#include <QStringList>
-#include <QTimer>
-
-#include <qdeclarativedebugclient.h>
-#include <qmlprofilertraceclient.h>
-#include <qmlprofilereventlist.h>
-#include <qv8profilerclient.h>
-
-QT_FORWARD_DECLARE_CLASS(QProcess)
-
-class QmlProfilerApplication : public QCoreApplication
-{
-    Q_OBJECT
-public:
-    QmlProfilerApplication(int &argc, char **argv);
-    ~QmlProfilerApplication();
-
-    bool parseArguments();
-    void printUsage();
-    int exec();
-
-public slots:
-    void userCommand(const QString &command);
-
-private slots:
-    void run();
-    void tryToConnect();
-    void connected();
-    void connectionStateChanged(QAbstractSocket::SocketState state);
-    void connectionError(QAbstractSocket::SocketError error);
-    void processHasOutput();
-    void processFinished();
-
-    void traceClientEnabled();
-    void profilerClientEnabled();
-    void traceFinished();
-    void recordingChanged();
-
-    void print(const QString &line);
-    void logError(const QString &error);
-    void logStatus(const QString &status);
-
-    void qmlComplete();
-    void v8Complete();
-
-private:
-    void printCommands();
-    QString traceFileName() const;
-
-    enum ApplicationMode {
-        LaunchMode,
-        AttachMode
-    } m_runMode;
-
-    // LaunchMode
-    QString m_programPath;
-    QStringList m_programArguments;
-    QProcess *m_process;
-    QString m_tracePrefix;
-
-    QString m_hostName;
-    quint16 m_port;
-    bool m_verbose;
-    bool m_quitAfterSave;
-
-    QmlJsDebugClient::QDeclarativeDebugConnection m_connection;
-    QmlJsDebugClient::QmlProfilerTraceClient m_qmlProfilerClient;
-    QmlJsDebugClient::QV8ProfilerClient m_v8profilerClient;
-    QmlJsDebugClient::QmlProfilerEventList m_eventList;
-    QTimer m_connectTimer;
-    uint m_connectionAttempts;
-
-    bool m_qmlDataReady;
-    bool m_v8DataReady;
-};
-
-#endif // QMLPROFILERAPPLICATION_H
diff --git a/src/tools/qmlprofilertool/qmlprofilertool.pro b/src/tools/qmlprofilertool/qmlprofilertool.pro
deleted file mode 100644
index ca582eeb768e5e12fa9b3389c81150914327835e..0000000000000000000000000000000000000000
--- a/src/tools/qmlprofilertool/qmlprofilertool.pro
+++ /dev/null
@@ -1,28 +0,0 @@
-QT       = core
-include(../../../qtcreator.pri)
-include(../../rpath.pri)
-
-TEMPLATE = app
-TARGET   = qmlprofiler
-DESTDIR = $$IDE_BIN_PATH
-
-CONFIG   += console
-CONFIG   -= app_bundle
-
-include(../../shared/symbianutils/symbianutils.pri)
-include(../../libs/qmljsdebugclient/qmljsdebugclient-lib.pri)
-
-INCLUDEPATH += ../../libs/qmljsdebugclient
-
-SOURCES += main.cpp \
-    qmlprofilerapplication.cpp \
-    commandlistener.cpp
-
-HEADERS += \
-    qmlprofilerapplication.h \
-    commandlistener.h \
-    constants.h
-
-target.path=/bin
-INSTALLS+=target
-
diff --git a/src/tools/tools.pro b/src/tools/tools.pro
index bd5bac6c8f042997e896a7d282aa8569d1d9e291..b6b159f591d850cd632d32adb4382430e2ede949 100644
--- a/src/tools/tools.pro
+++ b/src/tools/tools.pro
@@ -1,7 +1,6 @@
 TEMPLATE = subdirs
 
 SUBDIRS = qtpromaker \
-    qmlprofilertool \
      qmlpuppet
 
 win32 {