diff --git a/src/plugins/debugger/qml/canvasframerate.cpp b/src/plugins/debugger/qml/canvasframerate.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5cbf1d690ddb88244b2951186db4ac7b332f1f2c
--- /dev/null
+++ b/src/plugins/debugger/qml/canvasframerate.cpp
@@ -0,0 +1,569 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+#include "canvasframerate.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qmargins.h>
+
+#include <QtGui/qapplication.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qtooltip.h>
+#include <QtGui/qslider.h>
+#include <QtGui/qscrollbar.h>
+#include <QtGui/qspinbox.h>
+#include <QtGui/qgroupbox.h>
+#include <QtGui/qboxlayout.h>
+#include <QtGui/qlabel.h>
+#include <QtGui/qlineedit.h>
+#include <QtGui/qpushbutton.h>
+#include <QtGui/qtabwidget.h>
+#include <QtGui/qevent.h>
+
+
+namespace Debugger {
+namespace Internal {
+
+class QLineGraph : public QWidget
+{
+Q_OBJECT
+public:
+    QLineGraph(QAbstractSlider *slider, QWidget * = 0);
+
+    void setPosition(int);
+
+public slots:
+    void addSample(int, int, int, bool);
+    void setResolutionForHeight(int);
+    void clear();
+
+protected:
+    virtual void paintEvent(QPaintEvent *);
+    virtual void mouseMoveEvent(QMouseEvent *);
+    virtual void leaveEvent(QEvent *);
+    virtual void wheelEvent(QWheelEvent *event);
+
+private slots:
+    void sliderChanged(int);
+
+private:
+    void updateSlider();
+    void drawSample(QPainter *, int, const QRect &, QList<QRect> *);
+    void drawTime(QPainter *, const QRect &);
+    QRect findContainingRect(const QList<QRect> &rects, const QPoint &pos) const;
+    struct Sample {
+        int sample[3];
+        bool isBreak;
+    };
+    QList<Sample> _samples;
+
+    QAbstractSlider *slider;
+    int position;
+    int samplesPerWidth;
+    int resolutionForHeight;
+    bool ignoreScroll;
+    QMargins graphMargins;
+
+    QList<QRect> rectsPaintTime;    // time to do a paintEvent()
+    QList<QRect> rectsTimeBetween;  // time between frames
+    QRect highlightedBar;
+};
+
+QLineGraph::QLineGraph(QAbstractSlider *slider, QWidget *parent)
+: QWidget(parent), slider(slider), position(-1), samplesPerWidth(99), resolutionForHeight(50),
+  ignoreScroll(false), graphMargins(65, 10, 71, 35)
+{
+    setMouseTracking(true);
+
+    slider->setMaximum(0);
+    slider->setMinimum(0);
+    slider->setSingleStep(1);
+
+    connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderChanged(int)));
+}
+
+void QLineGraph::sliderChanged(int v)
+{
+    if (ignoreScroll)
+        return;
+
+    if (v == slider->maximum())
+        position = -1;
+    else
+        position = v;
+
+    update();
+
+    // update highlightedRect
+    QPoint pos = mapFromGlobal(QCursor::pos());
+    if (geometry().contains(pos)) {
+        QMouseEvent *me = new QMouseEvent(QEvent::MouseMove, pos,
+                Qt::NoButton, Qt::NoButton, Qt::NoModifier);
+        QApplication::postEvent(this, me);
+    }
+}
+
+void QLineGraph::clear()
+{
+    _samples.clear();
+    rectsPaintTime.clear();
+    rectsTimeBetween.clear();
+    highlightedBar = QRect();
+    position = -1;
+
+    updateSlider();
+    update();
+}
+
+void QLineGraph::updateSlider()
+{
+    ignoreScroll = true;
+    slider->setMaximum(qMax(0, _samples.count() - samplesPerWidth - 1));
+
+    if (position == -1) {
+        slider->setValue(slider->maximum());
+    } else {
+        slider->setValue(position);
+    }
+    ignoreScroll = false;
+}
+
+void QLineGraph::addSample(int a, int b, int d, bool isBreak)
+{
+    Sample s;
+    s.isBreak = isBreak;
+    s.sample[0] = a;
+    s.sample[1] = b;
+    s.sample[2] = d;
+    _samples << s;
+    updateSlider();
+    update();
+}
+
+void QLineGraph::setPosition(int p)
+{
+    sliderChanged(p);
+}
+
+void QLineGraph::drawTime(QPainter *p, const QRect &rect)
+{
+    if (_samples.isEmpty())
+        return;
+
+    int first = position;
+    if (first == -1)
+        first = qMax(0, _samples.count() - samplesPerWidth - 1);
+    int last = qMin(_samples.count() - 1, first + samplesPerWidth);
+
+    qreal scaleX = qreal(rect.width()) / qreal(samplesPerWidth);
+
+    int t = 0;
+
+    for (int ii = first; ii <= last; ++ii) {
+        int sampleTime = _samples.at(ii).sample[2] / 1000;
+        if (sampleTime != t) {
+
+            int xEnd = rect.left() + scaleX * (ii - first);
+            p->drawLine(xEnd, rect.bottom(), xEnd, rect.bottom() + 7);
+
+            QRect text(xEnd - 30, rect.bottom() + 10, 60, 30);
+
+            p->drawText(text, Qt::AlignHCenter | Qt::AlignTop, QString::number(_samples.at(ii).sample[2]));
+
+            t = sampleTime;
+        }
+    }
+
+}
+
+void QLineGraph::drawSample(QPainter *p, int s, const QRect &rect, QList<QRect> *record)
+{
+    if (_samples.isEmpty())
+        return;
+
+    int first = position;
+    if (first == -1)
+        first = qMax(0, _samples.count() - samplesPerWidth - 1);
+    int last = qMin(_samples.count() - 1, first + samplesPerWidth);
+
+    qreal scaleY = qreal(rect.height()) / resolutionForHeight;
+    qreal scaleX = qreal(rect.width()) / qreal(samplesPerWidth);
+
+    int xEnd;
+    int lastXEnd = rect.left();
+
+    p->save();
+    p->setPen(Qt::NoPen);
+    for (int ii = first + 1; ii <= last; ++ii) {
+
+        xEnd = rect.left() + scaleX * (ii - first);
+        int yEnd = rect.bottom() - _samples.at(ii).sample[s] * scaleY;
+
+        if (!(s == 0 && _samples.at(ii).isBreak)) {
+            QRect bar(lastXEnd, yEnd, scaleX, _samples.at(ii).sample[s] * scaleY);
+            record->append(bar);
+            p->drawRect(bar);
+        }
+
+        lastXEnd = xEnd;
+    }
+    p->restore();
+}
+
+void QLineGraph::paintEvent(QPaintEvent *)
+{
+    QPainter p(this);
+    p.setRenderHint(QPainter::Antialiasing);
+
+    QRect r(graphMargins.left(), graphMargins.top(),
+            width() - graphMargins.right(), height() - graphMargins.bottom());
+
+    p.save();
+    p.rotate(-90);
+    p.translate(-r.height()/2 - r.width()/2 - graphMargins.right(), -r.height()/2);
+    p.drawText(r, Qt::AlignCenter, tr("Frame rate"));
+    p.restore();
+
+    p.setBrush(QColor("lightsteelblue"));
+    rectsTimeBetween.clear();
+    drawSample(&p, 0, r, &rectsTimeBetween);
+
+    p.setBrush(QColor("pink"));
+    rectsPaintTime.clear();
+    drawSample(&p, 1, r, &rectsPaintTime);
+
+    if (!highlightedBar.isNull()) {
+        p.setBrush(Qt::darkGreen);
+        p.drawRect(highlightedBar);
+    }
+
+    p.setBrush(Qt::NoBrush);
+    p.drawRect(r);
+
+    slider->setGeometry(x() + r.x(), slider->y(), r.width(), slider->height());
+
+    for (int ii = 0; ii <= resolutionForHeight; ++ii) {
+        int y = 1 + r.bottom() - ii * r.height() / resolutionForHeight;
+
+        if ((ii % 10) == 0) {
+            p.drawLine(r.left() - 20, y, r.left(), y);
+            QRect text(r.left() - 20 - 53, y - 10, 50, 20);
+            p.drawText(text, Qt::AlignRight | Qt::AlignVCenter, QString::number(ii));
+        } else {
+            p.drawLine(r.left() - 7, y, r.left(), y);
+        }
+    }
+
+    drawTime(&p, r);
+}
+
+void QLineGraph::mouseMoveEvent(QMouseEvent *event)
+{
+    QPoint pos = event->pos();
+
+    QRect rect = findContainingRect(rectsPaintTime, pos);
+    if (rect.isNull())
+        rect = findContainingRect(rectsTimeBetween, pos);
+
+    if (!highlightedBar.isNull())
+        update(highlightedBar.adjusted(-1, -1, 1, 1));
+    highlightedBar = rect;
+
+    if (!rect.isNull()) {
+        QRect graph(graphMargins.left(), graphMargins.top(),
+                    width() - graphMargins.right(), height() - graphMargins.bottom());
+        qreal scaleY = qreal(graph.height()) / resolutionForHeight;
+        QToolTip::showText(event->globalPos(), QString::number(qRound(rect.height() / scaleY)), this, rect);
+        update(rect.adjusted(-1, -1, 1, 1));
+    }
+}
+
+void QLineGraph::leaveEvent(QEvent *)
+{
+    if (!highlightedBar.isNull()) {
+        QRect bar = highlightedBar.adjusted(-1, -1, 1, 1);
+        highlightedBar = QRect();
+        update(bar);
+    }
+}
+
+void QLineGraph::wheelEvent(QWheelEvent *event)
+{
+    QWheelEvent we(QPoint(0,0), event->delta(), event->buttons(), event->modifiers(), event->orientation());
+    QApplication::sendEvent(slider, &we);
+}
+
+void QLineGraph::setResolutionForHeight(int resolution)
+{
+    resolutionForHeight = resolution;
+    update();
+}
+
+QRect QLineGraph::findContainingRect(const QList<QRect> &rects, const QPoint &pos) const
+{
+    for (int i=0; i<rects.count(); ++i) {
+        if (rects[i].contains(pos))
+            return rects[i];
+    }
+    return QRect();
+}
+
+
+class GraphWindow : public QWidget
+{
+    Q_OBJECT
+public:
+    GraphWindow(QWidget *parent = 0);
+
+    virtual QSize sizeHint() const;
+
+public slots:
+    void addSample(int, int, int, bool);
+    void setResolutionForHeight(int);
+    void clear();
+
+private:
+    QLineGraph *m_graph;
+};
+
+GraphWindow::GraphWindow(QWidget *parent)
+    : QWidget(parent)
+{
+    QSlider *scroll = new QSlider(Qt::Horizontal);
+    scroll->setFocusPolicy(Qt::WheelFocus);
+    m_graph = new QLineGraph(scroll);
+
+    setFocusPolicy(Qt::WheelFocus);
+    setFocusProxy(scroll);
+
+    QVBoxLayout *layout = new QVBoxLayout(this);
+    layout->setContentsMargins(0, 0, 5, 0);
+    layout->setSpacing(0);
+    layout->addWidget(m_graph, 2);
+    layout->addWidget(new QLabel(tr("Total time elapsed (ms)")), 0, Qt::AlignHCenter);
+    layout->addWidget(scroll);
+}
+
+void GraphWindow::addSample(int a, int b, int d, bool isBreak)
+{
+    m_graph->addSample(a, b, d, isBreak);
+}
+
+void GraphWindow::setResolutionForHeight(int res)
+{
+    m_graph->setResolutionForHeight(res);
+}
+
+void GraphWindow::clear()
+{
+    m_graph->clear();
+}
+
+QSize GraphWindow::sizeHint() const
+{
+    return QSize(400, 220);
+}
+
+
+class CanvasFrameRatePlugin : public QDeclarativeDebugClient
+{
+    Q_OBJECT
+public:
+    CanvasFrameRatePlugin(QDeclarativeDebugConnection *client);
+
+signals:
+    void sample(int, int, int, bool);
+
+protected:
+    virtual void messageReceived(const QByteArray &);
+
+private:
+    int lb;
+    int ld;
+};
+
+CanvasFrameRatePlugin::CanvasFrameRatePlugin(QDeclarativeDebugConnection *client)
+: QDeclarativeDebugClient(QLatin1String("CanvasFrameRate"), client), lb(-1)
+{
+}
+
+void CanvasFrameRatePlugin::messageReceived(const QByteArray &data)
+{
+    QByteArray rwData = data;
+    QDataStream stream(&rwData, QIODevice::ReadOnly);
+
+    int b; int c; int d; bool isBreak;
+    stream >> b >> c >> d >> isBreak;
+
+    if (lb != -1)
+        emit sample(c, lb, ld, isBreak);
+
+    lb = b;
+    ld = d;
+}
+
+CanvasFrameRate::CanvasFrameRate(QWidget *parent)
+: QWidget(parent),
+  m_plugin(0)
+{
+    m_tabs = new QTabWidget(this);
+
+    QHBoxLayout *bottom = new QHBoxLayout;
+    bottom->setMargin(0);
+    bottom->setSpacing(10);
+
+    m_res = new QSpinBox;
+    m_res->setRange(30, 200);
+    m_res->setValue(m_res->minimum());
+    m_res->setSingleStep(10);
+    m_res->setSuffix(QLatin1String("ms"));
+    bottom->addWidget(new QLabel(tr("Resolution:")));
+    bottom->addWidget(m_res);
+
+    bottom->addStretch();
+
+    m_clearButton = new QPushButton(tr("Clear"));
+    connect(m_clearButton, SIGNAL(clicked()), SLOT(clearGraph()));
+    bottom->addWidget(m_clearButton);
+
+    QPushButton *pb = new QPushButton(tr("New Graph"), this);
+    connect(pb, SIGNAL(clicked()), this, SLOT(newTab()));
+    bottom->addWidget(pb);
+
+    m_group = new QGroupBox(tr("Enabled"));
+    m_group->setCheckable(true);
+    m_group->setChecked(false);
+    connect(m_group, SIGNAL(toggled(bool)), SLOT(enabledToggled(bool)));
+
+    QVBoxLayout *groupLayout = new QVBoxLayout(m_group);
+    groupLayout->setContentsMargins(5, 0, 5, 0);
+    groupLayout->setSpacing(2);
+    groupLayout->addWidget(m_tabs);
+    groupLayout->addLayout(bottom);
+
+    QVBoxLayout *layout = new QVBoxLayout;
+    layout->setContentsMargins(0, 10, 0, 0);
+    layout->setSpacing(0);
+    layout->addWidget(m_group);
+    setLayout(layout);
+}
+
+void CanvasFrameRate::reset(QDeclarativeDebugConnection *conn)
+{
+    delete m_plugin;
+    m_plugin = 0;
+
+    QWidget *w;
+    for (int i = 0; i < m_tabs->count(); ++i) {
+        w = m_tabs->widget(i);
+        m_tabs->removeTab(i);
+        delete w;
+    }
+
+    if (conn) {
+        connect(conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
+                SLOT(connectionStateChanged(QAbstractSocket::SocketState)));
+        if (conn->state() == QAbstractSocket::ConnectedState)
+            handleConnected(conn);
+    }
+}
+
+void CanvasFrameRate::connectionStateChanged(QAbstractSocket::SocketState state)
+{
+    if (state == QAbstractSocket::UnconnectedState) {
+        delete m_plugin;
+        m_plugin = 0;
+    } else if (state == QAbstractSocket::ConnectedState) {
+        handleConnected(qobject_cast<QDeclarativeDebugConnection*>(sender()));
+    }
+}
+
+void CanvasFrameRate::handleConnected(QDeclarativeDebugConnection *conn)
+{
+    delete m_plugin;
+    m_plugin = new CanvasFrameRatePlugin(conn);
+    enabledToggled(m_group->isChecked());
+    newTab();
+}
+
+void CanvasFrameRate::setSizeHint(const QSize &size)
+{
+    m_sizeHint = size;
+}
+
+QSize CanvasFrameRate::sizeHint() const
+{
+    return m_sizeHint;
+}
+
+void CanvasFrameRate::clearGraph()
+{
+    if (m_tabs->count()) {
+        GraphWindow *w = qobject_cast<GraphWindow*>(m_tabs->currentWidget());
+        if (w)
+            w->clear();
+    }
+}
+
+void CanvasFrameRate::newTab()
+{
+    if (!m_plugin)
+        return;
+
+    if (m_tabs->count()) {
+        QWidget *w = m_tabs->widget(m_tabs->count() - 1);
+        QObject::disconnect(m_plugin, SIGNAL(sample(int,int,int,bool)),
+                            w, SLOT(addSample(int,int,int,bool)));
+    }
+
+    int count = m_tabs->count();
+
+    GraphWindow *graph = new GraphWindow;
+    graph->setResolutionForHeight(m_res->value());
+    connect(m_plugin, SIGNAL(sample(int,int,int,bool)),
+            graph, SLOT(addSample(int,int,int,bool)));
+    connect(m_res, SIGNAL(valueChanged(int)),
+            graph, SLOT(setResolutionForHeight(int)));
+
+    QString name = QLatin1String("Graph ") + QString::number(count + 1);
+    m_tabs->addTab(graph, name);
+    m_tabs->setCurrentIndex(count);
+}
+
+void CanvasFrameRate::enabledToggled(bool checked)
+{
+    if (m_plugin)
+        static_cast<QDeclarativeDebugClient *>(m_plugin)->setEnabled(checked);
+}
+
+} // Internal
+} // Debugger
+
+#include "canvasframerate.moc"
diff --git a/src/plugins/debugger/qml/canvasframerate.h b/src/plugins/debugger/qml/canvasframerate.h
new file mode 100644
index 0000000000000000000000000000000000000000..ad35d9a7efb9ba978968f8991f205603e6c4db80
--- /dev/null
+++ b/src/plugins/debugger/qml/canvasframerate.h
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+#ifndef CANVASFRAMERATE_H
+#define CANVASFRAMERATE_H
+
+#include <private/qdeclarativedebugclient_p.h>
+
+#include <QtCore/qpointer.h>
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_NAMESPACE
+class QTabWidget;
+class QSlider;
+class QGroupBox;
+class QLabel;
+class QSpinBox;
+class QPushButton;
+QT_END_NAMESPACE
+
+
+namespace Debugger {
+namespace Internal {
+
+
+class CanvasFrameRatePlugin;
+
+class CanvasFrameRate : public QWidget
+{
+    Q_OBJECT
+public:
+    CanvasFrameRate(QWidget *parent = 0);
+
+    void reset(QDeclarativeDebugConnection *conn);
+
+    void setSizeHint(const QSize &);
+    virtual QSize sizeHint() const;
+
+signals:
+    void contextHelpIdChanged(const QString &helpId);
+
+private slots:
+    void clearGraph();
+    void newTab();
+    void enabledToggled(bool);
+    void connectionStateChanged(QAbstractSocket::SocketState state);
+
+private:
+    void handleConnected(QDeclarativeDebugConnection *conn);
+
+    QGroupBox *m_group;
+    QTabWidget *m_tabs;
+    QSpinBox *m_res;
+    QPushButton *m_clearButton;
+    CanvasFrameRatePlugin *m_plugin;
+    QSize m_sizeHint;
+};
+
+} // Internal
+} // Debugger
+
+#endif // CANVASFRAMERATE_H
+
diff --git a/src/plugins/debugger/qml/qml.pri b/src/plugins/debugger/qml/qml.pri
index dc9d548c57b0ad72d46ddfbe9cbefbb21e13f9b8..5191c96b41fac3f071a3e189d3a7017b0003c626 100644
--- a/src/plugins/debugger/qml/qml.pri
+++ b/src/plugins/debugger/qml/qml.pri
@@ -1,8 +1,12 @@
 HEADERS += \
     $$PWD/qmlengine.h \
+    $$PWD/canvasframerate.h \
 
 SOURCES += \
     $$PWD/qmlengine.cpp \
+    $$PWD/canvasframerate.cpp \
+
+QT += declarative
 
 FORMS +=
 
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index 6767fa75381c19b5b0fcc05460551d994a77e96c..8c987cd14a4dacfb2d681b8e17cbd11092950fdf 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -30,6 +30,7 @@
 #include "qmlengine.h"
 
 #include "debuggerconstants.h"
+#include "debuggerplugin.h"
 #include "debuggerdialogs.h"
 #include "debuggerstringutils.h"
 
@@ -40,6 +41,10 @@
 #include "watchhandler.h"
 #include "watchutils.h"
 
+#include "canvasframerate.h"
+
+#include <projectexplorer/environment.h>
+
 #include <utils/qtcassert.h>
 
 #include <QtCore/QDateTime>
@@ -55,6 +60,10 @@
 #include <QtGui/QToolTip>
 
 #include <QtNetwork/QTcpSocket>
+#include <QtNetwork/QHostAddress>
+
+#include <private/qdeclarativedebug_p.h>
+#include <private/qdeclarativedebugclient_p.h>
 
 #define DEBUG_QML 1
 #if DEBUG_QML
@@ -97,6 +106,36 @@ QString QmlEngine::QmlCommand::toString() const
 }
 
 
+///////////////////////////////////////////////////////////////////////
+//
+// QmlDebuggerClient
+//
+///////////////////////////////////////////////////////////////////////
+
+class QmlDebuggerClient : public QDeclarativeDebugClient
+{
+    Q_OBJECT
+
+public:
+    QmlDebuggerClient(QDeclarativeDebugConnection *connection, QmlEngine *engine)
+        : QDeclarativeDebugClient(QLatin1String("Debugger"), connection)
+        , m_connection(connection), m_engine(engine)
+    {
+        setEnabled(true);
+    }
+
+    void messageReceived(const QByteArray &data)
+    {
+        m_engine->messageReceived(data);
+    }
+
+
+    QDeclarativeDebugConnection *m_connection;
+    QmlEngine *m_engine;
+};
+
+
+
 ///////////////////////////////////////////////////////////////////////
 //
 // QmlEngine
@@ -109,6 +148,13 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters)
     m_congestion = 0;
     m_inAir = 0;
 
+    m_conn = 0;
+    m_client = 0;
+    m_engineQuery = 0;
+    m_contextQuery = 0;
+
+    m_frameRate = 0;
+
     m_sendTimer.setSingleShot(true);
     m_sendTimer.setInterval(100); // ms
     connect(&m_sendTimer, SIGNAL(timeout()), this, SLOT(handleSendTimer()));
@@ -128,6 +174,7 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters)
     //connect(m_socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy, QAuthenticator *)))
     //connect(m_socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
     //    thism SLOT(socketStateChanged(QAbstractSocket::SocketState)));
+
 }
 
 QmlEngine::~QmlEngine()
@@ -153,8 +200,9 @@ void QmlEngine::socketReadyRead()
 
 void QmlEngine::socketConnected()
 {
+    qDebug() << "SOCKET CONNECTED.";
     showStatusMessage("Socket connected.");
-    m_socket->waitForConnected(2000);
+    //m_socket->waitForConnected(2000);
     //sendCommand("Locator", "redirect", "ID");
 }
 
@@ -168,6 +216,7 @@ void QmlEngine::socketError(QAbstractSocket::SocketError)
     QString msg = tr("%1.").arg(m_socket->errorString());
     //QMessageBox::critical(q->mainWindow(), tr("Error"), msg);
     showStatusMessage(msg);
+    qDebug() << "SOCKET ERROR: " << msg;
     exitDebugger();
 }
 
@@ -199,19 +248,95 @@ void QmlEngine::exitDebugger()
     SDEBUG("QmlEngine::exitDebugger()");
 }
 
+const int serverPort = 3768;
+
 void QmlEngine::startDebugger()
 {
-    qDebug() << "STARTING QML ENGINE";
-    setState(InferiorRunningRequested);
-    showStatusMessage(tr("Running requested..."), 5000);
-/*    const DebuggerStartParameters &sp = startParameters();
+    QTC_ASSERT(state() == DebuggerNotReady, setState(DebuggerNotReady));
+    setState(EngineStarting);
+    const DebuggerStartParameters &sp = startParameters();
     const int pos = sp.remoteChannel.indexOf(QLatin1Char(':'));
     const QString host = sp.remoteChannel.left(pos);
     const quint16 port = sp.remoteChannel.mid(pos + 1).toInt();
+    qDebug() << "STARTING QML ENGINE" <<  host << port << sp.remoteChannel
+        << sp.executable << sp.processArgs << sp.workingDirectory;
+  
+    ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment(); // empty env by default
+    env.set("QML_DEBUG_SERVER_PORT", QString::number(serverPort));
+
+    connect(&m_proc, SIGNAL(error(QProcess::ProcessError)),
+        SLOT(handleProcError(QProcess::ProcessError)));
+    connect(&m_proc, SIGNAL(finished(int, QProcess::ExitStatus)),
+        SLOT(handleProcFinished(int, QProcess::ExitStatus)));
+    connect(&m_proc, SIGNAL(readyReadStandardOutput()),
+        SLOT(readProcStandardOutput()));
+    connect(&m_proc, SIGNAL(readyReadStandardError()),
+        SLOT(readProcStandardError()));
+
+    setState(AdapterStarting);
+    m_proc.setEnvironment(env.toStringList());
+    m_proc.setWorkingDirectory(sp.workingDirectory);
+    m_proc.start(sp.executable, sp.processArgs);
+
     //QTimer::singleShot(0, this, SLOT(runInferior()));
-    m_socket->connectToHost(host, port); */
+
+    if (!m_proc.waitForStarted()) {
+        setState(AdapterStartFailed);
+        startFailed();
+        return;
+    }
+    qDebug() << "PROC STARTED.";
+    //m_socket->connectToHost(host, port);
+    //startSuccessful();
+    //showStatusMessage(tr("Running requested..."), 5000);
+    //setState(InferiorRunning); // FIXME
+
+    setState(AdapterStarted);
+    setState(InferiorStarting);
+
+    //m_frameRate = new CanvasFrameRate(0);
+    //m_frameRate->show();
+}
+
+void QmlEngine::setupConnection()
+{
+    QTC_ASSERT(m_conn == 0, /**/);
+    m_conn = new QDeclarativeDebugConnection(this);
+
+    connect(m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
+            SLOT(connectionStateChanged()));
+    connect(m_conn, SIGNAL(error(QAbstractSocket::SocketError)),
+            SLOT(connectionError()));
+    connect(m_conn, SIGNAL(connected()),
+            SLOT(connectionConnected()));
+
+    QTC_ASSERT(m_client == 0, /**/);
+    m_client = new QmlDebuggerClient(m_conn, this);
+
+    //m_objectTreeWidget->setEngineDebug(m_client);
+    //m_propertiesWidget->setEngineDebug(m_client);
+    //m_watchTableModel->setEngineDebug(m_client);
+    //m_expressionWidget->setEngineDebug(m_client);
+
+    //   resetViews();
+    //   m_frameRateWidget->reset(m_conn);
+    //   reloadEngines();
+
+    QHostAddress ha(QHostAddress::LocalHost);
+
+    qDebug() << "CONNECTING TO " << ha.toString() << serverPort;
+    m_conn->connectToHost(ha, serverPort);
+
+    if (!m_conn->waitForConnected()) {
+        qDebug() << "CONNECTION FAILED";
+        setState(InferiorStartFailed);
+        startFailed();
+        return;
+    }
+
+    qDebug() << "CONNECTION SUCCESSFUL";
+    setState(InferiorRunning);
     startSuccessful();
-    setState(InferiorRunning); // FIXME
 }
 
 void QmlEngine::continueInferior()
@@ -231,6 +356,7 @@ void QmlEngine::runInferior()
 
 void QmlEngine::interruptInferior()
 {
+    qDebug() << "INTERRUPT";
     QByteArray reply;
     QDataStream rs(&reply, QIODevice::WriteOnly);
     rs << QByteArray("INTERRUPT");
@@ -503,6 +629,12 @@ void QmlEngine::handleSendTimer()
 */
 }
 
+void QmlEngine::sendMessage(const QByteArray &msg)
+{
+    QTC_ASSERT(m_client, return);
+    m_client->sendMessage(msg);
+}
+
 void QmlEngine::sendCommandNow(const QmlCommand &cmd)
 {
     ++m_inAir;
@@ -743,5 +875,131 @@ void QmlEngine::messageReceived(const QByteArray &message)
 
 }
 
+QString QmlEngine::errorMessage(QProcess::ProcessError error)
+{
+    switch (error) {
+        case QProcess::FailedToStart:
+            return tr("The Gdb process failed to start. Either the "
+                "invoked program is missing, or you may have insufficient "
+                "permissions to invoke the program.");
+        case QProcess::Crashed:
+            return tr("The Gdb process crashed some time after starting "
+                "successfully.");
+        case QProcess::Timedout:
+            return tr("The last waitFor...() function timed out. "
+                "The state of QProcess is unchanged, and you can try calling "
+                "waitFor...() again.");
+        case QProcess::WriteError:
+            return tr("An error occurred when attempting to write "
+                "to the Gdb process. For example, the process may not be running, "
+                "or it may have closed its input channel.");
+        case QProcess::ReadError:
+            return tr("An error occurred when attempting to read from "
+                "the Gdb process. For example, the process may not be running.");
+        default:
+            return tr("An unknown error in the Gdb process occurred. ");
+    }
+}
+
+void QmlEngine::handleProcError(QProcess::ProcessError error)
+{
+    showMessage(_("HANDLE QML ERROR"));
+    switch (error) {
+    case QProcess::Crashed:
+        break; // will get a processExited() as well
+    // impossible case QProcess::FailedToStart:
+    case QProcess::ReadError:
+    case QProcess::WriteError:
+    case QProcess::Timedout:
+    default:
+        m_proc.kill();
+        setState(EngineShuttingDown, true);
+        plugin()->showMessageBox(QMessageBox::Critical, tr("Gdb I/O Error"),
+                       errorMessage(error));
+        break;
+    }
+}
+
+void QmlEngine::handleProcFinished(int code, QProcess::ExitStatus type)
+{
+    showMessage(_("QML VIEWER PROCESS FINISHED, status %1, code %2").arg(type).arg(code));
+    setState(DebuggerNotReady, true);
+}
+
+void QmlEngine::readProcStandardError()
+{
+    qDebug() << "STD ERR" << m_proc.readAllStandardError();
+    if (!m_conn)
+        setupConnection();
+}
+
+void QmlEngine::readProcStandardOutput()
+{
+    qDebug() << "STD ERR" << m_proc.readAllStandardOutput();
+}
+
+void QmlEngine::connectionStateChanged()
+{
+    QTC_ASSERT(m_conn, return);
+    QAbstractSocket::SocketState state = m_conn->state();
+    qDebug() << "CONNECTION STATE: " << state;
+    switch (state) {
+        case QAbstractSocket::UnconnectedState:
+        {
+            showStatusMessage(tr("[QmlEngine] disconnected.\n\n"));
+
+            delete m_engineQuery;
+            m_engineQuery = 0;
+            delete m_contextQuery;
+            m_contextQuery = 0;
+
+//            resetViews();
+
+//            updateMenuActions();
+
+            break;
+        }
+        case QAbstractSocket::HostLookupState:
+            showStatusMessage(tr("[QmlEngine] resolving host..."));
+            break;
+        case QAbstractSocket::ConnectingState:
+            showStatusMessage(tr("[QmlEngine] connecting to debug server..."));
+            break;
+        case QAbstractSocket::ConnectedState:
+            showStatusMessage(tr("[QmlEngine] connected.\n"));
+            //setupConnection()
+            break;
+        case QAbstractSocket::ClosingState:
+            showStatusMessage(tr("[QmlEngine] closing..."));
+            break;
+        case QAbstractSocket::BoundState:
+            showStatusMessage(tr("[QmlEngine] bound state"));
+            break;
+        case QAbstractSocket::ListeningState:
+            showStatusMessage(tr("[QmlEngine] listening state"));
+            break;
+        default:
+            showStatusMessage(tr("[QmlEngine] unknown state: %1").arg(state));
+            break;
+    }
+}
+
+void QmlEngine::connectionError()
+{
+    QTC_ASSERT(m_conn, return);
+    showStatusMessage(tr("[QmlEngine] error: (%1) %2", "%1=error code, %2=error message")
+            .arg(m_conn->error()).arg(m_conn->errorString()));
+}
+
+void QmlEngine::connectionConnected()
+{
+    QTC_ASSERT(m_conn, return);
+    showStatusMessage(tr("[QmlEngine] error: (%1) %2", "%1=error code, %2=error message")
+            .arg(m_conn->error()).arg(m_conn->errorString()));
+}
+
+
 } // namespace Internal
 } // namespace Debugger
+
+#include "qmlengine.moc"
diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h
index 5fc3c3ca86f4db0af7ccde9ace626c162d0b7358..bec97673375b473c102a4f5cd7a9ee085257ab8e 100644
--- a/src/plugins/debugger/qml/qmlengine.h
+++ b/src/plugins/debugger/qml/qmlengine.h
@@ -36,14 +36,20 @@
 #include <QtCore/QHash>
 #include <QtCore/QObject>
 #include <QtCore/QPoint>
+#include <QtCore/QProcess>
 #include <QtCore/QQueue>
 #include <QtCore/QTimer>
 #include <QtCore/QVariant>
 
 #include <QtNetwork/QAbstractSocket>
+#include <QtNetwork/QTcpSocket>
 
 QT_BEGIN_NAMESPACE
 class QTcpSocket;
+class QDeclarativeDebugConnection;
+class QDeclarativeEngineDebug;
+class QDeclarativeDebugEnginesQuery;
+class QDeclarativeDebugRootContextQuery;
 QT_END_NAMESPACE
 
 namespace Debugger {
@@ -52,6 +58,8 @@ namespace Internal {
 class ScriptAgent;
 class WatchData;
 class QmlResponse;
+class CanvasFrameRate;
+class QmlDebuggerClient;
 
 class DEBUGGER_EXPORT QmlEngine : public DebuggerEngine
 {
@@ -120,7 +128,22 @@ private:
     unsigned int debuggerCapabilities() const;
 
     Q_SLOT void startDebugging();
+    void setupConnection();
 
+    void sendMessage(const QByteArray &msg);
+
+private slots:
+    void handleProcFinished(int, QProcess::ExitStatus status);
+    void handleProcError(QProcess::ProcessError error);
+    void readProcStandardOutput();
+    void readProcStandardError();
+
+    void connectionError();
+    void connectionConnected();
+    void connectionStateChanged();
+
+private:
+    QString errorMessage(QProcess::ProcessError error);
     typedef void (QmlEngine::*QmlCommandCallback)
         (const QmlResponse &record, const QVariant &cookie);
 
@@ -159,9 +182,13 @@ private:
     QTcpSocket *m_socket;
     QByteArray m_inbuffer;
     QList<QByteArray> m_services;
+    QProcess m_proc;
 
-signals:
-    void sendMessage(const QByteArray &);
+    QDeclarativeDebugConnection *m_conn;
+    QmlDebuggerClient *m_client;
+    QDeclarativeDebugEnginesQuery *m_engineQuery;
+    QDeclarativeDebugRootContextQuery *m_contextQuery;
+    CanvasFrameRate *m_frameRate;
 };
 
 } // namespace Internal