From 1bf3418314ae4412a0938a728a7a3e30a47f9f85 Mon Sep 17 00:00:00 2001
From: Bea Lam <bea.lam@nokia.com>
Date: Fri, 11 Dec 2009 14:56:04 +1000
Subject: [PATCH] Add qmlinspector plugin.

---
 src/plugins/plugins.pro                       |   9 +
 .../qmlinspector/QmlInspector.pluginspec      |  28 +
 .../components/canvasframerate.cpp            | 569 ++++++++++++++++++
 .../qmlinspector/components/canvasframerate.h |  80 +++
 .../qmlinspector/components/engine.cpp        | 209 +++++++
 src/plugins/qmlinspector/components/engine.h  |  91 +++
 .../qmlinspector/components/engine.png        | Bin 0 -> 6394 bytes
 .../qmlinspector/components/engines.qml       |  46 ++
 .../components/expressionquerywidget.cpp      | 264 ++++++++
 .../components/expressionquerywidget.h        |  94 +++
 .../components/objectpropertiesview.cpp       | 263 ++++++++
 .../components/objectpropertiesview.h         |  81 +++
 .../qmlinspector/components/objecttree.cpp    | 219 +++++++
 .../qmlinspector/components/objecttree.h      |  84 +++
 .../qmlinspector/components/qmldebugger.pri   |  16 +
 .../qmlinspector/components/qmldebugger.qrc   |   7 +
 .../qmlinspector/components/refresh.png       | Bin 0 -> 6169 bytes
 .../qmlinspector/components/standalone.pro    |  19 +
 .../qmlinspector/components/watchtable.cpp    | 354 +++++++++++
 .../qmlinspector/components/watchtable.h      | 142 +++++
 src/plugins/qmlinspector/images/logo.png      | Bin 0 -> 2662 bytes
 .../qmlinspector/inspectoroutputpane.cpp      | 138 +++++
 .../qmlinspector/inspectoroutputpane.h        |  82 +++
 src/plugins/qmlinspector/qmlinspector.h       |  53 ++
 src/plugins/qmlinspector/qmlinspector.pro     |  27 +
 src/plugins/qmlinspector/qmlinspector.qrc     |   6 +
 src/plugins/qmlinspector/qmlinspectormode.cpp | 555 +++++++++++++++++
 src/plugins/qmlinspector/qmlinspectormode.h   | 121 ++++
 .../qmlinspector/qmlinspectorplugin.cpp       | 163 +++++
 src/plugins/qmlinspector/qmlinspectorplugin.h |  78 +++
 src/plugins/qmlinspector/runcontrol.cpp       | 162 +++++
 src/plugins/qmlinspector/runcontrol.h         |  94 +++
 32 files changed, 4054 insertions(+)
 create mode 100644 src/plugins/qmlinspector/QmlInspector.pluginspec
 create mode 100644 src/plugins/qmlinspector/components/canvasframerate.cpp
 create mode 100644 src/plugins/qmlinspector/components/canvasframerate.h
 create mode 100644 src/plugins/qmlinspector/components/engine.cpp
 create mode 100644 src/plugins/qmlinspector/components/engine.h
 create mode 100644 src/plugins/qmlinspector/components/engine.png
 create mode 100644 src/plugins/qmlinspector/components/engines.qml
 create mode 100644 src/plugins/qmlinspector/components/expressionquerywidget.cpp
 create mode 100644 src/plugins/qmlinspector/components/expressionquerywidget.h
 create mode 100644 src/plugins/qmlinspector/components/objectpropertiesview.cpp
 create mode 100644 src/plugins/qmlinspector/components/objectpropertiesview.h
 create mode 100644 src/plugins/qmlinspector/components/objecttree.cpp
 create mode 100644 src/plugins/qmlinspector/components/objecttree.h
 create mode 100644 src/plugins/qmlinspector/components/qmldebugger.pri
 create mode 100644 src/plugins/qmlinspector/components/qmldebugger.qrc
 create mode 100644 src/plugins/qmlinspector/components/refresh.png
 create mode 100644 src/plugins/qmlinspector/components/standalone.pro
 create mode 100644 src/plugins/qmlinspector/components/watchtable.cpp
 create mode 100644 src/plugins/qmlinspector/components/watchtable.h
 create mode 100644 src/plugins/qmlinspector/images/logo.png
 create mode 100644 src/plugins/qmlinspector/inspectoroutputpane.cpp
 create mode 100644 src/plugins/qmlinspector/inspectoroutputpane.h
 create mode 100644 src/plugins/qmlinspector/qmlinspector.h
 create mode 100644 src/plugins/qmlinspector/qmlinspector.pro
 create mode 100644 src/plugins/qmlinspector/qmlinspector.qrc
 create mode 100644 src/plugins/qmlinspector/qmlinspectormode.cpp
 create mode 100644 src/plugins/qmlinspector/qmlinspectormode.h
 create mode 100644 src/plugins/qmlinspector/qmlinspectorplugin.cpp
 create mode 100644 src/plugins/qmlinspector/qmlinspectorplugin.h
 create mode 100644 src/plugins/qmlinspector/runcontrol.cpp
 create mode 100644 src/plugins/qmlinspector/runcontrol.h

diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 77cf85e11db..11060df7620 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -37,6 +37,10 @@ SUBDIRS   = plugin_coreplugin \
             plugin_mercurial \
             debugger/dumper.pro
 
+contains(QT_CONFIG, declarative) {
+    SUBDIRS += plugin_qmlinspector
+}
+
 plugin_coreplugin.subdir = coreplugin
 
 plugin_welcome.subdir = welcome
@@ -180,6 +184,11 @@ plugin_qmlprojectmanager.depends += plugin_projectexplorer
 plugin_qmlprojectmanager.depends += plugin_help
 plugin_qmlprojectmanager.depends += plugin_qmleditor
 
+plugin_qmlinspector.subdir = qmlinspector
+plugin_qmlinspector.depends += plugin_projectexplorer
+plugin_qmlinspector.depends += plugin_coreplugin
+plugin_qmlinspector.depends += plugin_texteditor
+
 plugin_mercurial.subdir = mercurial
 plugin_mercurial.depends = plugin_texteditor
 plugin_mercurial.depends = plugin_vcsbase
diff --git a/src/plugins/qmlinspector/QmlInspector.pluginspec b/src/plugins/qmlinspector/QmlInspector.pluginspec
new file mode 100644
index 00000000000..9ad51d42309
--- /dev/null
+++ b/src/plugins/qmlinspector/QmlInspector.pluginspec
@@ -0,0 +1,28 @@
+<plugin name="QmlInspector" version="1.3.80" compatVersion="1.3.80">
+    <vendor>Nokia Corporation</vendor>
+    <copyright>(C) 2008-2009 Nokia Corporation</copyright>
+    <license>
+Commercial Usage
+
+Licensees holding valid Qt Commercial licenses may use this plugin 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 plugin may be used under the terms of the GNU Lesser
+General Public License version 2.1 as published by the Free Software
+Foundation.  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.</license>
+    <description>Qml support</description>
+    <url>http://qt.nokia.com</url>
+    <dependencyList>
+        <dependency name="QmlProjectManager" version="1.3.80"/>
+        <dependency name="ProjectExplorer" version="1.3.80"/>
+        <dependency name="CppTools" version="1.3.80"/>
+        <dependency name="CppEditor" version="1.3.80"/>
+        <dependency name="Help" version="1.3.80"/>
+    </dependencyList>
+</plugin>
diff --git a/src/plugins/qmlinspector/components/canvasframerate.cpp b/src/plugins/qmlinspector/components/canvasframerate.cpp
new file mode 100644
index 00000000000..91c762fad5e
--- /dev/null
+++ b/src/plugins/qmlinspector/components/canvasframerate.cpp
@@ -0,0 +1,569 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 <private/qmldebugclient_p.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>
+
+
+QT_BEGIN_NAMESPACE
+
+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 QmlDebugClient
+{
+    Q_OBJECT
+public:
+    CanvasFrameRatePlugin(QmlDebugConnection *client);
+
+signals:
+    void sample(int, int, int, bool);
+
+protected:
+    virtual void messageReceived(const QByteArray &);
+
+private:
+    int lb;
+    int ld;
+};
+
+CanvasFrameRatePlugin::CanvasFrameRatePlugin(QmlDebugConnection *client)
+: QmlDebugClient(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(QmlDebugConnection *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<QmlDebugConnection*>(sender()));
+    }        
+}
+
+void CanvasFrameRate::handleConnected(QmlDebugConnection *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<QmlDebugClient *>(m_plugin)->setEnabled(checked);
+}
+
+QT_END_NAMESPACE
+
+#include "canvasframerate.moc"
diff --git a/src/plugins/qmlinspector/components/canvasframerate.h b/src/plugins/qmlinspector/components/canvasframerate.h
new file mode 100644
index 00000000000..88335a6df02
--- /dev/null
+++ b/src/plugins/qmlinspector/components/canvasframerate.h
@@ -0,0 +1,80 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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/qmldebugclient_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;
+
+class CanvasFrameRatePlugin;
+
+class CanvasFrameRate : public QWidget
+{
+    Q_OBJECT
+public:
+    CanvasFrameRate(QWidget *parent = 0);
+    
+    void reset(QmlDebugConnection *conn);
+
+    void setSizeHint(const QSize &);
+    virtual QSize sizeHint() const;
+
+private slots:
+    void clearGraph();
+    void newTab();
+    void enabledToggled(bool);
+    void connectionStateChanged(QAbstractSocket::SocketState state);
+
+private:
+    void handleConnected(QmlDebugConnection *conn);
+
+    QGroupBox *m_group;
+    QTabWidget *m_tabs;
+    QSpinBox *m_res;
+    QPushButton *m_clearButton;
+    CanvasFrameRatePlugin *m_plugin;
+    QSize m_sizeHint;
+};
+
+QT_END_NAMESPACE
+
+#endif // CANVASFRAMERATE_H
+
diff --git a/src/plugins/qmlinspector/components/engine.cpp b/src/plugins/qmlinspector/components/engine.cpp
new file mode 100644
index 00000000000..1a768d4e3b4
--- /dev/null
+++ b/src/plugins/qmlinspector/components/engine.cpp
@@ -0,0 +1,209 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 "engine.h"
+#include "objectpropertiesview.h"
+#include "expressionquerywidget.h"
+#include "objecttree.h"
+#include "watchtable.h"
+
+#include <private/qmlenginedebug_p.h>
+#include <private/qmldebugclient_p.h>
+#include <private/qmldebugservice_p.h>
+
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlgraphicsitem.h>
+
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QSplitter>
+#include <QTabWidget>
+#include <QFile>
+
+
+QT_BEGIN_NAMESPACE
+
+
+class DebuggerEngineItem : public QObject
+{
+    Q_OBJECT
+    Q_PROPERTY(QString name READ name CONSTANT);
+    Q_PROPERTY(int engineId READ engineId CONSTANT);
+
+public:
+    DebuggerEngineItem(const QString &name, int id)
+    : m_name(name), m_engineId(id) {}
+
+    QString name() const { return m_name; }
+    int engineId() const { return m_engineId; }
+
+private:
+    QString m_name;
+    int m_engineId;
+};
+
+EnginePane::EnginePane(QmlDebugConnection *conn, QWidget *parent)
+: QWidget(parent), m_client(new QmlEngineDebug(conn, this)), m_engines(0), m_context(0), m_watchTableModel(0), m_exprQueryWidget(0)
+{
+    QVBoxLayout *layout = new QVBoxLayout(this);
+    layout->setContentsMargins(0, 0, 0, 0);
+
+    QFile enginesFile(":/engines.qml");
+    enginesFile.open(QFile::ReadOnly);
+    Q_ASSERT(enginesFile.isOpen());
+
+    m_engineView = new QmlView(this);
+    m_engineView->rootContext()->setContextProperty("engines", qVariantFromValue(&m_engineItems));
+    m_engineView->setContentResizable(true);
+    m_engineView->setQml(enginesFile.readAll());
+    m_engineView->execute();
+    m_engineView->setFixedHeight(100);
+    QObject::connect(m_engineView->root(), SIGNAL(engineClicked(int)),
+                     this, SLOT(engineSelected(int)));
+    QObject::connect(m_engineView->root(), SIGNAL(refreshEngines()),
+                     this, SLOT(refreshEngines()));
+
+    m_engineView->setVisible(false);
+    layout->addWidget(m_engineView);
+
+    QSplitter *splitter = new QSplitter;
+
+    m_objTree = new ObjectTree(m_client, this);
+    m_propertiesView = new ObjectPropertiesView(m_client);
+    m_watchTableModel = new WatchTableModel(m_client, this);
+
+    m_watchTableView = new WatchTableView(m_watchTableModel);
+    m_watchTableView->setModel(m_watchTableModel);
+    WatchTableHeaderView *header = new WatchTableHeaderView(m_watchTableModel);
+    m_watchTableView->setHorizontalHeader(header);
+
+    connect(m_objTree, SIGNAL(currentObjectChanged(QmlDebugObjectReference)),
+            m_propertiesView, SLOT(reload(QmlDebugObjectReference)));
+    connect(m_objTree, SIGNAL(expressionWatchRequested(QmlDebugObjectReference,QString)),
+            m_watchTableModel, SLOT(expressionWatchRequested(QmlDebugObjectReference,QString)));
+
+    connect(m_propertiesView, SIGNAL(activated(QmlDebugObjectReference,QmlDebugPropertyReference)),
+            m_watchTableModel, SLOT(togglePropertyWatch(QmlDebugObjectReference,QmlDebugPropertyReference)));
+
+    connect(m_watchTableModel, SIGNAL(watchCreated(QmlDebugWatch*)),
+            m_propertiesView, SLOT(watchCreated(QmlDebugWatch*)));
+
+    connect(m_watchTableView, SIGNAL(objectActivated(int)),
+            m_objTree, SLOT(setCurrentObject(int)));
+    
+    m_exprQueryWidget = new ExpressionQueryWidget(ExpressionQueryWidget::SeparateEntryMode, m_client);
+    connect(m_objTree, SIGNAL(currentObjectChanged(QmlDebugObjectReference)),
+            m_exprQueryWidget, SLOT(setCurrentObject(QmlDebugObjectReference)));
+    
+    QSplitter *propertiesTab = new QSplitter(Qt::Vertical);
+    propertiesTab->addWidget(m_propertiesView);
+    propertiesTab->addWidget(m_exprQueryWidget);
+    propertiesTab->setStretchFactor(0, 2);
+    propertiesTab->setStretchFactor(1, 1);
+    
+    m_tabs = new QTabWidget(this);
+    m_tabs->addTab(propertiesTab, tr("Properties"));
+    m_tabs->addTab(m_watchTableView, tr("Watched"));
+
+    splitter->addWidget(m_objTree);
+    splitter->addWidget(m_tabs);
+    splitter->setStretchFactor(1, 2);
+    layout->addWidget(splitter);
+}
+
+void EnginePane::engineSelected(int id)
+{
+    qWarning() << "Engine selected" << id;
+    queryContext(id);
+}
+
+void EnginePane::queryContext(int id)
+{
+    if (m_context) {
+        delete m_context;
+        m_context = 0;
+    }
+
+    m_context = m_client->queryRootContexts(QmlDebugEngineReference(id), this);
+    if (!m_context->isWaiting())
+        contextChanged();
+    else
+        QObject::connect(m_context, SIGNAL(stateChanged(QmlDebugQuery::State)),
+                         this, SLOT(contextChanged()));
+}
+
+void EnginePane::contextChanged()
+{
+    //dump(m_context->rootContext(), 0);
+
+    foreach (const QmlDebugObjectReference &object, m_context->rootContext().objects())
+        m_objTree->reload(object.debugId());
+
+    delete m_context; m_context = 0;
+}
+
+void EnginePane::refreshEngines()
+{
+    if (m_engines)
+        return;
+
+    m_engines = m_client->queryAvailableEngines(this);
+    if (!m_engines->isWaiting())
+        enginesChanged();
+    else
+        QObject::connect(m_engines, SIGNAL(stateChanged(QmlDebugQuery::State)), 
+                         this, SLOT(enginesChanged()));
+}
+
+void EnginePane::enginesChanged()
+{
+    qDeleteAll(m_engineItems);
+    m_engineItems.clear();
+
+    QList<QmlDebugEngineReference> engines = m_engines->engines();
+    delete m_engines; m_engines = 0;
+
+    if (engines.isEmpty())
+        qWarning("qmldebugger: no engines found!");
+
+    for (int ii = 0; ii < engines.count(); ++ii)
+        m_engineItems << new DebuggerEngineItem(engines.at(ii).name(),
+                                                engines.at(ii).debugId());
+
+    m_engineView->rootContext()->setContextProperty("engines", qVariantFromValue(&m_engineItems));
+
+    m_engineView->setVisible(m_engineItems.count() > 1);
+    if (m_engineItems.count() == 1)
+        engineSelected(qobject_cast<DebuggerEngineItem*>(m_engineItems.at(0))->engineId());
+}
+
+
+#include "engine.moc"
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/qmlinspector/components/engine.h b/src/plugins/qmlinspector/components/engine.h
new file mode 100644
index 00000000000..9f232e68e1d
--- /dev/null
+++ b/src/plugins/qmlinspector/components/engine.h
@@ -0,0 +1,91 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 ENGINE_H
+#define ENGINE_H
+
+#include <private/qmldebug_p.h>
+
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlview.h>
+
+#include <QtCore/qpointer.h>
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_NAMESPACE
+
+class ObjectPropertiesView;
+class QmlDebugConnection;
+class QmlDebugPropertyReference;
+class QmlDebugWatch;
+class ObjectTree;
+class WatchTableModel;
+class WatchTableView;
+class ExpressionQueryWidget;
+
+class QTabWidget;
+
+class EnginePane : public QWidget
+{
+Q_OBJECT
+public:
+    EnginePane(QmlDebugConnection *, QWidget *parent = 0);
+
+public slots:
+    void refreshEngines();
+
+private slots:
+    void enginesChanged();
+
+    void queryContext(int);
+    void contextChanged();
+
+    void engineSelected(int);
+
+private:
+    QmlEngineDebug *m_client;
+    QmlDebugEnginesQuery *m_engines;
+    QmlDebugRootContextQuery *m_context;
+
+    ObjectTree *m_objTree;
+    QTabWidget *m_tabs;
+    WatchTableView *m_watchTableView;
+    WatchTableModel *m_watchTableModel;
+    ExpressionQueryWidget *m_exprQueryWidget;
+
+    QmlView *m_engineView;
+    QList<QObject *> m_engineItems;
+
+    ObjectPropertiesView *m_propertiesView;
+};
+
+QT_END_NAMESPACE
+
+#endif // ENGINE_H
+
diff --git a/src/plugins/qmlinspector/components/engine.png b/src/plugins/qmlinspector/components/engine.png
new file mode 100644
index 0000000000000000000000000000000000000000..a0a8a04a63bc865dd84d179783a39f19fda30571
GIT binary patch
literal 6394
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%0DU(0@19XC
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
IM6N<$f@bPMkpKVy

literal 0
HcmV?d00001

diff --git a/src/plugins/qmlinspector/components/engines.qml b/src/plugins/qmlinspector/components/engines.qml
new file mode 100644
index 00000000000..1e9335b5883
--- /dev/null
+++ b/src/plugins/qmlinspector/components/engines.qml
@@ -0,0 +1,46 @@
+import Qt 4.6
+
+Item {
+    height: 100
+    id: Root
+    signal engineClicked(int id)
+    signal refreshEngines()
+
+    Row {
+        anchors.fill: parent
+        Repeater {
+            model: engines
+            Item {
+                width: 100; height: 100;
+                Image { 
+                    id: EngineIcon; 
+                    source: "qrc:/engine.png"
+                    anchors.horizontalCenter: parent.horizontalCenter
+                }
+                Text { 
+                    anchors.top: EngineIcon.bottom; 
+                    text: modelData.name + "(" + modelData.engineId + ")"
+                    anchors.horizontalCenter: parent.horizontalCenter
+                }
+                MouseRegion {
+                    anchors.fill: parent
+                    onClicked: Root.engineClicked(modelData.engineId);
+                }
+            }
+        }
+    }
+
+
+    Image { 
+        y: 15
+        source: "qrc:/refresh.png";
+        width: 75; 
+        height: 63; 
+        smooth: true 
+        anchors.right: parent.right
+        MouseRegion {
+            anchors.fill: parent
+            onClicked: Root.refreshEngines()
+        }
+    }
+}
diff --git a/src/plugins/qmlinspector/components/expressionquerywidget.cpp b/src/plugins/qmlinspector/components/expressionquerywidget.cpp
new file mode 100644
index 00000000000..94299c0b029
--- /dev/null
+++ b/src/plugins/qmlinspector/components/expressionquerywidget.cpp
@@ -0,0 +1,264 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 "expressionquerywidget.h"
+
+#include <QtCore/qdebug.h>
+
+#include <QtGui/qlabel.h>
+#include <QtGui/qtextedit.h>
+#include <QtGui/qlineedit.h>
+#include <QtGui/qpushbutton.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qgroupbox.h>
+#include <QtGui/qtextobject.h>
+#include <QtGui/qlayout.h>
+
+ExpressionQueryWidget::ExpressionQueryWidget(Mode mode, QmlEngineDebug *client, QWidget *parent)
+    : QWidget(parent),
+      m_mode(mode),
+      m_client(client),
+      m_query(0),
+      m_textEdit(new QTextEdit),
+      m_lineEdit(0)
+{
+    m_prompt = QLatin1String(">> ");
+
+    QVBoxLayout *layout = new QVBoxLayout(this);
+    layout->setMargin(0);
+    layout->setSpacing(0);
+    layout->addWidget(m_textEdit);
+
+    updateTitle();
+
+    if (m_mode == SeparateEntryMode) {
+        m_lineEdit = new QLineEdit;
+        connect(m_lineEdit, SIGNAL(returnPressed()), SLOT(executeExpression()));
+        QHBoxLayout *hbox = new QHBoxLayout;
+        hbox->setMargin(5);
+        hbox->setSpacing(5);
+        hbox->addWidget(new QLabel(tr("Expression:")));
+        hbox->addWidget(m_lineEdit);
+        layout->addLayout(hbox);
+
+        m_textEdit->setReadOnly(true);
+        m_lineEdit->installEventFilter(this);
+    } else {
+        m_textEdit->installEventFilter(this);
+        appendPrompt();
+    }
+}
+
+void ExpressionQueryWidget::setEngineDebug(QmlEngineDebug *client)
+{
+    m_client = client;
+}
+
+void ExpressionQueryWidget::clear()
+{
+    m_textEdit->clear();
+    if (m_lineEdit)
+        m_lineEdit->clear();
+    if (m_mode == ShellMode)
+        appendPrompt();
+}
+
+void ExpressionQueryWidget::updateTitle()
+{
+    if (m_currObject.debugId() < 0) {
+        m_title = tr("Expression queries");
+    } else {
+        QString desc = QLatin1String("<")
+            + m_currObject.className() + QLatin1String(": ")
+            + (m_currObject.name().isEmpty() ? QLatin1String("<unnamed>") : m_currObject.name())
+            + QLatin1String(">");
+        m_title = tr("Expression queries (using context for %1)" , "Selected object").arg(desc);
+    }
+}
+
+void ExpressionQueryWidget::appendPrompt()
+{
+    m_textEdit->moveCursor(QTextCursor::End);
+
+    if (m_mode == SeparateEntryMode) {
+        m_textEdit->insertPlainText("\n");
+    } else {
+        m_textEdit->setTextColor(Qt::gray);
+        m_textEdit->append(m_prompt);
+    }
+}
+
+void ExpressionQueryWidget::setCurrentObject(const QmlDebugObjectReference &obj)
+{
+    m_currObject = obj;
+    updateTitle();
+}
+
+void ExpressionQueryWidget::checkCurrentContext()
+{
+    m_textEdit->moveCursor(QTextCursor::End);
+
+    if (m_currObject.debugId() != -1 && m_currObject.debugId() != m_objectAtLastFocus.debugId())
+        showCurrentContext();
+    m_objectAtLastFocus = m_currObject;
+}
+
+void ExpressionQueryWidget::showCurrentContext()
+{
+    if (m_mode == ShellMode) {
+        // clear the initial prompt
+        if (m_textEdit->document()->lineCount() == 1)
+            m_textEdit->clear();
+    }
+
+    m_textEdit->moveCursor(QTextCursor::End);
+    m_textEdit->setTextColor(Qt::darkGreen);
+    m_textEdit->append(m_currObject.className()
+            + QLatin1String(": ")
+            + (m_currObject.name().isEmpty() ? QLatin1String("<unnamed object>") : m_currObject.name()));
+    appendPrompt();
+}
+
+void ExpressionQueryWidget::executeExpression()
+{
+    if (!m_client)
+        return;
+        
+    if (m_mode == SeparateEntryMode)
+        m_expr = m_lineEdit->text().trimmed();
+    else
+        m_expr = m_expr.trimmed();
+
+    if (!m_expr.isEmpty() && m_currObject.debugId() != -1) {
+        if (m_query)
+            delete m_query;
+        m_query = m_client->queryExpressionResult(m_currObject.debugId(), m_expr, this);
+        if (!m_query->isWaiting())
+            showResult();
+        else
+            QObject::connect(m_query, SIGNAL(stateChanged(QmlDebugQuery::State)),
+                            this, SLOT(showResult()));
+
+        m_lastExpr = m_expr;
+        if (m_lineEdit)
+            m_lineEdit->clear();
+    }
+}
+
+void ExpressionQueryWidget::showResult()
+{
+    if (m_query) {
+        m_textEdit->moveCursor(QTextCursor::End);
+        QVariant value = m_query->result();
+        QString result;
+        
+        if (value.type() == QVariant::List || value.type() == QVariant::StringList) {
+            result = tr("<%1 items>", "%1 = number of items").arg(value.toList().count());
+        } else if (value.isNull()) {
+            result = QLatin1String("<no value>");
+        } else {
+            result = value.toString();
+        }
+
+        if (m_mode == SeparateEntryMode) {
+            m_textEdit->setTextColor(Qt::black);
+            m_textEdit->setFontWeight(QFont::Bold);
+            m_textEdit->insertPlainText(m_expr + " : ");
+            m_textEdit->setFontWeight(QFont::Normal);
+            m_textEdit->insertPlainText(result);
+        } else {
+            m_textEdit->setTextColor(Qt::darkGreen);
+            m_textEdit->insertPlainText(" => ");
+            m_textEdit->setTextColor(Qt::black);
+            m_textEdit->insertPlainText(result);
+        }
+        appendPrompt();
+        m_expr.clear();
+    }
+}
+
+bool ExpressionQueryWidget::eventFilter(QObject *obj, QEvent *event)
+{
+    if (obj == m_textEdit) {
+        switch (event->type()) {
+            case QEvent::KeyPress:
+            {
+                QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
+                int key = keyEvent->key();
+                if (key == Qt::Key_Return || key == Qt::Key_Enter) {
+                    executeExpression();
+                    return true;
+                } else if (key == Qt::Key_Backspace) {
+                    // ensure m_expr doesn't contain backspace characters
+                    QTextCursor cursor = m_textEdit->textCursor();
+                    bool atLastLine = !(cursor.block().next().isValid());
+                    if (!atLastLine)
+                        return true;
+                    if (cursor.columnNumber() <= m_prompt.count())
+                        return true;
+                    cursor.deletePreviousChar();
+                    m_expr = cursor.block().text().mid(m_prompt.count());
+                    return true;
+                } else {
+                    m_textEdit->moveCursor(QTextCursor::End);
+                    m_textEdit->setTextColor(Qt::black);
+                    m_expr += keyEvent->text();
+                }
+                break;
+            }
+            case QEvent::FocusIn:
+                checkCurrentContext();
+                m_textEdit->moveCursor(QTextCursor::End);
+                break;
+            default:
+                break;
+        }
+    } else if (obj == m_lineEdit) {
+        switch (event->type()) {
+            case QEvent::KeyPress:
+            {
+                QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
+                int key = keyEvent->key();
+                if (key == Qt::Key_Up && m_lineEdit->text() != m_lastExpr) {
+                    m_expr = m_lineEdit->text();
+                    if (!m_lastExpr.isEmpty())
+                        m_lineEdit->setText(m_lastExpr);
+                } else if (key == Qt::Key_Down) {
+                    m_lineEdit->setText(m_expr);
+                }
+                break;
+            }
+            case QEvent::FocusIn:
+                checkCurrentContext();
+                break;
+            default:
+                break;
+        }
+    }
+    return QWidget::eventFilter(obj, event);
+}
diff --git a/src/plugins/qmlinspector/components/expressionquerywidget.h b/src/plugins/qmlinspector/components/expressionquerywidget.h
new file mode 100644
index 00000000000..f2315b54596
--- /dev/null
+++ b/src/plugins/qmlinspector/components/expressionquerywidget.h
@@ -0,0 +1,94 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 EXPRESSIONQUERYWIDGET_H
+#define EXPRESSIONQUERYWIDGET_H
+
+#include <private/qmldebug_p.h>
+
+#include <QtGui/qwidget.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class QGroupBox;
+class QTextEdit;
+class QLineEdit;
+class QPushButton;
+
+class ExpressionQueryWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    enum Mode {
+        SeparateEntryMode,
+        ShellMode
+    };
+
+    ExpressionQueryWidget(Mode mode = SeparateEntryMode, QmlEngineDebug *client = 0, QWidget *parent = 0);
+    
+    void setEngineDebug(QmlEngineDebug *client);
+    void clear();
+
+protected:
+    bool eventFilter(QObject *obj, QEvent *event);
+
+public slots:
+    void setCurrentObject(const QmlDebugObjectReference &obj);
+
+private slots:
+    void executeExpression();
+    void showResult();
+
+private:
+    void appendPrompt();
+    void checkCurrentContext();
+    void showCurrentContext();
+    void updateTitle();
+
+    Mode m_mode;
+
+    QmlEngineDebug *m_client;
+    QmlDebugExpressionQuery *m_query;
+    QTextEdit *m_textEdit;
+    QLineEdit *m_lineEdit;
+    QPushButton *m_button;
+    QString m_prompt;
+    QString m_expr;
+    QString m_lastExpr;
+
+    QString m_title;
+
+    QmlDebugObjectReference m_currObject;
+    QmlDebugObjectReference m_objectAtLastFocus;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/plugins/qmlinspector/components/objectpropertiesview.cpp b/src/plugins/qmlinspector/components/objectpropertiesview.cpp
new file mode 100644
index 00000000000..b82a9b30706
--- /dev/null
+++ b/src/plugins/qmlinspector/components/objectpropertiesview.cpp
@@ -0,0 +1,263 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 "objectpropertiesview.h"
+
+#include <private/qmldebugservice_p.h>
+#include <private/qmldebug_p.h>
+#include <private/qmldebugclient_p.h>
+
+#include <QtCore/qdebug.h>
+
+#include <QtGui/qtreewidget.h>
+#include <QtGui/qlayout.h>
+#include <QtGui/qheaderview.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class PropertiesViewItem : public QObject, public QTreeWidgetItem
+{
+    Q_OBJECT
+public:
+    enum Type {
+        BindingType,
+        OtherType
+    };
+    
+    PropertiesViewItem(QTreeWidget *widget, Type type = OtherType);
+    PropertiesViewItem(QTreeWidgetItem *parent, Type type = OtherType);
+
+    QmlDebugPropertyReference property;
+    Type type;
+};
+
+PropertiesViewItem::PropertiesViewItem(QTreeWidget *widget, Type type)
+    : QTreeWidgetItem(widget), type(type)
+{
+}
+
+PropertiesViewItem::PropertiesViewItem(QTreeWidgetItem *parent, Type type)
+    : QTreeWidgetItem(parent), type(type)
+{
+}
+
+ObjectPropertiesView::ObjectPropertiesView(QmlEngineDebug *client, QWidget *parent)
+    : QWidget(parent),
+      m_client(client),
+      m_query(0),
+      m_watch(0)
+{
+    QVBoxLayout *layout = new QVBoxLayout;
+    layout->setContentsMargins(0, 0, 0, 0);
+    layout->setSpacing(0);
+    setLayout(layout);
+
+    m_tree = new QTreeWidget(this);
+    m_tree->setAlternatingRowColors(true);
+    m_tree->setExpandsOnDoubleClick(false);
+    m_tree->setHeaderLabels(QStringList()
+            << tr("Name") << tr("Value") << tr("Type"));
+    QObject::connect(m_tree, SIGNAL(itemActivated(QTreeWidgetItem *, int)),
+                     this, SLOT(itemActivated(QTreeWidgetItem *)));
+
+    m_tree->setColumnCount(3);
+    m_tree->header()->setDefaultSectionSize(150);
+
+    layout->addWidget(m_tree);
+}
+
+void ObjectPropertiesView::setEngineDebug(QmlEngineDebug *client)
+{
+    m_client = client;
+}
+
+void ObjectPropertiesView::clear()
+{
+    setObject(QmlDebugObjectReference());
+}
+
+void ObjectPropertiesView::reload(const QmlDebugObjectReference &obj)
+{
+    if (!m_client)
+        return;
+    if (m_query)
+        delete m_query;
+
+    m_query = m_client->queryObjectRecursive(obj, this);
+    if (!m_query->isWaiting())
+        queryFinished();
+    else
+        QObject::connect(m_query, SIGNAL(stateChanged(QmlDebugQuery::State)),
+                         this, SLOT(queryFinished()));
+}
+
+void ObjectPropertiesView::queryFinished()
+{
+    if (!m_client || !m_query)
+        return;
+
+    QmlDebugObjectReference obj = m_query->object();
+
+    QmlDebugWatch *watch = m_client->addWatch(obj, this);
+    if (watch->state() == QmlDebugWatch::Dead) {
+        delete watch;
+        watch = 0;
+    } else {
+        if (m_watch) {
+            m_client->removeWatch(m_watch);
+            delete m_watch;
+        }
+        m_watch = watch;
+        QObject::connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)),
+                        this, SLOT(valueChanged(QByteArray,QVariant)));
+    }
+
+    delete m_query;
+    m_query = 0;
+
+    setObject(obj);
+}
+
+void ObjectPropertiesView::setPropertyValue(PropertiesViewItem *item, const QVariant &value, bool makeGray)
+{
+    if (value.type() == QVariant::List || value.type() == QVariant::StringList) {
+        PropertiesViewItem *bindingItem = static_cast<PropertiesViewItem*>(item->takeChild(item->childCount() - 1));
+        if (bindingItem && bindingItem->type != PropertiesViewItem::BindingType) {
+            delete bindingItem;
+            bindingItem = 0;
+        }    
+            
+        qDeleteAll(item->takeChildren());
+        
+        QVariantList variants = value.toList();
+        item->setText(1, tr("<%1 items>", "%1 = number of items").arg(variants.count()));
+        item->setText(2, QString::fromUtf8(value.typeName()));
+        
+        PropertiesViewItem *child;
+        for (int i=0; i<variants.count(); ++i) {
+            child = new PropertiesViewItem(item);
+            setPropertyValue(child, variants[i], makeGray);
+        }
+        
+        if (bindingItem)
+            item->addChild(bindingItem);
+
+        item->setExpanded(false);
+    } else {
+        item->setText(1, (value.isNull() ? QLatin1String("<no value>") : value.toString()));
+        item->setExpanded(true);
+    }
+    
+    if (makeGray) {
+        for (int i=0; i<m_tree->columnCount(); ++i)
+            item->setForeground(i, Qt::gray);
+    }    
+}
+
+void ObjectPropertiesView::setObject(const QmlDebugObjectReference &object)
+{
+    m_object = object;
+    m_tree->clear();
+
+    QList<QmlDebugPropertyReference> properties = object.properties();
+    for (int i=0; i<properties.count(); ++i) {
+        const QmlDebugPropertyReference &p = properties[i];
+
+        PropertiesViewItem *item = new PropertiesViewItem(m_tree);
+        item->property = p;
+
+        item->setText(0, p.name());
+        item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+        
+        setPropertyValue(item, p.value(), !p.hasNotifySignal());
+        item->setText(2, p.valueTypeName());
+
+        // binding is set after property value to ensure it is added to the end of the
+        // list, if the value is a list
+        if (!p.binding().isEmpty()) {
+            PropertiesViewItem *binding = new PropertiesViewItem(item, PropertiesViewItem::BindingType);
+            binding->setText(1, p.binding());
+            binding->setForeground(1, Qt::darkGreen);
+        }
+    }
+}
+
+void ObjectPropertiesView::watchCreated(QmlDebugWatch *watch)
+{
+    if (watch->objectDebugId() == m_object.debugId()
+            && qobject_cast<QmlDebugPropertyWatch*>(watch)) {
+        connect(watch, SIGNAL(stateChanged(QmlDebugWatch::State)), SLOT(watchStateChanged()));
+        setWatched(qobject_cast<QmlDebugPropertyWatch*>(watch)->name(), true);
+    }
+}
+
+void ObjectPropertiesView::watchStateChanged()
+{
+    QmlDebugWatch *watch = qobject_cast<QmlDebugWatch*>(sender());
+
+    if (watch->objectDebugId() == m_object.debugId()
+            && qobject_cast<QmlDebugPropertyWatch*>(watch)
+            && watch->state() == QmlDebugWatch::Inactive) {
+        setWatched(qobject_cast<QmlDebugPropertyWatch*>(watch)->name(), false);
+    }
+}
+
+void ObjectPropertiesView::setWatched(const QString &property, bool watched)
+{
+    for (int i=0; i<m_tree->topLevelItemCount(); ++i) {
+        PropertiesViewItem *item = static_cast<PropertiesViewItem *>(m_tree->topLevelItem(i));
+        if (item->property.name() == property && item->property.hasNotifySignal()) {
+            QFont font = m_tree->font();
+            font.setBold(watched);
+            item->setFont(0, font);
+        }
+    }
+}
+
+void ObjectPropertiesView::valueChanged(const QByteArray &name, const QVariant &value)
+{
+    for (int i=0; i<m_tree->topLevelItemCount(); ++i) {
+        PropertiesViewItem *item = static_cast<PropertiesViewItem *>(m_tree->topLevelItem(i));
+        if (item->property.name() == name) {
+            setPropertyValue(item, value, !item->property.hasNotifySignal());
+            return;
+        }
+    }
+}
+
+void ObjectPropertiesView::itemActivated(QTreeWidgetItem *i)
+{
+    PropertiesViewItem *item = static_cast<PropertiesViewItem *>(i);
+    if (!item->property.name().isEmpty())
+        emit activated(m_object, item->property);
+}
+
+QT_END_NAMESPACE
+
+#include "objectpropertiesview.moc"
diff --git a/src/plugins/qmlinspector/components/objectpropertiesview.h b/src/plugins/qmlinspector/components/objectpropertiesview.h
new file mode 100644
index 00000000000..2def0b57ccc
--- /dev/null
+++ b/src/plugins/qmlinspector/components/objectpropertiesview.h
@@ -0,0 +1,81 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 PROPERTIESTABLEMODEL_H
+#define PROPERTIESTABLEMODEL_H
+
+#include <private/qmldebug_p.h>
+
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTreeWidget;
+class QTreeWidgetItem;
+class QmlDebugConnection;
+class PropertiesViewItem;
+
+class ObjectPropertiesView : public QWidget
+{
+    Q_OBJECT
+public:
+    ObjectPropertiesView(QmlEngineDebug *client = 0, QWidget *parent = 0);
+
+    void setEngineDebug(QmlEngineDebug *client);
+    void clear();
+    
+signals:
+    void activated(const QmlDebugObjectReference &, const QmlDebugPropertyReference &);
+
+public slots:
+    void reload(const QmlDebugObjectReference &);
+    void watchCreated(QmlDebugWatch *);
+
+private slots:
+    void queryFinished();
+    void watchStateChanged();
+    void valueChanged(const QByteArray &name, const QVariant &value);
+    void itemActivated(QTreeWidgetItem *i);
+
+private:
+    void setObject(const QmlDebugObjectReference &object);
+    void setWatched(const QString &property, bool watched);
+    void setPropertyValue(PropertiesViewItem *item, const QVariant &value, bool makeGray);
+
+    QmlEngineDebug *m_client;
+    QmlDebugObjectQuery *m_query;
+    QmlDebugWatch *m_watch;
+
+    QTreeWidget *m_tree;
+    QmlDebugObjectReference m_object;
+};
+
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmlinspector/components/objecttree.cpp b/src/plugins/qmlinspector/components/objecttree.cpp
new file mode 100644
index 00000000000..cb27f818926
--- /dev/null
+++ b/src/plugins/qmlinspector/components/objecttree.cpp
@@ -0,0 +1,219 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 <QtGui/qevent.h>
+#include <QtGui/qmenu.h>
+#include <QtGui/qaction.h>
+
+#include <QInputDialog>
+
+#include <private/qmldebugservice_p.h>
+#include <private/qmldebug_p.h>
+#include <private/qmldebugclient_p.h>
+
+#include "objecttree.h"
+
+Q_DECLARE_METATYPE(QmlDebugObjectReference)
+
+ObjectTree::ObjectTree(QmlEngineDebug *client, QWidget *parent)
+    : QTreeWidget(parent),
+      m_client(client),
+      m_query(0)
+{
+    setHeaderHidden(true);
+    setMinimumWidth(250);
+    setExpandsOnDoubleClick(false);
+
+    connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
+            SLOT(currentItemChanged(QTreeWidgetItem *)));
+    connect(this, SIGNAL(itemActivated(QTreeWidgetItem *, int)),
+            SLOT(activated(QTreeWidgetItem *)));            
+}
+
+void ObjectTree::setEngineDebug(QmlEngineDebug *client)
+{
+    m_client = client;
+}
+
+void ObjectTree::reload(int objectDebugId)
+{
+    if (!m_client)
+        return;
+        
+    if (m_query) {
+        delete m_query;
+        m_query = 0;
+    }
+
+    m_query = m_client->queryObjectRecursive(QmlDebugObjectReference(objectDebugId), this);
+    if (!m_query->isWaiting())
+        objectFetched();
+    else
+        QObject::connect(m_query, SIGNAL(stateChanged(QmlDebugQuery::State)), 
+                         this, SLOT(objectFetched()));
+}
+
+void ObjectTree::setCurrentObject(int debugId)
+{
+    QTreeWidgetItem *item = findItemByObjectId(debugId);
+    if (item) {
+        setCurrentItem(item);
+        scrollToItem(item);
+        item->setExpanded(true);
+    }
+}
+
+void ObjectTree::objectFetched()
+{
+    dump(m_query->object(), 0);
+    buildTree(m_query->object(), 0);
+    setCurrentItem(topLevelItem(0));
+
+    delete m_query;
+    m_query = 0;
+}
+
+void ObjectTree::currentItemChanged(QTreeWidgetItem *item)
+{
+    if (!item)
+        return;
+
+    QmlDebugObjectReference obj = item->data(0, Qt::UserRole).value<QmlDebugObjectReference>();
+    if (obj.debugId() >= 0)
+        emit currentObjectChanged(obj);
+}
+
+void ObjectTree::activated(QTreeWidgetItem *item)
+{
+    if (!item)
+        return;
+
+    QmlDebugObjectReference obj = item->data(0, Qt::UserRole).value<QmlDebugObjectReference>();
+    if (obj.debugId() >= 0)
+        emit activated(obj);
+}
+
+void ObjectTree::buildTree(const QmlDebugObjectReference &obj, QTreeWidgetItem *parent)
+{
+    if (!parent)
+        clear();
+
+    QTreeWidgetItem *item = parent ? new QTreeWidgetItem(parent) : new QTreeWidgetItem(this);
+    item->setText(0, obj.className());
+    item->setData(0, Qt::UserRole, qVariantFromValue(obj));
+
+    if (parent && obj.contextDebugId() >= 0
+            && obj.contextDebugId() != parent->data(0, Qt::UserRole
+                    ).value<QmlDebugObjectReference>().contextDebugId()) {
+        QmlDebugFileReference source = obj.source();
+        if (!source.url().isEmpty()) {
+            QString toolTipString = QLatin1String("URL: ") + source.url().toString();
+            item->setToolTip(0, toolTipString);
+        }
+        item->setForeground(0, QColor("orange"));
+    } else {
+        item->setExpanded(true);
+    }
+
+    if (obj.contextDebugId() < 0)
+        item->setForeground(0, Qt::lightGray);
+
+    for (int ii = 0; ii < obj.children().count(); ++ii)
+        buildTree(obj.children().at(ii), item);
+}
+
+void ObjectTree::dump(const QmlDebugContextReference &ctxt, int ind)
+{
+    QByteArray indent(ind * 4, ' ');
+    qWarning().nospace() << indent.constData() << ctxt.debugId() << " " 
+                         << qPrintable(ctxt.name());
+
+    for (int ii = 0; ii < ctxt.contexts().count(); ++ii)
+        dump(ctxt.contexts().at(ii), ind + 1);
+
+    for (int ii = 0; ii < ctxt.objects().count(); ++ii)
+        dump(ctxt.objects().at(ii), ind);
+}
+
+void ObjectTree::dump(const QmlDebugObjectReference &obj, int ind)
+{
+    QByteArray indent(ind * 4, ' ');
+    qWarning().nospace() << indent.constData() << qPrintable(obj.className())
+                         << " " << qPrintable(obj.name()) << " " 
+                         << obj.debugId();
+
+    for (int ii = 0; ii < obj.children().count(); ++ii)
+        dump(obj.children().at(ii), ind + 1);
+}
+
+QTreeWidgetItem *ObjectTree::findItemByObjectId(int debugId) const
+{
+    for (int i=0; i<topLevelItemCount(); ++i) {
+        QTreeWidgetItem *item = findItem(topLevelItem(i), debugId);
+        if (item)
+            return item;
+    }
+
+    return 0;
+}
+
+QTreeWidgetItem *ObjectTree::findItem(QTreeWidgetItem *item, int debugId) const
+{
+    if (item->data(0, Qt::UserRole).value<QmlDebugObjectReference>().debugId() == debugId)
+        return item;
+
+    QTreeWidgetItem *child;
+    for (int i=0; i<item->childCount(); ++i) {
+        child = findItem(item->child(i), debugId);
+        if (child)
+            return child;
+    }
+
+    return 0;
+}
+
+void ObjectTree::mousePressEvent(QMouseEvent *me)
+{
+    QTreeWidget::mousePressEvent(me);
+    if (!currentItem())
+        return;
+    if(me->button()  == Qt::RightButton && me->type() == QEvent::MouseButtonPress) {
+        QAction action(tr("Add watch..."), 0);
+        QList<QAction *> actions;
+        actions << &action;
+        QmlDebugObjectReference obj =
+                currentItem()->data(0, Qt::UserRole).value<QmlDebugObjectReference>();
+        if (QMenu::exec(actions, me->globalPos())) {
+            bool ok = false;
+            QString watch = QInputDialog::getText(this, tr("Watch expression"),
+                    tr("Expression:"), QLineEdit::Normal, QString(), &ok);
+            if (ok && !watch.isEmpty()) 
+                emit expressionWatchRequested(obj, watch);
+        }
+    } 
+}
diff --git a/src/plugins/qmlinspector/components/objecttree.h b/src/plugins/qmlinspector/components/objecttree.h
new file mode 100644
index 00000000000..d7ac02c0259
--- /dev/null
+++ b/src/plugins/qmlinspector/components/objecttree.h
@@ -0,0 +1,84 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 OBJECTTREE_H
+#define OBJECTTREE_H
+
+#include <QtGui/qtreewidget.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTreeWidgetItem;
+
+class QmlEngineDebug;
+class QmlDebugObjectReference;
+class QmlDebugObjectQuery;
+class QmlDebugContextReference;
+class QmlDebugConnection;
+
+
+class ObjectTree : public QTreeWidget
+{
+    Q_OBJECT
+public:
+    ObjectTree(QmlEngineDebug *client = 0, QWidget *parent = 0);
+
+    void setEngineDebug(QmlEngineDebug *client);
+    
+signals:
+    void currentObjectChanged(const QmlDebugObjectReference &);
+    void activated(const QmlDebugObjectReference &);
+    void expressionWatchRequested(const QmlDebugObjectReference &, const QString &);
+
+public slots:
+    void reload(int objectDebugId);     // set the root object
+    void setCurrentObject(int debugId); // select an object in the tree
+
+protected:
+    virtual void mousePressEvent(QMouseEvent *);
+
+private slots:
+    void objectFetched();
+    void currentItemChanged(QTreeWidgetItem *);
+    void activated(QTreeWidgetItem *);
+
+private:
+    QTreeWidgetItem *findItemByObjectId(int debugId) const;
+    QTreeWidgetItem *findItem(QTreeWidgetItem *item, int debugId) const;
+    void dump(const QmlDebugContextReference &, int);
+    void dump(const QmlDebugObjectReference &, int);
+    void buildTree(const QmlDebugObjectReference &, QTreeWidgetItem *parent);
+
+    QmlEngineDebug *m_client;
+    QmlDebugObjectQuery *m_query;
+};
+
+QT_END_NAMESPACE
+
+
+#endif
diff --git a/src/plugins/qmlinspector/components/qmldebugger.pri b/src/plugins/qmlinspector/components/qmldebugger.pri
new file mode 100644
index 00000000000..aad5eb14fa8
--- /dev/null
+++ b/src/plugins/qmlinspector/components/qmldebugger.pri
@@ -0,0 +1,16 @@
+QT += network declarative
+contains(QT_CONFIG, opengles2)|contains(QT_CONFIG, opengles1): QT += opengl
+
+# Input
+HEADERS += $$PWD/canvasframerate.h \
+           $$PWD/watchtable.h \
+           $$PWD/objecttree.h \
+           $$PWD/objectpropertiesview.h \
+           $$PWD/expressionquerywidget.h
+
+SOURCES += $$PWD/canvasframerate.cpp \
+           $$PWD/watchtable.cpp \
+           $$PWD/objecttree.cpp \
+           $$PWD/objectpropertiesview.cpp \
+           $$PWD/expressionquerywidget.cpp
+
diff --git a/src/plugins/qmlinspector/components/qmldebugger.qrc b/src/plugins/qmlinspector/components/qmldebugger.qrc
new file mode 100644
index 00000000000..cb53ad5ea6f
--- /dev/null
+++ b/src/plugins/qmlinspector/components/qmldebugger.qrc
@@ -0,0 +1,7 @@
+<RCC>
+    <qresource prefix="/">
+        <file>engines.qml</file>
+        <file>engine.png</file>
+        <file>refresh.png</file>
+    </qresource>
+</RCC>
diff --git a/src/plugins/qmlinspector/components/refresh.png b/src/plugins/qmlinspector/components/refresh.png
new file mode 100644
index 0000000000000000000000000000000000000000..8befc804f22b4a2b1adf57eb012c31b4f95ce7d3
GIT binary patch
literal 6169
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

literal 0
HcmV?d00001

diff --git a/src/plugins/qmlinspector/components/standalone.pro b/src/plugins/qmlinspector/components/standalone.pro
new file mode 100644
index 00000000000..72d051f3154
--- /dev/null
+++ b/src/plugins/qmlinspector/components/standalone.pro
@@ -0,0 +1,19 @@
+DESTDIR = ../../../bin
+TARGET = qmldebugger
+
+include(qmldebugger.pri)
+
+HEADERS += $$PWD/qmldebugger.h \
+           $$PWD/engine.h
+
+SOURCES += $$PWD/qmldebugger.cpp \
+           $$PWD/engine.cpp \
+           $$PWD/main.cpp 
+
+RESOURCES += $$PWD/qmldebugger.qrc
+OTHER_FILES += $$PWD/engines.qml
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+CONFIG += console
diff --git a/src/plugins/qmlinspector/components/watchtable.cpp b/src/plugins/qmlinspector/components/watchtable.cpp
new file mode 100644
index 00000000000..991c44b63d3
--- /dev/null
+++ b/src/plugins/qmlinspector/components/watchtable.cpp
@@ -0,0 +1,354 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 "watchtable.h"
+
+#include <QtCore/qdebug.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qaction.h>
+#include <QtGui/qmenu.h>
+
+#include <private/qmldebug_p.h>
+#include <QtDeclarative/qmlmetatype.h>
+
+QT_BEGIN_NAMESPACE
+
+
+WatchTableModel::WatchTableModel(QmlEngineDebug *client, QObject *parent)
+    : QAbstractTableModel(parent),
+      m_client(client)
+{
+}
+
+WatchTableModel::~WatchTableModel()
+{    
+    for (int i=0; i<m_columns.count(); ++i)
+        delete m_columns[i].watch;
+}
+
+void WatchTableModel::setEngineDebug(QmlEngineDebug *client)
+{
+    m_client = client;
+}
+
+void WatchTableModel::addWatch(QmlDebugWatch *watch, const QString &title)
+{
+    QString property;
+    if (qobject_cast<QmlDebugPropertyWatch *>(watch))
+        property = qobject_cast<QmlDebugPropertyWatch *>(watch)->name();
+
+    connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)),
+            SLOT(watchedValueChanged(QByteArray,QVariant)));
+
+    connect(watch, SIGNAL(stateChanged(QmlDebugWatch::State)), SLOT(watchStateChanged()));
+
+    int col = columnCount(QModelIndex());
+    beginInsertColumns(QModelIndex(), col, col);
+
+    WatchedEntity e;
+    e.title = title;
+    e.hasFirstValue = false;
+    e.property = property;
+    e.watch = watch;
+    m_columns.append(e);
+
+    endInsertColumns();
+}
+
+void WatchTableModel::removeWatch(QmlDebugWatch *watch)
+{
+    int column = columnForWatch(watch);
+    if (column == -1)
+        return;
+
+    WatchedEntity entity = m_columns.takeAt(column);
+
+    for (QList<Value>::Iterator iter = m_values.begin(); iter != m_values.end();) {
+        if (iter->column == column) {
+            iter = m_values.erase(iter);
+        } else {
+            if(iter->column > column)
+                --iter->column;
+            ++iter;
+        }
+    }
+
+    reset();
+}
+
+void WatchTableModel::updateWatch(QmlDebugWatch *watch, const QVariant &value)
+{
+    int column = columnForWatch(watch);
+    if (column == -1)
+        return;
+
+    addValue(column, value);
+
+    if (!m_columns[column].hasFirstValue) {
+        m_columns[column].hasFirstValue = true;
+        m_values[m_values.count() - 1].first = true;
+    }
+}
+
+QmlDebugWatch *WatchTableModel::findWatch(int column) const
+{
+    if (column < m_columns.count())
+        return m_columns.at(column).watch;
+    return 0;
+}
+
+QmlDebugWatch *WatchTableModel::findWatch(int objectDebugId, const QString &property) const
+{
+    for (int i=0; i<m_columns.count(); ++i) {
+        if (m_columns[i].watch->objectDebugId() == objectDebugId
+                && m_columns[i].property == property) {
+            return m_columns[i].watch;
+        }
+    }
+    return 0;
+}
+
+int WatchTableModel::rowCount(const QModelIndex &) const
+{
+    return m_values.count();
+}
+
+int WatchTableModel::columnCount(const QModelIndex &) const
+{
+    return m_columns.count();
+}
+
+QVariant WatchTableModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+    if (orientation == Qt::Horizontal) {
+        if (section < m_columns.count() && role == Qt::DisplayRole)
+            return m_columns.at(section).title;
+    } else {
+        if (role == Qt::DisplayRole)
+            return section + 1;
+    }
+    return QVariant();
+}
+
+QVariant WatchTableModel::data(const QModelIndex &idx, int role) const
+{
+    if (m_values.at(idx.row()).column == idx.column()) {
+        if (role == Qt::DisplayRole) {
+            const QVariant &value = m_values.at(idx.row()).variant;
+            QString str = value.toString();
+
+            if (str.isEmpty() && QmlMetaType::isObject(value.userType())) {
+                QObject *o = QmlMetaType::toQObject(value);
+                if(o) {
+                    QString objectName = o->objectName();
+                    if(objectName.isEmpty())
+                        objectName = QLatin1String("<unnamed>");
+                    str = QLatin1String(o->metaObject()->className()) +
+                          QLatin1String(": ") + objectName;
+                }
+            }
+
+            if(str.isEmpty()) {
+                QDebug d(&str);
+                d << value;
+            }
+            return QVariant(str);
+        } else if(role == Qt::BackgroundRole) {
+            if(m_values.at(idx.row()).first)
+                return QColor(Qt::green);
+            else
+                return QVariant();
+        } else {
+            return QVariant();
+        }
+    } else {
+        return QVariant();
+    }
+}
+
+void WatchTableModel::watchStateChanged()
+{
+    QmlDebugWatch *watch = qobject_cast<QmlDebugWatch*>(sender());
+
+    if (watch && watch->state() == QmlDebugWatch::Inactive) {
+        removeWatch(watch);
+        watch->deleteLater();
+    }
+}
+
+int WatchTableModel::columnForWatch(QmlDebugWatch *watch) const
+{
+    for (int i=0; i<m_columns.count(); ++i) {
+        if (m_columns.at(i).watch == watch)
+            return i;
+    }
+    return -1;
+}
+
+void WatchTableModel::addValue(int column, const QVariant &value)
+{
+    int row = columnCount(QModelIndex());
+    beginInsertRows(QModelIndex(), row, row);
+
+    Value v;
+    v.column = column;
+    v.variant = value;
+    v.first = false;
+    m_values.append(v);
+
+    endInsertRows();
+}
+
+void WatchTableModel::togglePropertyWatch(const QmlDebugObjectReference &object, const QmlDebugPropertyReference &property)
+{
+    if (!m_client || !property.hasNotifySignal())
+        return;
+
+    QmlDebugWatch *watch = findWatch(object.debugId(), property.name());
+    if (watch) {
+        // watch will be deleted in watchStateChanged()
+        m_client->removeWatch(watch);
+        return;
+    }
+
+    watch = m_client->addWatch(property, this);
+    if (watch->state() == QmlDebugWatch::Dead) {
+        delete watch;
+        watch = 0;
+    } else {
+        QString desc = property.name()
+                + QLatin1String(" on\n")
+                + object.className()
+                + QLatin1String(":\n")
+                + (object.name().isEmpty() ? QLatin1String("<unnamed object>") : object.name());
+        addWatch(watch, desc);
+        emit watchCreated(watch);
+    }
+}
+
+void WatchTableModel::watchedValueChanged(const QByteArray &propertyName, const QVariant &value)
+{
+    Q_UNUSED(propertyName);
+    QmlDebugWatch *watch = qobject_cast<QmlDebugWatch*>(sender());
+    if (watch)
+        updateWatch(watch, value);
+}
+
+void WatchTableModel::expressionWatchRequested(const QmlDebugObjectReference &obj, const QString &expr)
+{
+    if (!m_client)
+        return;
+        
+    QmlDebugWatch *watch = m_client->addWatch(obj, expr, this);
+
+    if (watch->state() == QmlDebugWatch::Dead) {
+        delete watch;
+        watch = 0;
+    } else {
+        addWatch(watch, expr);
+        emit watchCreated(watch);
+    }
+}
+
+void WatchTableModel::removeWatchAt(int column)
+{
+    if (!m_client)
+        return;
+        
+    QmlDebugWatch *watch = findWatch(column);
+    if (watch) {
+        m_client->removeWatch(watch);
+        delete watch;
+        watch = 0;
+    }
+}
+
+void WatchTableModel::removeAllWatches()
+{
+    for (int i=0; i<m_columns.count(); ++i) {
+        if (m_client)
+            m_client->removeWatch(m_columns[i].watch);
+        else    
+            delete m_columns[i].watch;
+    }
+    m_columns.clear();
+    m_values.clear();
+    reset();
+}
+
+//----------------------------------------------
+
+WatchTableHeaderView::WatchTableHeaderView(WatchTableModel *model, QWidget *parent)
+    : QHeaderView(Qt::Horizontal, parent),
+      m_model(model)
+{
+    setClickable(true);
+}
+
+void WatchTableHeaderView::mousePressEvent(QMouseEvent *me)
+{
+    QHeaderView::mousePressEvent(me);
+
+    if (me->button() == Qt::RightButton && me->type() == QEvent::MouseButtonPress) {
+        int col = logicalIndexAt(me->pos());
+        if (col >= 0) {
+            QAction action(tr("Stop watching"), 0);
+            QList<QAction *> actions;
+            actions << &action;
+            if (QMenu::exec(actions, me->globalPos()))
+                m_model->removeWatchAt(col);
+        }
+    } 
+}
+
+
+//----------------------------------------------
+
+WatchTableView::WatchTableView(WatchTableModel *model, QWidget *parent)
+    : QTableView(parent),
+      m_model(model)
+{
+    setAlternatingRowColors(true);
+    connect(model, SIGNAL(watchCreated(QmlDebugWatch*)), SLOT(watchCreated(QmlDebugWatch*)));
+    connect(this, SIGNAL(activated(QModelIndex)), SLOT(indexActivated(QModelIndex)));
+}
+
+void WatchTableView::indexActivated(const QModelIndex &index)
+{
+    QmlDebugWatch *watch = m_model->findWatch(index.column());
+    if (watch)
+        emit objectActivated(watch->objectDebugId());
+}
+
+void WatchTableView::watchCreated(QmlDebugWatch *watch)
+{
+    int column = m_model->columnForWatch(watch);
+    resizeColumnToContents(column);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmlinspector/components/watchtable.h b/src/plugins/qmlinspector/components/watchtable.h
new file mode 100644
index 00000000000..e2602671095
--- /dev/null
+++ b/src/plugins/qmlinspector/components/watchtable.h
@@ -0,0 +1,142 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 WATCHTABLEMODEL_H
+#define WATCHTABLEMODEL_H
+
+#include <QtCore/qpointer.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qabstractitemmodel.h>
+
+#include <QtGui/qwidget.h>
+#include <QtGui/qheaderview.h>
+#include <QtGui/qtableview.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlDebugWatch;
+class QmlEngineDebug;
+class QmlDebugConnection;
+class QmlDebugPropertyReference;
+class QmlDebugObjectReference;
+
+class WatchTableModel : public QAbstractTableModel
+{
+    Q_OBJECT
+public:
+    WatchTableModel(QmlEngineDebug *client = 0, QObject *parent = 0);
+    ~WatchTableModel();
+
+    void setEngineDebug(QmlEngineDebug *client);
+    
+    QmlDebugWatch *findWatch(int column) const;
+    int columnForWatch(QmlDebugWatch *watch) const;
+
+    void removeWatchAt(int column);
+    void removeAllWatches();
+
+    int rowCount(const QModelIndex &parent = QModelIndex()) const;
+    int columnCount(const QModelIndex &parent = QModelIndex()) const;
+    QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+signals:
+    void watchCreated(QmlDebugWatch *watch);
+
+public slots:
+    void togglePropertyWatch(const QmlDebugObjectReference &obj, const QmlDebugPropertyReference &prop);
+    void expressionWatchRequested(const QmlDebugObjectReference &, const QString &);
+
+private slots:
+    void watchStateChanged();
+    void watchedValueChanged(const QByteArray &propertyName, const QVariant &value);
+
+private:
+    void addWatch(QmlDebugWatch *watch, const QString &title);
+    void removeWatch(QmlDebugWatch *watch);
+    void updateWatch(QmlDebugWatch *watch, const QVariant &value);
+
+    QmlDebugWatch *findWatch(int objectDebugId, const QString &property) const;
+
+    void addValue(int column, const QVariant &value);
+
+    struct WatchedEntity
+    {
+        QString title;
+        bool hasFirstValue;
+        QString property;
+        QPointer<QmlDebugWatch> watch;
+    };
+
+    struct Value {
+        int column;
+        QVariant variant;
+        bool first;
+    };
+
+    QmlEngineDebug *m_client;
+    QList<WatchedEntity> m_columns;
+    QList<Value> m_values;
+};
+
+
+class WatchTableHeaderView : public QHeaderView
+{
+    Q_OBJECT
+public:
+    WatchTableHeaderView(WatchTableModel *model, QWidget *parent = 0);
+
+protected:
+    void mousePressEvent(QMouseEvent *me);
+
+private:
+    WatchTableModel *m_model;
+};
+
+
+class WatchTableView : public QTableView
+{
+    Q_OBJECT
+public:
+    WatchTableView(WatchTableModel *model, QWidget *parent = 0);
+
+signals:
+    void objectActivated(int objectDebugId);
+
+private slots:
+    void indexActivated(const QModelIndex &index);
+    void watchCreated(QmlDebugWatch *watch);
+
+private:
+    WatchTableModel *m_model;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // WATCHTABLEMODEL_H
diff --git a/src/plugins/qmlinspector/images/logo.png b/src/plugins/qmlinspector/images/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..5ac14a5a81cea8a3482acf218b71df807bc11a26
GIT binary patch
literal 2662
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
U`D=bPHvj+t07*qoM6N<$g2Z_e$p8QV

literal 0
HcmV?d00001

diff --git a/src/plugins/qmlinspector/inspectoroutputpane.cpp b/src/plugins/qmlinspector/inspectoroutputpane.cpp
new file mode 100644
index 00000000000..84b0a1cd57c
--- /dev/null
+++ b/src/plugins/qmlinspector/inspectoroutputpane.cpp
@@ -0,0 +1,138 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 "inspectoroutputpane.h"
+
+#include <QtGui/qtextedit.h>
+
+InspectorOutputPane::InspectorOutputPane(QObject *parent)
+    : Core::IOutputPane(parent),
+      m_textEdit(new QTextEdit)
+{
+}
+
+InspectorOutputPane::~InspectorOutputPane()
+{
+    delete m_textEdit;
+}
+
+QWidget *InspectorOutputPane::outputWidget(QWidget *parent)
+{
+    Q_UNUSED(parent);
+    return m_textEdit;
+}
+
+QList<QWidget*> InspectorOutputPane::toolBarWidgets() const
+{
+    return QList<QWidget *>();
+}
+
+QString InspectorOutputPane::name() const
+{
+    return tr("Inspector Output");
+}
+
+int InspectorOutputPane::priorityInStatusBar() const
+{
+    return 1;
+}
+
+void InspectorOutputPane::clearContents()
+{
+    m_textEdit->clear();
+}
+
+void InspectorOutputPane::visibilityChanged(bool visible)
+{
+    Q_UNUSED(visible);
+}
+
+void InspectorOutputPane::setFocus()
+{
+    m_textEdit->setFocus();
+}
+
+bool InspectorOutputPane::hasFocus()
+{
+    return m_textEdit->hasFocus();
+}
+
+bool InspectorOutputPane::canFocus()
+{
+    return true;
+}
+
+bool InspectorOutputPane::canNavigate()
+{
+    return false;
+}
+
+bool InspectorOutputPane::canNext()
+{
+    return false;
+}
+
+bool InspectorOutputPane::canPrevious()
+{
+    return false;
+}
+
+void InspectorOutputPane::goToNext()
+{
+}
+
+void InspectorOutputPane::goToPrev()
+{
+}
+
+void InspectorOutputPane::addOutput(RunControl *, const QString &text)
+{
+    m_textEdit->insertPlainText(text);
+    m_textEdit->moveCursor(QTextCursor::End);
+}
+
+void InspectorOutputPane::addOutputInline(RunControl *, const QString &text)
+{
+    m_textEdit->insertPlainText(text);
+    m_textEdit->moveCursor(QTextCursor::End);
+}
+
+void InspectorOutputPane::addErrorOutput(RunControl *, const QString &text)
+{
+    m_textEdit->append(text);
+    m_textEdit->moveCursor(QTextCursor::End);
+}
+
+void InspectorOutputPane::addInspectorStatus(const QString &text)
+{
+    m_textEdit->setTextColor(Qt::darkGreen);
+    m_textEdit->append(text);
+    m_textEdit->moveCursor(QTextCursor::End);
+    m_textEdit->setTextColor(Qt::black);
+}
+
diff --git a/src/plugins/qmlinspector/inspectoroutputpane.h b/src/plugins/qmlinspector/inspectoroutputpane.h
new file mode 100644
index 00000000000..3b5b299d508
--- /dev/null
+++ b/src/plugins/qmlinspector/inspectoroutputpane.h
@@ -0,0 +1,82 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 INSPECTOROUTPUTPANE_H
+#define INSPECTOROUTPUTPANE_H 
+
+#include <coreplugin/ioutputpane.h>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QTextEdit;
+
+class RunControl;
+
+class InspectorOutputPane : public Core::IOutputPane
+{
+    Q_OBJECT
+public:
+    InspectorOutputPane(QObject *parent = 0);
+    virtual ~InspectorOutputPane();
+
+    virtual QWidget *outputWidget(QWidget *parent);
+    virtual QList<QWidget*> toolBarWidgets() const;
+    virtual QString name() const;
+
+    virtual int priorityInStatusBar() const;
+
+    virtual void clearContents();
+    virtual void visibilityChanged(bool visible);
+
+    virtual void setFocus();
+    virtual bool hasFocus();
+    virtual bool canFocus();
+
+    virtual bool canNavigate();
+    virtual bool canNext();
+    virtual bool canPrevious();
+    virtual void goToNext();
+    virtual void goToPrev();
+
+public slots:
+    void addOutput(RunControl *, const QString &text);
+    void addOutputInline(RunControl *, const QString &text);
+
+    void addErrorOutput(RunControl *, const QString &text);
+    void addInspectorStatus(const QString &text);
+
+private:
+    QTextEdit *m_textEdit;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/plugins/qmlinspector/qmlinspector.h b/src/plugins/qmlinspector/qmlinspector.h
new file mode 100644
index 00000000000..9c01ab771cb
--- /dev/null
+++ b/src/plugins/qmlinspector/qmlinspector.h
@@ -0,0 +1,53 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 QMLINSPECTOR_H
+#define QMLINSPECTOR_H
+
+#include <QString>
+
+namespace QmlInspector {
+    namespace Constants {
+        const char * const RUN = "QmlInspector.Run";
+        const char * const STOP = "QmlInspector.Stop";
+
+        const char * const C_INSPECTOR = "QmlInspector";
+    };
+    
+    class StartParameters
+    {
+    public:
+        StartParameters() : port(0) {}
+        ~StartParameters() {}
+        
+        QString address;
+        quint16 port;
+    };
+};
+
+#endif
diff --git a/src/plugins/qmlinspector/qmlinspector.pro b/src/plugins/qmlinspector/qmlinspector.pro
new file mode 100644
index 00000000000..7e9a4f1214f
--- /dev/null
+++ b/src/plugins/qmlinspector/qmlinspector.pro
@@ -0,0 +1,27 @@
+TEMPLATE = lib
+TARGET = QmlInspector
+
+INCLUDEPATH += .
+DEPENDPATH += .
+
+include(components/qmldebugger.pri)
+
+HEADERS += qmlinspectorplugin.h \
+           qmlinspector.h \
+           qmlinspectormode.h \
+           inspectoroutputpane.h \
+           runcontrol.h
+
+SOURCES += qmlinspectorplugin.cpp \
+           qmlinspectormode.cpp \
+           inspectoroutputpane.cpp \
+           runcontrol.cpp 
+
+OTHER_FILES += QmlInspector.pluginspec
+RESOURCES += qmlinspector.qrc
+
+include(../../qtcreatorplugin.pri)
+include(../../plugins/projectexplorer/projectexplorer.pri)
+include(../../plugins/coreplugin/coreplugin.pri)
+include(../../plugins/texteditor/texteditor.pri)
+
diff --git a/src/plugins/qmlinspector/qmlinspector.qrc b/src/plugins/qmlinspector/qmlinspector.qrc
new file mode 100644
index 00000000000..45e8ddaad5d
--- /dev/null
+++ b/src/plugins/qmlinspector/qmlinspector.qrc
@@ -0,0 +1,6 @@
+<RCC>
+    <qresource prefix="/qmlinspector" >
+        <file>images/logo.png</file>
+    </qresource>
+</RCC>
+
diff --git a/src/plugins/qmlinspector/qmlinspectormode.cpp b/src/plugins/qmlinspector/qmlinspectormode.cpp
new file mode 100644
index 00000000000..636c488defb
--- /dev/null
+++ b/src/plugins/qmlinspector/qmlinspectormode.cpp
@@ -0,0 +1,555 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 "qmlinspector.h"
+#include "qmlinspectormode.h"
+
+#include "components/objectpropertiesview.h"
+#include "components/objecttree.h"
+#include "components/watchtable.h"
+#include "components/canvasframerate.h"
+#include "components/expressionquerywidget.h"
+
+#include <private/qmldebug_p.h>
+#include <private/qmldebugclient_p.h>
+
+#include <utils/styledbar.h>
+#include <utils/fancymainwindow.h>
+
+#include <coreplugin/basemode.h>
+#include <coreplugin/findplaceholder.h>
+#include <coreplugin/minisplitter.h>
+#include <coreplugin/outputpane.h>
+#include <coreplugin/rightpane.h>
+#include <coreplugin/navigationwidget.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/uniqueidmanager.h>
+
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+
+#include <texteditor/itexteditor.h>
+
+#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/project.h>
+
+#include <QtCore/QStringList>
+#include <QtCore/QtPlugin>
+#include <QtCore/QDebug>
+
+#include <QtGui/qtoolbutton.h>
+#include <QtGui/qtoolbar.h>
+#include <QtGui/qboxlayout.h>
+#include <QtGui/qlabel.h>
+#include <QtGui/qdockwidget.h>
+#include <QtGui/qaction.h>
+#include <QtGui/qlineedit.h>
+#include <QtGui/qlabel.h>
+#include <QtGui/qspinbox.h>
+
+
+QT_BEGIN_NAMESPACE
+
+
+class EngineSpinBox : public QSpinBox
+{
+    Q_OBJECT
+public:
+    struct EngineInfo
+    {
+        QString name;
+        int id;
+    };
+
+    EngineSpinBox(QWidget *parent = 0);
+
+    void addEngine(int engine, const QString &name);
+    void clearEngines();
+
+protected:
+    virtual QString textFromValue(int value) const;
+    virtual int valueFromText(const QString &text) const;
+
+private:
+    QList<EngineInfo> m_engines;
+};
+
+EngineSpinBox::EngineSpinBox(QWidget *parent)
+    : QSpinBox(parent)
+{
+    setEnabled(false);
+    setReadOnly(true);
+    setRange(0, 0);
+}
+
+void EngineSpinBox::addEngine(int engine, const QString &name)
+{
+    EngineInfo info;
+    info.id = engine;
+    if (name.isEmpty())
+        info.name = tr("Engine %1", "engine number").arg(engine);
+    else
+        info.name = name;
+    m_engines << info;
+
+    setRange(0, m_engines.count()-1);
+}
+
+void EngineSpinBox::clearEngines()
+{
+    m_engines.clear();
+}
+
+QString EngineSpinBox::textFromValue(int value) const
+{
+    for (int i=0; i<m_engines.count(); ++i) {
+        if (m_engines[i].id == value)
+            return m_engines[i].name;
+    }
+    return QLatin1String("<None>");
+}
+
+int EngineSpinBox::valueFromText(const QString &text) const
+{
+    for (int i=0; i<m_engines.count(); ++i) {
+        if (m_engines[i].name == text)
+            return m_engines[i].id;
+    }
+    return -1;
+}
+
+
+QmlInspectorMode::QmlInspectorMode(QObject *parent)
+  : Core::BaseMode(parent),
+    m_conn(0),
+    m_client(0),
+    m_engineQuery(0),
+    m_contextQuery(0)
+{    
+    m_watchTableModel = new WatchTableModel(0, this);
+
+    initActions();
+    setWidget(createModeWindow());
+
+    setName(tr("QML Inspect"));
+    setIcon(QIcon(":/qmlinspector/images/logo.png"));
+    setUniqueModeName("QML_INSPECT_MODE");    
+}
+
+quint16 QmlInspectorMode::viewerPort() const
+{
+    return m_portSpinBox->value();
+}
+
+void QmlInspectorMode::connectToViewer()
+{
+    if (m_conn && m_conn->state() != QAbstractSocket::UnconnectedState)
+        return;
+
+    delete m_client; m_client = 0;
+
+    if (m_conn) {
+        m_conn->disconnectFromHost();
+        delete m_conn;
+    }
+
+    m_conn = new QmlDebugConnection(this);
+    connect(m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
+            SLOT(connectionStateChanged()));
+    connect(m_conn, SIGNAL(error(QAbstractSocket::SocketError)),
+            SLOT(connectionError()));
+    m_conn->connectToHost(m_addressEdit->text(), m_portSpinBox->value());
+}
+
+void QmlInspectorMode::disconnectFromViewer()
+{
+    m_conn->disconnectFromHost();
+}
+
+void QmlInspectorMode::connectionStateChanged()
+{
+    switch (m_conn->state()) {
+        default:
+        case QAbstractSocket::UnconnectedState:
+        {
+            emit statusMessage(tr("[Inspector] disconnected.\n\n"));
+            m_addressEdit->setEnabled(true);
+            m_portSpinBox->setEnabled(true);
+
+            delete m_engineQuery;
+            m_engineQuery = 0;
+            delete m_contextQuery;
+            m_contextQuery = 0;
+            break;
+        }
+        case QAbstractSocket::HostLookupState:
+            emit statusMessage(tr("[Inspector] resolving host..."));
+            break;
+        case QAbstractSocket::ConnectingState:
+            emit statusMessage(tr("[Inspector] connecting to debug server..."));
+            break;
+        case QAbstractSocket::ConnectedState:
+        {
+            emit statusMessage(tr("[Inspector] connected.\n"));
+            m_addressEdit->setEnabled(false);
+            m_portSpinBox->setEnabled(false);
+
+            if (!m_client) {
+                m_client = new QmlEngineDebug(m_conn, this);
+                m_objectTreeWidget->setEngineDebug(m_client);
+                m_propertiesWidget->setEngineDebug(m_client);
+                m_watchTableModel->setEngineDebug(m_client);
+                m_expressionWidget->setEngineDebug(m_client);
+            }
+            
+            m_objectTreeWidget->clear();
+            m_propertiesWidget->clear();
+            m_expressionWidget->clear();
+            m_watchTableModel->removeAllWatches();
+            m_frameRateWidget->reset(m_conn);
+
+            reloadEngines();
+            break;
+        }
+        case QAbstractSocket::ClosingState:
+            emit statusMessage(tr("[Inspector] closing..."));
+            break;
+    }
+}
+
+void QmlInspectorMode::connectionError()
+{
+    emit statusMessage(tr("[Inspector] error: (%1) %2", "%1=error code, %2=error message")
+            .arg(m_conn->error()).arg(m_conn->errorString()));
+}
+
+void QmlInspectorMode::initActions()
+{
+    m_actions.startAction = new QAction(tr("Start Inspector"), this);
+    m_actions.startAction->setIcon(QIcon(ProjectExplorer::Constants::ICON_RUN));
+    
+    m_actions.stopAction = new QAction(tr("Stop Inspector"), this);
+    m_actions.stopAction->setIcon(QIcon(ProjectExplorer::Constants::ICON_STOP));
+
+    Core::ICore *core = Core::ICore::instance();
+    Core::ActionManager *am = core->actionManager();
+    Core::UniqueIDManager *uidm = core->uniqueIDManager();
+
+    QList<int> context;
+    context << uidm->uniqueIdentifier(QmlInspector::Constants::C_INSPECTOR);
+
+    am->registerAction(m_actions.startAction, QmlInspector::Constants::RUN, context);
+    connect(m_actions.startAction, SIGNAL(triggered()), SIGNAL(startViewer()));
+    
+    am->registerAction(m_actions.stopAction, QmlInspector::Constants::STOP, context);
+    connect(m_actions.stopAction, SIGNAL(triggered()), SIGNAL(stopViewer()));
+}    
+
+
+QToolButton *QmlInspectorMode::createToolButton(QAction *action)
+{
+    QToolButton *button = new QToolButton;
+    button->setDefaultAction(action);
+    return button;
+}
+
+QWidget *QmlInspectorMode::createMainView()
+{
+    initWidgets();
+
+    Utils::FancyMainWindow *mainWindow = new Utils::FancyMainWindow;
+    mainWindow->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North);
+    mainWindow->setDocumentMode(true);
+
+    QBoxLayout *editorHolderLayout = new QVBoxLayout;
+    editorHolderLayout->setMargin(0);
+    editorHolderLayout->setSpacing(0);
+
+    QWidget *editorAndFindWidget = new QWidget;
+    editorAndFindWidget->setLayout(editorHolderLayout);
+    editorHolderLayout->addWidget(new Core::EditorManagerPlaceHolder(this));
+    editorHolderLayout->addWidget(new Core::FindToolBarPlaceHolder(editorAndFindWidget));
+
+    Utils::StyledBar *treeOptionBar = new Utils::StyledBar;
+    QHBoxLayout *treeOptionBarLayout = new QHBoxLayout(treeOptionBar);
+    treeOptionBarLayout->setContentsMargins(5, 0, 5, 0);
+    treeOptionBarLayout->setSpacing(5);
+    treeOptionBarLayout->addWidget(new QLabel(tr("QML engine:")));
+    treeOptionBarLayout->addWidget(m_engineSpinBox);
+
+    QWidget *treeWindow = new QWidget;
+    QVBoxLayout *treeWindowLayout = new QVBoxLayout(treeWindow);
+    treeWindowLayout->setMargin(0);
+    treeWindowLayout->setSpacing(0);
+    treeWindowLayout->addWidget(treeOptionBar);
+    treeWindowLayout->addWidget(m_objectTreeWidget);    
+
+    Core::MiniSplitter *documentAndTree = new Core::MiniSplitter;
+    documentAndTree->addWidget(editorAndFindWidget);
+    documentAndTree->addWidget(new Core::RightPanePlaceHolder(this));
+    documentAndTree->addWidget(treeWindow);
+    documentAndTree->setStretchFactor(0, 2);
+    documentAndTree->setStretchFactor(1, 0);
+    documentAndTree->setStretchFactor(2, 0);
+
+    Utils::StyledBar *configBar = new Utils::StyledBar;
+    configBar->setProperty("topBorder", true);
+
+    QHBoxLayout *configBarLayout = new QHBoxLayout(configBar);
+    configBarLayout->setMargin(0);
+    configBarLayout->setSpacing(5);
+    
+    Core::ICore *core = Core::ICore::instance();
+    Core::ActionManager *am = core->actionManager();    
+    configBarLayout->addWidget(createToolButton(am->command(QmlInspector::Constants::RUN)->action()));
+    configBarLayout->addWidget(createToolButton(am->command(QmlInspector::Constants::STOP)->action()));
+    configBarLayout->addWidget(m_addressEdit);
+    configBarLayout->addWidget(m_portSpinBox);
+    configBarLayout->addStretch();
+       
+    QWidget *widgetAboveTabs = new QWidget;
+    QVBoxLayout *widgetAboveTabsLayout = new QVBoxLayout(widgetAboveTabs);
+    widgetAboveTabsLayout->setMargin(0);
+    widgetAboveTabsLayout->setSpacing(0);    
+    widgetAboveTabsLayout->addWidget(documentAndTree);
+    widgetAboveTabsLayout->addWidget(configBar); 
+    
+    Core::MiniSplitter *mainSplitter = new Core::MiniSplitter(Qt::Vertical);    
+    mainSplitter->addWidget(widgetAboveTabs);
+    mainSplitter->addWidget(createBottomWindow());
+    mainSplitter->setStretchFactor(0, 3);
+    mainSplitter->setStretchFactor(1, 1);    
+
+    QWidget *centralWidget = new QWidget;
+    QVBoxLayout *centralLayout = new QVBoxLayout(centralWidget);
+    centralLayout->setMargin(0);
+    centralLayout->setSpacing(0);
+    centralLayout->addWidget(mainSplitter);
+
+    mainWindow->setCentralWidget(centralWidget);
+   
+    return mainWindow;
+}
+
+QWidget *QmlInspectorMode::createBottomWindow()
+{
+    Utils::FancyMainWindow *win = new Utils::FancyMainWindow;
+    win->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North);
+    win->setDocumentMode(true);
+    win->setTrackingEnabled(true);
+
+    Core::MiniSplitter *leftSplitter = new Core::MiniSplitter(Qt::Vertical);    
+    leftSplitter->addWidget(m_propertiesWidget);
+    leftSplitter->addWidget(m_expressionWidget);
+    leftSplitter->setStretchFactor(0, 2);
+    leftSplitter->setStretchFactor(1, 1);
+
+    Core::MiniSplitter *propSplitter = new Core::MiniSplitter(Qt::Horizontal);    
+    propSplitter->addWidget(leftSplitter);
+    propSplitter->addWidget(m_watchTableView);
+    propSplitter->setStretchFactor(0, 2);
+    propSplitter->setStretchFactor(1, 1);
+    propSplitter->setWindowTitle(tr("Properties and Watchers"));
+
+    QDockWidget *propertiesDock = win->addDockForWidget(propSplitter);
+    win->addDockWidget(Qt::TopDockWidgetArea, propertiesDock);
+
+    QDockWidget *frameRateDock = win->addDockForWidget(m_frameRateWidget);
+    win->addDockWidget(Qt::TopDockWidgetArea, frameRateDock);
+
+    // stack the dock widgets as tabs
+    win->tabifyDockWidget(frameRateDock, propertiesDock);
+
+    return win;
+}
+
+QWidget *QmlInspectorMode::createModeWindow()
+{
+    // right-side window with editor, output etc.
+    Core::MiniSplitter *mainWindowSplitter = new Core::MiniSplitter;
+    mainWindowSplitter->addWidget(createMainView());
+    mainWindowSplitter->addWidget(new Core::OutputPanePlaceHolder(this));
+    mainWindowSplitter->setStretchFactor(0, 10);
+    mainWindowSplitter->setStretchFactor(1, 0);
+    mainWindowSplitter->setOrientation(Qt::Vertical);
+
+    // navigation + right-side window
+    Core::MiniSplitter *splitter = new Core::MiniSplitter;
+    splitter->addWidget(new Core::NavigationWidgetPlaceHolder(this));
+    splitter->addWidget(mainWindowSplitter);
+    splitter->setStretchFactor(0, 0);
+    splitter->setStretchFactor(1, 1);
+    return splitter;
+}
+
+void QmlInspectorMode::initWidgets()
+{
+    m_objectTreeWidget = new ObjectTree;
+    m_propertiesWidget = new ObjectPropertiesView;
+    m_watchTableView = new WatchTableView(m_watchTableModel);
+    m_frameRateWidget = new CanvasFrameRate;
+    m_expressionWidget = new ExpressionQueryWidget(ExpressionQueryWidget::ShellMode);
+
+    // FancyMainWindow uses widgets' window titles for tab labels
+    m_objectTreeWidget->setWindowTitle(tr("Object Tree"));
+    m_frameRateWidget->setWindowTitle(tr("Frame rate"));
+    
+    m_watchTableView->setModel(m_watchTableModel);
+    WatchTableHeaderView *header = new WatchTableHeaderView(m_watchTableModel);
+    m_watchTableView->setHorizontalHeader(header);
+
+    connect(m_objectTreeWidget, SIGNAL(activated(QmlDebugObjectReference)),
+            this, SLOT(treeObjectActivated(QmlDebugObjectReference)));
+
+    connect(m_objectTreeWidget, SIGNAL(currentObjectChanged(QmlDebugObjectReference)),
+            m_propertiesWidget, SLOT(reload(QmlDebugObjectReference)));
+
+    connect(m_objectTreeWidget, SIGNAL(expressionWatchRequested(QmlDebugObjectReference,QString)),
+            m_watchTableModel, SLOT(expressionWatchRequested(QmlDebugObjectReference,QString)));
+
+    connect(m_propertiesWidget, SIGNAL(activated(QmlDebugObjectReference,QmlDebugPropertyReference)),
+            m_watchTableModel, SLOT(togglePropertyWatch(QmlDebugObjectReference,QmlDebugPropertyReference)));
+
+    connect(m_watchTableModel, SIGNAL(watchCreated(QmlDebugWatch*)),
+            m_propertiesWidget, SLOT(watchCreated(QmlDebugWatch*)));
+
+    connect(m_watchTableModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
+            m_watchTableView, SLOT(scrollToBottom()));
+
+    connect(m_watchTableView, SIGNAL(objectActivated(int)),
+            m_objectTreeWidget, SLOT(setCurrentObject(int)));    
+
+    connect(m_objectTreeWidget, SIGNAL(currentObjectChanged(QmlDebugObjectReference)),
+            m_expressionWidget, SLOT(setCurrentObject(QmlDebugObjectReference)));
+
+    m_addressEdit = new QLineEdit;
+    m_addressEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
+    m_addressEdit->setText("127.0.0.1");
+
+    m_portSpinBox = new QSpinBox;
+    m_portSpinBox->setMinimum(1024);
+    m_portSpinBox->setMaximum(20000);
+    m_portSpinBox->setValue(3768);
+
+    m_engineSpinBox = new EngineSpinBox;
+    m_engineSpinBox->setEnabled(false);
+    connect(m_engineSpinBox, SIGNAL(valueChanged(int)),
+            SLOT(queryEngineContext(int))); 
+}
+
+void QmlInspectorMode::reloadEngines()
+{
+    if (m_engineQuery) {
+        emit statusMessage("[Inspector] Waiting for response to previous engine query");
+        return;
+    }
+
+    m_engineSpinBox->setEnabled(false);
+
+    m_engineQuery = m_client->queryAvailableEngines(this);
+    if (!m_engineQuery->isWaiting())
+        enginesChanged();
+    else
+        QObject::connect(m_engineQuery, SIGNAL(stateChanged(QmlDebugQuery::State)), 
+                         this, SLOT(enginesChanged()));    
+}
+
+void QmlInspectorMode::enginesChanged()
+{
+    m_engineSpinBox->clearEngines();
+
+    QList<QmlDebugEngineReference> engines = m_engineQuery->engines();
+    delete m_engineQuery; m_engineQuery = 0;
+
+    if (engines.isEmpty())
+        qWarning("qmldebugger: no engines found!");
+
+    m_engineSpinBox->setEnabled(true);
+
+    for (int i=0; i<engines.count(); ++i)
+        m_engineSpinBox->addEngine(engines.at(i).debugId(), engines.at(i).name());
+
+    if (engines.count() > 0) {
+        m_engineSpinBox->setValue(engines.at(0).debugId());
+        queryEngineContext(engines.at(0).debugId());
+    }
+}
+
+void QmlInspectorMode::queryEngineContext(int id)
+{
+    if (id < 0)
+        return;
+
+    if (m_contextQuery) {
+        delete m_contextQuery;
+        m_contextQuery = 0;
+    }
+
+    m_contextQuery = m_client->queryRootContexts(QmlDebugEngineReference(id), this);
+    if (!m_contextQuery->isWaiting())
+        contextChanged();
+    else
+        QObject::connect(m_contextQuery, SIGNAL(stateChanged(QmlDebugQuery::State)),
+                         this, SLOT(contextChanged()));
+}
+
+void QmlInspectorMode::contextChanged()
+{
+    //dump(m_contextQuery->rootContext(), 0);
+
+    foreach (const QmlDebugObjectReference &object, m_contextQuery->rootContext().objects())
+        m_objectTreeWidget->reload(object.debugId());
+
+    delete m_contextQuery; m_contextQuery = 0;
+}
+
+void QmlInspectorMode::treeObjectActivated(const QmlDebugObjectReference &obj)
+{
+    QmlDebugFileReference source = obj.source();
+    QString fileName = source.url().toLocalFile();
+
+    if (source.lineNumber() < 0 || !QFile::exists(fileName))
+        return;
+
+    Core::EditorManager *editorManager = Core::EditorManager::instance();
+    TextEditor::ITextEditor *editor = qobject_cast<TextEditor::ITextEditor*>(editorManager->openEditor(fileName));
+    if (editor) {
+        editorManager->ensureEditorManagerVisible();
+        editorManager->addCurrentPositionToNavigationHistory();
+        editor->gotoLine(source.lineNumber());
+        editor->widget()->setFocus();
+    }
+}
+
+QT_END_NAMESPACE
+
+#include "qmlinspectormode.moc"
+
diff --git a/src/plugins/qmlinspector/qmlinspectormode.h b/src/plugins/qmlinspector/qmlinspectormode.h
new file mode 100644
index 00000000000..00f136dba2e
--- /dev/null
+++ b/src/plugins/qmlinspector/qmlinspectormode.h
@@ -0,0 +1,121 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 QMLINSPECTORMODE_H
+#define QMLINSPECTORMODE_H
+
+#include <coreplugin/basemode.h>
+
+#include <QtGui/QAction>
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QToolButton;
+class QLineEdit;
+class QSpinBox;
+class QLabel;
+
+class QmlEngineDebug;
+class QmlDebugConnection;
+class QmlDebugEnginesQuery;
+class QmlDebugRootContextQuery;
+class QmlDebugObjectReference;
+class ObjectTree;
+class WatchTableModel;
+class WatchTableView;
+class ObjectPropertiesView;
+class CanvasFrameRate;
+class ExpressionQueryWidget;
+class EngineSpinBox;
+    
+
+class QmlInspectorMode : public Core::BaseMode
+{
+    Q_OBJECT
+
+public:
+    QmlInspectorMode(QObject *parent = 0);
+    
+    
+    quint16 viewerPort() const;
+    
+signals:
+    void startViewer();
+    void stopViewer();
+    void statusMessage(const QString &text);
+    
+public slots: 
+    void connectToViewer(); // using host, port from widgets
+    void disconnectFromViewer(); 
+
+private slots:
+    void connectionStateChanged();
+    void connectionError();
+    void reloadEngines();
+    void enginesChanged();
+    void queryEngineContext(int);
+    void contextChanged();
+    void treeObjectActivated(const QmlDebugObjectReference &obj);
+
+private:
+    struct Actions {
+        QAction *startAction;
+        QAction *stopAction;
+    };
+    
+    void initActions();
+    QWidget *createModeWindow();
+    QWidget *createMainView();
+    void initWidgets();
+    QWidget *createBottomWindow();
+    QToolButton *createToolButton(QAction *action);
+    
+    Actions m_actions;
+    
+    QmlDebugConnection *m_conn;
+    QmlEngineDebug *m_client;
+
+    QmlDebugEnginesQuery *m_engineQuery;
+    QmlDebugRootContextQuery *m_contextQuery;
+    
+    ObjectTree *m_objectTreeWidget;
+    ObjectPropertiesView *m_propertiesWidget;
+    WatchTableModel *m_watchTableModel;
+    WatchTableView *m_watchTableView;
+    CanvasFrameRate *m_frameRateWidget;
+    ExpressionQueryWidget *m_expressionWidget;
+
+    QLineEdit *m_addressEdit;
+    QSpinBox *m_portSpinBox;
+    EngineSpinBox *m_engineSpinBox;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmlinspector/qmlinspectorplugin.cpp b/src/plugins/qmlinspector/qmlinspectorplugin.cpp
new file mode 100644
index 00000000000..a81184b379f
--- /dev/null
+++ b/src/plugins/qmlinspector/qmlinspectorplugin.cpp
@@ -0,0 +1,163 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 "runcontrol.h"
+#include "qmlinspector.h"
+#include "qmlinspectormode.h"
+#include "inspectoroutputpane.h"
+#include "qmlinspectorplugin.h"
+
+#include <private/qmldebug_p.h>
+#include <private/qmldebugclient_p.h>
+
+#include <coreplugin/icore.h>
+
+#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/project.h>
+
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/uniqueidmanager.h>
+
+#include <extensionsystem/pluginmanager.h>
+
+#include <QtCore/QStringList>
+#include <QtCore/QtPlugin>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+
+QmlInspectorPlugin::QmlInspectorPlugin()
+    : m_inspectMode(0),
+      m_runControl(0)
+{
+}
+
+QmlInspectorPlugin::~QmlInspectorPlugin()
+{
+}
+
+void QmlInspectorPlugin::shutdown()
+{
+    removeObject(m_inspectMode);
+    delete m_inspectMode;
+    m_inspectMode = 0;
+
+    removeObject(m_outputPane);
+    delete m_outputPane;
+    m_outputPane = 0;
+}
+
+bool QmlInspectorPlugin::initialize(const QStringList &arguments, QString *errorString)
+{
+    Q_UNUSED(arguments);
+    Q_UNUSED(errorString);
+
+    Core::ICore *core = Core::ICore::instance();
+    Core::UniqueIDManager *uidm = core->uniqueIDManager();
+
+    QList<int> context;
+    context.append(uidm->uniqueIdentifier(QmlInspector::Constants::C_INSPECTOR));
+    context.append(uidm->uniqueIdentifier(Core::Constants::C_EDITORMANAGER));
+    context.append(uidm->uniqueIdentifier(Core::Constants::C_NAVIGATION_PANE));
+
+    m_inspectMode = new QmlInspectorMode(this);
+    connect(m_inspectMode, SIGNAL(startViewer()), SLOT(startViewer()));
+    connect(m_inspectMode, SIGNAL(stopViewer()), SLOT(stopViewer()));
+    m_inspectMode->setContext(context);
+    addObject(m_inspectMode);
+
+    m_outputPane = new InspectorOutputPane;
+    addObject(m_outputPane);
+
+    connect(m_inspectMode, SIGNAL(statusMessage(QString)),
+            m_outputPane, SLOT(addInspectorStatus(QString)));
+
+    m_runControlFactory = new QmlInspectorRunControlFactory(this);
+    addAutoReleasedObject(m_runControlFactory);
+    
+    return true;
+}
+
+void QmlInspectorPlugin::extensionsInitialized()
+{
+}
+
+void QmlInspectorPlugin::startViewer()
+{
+    stopViewer();
+    
+    ProjectExplorer::Project *project = 0;
+    ProjectExplorer::ProjectExplorerPlugin *plugin = ProjectExplorer::ProjectExplorerPlugin::instance();
+    if (plugin)
+        project = plugin->currentProject();
+    if (!project) {
+        qDebug() << "No project loaded"; // TODO should this just run the debugger without a viewer?
+        return;
+    }
+        
+    ProjectExplorer::RunConfiguration *rc = project->activeRunConfiguration();
+
+    QmlInspector::StartParameters sp;
+    sp.port = m_inspectMode->viewerPort();
+
+    m_runControl = m_runControlFactory->create(rc, ProjectExplorer::Constants::RUNMODE, sp);
+
+    if (m_runControl) {
+        connect(m_runControl, SIGNAL(started()), m_inspectMode, SLOT(connectToViewer()));
+        connect(m_runControl, SIGNAL(finished()), m_inspectMode, SLOT(disconnectFromViewer()));
+
+        connect(m_runControl, SIGNAL(addToOutputWindow(RunControl*,QString)),
+                m_outputPane, SLOT(addOutput(RunControl*,QString)));
+        connect(m_runControl, SIGNAL(addToOutputWindowInline(RunControl*,QString)),
+                m_outputPane, SLOT(addOutputInline(RunControl*,QString)));
+        connect(m_runControl, SIGNAL(error(RunControl*,QString)),
+                m_outputPane, SLOT(addErrorOutput(RunControl*,QString)));
+ 
+        m_runControl->start();
+        m_outputPane->popup(false);
+    }
+    
+}
+
+void QmlInspectorPlugin::stopViewer()
+{
+    if (m_runControl) {
+        m_runControl->stop();
+        m_runControl->deleteLater();
+        m_runControl = 0;
+    }
+}
+
+
+Q_EXPORT_PLUGIN(QmlInspectorPlugin)
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/qmlinspector/qmlinspectorplugin.h b/src/plugins/qmlinspector/qmlinspectorplugin.h
new file mode 100644
index 00000000000..a1735d4c3bf
--- /dev/null
+++ b/src/plugins/qmlinspector/qmlinspectorplugin.h
@@ -0,0 +1,78 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 QMLINSPECTORPLUGIN_H
+#define QMLINSPECTORPLUGIN_H
+
+#include <extensionsystem/iplugin.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QStringList;
+
+
+class QmlInspectorRunControlFactory;
+class QmlInspectorMode;
+class InspectorOutputPane;
+
+namespace ProjectExplorer
+{
+    class RunControl;
+}
+
+class QmlInspectorPlugin : public ExtensionSystem::IPlugin
+{
+    Q_OBJECT
+
+public:
+    QmlInspectorPlugin();
+    ~QmlInspectorPlugin();
+
+    virtual bool initialize(const QStringList &arguments, QString *errorString);
+    virtual void extensionsInitialized();
+    virtual void shutdown();
+
+private slots:
+    void startViewer();
+    void stopViewer();
+
+private:
+    QmlInspectorMode *m_inspectMode;
+    InspectorOutputPane *m_outputPane;
+    
+    QmlInspectorRunControlFactory *m_runControlFactory;
+    QPointer<ProjectExplorer::RunControl> m_runControl;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QMLINSPECTORPLUGIN_H
diff --git a/src/plugins/qmlinspector/runcontrol.cpp b/src/plugins/qmlinspector/runcontrol.cpp
new file mode 100644
index 00000000000..72254310594
--- /dev/null
+++ b/src/plugins/qmlinspector/runcontrol.cpp
@@ -0,0 +1,162 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 "runcontrol.h"
+
+#include <projectexplorer/applicationlauncher.h>
+#include <projectexplorer/applicationrunconfiguration.h>
+#include <projectexplorer/projectexplorerconstants.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qtimer.h>
+
+using namespace ProjectExplorer;
+
+
+QmlInspectorRunControlFactory::QmlInspectorRunControlFactory(QObject *parent)
+    : ProjectExplorer::IRunControlFactory(parent)
+{
+}
+
+bool QmlInspectorRunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const
+{
+    Q_UNUSED(runConfiguration);
+    if (mode != ProjectExplorer::Constants::RUNMODE)
+        return false;
+    return true;
+}
+
+ProjectExplorer::RunControl *QmlInspectorRunControlFactory::create(RunConfiguration *runConfiguration, const QString &mode)
+{
+    Q_UNUSED(mode);
+    return new QmlInspectorRunControl(runConfiguration);
+}
+
+ProjectExplorer::RunControl *QmlInspectorRunControlFactory::create(ProjectExplorer::RunConfiguration *runConfiguration,
+const QString &mode, const QmlInspector::StartParameters &sp)
+{
+    Q_UNUSED(mode);
+    return new QmlInspectorRunControl(runConfiguration, sp);
+}
+                
+QString QmlInspectorRunControlFactory::displayName() const
+{
+    return tr("Qml Inspector");
+}
+
+QWidget *QmlInspectorRunControlFactory::configurationWidget(RunConfiguration *runConfiguration)
+{
+    Q_UNUSED(runConfiguration);
+    return 0;
+}
+
+
+
+QmlInspectorRunControl::QmlInspectorRunControl(ProjectExplorer::RunConfiguration *runConfiguration,
+const QmlInspector::StartParameters &sp)
+    : ProjectExplorer::RunControl(runConfiguration),
+      m_configuration(runConfiguration),
+      m_running(false),
+      m_viewerLauncher(0),
+      m_startParams(sp)
+{
+}
+
+QmlInspectorRunControl::~QmlInspectorRunControl()
+{
+}
+
+void QmlInspectorRunControl::start()
+{
+    if (m_running || m_viewerLauncher)
+        return;
+
+    m_viewerLauncher = new ProjectExplorer::ApplicationLauncher(this);
+    connect(m_viewerLauncher, SIGNAL(applicationError(QString)), SLOT(applicationError(QString)));
+    connect(m_viewerLauncher, SIGNAL(processExited(int)), SLOT(viewerExited()));
+    connect(m_viewerLauncher, SIGNAL(appendOutput(QString)), SLOT(appendOutput(QString)));
+    connect(m_viewerLauncher, SIGNAL(bringToForegroundRequested(qint64)),
+            this, SLOT(appStarted()));
+
+    LocalApplicationRunConfiguration *rc = qobject_cast<LocalApplicationRunConfiguration *>(m_configuration);
+    if (!rc)
+        return;
+
+    ProjectExplorer::Environment env = rc->environment();
+    env.set("QML_DEBUG_SERVER_PORT", QString::number(m_startParams.port));
+
+    QStringList arguments = rc->commandLineArguments();
+    arguments << QLatin1String("-stayontop");
+
+    m_viewerLauncher->setEnvironment(env.toStringList());
+    m_viewerLauncher->setWorkingDirectory(rc->workingDirectory());
+
+    m_running = true;
+
+    m_viewerLauncher->start(static_cast<ApplicationLauncher::Mode>(rc->runMode()),
+                            rc->executable(), arguments);
+}
+
+void QmlInspectorRunControl::stop()
+{
+    if (m_viewerLauncher->isRunning())
+        m_viewerLauncher->stop();
+}
+
+bool QmlInspectorRunControl::isRunning() const
+{
+    return m_running;
+}
+
+void QmlInspectorRunControl::appStarted()
+{
+    QTimer::singleShot(500, this, SLOT(delayedStart()));
+}
+
+void QmlInspectorRunControl::appendOutput(const QString &s)
+{
+    emit addToOutputWindow(this, s);
+}
+
+void QmlInspectorRunControl::delayedStart()
+{
+    emit started();
+}
+
+void QmlInspectorRunControl::viewerExited()
+{
+    m_running = false;
+    emit finished();
+    
+    deleteLater();
+}
+
+void QmlInspectorRunControl::applicationError(const QString &s)
+{
+    emit error(this, s);
+}
diff --git a/src/plugins/qmlinspector/runcontrol.h b/src/plugins/qmlinspector/runcontrol.h
new file mode 100644
index 00000000000..b2523b5347a
--- /dev/null
+++ b/src/plugins/qmlinspector/runcontrol.h
@@ -0,0 +1,94 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 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 QMLINSPECTORRUNCONTROL_H
+#define QMLINSPECTORRUNCONTROL_H
+
+#include "qmlinspector.h"
+
+#include <projectexplorer/runconfiguration.h>
+
+#include <QtCore/qobject.h>
+
+namespace ProjectExplorer {
+    class ApplicationLauncher;
+}
+
+class QmlInspectorRunControlFactory : public ProjectExplorer::IRunControlFactory
+{
+    Q_OBJECT
+
+public:
+    explicit QmlInspectorRunControlFactory(QObject *parent);
+
+    virtual bool canRun(
+                ProjectExplorer::RunConfiguration *runConfiguration,
+                const QString &mode) const;
+
+    virtual ProjectExplorer::RunControl *create(
+                ProjectExplorer::RunConfiguration *runConfiguration,
+                const QString &mode);
+
+    ProjectExplorer::RunControl *create(
+                ProjectExplorer::RunConfiguration *runConfiguration,
+                const QString &mode,
+                const QmlInspector::StartParameters &sp);
+                
+    virtual QString displayName() const;
+
+    virtual QWidget *configurationWidget(ProjectExplorer::RunConfiguration *runConfiguration);
+};
+
+class QmlInspectorRunControl : public ProjectExplorer::RunControl
+{
+    Q_OBJECT
+
+public:
+    explicit QmlInspectorRunControl(ProjectExplorer::RunConfiguration *runConfiguration,
+                                    const QmlInspector::StartParameters &sp = QmlInspector::StartParameters());
+    ~QmlInspectorRunControl();
+    
+    virtual void start();
+    virtual void stop();
+    virtual bool isRunning() const;
+
+private slots:
+    void appendOutput(const QString &s);
+    void appStarted();
+    void delayedStart();
+    void viewerExited();
+    void applicationError(const QString &error);
+
+private:
+    ProjectExplorer::RunConfiguration *m_configuration;
+    bool m_running;
+    ProjectExplorer::ApplicationLauncher *m_viewerLauncher;
+    QmlInspector::StartParameters m_startParams;
+};
+
+#endif
-- 
GitLab