diff --git a/.gitignore b/.gitignore
index 5b4d2f244022dcfb3641e1184aa8fc69dde5ac1f..021ff2a1ca072ec95832ade50d77a8218c754745 100644
--- a/.gitignore
+++ b/.gitignore
@@ -119,6 +119,8 @@ translations/*.qm
 translations/*_untranslated.ts
 qrc_*.cpp
 
+src/declarative/qtdeclarativeversion.h
+
 # Test generated files
 QObject.log
 tst_*
diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri
index 75287b4563b46d40767c348fda02f563b85c49ac..044db3c75680e7694125b4bcf2012ede423f03d3 100644
--- a/src/declarative/debugger/debugger.pri
+++ b/src/declarative/debugger/debugger.pri
@@ -8,7 +8,10 @@ SOURCES += \
     $$PWD/qdeclarativedebug.cpp \
     $$PWD/qdeclarativedebugtrace.cpp \
     $$PWD/qdeclarativedebughelper.cpp \
-    $$PWD/qdeclarativedebugserver.cpp
+    $$PWD/qdeclarativedebugserver.cpp \
+    $$PWD/qdeclarativeobserverservice.cpp \
+    $$PWD/qjsdebuggeragent.cpp \
+    $$PWD/qjsdebugservice.cpp
 
 HEADERS += \
     $$PWD/qdeclarativedebuggerstatus_p.h \
@@ -20,4 +23,8 @@ HEADERS += \
     $$PWD/qdeclarativedebugtrace_p.h \
     $$PWD/qdeclarativedebughelper_p.h \
     $$PWD/qdeclarativedebugserver_p.h \
-    debugger/qdeclarativedebugserverconnection_p.h
+    $$PWD/qdeclarativedebugserverconnection_p.h \
+    $$PWD/qdeclarativeobserverservice_p.h \
+    $$PWD/qdeclarativeobserverinterface_p.h \
+    $$PWD/qjsdebuggeragent_p.h \
+    $$PWD/qjsdebugservice_p.h
diff --git a/src/declarative/debugger/qdeclarativedebugserver.cpp b/src/declarative/debugger/qdeclarativedebugserver.cpp
index 208f77ea95419e21bf843f11b193a824e7da910c..c4bf770eb7d251b8733e7c595345f89d8c936363 100644
--- a/src/declarative/debugger/qdeclarativedebugserver.cpp
+++ b/src/declarative/debugger/qdeclarativedebugserver.cpp
@@ -188,7 +188,7 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance()
                 int separatorIndex = appD->qmljsDebugArgumentsString().indexOf(QLatin1Char(','));
                 port = appD->qmljsDebugArgumentsString().mid(5, separatorIndex - 5).toInt(&ok);
                 pluginName = QLatin1String("qmldbg_tcp");
-            } else if (appD->qmljsDebugArgumentsString().contains("ost")) {
+            } else if (appD->qmljsDebugArgumentsString().contains(QLatin1String("ost"))) {
                 pluginName = QLatin1String("qmldbg_ost");
                 ok = true;
             }
@@ -253,6 +253,17 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
         int version;
         in >> version >> d->clientPlugins;
 
+        // Send the hello answer immediately, since it needs to arrive before
+        // the plugins below start sending messages.
+        QByteArray helloAnswer;
+        {
+            QDataStream out(&helloAnswer, QIODevice::WriteOnly);
+            out << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys();
+        }
+        d->connection->send(helloAnswer);
+
+        d->gotHello = true;
+
         QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin();
         for (; iter != d->plugins.end(); ++iter) {
             QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
@@ -262,14 +273,6 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
             iter.value()->statusChanged(newStatus);
         }
 
-        QByteArray helloAnswer;
-        {
-            QDataStream out(&helloAnswer, QIODevice::WriteOnly);
-            out << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys();
-        }
-        d->connection->send(helloAnswer);
-
-        d->gotHello = true;
         qWarning("QDeclarativeDebugServer: Connection established");
     } else {
 
diff --git a/src/declarative/debugger/qdeclarativeobserverinterface_p.h b/src/declarative/debugger/qdeclarativeobserverinterface_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..501c1323a3aedd47373a5dd33d5529800e1d797d
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativeobserverinterface_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEOBSERVERINTERFACE_H
+#define QDECLARATIVEOBSERVERINTERFACE_H
+
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QDeclarativeObserverInterface
+{
+public:
+    QDeclarativeObserverInterface() {}
+    virtual ~QDeclarativeObserverInterface() {}
+
+    virtual void activate() = 0;
+    virtual void deactivate() = 0;
+};
+
+Q_DECLARE_INTERFACE(QDeclarativeObserverInterface, "com.trolltech.Qt.QDeclarativeObserverInterface/1.0")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEOBSERVERINTERFACE_H
diff --git a/src/declarative/debugger/qdeclarativeobserverservice.cpp b/src/declarative/debugger/qdeclarativeobserverservice.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a623c55d053d9db137b540edf51eca2a724cd886
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativeobserverservice.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qdeclarativeobserverservice_p.h"
+#include "private/qdeclarativeobserverinterface_p.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QPluginLoader>
+
+#include <QtDeclarative/QDeclarativeView>
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QDeclarativeObserverService, serviceInstance)
+
+QDeclarativeObserverService::QDeclarativeObserverService()
+    : QDeclarativeDebugService(QLatin1String("QDeclarativeObserverMode"))
+    , m_observer(0)
+{
+}
+
+QDeclarativeObserverService *QDeclarativeObserverService::instance()
+{
+    return serviceInstance();
+}
+
+void QDeclarativeObserverService::addView(QDeclarativeView *view)
+{
+    m_views.append(view);
+}
+
+void QDeclarativeObserverService::removeView(QDeclarativeView *view)
+{
+    m_views.removeAll(view);
+}
+
+void QDeclarativeObserverService::sendMessage(const QByteArray &message)
+{
+    if (status() != Enabled)
+        return;
+
+    QDeclarativeDebugService::sendMessage(message);
+}
+
+void QDeclarativeObserverService::statusChanged(Status status)
+{
+    if (m_views.isEmpty())
+        return;
+
+    if (status == Enabled) {
+        if (!m_observer)
+            m_observer = loadObserverPlugin();
+
+        if (!m_observer) {
+            qWarning() << "Error while loading observer plugin";
+            return;
+        }
+
+        m_observer->activate();
+    } else {
+        if (m_observer)
+            m_observer->deactivate();
+    }
+}
+
+void QDeclarativeObserverService::messageReceived(const QByteArray &message)
+{
+    emit gotMessage(message);
+}
+
+QDeclarativeObserverInterface *QDeclarativeObserverService::loadObserverPlugin()
+{
+    QStringList pluginCandidates;
+    const QStringList paths = QCoreApplication::libraryPaths();
+    foreach (const QString &libPath, paths) {
+        const QDir dir(libPath + QLatin1String("/qmltooling"));
+        if (dir.exists())
+            foreach (const QString &pluginPath, dir.entryList(QDir::Files))
+                pluginCandidates << dir.absoluteFilePath(pluginPath);
+    }
+
+    foreach (const QString &pluginPath, pluginCandidates) {
+        QPluginLoader loader(pluginPath);
+        if (!loader.load())
+            continue;
+
+        QDeclarativeObserverInterface *observer =
+                qobject_cast<QDeclarativeObserverInterface*>(loader.instance());
+
+        if (observer)
+            return observer;
+        loader.unload();
+    }
+    return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativeobserverservice_p.h b/src/declarative/debugger/qdeclarativeobserverservice_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..36f31dc5102e566e56de9261c824f39314ce800c
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativeobserverservice_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEOBSERVERSERVICE_H
+#define QDECLARATIVEOBSERVERSERVICE_H
+
+#include "private/qdeclarativedebugservice_p.h"
+#include <private/qdeclarativeglobal_p.h>
+
+#include <QtCore/QList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeView;
+class QDeclarativeObserverInterface;
+
+class Q_DECLARATIVE_EXPORT QDeclarativeObserverService : public QDeclarativeDebugService
+{
+    Q_OBJECT
+
+public:
+    QDeclarativeObserverService();
+    static QDeclarativeObserverService *instance();
+
+    void addView(QDeclarativeView *);
+    void removeView(QDeclarativeView *);
+    QList<QDeclarativeView*> views() const { return m_views; }
+
+    void sendMessage(const QByteArray &message);
+
+Q_SIGNALS:
+    void gotMessage(const QByteArray &message);
+
+protected:
+    virtual void statusChanged(Status status);
+    virtual void messageReceived(const QByteArray &);
+
+private:
+    static QDeclarativeObserverInterface *loadObserverPlugin();
+
+    QList<QDeclarativeView*> m_views;
+    QDeclarativeObserverInterface *m_observer;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEOBSERVERSERVICE_H
diff --git a/src/declarative/debugger/qjsdebuggeragent.cpp b/src/declarative/debugger/qjsdebuggeragent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..601c8c8ce8c566461f1c0c29dc59fff4a1862448
--- /dev/null
+++ b/src/declarative/debugger/qjsdebuggeragent.cpp
@@ -0,0 +1,576 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qjsdebuggeragent_p.h"
+#include "private/qdeclarativedebughelper_p.h"
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qset.h>
+#include <QtCore/qurl.h>
+#include <QtScript/qscriptcontextinfo.h>
+#include <QtScript/qscriptengine.h>
+#include <QtScript/qscriptvalueiterator.h>
+
+QT_BEGIN_NAMESPACE
+
+class QJSDebuggerAgentPrivate
+{
+public:
+    QJSDebuggerAgentPrivate(QJSDebuggerAgent *q)
+        : q(q), state(NoState)
+    {}
+
+    void continueExec();
+    void recordKnownObjects(const QList<JSAgentWatchData> &);
+    QList<JSAgentWatchData> getLocals(QScriptContext *);
+    void positionChange(qint64 scriptId, int lineNumber, int columnNumber);
+    QScriptEngine *engine() { return q->engine(); }
+    void stopped();
+
+public:
+    QJSDebuggerAgent *q;
+    JSDebuggerState state;
+    int stepDepth;
+    int stepCount;
+
+    QEventLoop loop;
+    QHash<qint64, QString> filenames;
+    JSAgentBreakpoints breakpoints;
+    // breakpoints by filename (without path)
+    QHash<QString, JSAgentBreakpointData> fileNameToBreakpoints;
+    QStringList watchExpressions;
+    QSet<qint64> knownObjectIds;
+};
+
+namespace {
+
+class SetupExecEnv
+{
+public:
+    SetupExecEnv(QJSDebuggerAgentPrivate *a)
+        : agent(a),
+          previousState(a->state),
+          hadException(a->engine()->hasUncaughtException())
+    {
+        agent->state = StoppedState;
+    }
+
+    ~SetupExecEnv()
+    {
+        if (!hadException && agent->engine()->hasUncaughtException())
+            agent->engine()->clearExceptions();
+        agent->state = previousState;
+    }
+
+private:
+    QJSDebuggerAgentPrivate *agent;
+    JSDebuggerState previousState;
+    bool hadException;
+};
+
+} // anonymous namespace
+
+static JSAgentWatchData fromScriptValue(const QString &expression,
+                                        const QScriptValue &value)
+{
+    static const QString arrayStr = QCoreApplication::translate
+            ("Debugger::JSAgentWatchData", "[Array of length %1]");
+    static const QString undefinedStr = QCoreApplication::translate
+            ("Debugger::JSAgentWatchData", "<undefined>");
+
+    JSAgentWatchData data;
+    data.exp = expression.toUtf8();
+    data.name = data.exp;
+    data.hasChildren = false;
+    data.value = value.toString().toUtf8();
+    data.objectId = value.objectId();
+    if (value.isArray()) {
+        data.type = "Array";
+        data.value = arrayStr.arg(value.property(QLatin1String("length")).toString()).toUtf8();
+        data.hasChildren = true;
+    } else if (value.isBool()) {
+        data.type = "Bool";
+        // data.value = value.toBool() ? "true" : "false";
+    } else if (value.isDate()) {
+        data.type = "Date";
+        data.value = value.toDateTime().toString().toUtf8();
+    } else if (value.isError()) {
+        data.type = "Error";
+    } else if (value.isFunction()) {
+        data.type = "Function";
+    } else if (value.isUndefined()) {
+        data.type = undefinedStr.toUtf8();
+    } else if (value.isNumber()) {
+        data.type = "Number";
+    } else if (value.isRegExp()) {
+        data.type = "RegExp";
+    } else if (value.isString()) {
+        data.type = "String";
+    } else if (value.isVariant()) {
+        data.type = "Variant";
+    } else if (value.isQObject()) {
+        const QObject *obj = value.toQObject();
+        data.type = "Object";
+        data.value += '[';
+        data.value += obj->metaObject()->className();
+        data.value += ']';
+        data.hasChildren = true;
+    } else if (value.isObject()) {
+        data.type = "Object";
+        data.hasChildren = true;
+        data.value = "[Object]";
+    } else if (value.isNull()) {
+        data.type = "<null>";
+    } else {
+        data.type = "<unknown>";
+    }
+    return data;
+}
+
+static QList<JSAgentWatchData> expandObject(const QScriptValue &object)
+{
+    QList<JSAgentWatchData> result;
+    QScriptValueIterator it(object);
+    while (it.hasNext()) {
+        it.next();
+        if (it.flags() & QScriptValue::SkipInEnumeration)
+            continue;
+        if (/*object.isQObject() &&*/ it.value().isFunction()) {
+            // Cosmetics: skip all functions and slot, there are too many of them,
+            // and it is not useful information in the debugger.
+            continue;
+        }
+        JSAgentWatchData data = fromScriptValue(it.name(), it.value());
+        result.append(data);
+    }
+    if (result.isEmpty()) {
+        JSAgentWatchData data;
+        data.name = "<no initialized data>";
+        data.hasChildren = false;
+        data.value = " ";
+        data.objectId = 0;
+        result.append(data);
+    }
+    return result;
+}
+
+static QString fileName(const QString &fileUrl)
+{
+    int lastDelimiterPos = fileUrl.lastIndexOf(QLatin1Char('/'));
+    return fileUrl.mid(lastDelimiterPos, fileUrl.size() - lastDelimiterPos);
+}
+
+void QJSDebuggerAgentPrivate::recordKnownObjects(const QList<JSAgentWatchData>& list)
+{
+    foreach (const JSAgentWatchData &data, list)
+        knownObjectIds << data.objectId;
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgentPrivate::getLocals(QScriptContext *ctx)
+{
+    QList<JSAgentWatchData> locals;
+    if (ctx) {
+        QScriptValue activationObject = ctx->activationObject();
+        QScriptValue thisObject = ctx->thisObject();
+        locals = expandObject(activationObject);
+        if (thisObject.isObject()
+                && thisObject.objectId() != engine()->globalObject().objectId()
+                && QScriptValueIterator(thisObject).hasNext())
+            locals.prepend(fromScriptValue(QLatin1String("this"), thisObject));
+        recordKnownObjects(locals);
+        knownObjectIds << activationObject.objectId();
+    }
+    return locals;
+}
+
+/*!
+  Constructs a new agent for the given \a engine. The agent will
+  report debugging-related events (e.g. step completion) to the given
+  \a backend.
+*/
+QJSDebuggerAgent::QJSDebuggerAgent(QScriptEngine *engine, QObject *parent)
+    : QObject(parent)
+    , QScriptEngineAgent(engine)
+    , d(new QJSDebuggerAgentPrivate(this))
+{
+    QJSDebuggerAgent::engine()->setAgent(this);
+}
+
+QJSDebuggerAgent::QJSDebuggerAgent(QDeclarativeEngine *engine, QObject *parent)
+    : QObject(parent)
+    , QScriptEngineAgent(QDeclarativeDebugHelper::getScriptEngine(engine))
+    , d(new QJSDebuggerAgentPrivate(this))
+{
+    QJSDebuggerAgent::engine()->setAgent(this);
+}
+
+/*!
+  Destroys this QJSDebuggerAgent.
+*/
+QJSDebuggerAgent::~QJSDebuggerAgent()
+{
+    engine()->setAgent(0);
+    delete d;
+}
+
+void QJSDebuggerAgent::setBreakpoints(const JSAgentBreakpoints &breakpoints)
+{
+    d->breakpoints = breakpoints;
+
+    d->fileNameToBreakpoints.clear();
+    foreach (const JSAgentBreakpointData &bp, breakpoints)
+        d->fileNameToBreakpoints.insertMulti(fileName(QString::fromUtf8(bp.fileUrl)), bp);
+}
+
+void QJSDebuggerAgent::setWatchExpressions(const QStringList &watchExpressions)
+{
+    d->watchExpressions = watchExpressions;
+}
+
+void QJSDebuggerAgent::stepOver()
+{
+    d->stepDepth = 0;
+    d->state = SteppingOverState;
+    d->continueExec();
+}
+
+void QJSDebuggerAgent::stepInto()
+{
+    d->stepDepth = 0;
+    d->state = SteppingIntoState;
+    d->continueExec();
+}
+
+void QJSDebuggerAgent::stepOut()
+{
+    d->stepDepth = 0;
+    d->state = SteppingOutState;
+    d->continueExec();
+}
+
+void QJSDebuggerAgent::continueExecution()
+{
+    d->state = NoState;
+    d->continueExec();
+}
+
+JSAgentWatchData QJSDebuggerAgent::executeExpression(const QString &expr)
+{
+    SetupExecEnv execEnv(d);
+
+    JSAgentWatchData data = fromScriptValue(expr, engine()->evaluate(expr));
+    d->knownObjectIds << data.objectId;
+    return data;
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgent::expandObjectById(quint64 objectId)
+{
+    SetupExecEnv execEnv(d);
+
+    QScriptValue v;
+    if (d->knownObjectIds.contains(objectId))
+        v = engine()->objectById(objectId);
+
+    QList<JSAgentWatchData> result = expandObject(v);
+    d->recordKnownObjects(result);
+    return result;
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgent::locals()
+{
+    SetupExecEnv execEnv(d);
+    return d->getLocals(engine()->currentContext());
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgent::localsAtFrame(int frameId)
+{
+    SetupExecEnv execEnv(d);
+
+    int deep = 0;
+    QScriptContext *ctx = engine()->currentContext();
+    while (ctx && deep < frameId) {
+        ctx = ctx->parentContext();
+        deep++;
+    }
+
+    return d->getLocals(ctx);
+}
+
+QList<JSAgentStackData> QJSDebuggerAgent::backtrace()
+{
+    SetupExecEnv execEnv(d);
+
+    QList<JSAgentStackData> backtrace;
+
+    for (QScriptContext *ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
+        QScriptContextInfo info(ctx);
+
+        JSAgentStackData frame;
+        frame.functionName = info.functionName().toUtf8();
+        if (frame.functionName.isEmpty()) {
+            if (ctx->parentContext()) {
+                switch (info.functionType()) {
+                case QScriptContextInfo::ScriptFunction:
+                    frame.functionName = "<anonymous>";
+                    break;
+                case QScriptContextInfo::NativeFunction:
+                    frame.functionName = "<native>";
+                    break;
+                case QScriptContextInfo::QtFunction:
+                case QScriptContextInfo::QtPropertyFunction:
+                    frame.functionName = "<native slot>";
+                    break;
+                }
+            } else {
+                frame.functionName = "<global>";
+            }
+        }
+        frame.lineNumber = info.lineNumber();
+        // if the line number is unknown, fallback to the function line number
+        if (frame.lineNumber == -1)
+            frame.lineNumber = info.functionStartLineNumber();
+
+        frame.fileUrl = info.fileName().toUtf8();
+        backtrace.append(frame);
+    }
+
+    return backtrace;
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgent::watches()
+{
+    SetupExecEnv execEnv(d);
+
+    QList<JSAgentWatchData> watches;
+    foreach (const QString &expr, d->watchExpressions)
+        watches << fromScriptValue(expr, engine()->evaluate(expr));
+    d->recordKnownObjects(watches);
+    return watches;
+}
+
+void QJSDebuggerAgent::setProperty(qint64 objectId,
+                                   const QString &property,
+                                   const QString &value)
+{
+    SetupExecEnv execEnv(d);
+
+    if (d->knownObjectIds.contains(objectId)) {
+        QScriptValue object = engine()->objectById(objectId);
+        if (object.isObject()) {
+            QScriptValue result = engine()->evaluate(value);
+            object.setProperty(property, result);
+        }
+    }
+}
+
+/*!
+  \reimp
+*/
+void QJSDebuggerAgent::scriptLoad(qint64 id, const QString &program,
+                                  const QString &fileName, int)
+{
+    Q_UNUSED(program);
+    d->filenames.insert(id, fileName);
+}
+
+/*!
+  \reimp
+*/
+void QJSDebuggerAgent::scriptUnload(qint64 id)
+{
+    d->filenames.remove(id);
+}
+
+/*!
+  \reimp
+*/
+void QJSDebuggerAgent::contextPush()
+{
+}
+
+/*!
+  \reimp
+*/
+void QJSDebuggerAgent::contextPop()
+{
+}
+
+/*!
+  \reimp
+*/
+void QJSDebuggerAgent::functionEntry(qint64 scriptId)
+{
+    Q_UNUSED(scriptId);
+    d->stepDepth++;
+}
+
+/*!
+  \reimp
+*/
+void QJSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnValue)
+{
+    Q_UNUSED(scriptId);
+    Q_UNUSED(returnValue);
+    d->stepDepth--;
+}
+
+/*!
+  \reimp
+*/
+void QJSDebuggerAgent::positionChange(qint64 scriptId, int lineNumber, int columnNumber)
+{
+    d->positionChange(scriptId, lineNumber, columnNumber);
+}
+
+void QJSDebuggerAgentPrivate::positionChange(qint64 scriptId, int lineNumber, int columnNumber)
+{
+    Q_UNUSED(columnNumber);
+
+    if (state == StoppedState)
+        return; //no re-entrency
+
+    // check breakpoints
+    if (!breakpoints.isEmpty()) {
+        QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
+        QScriptContext *ctx = engine()->currentContext();
+        QScriptContextInfo info(ctx);
+        if (it == filenames.constEnd()) {
+            // It is possible that the scripts are loaded before the agent is attached
+            QString filename = info.fileName();
+
+            JSAgentStackData frame;
+            frame.functionName = info.functionName().toUtf8();
+
+            QPair<QString, qint32> key = qMakePair(filename, lineNumber);
+            it = filenames.insert(scriptId, filename);
+        }
+
+        const QString filePath = it.value();
+        JSAgentBreakpoints bps = fileNameToBreakpoints.values(fileName(filePath)).toSet();
+
+        foreach (const JSAgentBreakpointData &bp, bps) {
+            if (bp.lineNumber == lineNumber) {
+                stopped();
+                return;
+            }
+        }
+    }
+
+    switch (state) {
+    case NoState:
+    case StoppedState:
+        // Do nothing
+        break;
+    case SteppingOutState:
+        if (stepDepth >= 0)
+            break;
+        //fallthough
+    case SteppingOverState:
+        if (stepDepth > 0)
+            break;
+        //fallthough
+    case SteppingIntoState:
+        stopped();
+        break;
+    }
+
+}
+
+/*!
+  \reimp
+*/
+void QJSDebuggerAgent::exceptionThrow(qint64 scriptId,
+                                     const QScriptValue &exception,
+                                     bool hasHandler)
+{
+    Q_UNUSED(scriptId);
+    Q_UNUSED(exception);
+    Q_UNUSED(hasHandler);
+//    qDebug() << Q_FUNC_INFO << exception.toString() << hasHandler;
+#if 0 //sometimes, we get exceptions that we should just ignore.
+    if (!hasHandler && state != StoppedState)
+        stopped(true, exception);
+#endif
+}
+
+/*!
+  \reimp
+*/
+void QJSDebuggerAgent::exceptionCatch(qint64 scriptId, const QScriptValue &exception)
+{
+    Q_UNUSED(scriptId);
+    Q_UNUSED(exception);
+}
+
+bool QJSDebuggerAgent::supportsExtension(Extension extension) const
+{
+    return extension == QScriptEngineAgent::DebuggerInvocationRequest;
+}
+
+QVariant QJSDebuggerAgent::extension(Extension extension, const QVariant &argument)
+{
+    if (extension == QScriptEngineAgent::DebuggerInvocationRequest) {
+        d->stopped();
+        return QVariant();
+    }
+    return QScriptEngineAgent::extension(extension, argument);
+}
+
+void QJSDebuggerAgentPrivate::stopped()
+{
+    bool becauseOfException = false;
+    const QScriptValue &exception = QScriptValue();
+
+    knownObjectIds.clear();
+    state = StoppedState;
+
+    emit q->stopped(becauseOfException, exception.toString());
+
+    loop.exec(QEventLoop::ExcludeUserInputEvents);
+}
+
+void QJSDebuggerAgentPrivate::continueExec()
+{
+    loop.quit();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qjsdebuggeragent_p.h b/src/declarative/debugger/qjsdebuggeragent_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..ce5a0449ebca0fccd9fe2cc2a66f512e8ba7b507
--- /dev/null
+++ b/src/declarative/debugger/qjsdebuggeragent_p.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QJSDEBUGGERAGENT_P_H
+#define QJSDEBUGGERAGENT_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtScript/qscriptengineagent.h>
+#include <QtCore/qset.h>
+
+QT_BEGIN_NAMESPACE
+class QScriptValue;
+class QDeclarativeEngine;
+QT_END_NAMESPACE
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QJSDebuggerAgentPrivate;
+
+enum JSDebuggerState
+{
+    NoState,
+    SteppingIntoState,
+    SteppingOverState,
+    SteppingOutState,
+    StoppedState
+};
+
+struct JSAgentWatchData
+{
+    QByteArray exp;
+    QByteArray name;
+    QByteArray value;
+    QByteArray type;
+    bool hasChildren;
+    quint64 objectId;
+};
+
+inline QDataStream &operator<<(QDataStream &s, const JSAgentWatchData &data)
+{
+    return s << data.exp << data.name << data.value
+             << data.type << data.hasChildren << data.objectId;
+}
+
+struct JSAgentStackData
+{
+    QByteArray functionName;
+    QByteArray fileUrl;
+    qint32 lineNumber;
+};
+
+inline QDataStream &operator<<(QDataStream &s, const JSAgentStackData &data)
+{
+    return s << data.functionName << data.fileUrl << data.lineNumber;
+}
+
+struct JSAgentBreakpointData
+{
+    QByteArray functionName;
+    QByteArray fileUrl;
+    qint32 lineNumber;
+};
+
+typedef QSet<JSAgentBreakpointData> JSAgentBreakpoints;
+
+inline QDataStream &operator<<(QDataStream &s, const JSAgentBreakpointData &data)
+{
+    return s << data.functionName << data.fileUrl << data.lineNumber;
+}
+
+inline QDataStream &operator>>(QDataStream &s, JSAgentBreakpointData &data)
+{
+    return s >> data.functionName >> data.fileUrl >> data.lineNumber;
+}
+
+inline bool operator==(const JSAgentBreakpointData &b1, const JSAgentBreakpointData &b2)
+{
+    return b1.lineNumber == b2.lineNumber && b1.fileUrl == b2.fileUrl;
+}
+
+inline uint qHash(const JSAgentBreakpointData &b)
+{
+    return b.lineNumber ^ qHash(b.fileUrl);
+}
+
+
+class QJSDebuggerAgent : public QObject, public QScriptEngineAgent
+{
+    Q_OBJECT
+
+public:
+    QJSDebuggerAgent(QScriptEngine *engine, QObject *parent = 0);
+    QJSDebuggerAgent(QDeclarativeEngine *engine, QObject *parent = 0);
+    ~QJSDebuggerAgent();
+
+    void setBreakpoints(const JSAgentBreakpoints &);
+    void setWatchExpressions(const QStringList &);
+
+    void stepOver();
+    void stepInto();
+    void stepOut();
+    void continueExecution();
+
+    JSAgentWatchData executeExpression(const QString &expr);
+    QList<JSAgentWatchData> expandObjectById(quint64 objectId);
+    QList<JSAgentWatchData> locals();
+    QList<JSAgentWatchData> localsAtFrame(int frameId);
+    QList<JSAgentStackData> backtrace();
+    QList<JSAgentWatchData> watches();
+    void setProperty(qint64 objectId,
+                     const QString &property,
+                     const QString &value);
+
+    // reimplemented
+    void scriptLoad(qint64 id, const QString &program,
+                    const QString &fileName, int baseLineNumber);
+    void scriptUnload(qint64 id);
+
+    void contextPush();
+    void contextPop();
+
+    void functionEntry(qint64 scriptId);
+    void functionExit(qint64 scriptId,
+                      const QScriptValue &returnValue);
+
+    void positionChange(qint64 scriptId,
+                        int lineNumber, int columnNumber);
+
+    void exceptionThrow(qint64 scriptId,
+                        const QScriptValue &exception,
+                        bool hasHandler);
+    void exceptionCatch(qint64 scriptId,
+                        const QScriptValue &exception);
+
+    bool supportsExtension(Extension extension) const;
+    QVariant extension(Extension extension,
+                       const QVariant &argument = QVariant());
+
+Q_SIGNALS:
+    void stopped(bool becauseOfException,
+                 const QString &exception);
+
+private:
+    friend class QJSDebuggerAgentPrivate;
+    QJSDebuggerAgentPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QJSDEBUGGERAGENT_P_H
diff --git a/src/declarative/debugger/qjsdebugservice.cpp b/src/declarative/debugger/qjsdebugservice.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f8cd095943172e4223c8638b86d781a7cf4df5b0
--- /dev/null
+++ b/src/declarative/debugger/qjsdebugservice.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qjsdebugservice_p.h"
+#include "private/qjsdebuggeragent_p.h"
+
+#include <QtCore/qdatastream.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+
+Q_GLOBAL_STATIC(QJSDebugService, serviceInstance)
+
+QJSDebugService::QJSDebugService(QObject *parent)
+    : QDeclarativeDebugService(QLatin1String("JSDebugger"), parent)
+    , m_agent(0)
+{
+}
+
+QJSDebugService::~QJSDebugService()
+{
+    delete m_agent;
+}
+
+QJSDebugService *QJSDebugService::instance()
+{
+    return serviceInstance();
+}
+
+void QJSDebugService::addEngine(QDeclarativeEngine *engine)
+{
+    Q_ASSERT(engine);
+    Q_ASSERT(!m_engines.contains(engine));
+
+    m_engines.append(engine);
+}
+
+void QJSDebugService::removeEngine(QDeclarativeEngine *engine)
+{
+    Q_ASSERT(engine);
+    Q_ASSERT(m_engines.contains(engine));
+
+    m_engines.removeAll(engine);
+}
+
+void QJSDebugService::statusChanged(Status status)
+{
+    if (status == Enabled && !m_engines.isEmpty() && !m_agent) {
+        // Multiple engines are currently unsupported
+        QDeclarativeEngine *engine = m_engines.first();
+        m_agent = new QJSDebuggerAgent(engine, engine);
+
+        connect(m_agent, SIGNAL(stopped(bool,QString)),
+                this, SLOT(executionStopped(bool,QString)));
+
+    } else if (status != Enabled && m_agent) {
+        delete m_agent;
+        m_agent = 0;
+    }
+}
+
+void QJSDebugService::messageReceived(const QByteArray &message)
+{
+    if (!m_agent) {
+        qWarning() << "QJSDebugService::messageReceived: No QJSDebuggerAgent available";
+        return;
+    }
+
+    QDataStream ds(message);
+    QByteArray command;
+    ds >> command;
+    if (command == "BREAKPOINTS") {
+        JSAgentBreakpoints breakpoints;
+        ds >> breakpoints;
+        m_agent->setBreakpoints(breakpoints);
+
+        //qDebug() << "BREAKPOINTS";
+        //foreach (const JSAgentBreakpointData &bp, breakpoints)
+        //    qDebug() << "BREAKPOINT: " << bp.fileUrl << bp.lineNumber;
+    } else if (command == "WATCH_EXPRESSIONS") {
+        QStringList watchExpressions;
+        ds >> watchExpressions;
+        m_agent->setWatchExpressions(watchExpressions);
+    } else if (command == "STEPOVER") {
+        m_agent->stepOver();
+    } else if (command == "STEPINTO" || command == "INTERRUPT") {
+        m_agent->stepInto();
+    } else if (command == "STEPOUT") {
+        m_agent->stepOut();
+    } else if (command == "CONTINUE") {
+        m_agent->continueExecution();
+    } else if (command == "EXEC") {
+        QByteArray id;
+        QString expr;
+        ds >> id >> expr;
+
+        JSAgentWatchData data = m_agent->executeExpression(expr);
+
+        QByteArray reply;
+        QDataStream rs(&reply, QIODevice::WriteOnly);
+        rs << QByteArray("RESULT") << id << data;
+        sendMessage(reply);
+    } else if (command == "EXPAND") {
+        QByteArray requestId;
+        quint64 objectId;
+        ds >> requestId >> objectId;
+
+        QList<JSAgentWatchData> result = m_agent->expandObjectById(objectId);
+
+        QByteArray reply;
+        QDataStream rs(&reply, QIODevice::WriteOnly);
+        rs << QByteArray("EXPANDED") << requestId << result;
+        sendMessage(reply);
+    } else if (command == "ACTIVATE_FRAME") {
+        int frameId;
+        ds >> frameId;
+
+        QList<JSAgentWatchData> locals = m_agent->localsAtFrame(frameId);
+
+        QByteArray reply;
+        QDataStream rs(&reply, QIODevice::WriteOnly);
+        rs << QByteArray("LOCALS") << frameId << locals;
+        sendMessage(reply);
+    } else if (command == "SET_PROPERTY") {
+        QByteArray id;
+        qint64 objectId;
+        QString property;
+        QString value;
+        ds >> id >> objectId >> property >> value;
+
+        m_agent->setProperty(objectId, property, value);
+
+        //TODO: feedback
+    } else if (command == "PING") {
+        int ping;
+        ds >> ping;
+        QByteArray reply;
+        QDataStream rs(&reply, QIODevice::WriteOnly);
+        rs << QByteArray("PONG") << ping;
+        sendMessage(reply);
+    } else {
+        qDebug() << Q_FUNC_INFO << "Unknown command" << command;
+    }
+
+    QDeclarativeDebugService::messageReceived(message);
+}
+
+void QJSDebugService::executionStopped(bool becauseOfException,
+                                       const QString &exception)
+{
+    const QList<JSAgentStackData> backtrace = m_agent->backtrace();
+    const QList<JSAgentWatchData> watches = m_agent->watches();
+    const QList<JSAgentWatchData> locals = m_agent->locals();
+
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    rs << QByteArray("STOPPED") << backtrace << watches << locals
+       << becauseOfException << exception;
+    sendMessage(reply);
+}
diff --git a/src/declarative/debugger/qjsdebugservice_p.h b/src/declarative/debugger/qjsdebugservice_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..6839ca8ffda1b5113832155e16fd8357f5644b14
--- /dev/null
+++ b/src/declarative/debugger/qjsdebugservice_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QJSDEBUGSERVICE_P_H
+#define QJSDEBUGSERVICE_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QPointer>
+
+#include "private/qdeclarativedebugservice_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeEngine;
+class QJSDebuggerAgent;
+
+class QJSDebugService : public QDeclarativeDebugService
+{
+    Q_OBJECT
+
+public:
+    QJSDebugService(QObject *parent = 0);
+    ~QJSDebugService();
+
+    static QJSDebugService *instance();
+
+    void addEngine(QDeclarativeEngine *);
+    void removeEngine(QDeclarativeEngine *);
+
+protected:
+    void statusChanged(Status status);
+    void messageReceived(const QByteArray &);
+
+private Q_SLOTS:
+    void executionStopped(bool becauseOfException,
+                          const QString &exception);
+
+private:
+    QList<QDeclarativeEngine *> m_engines;
+    QPointer<QJSDebuggerAgent> m_agent;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QJSDEBUGSERVICE_P_H
diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro
index 0a1f76a251a2d7a1bb628f83788e472a968ba1c8..adf1408c5806e293219e5217697aa300bef6de6d 100644
--- a/src/declarative/declarative.pro
+++ b/src/declarative/declarative.pro
@@ -21,6 +21,8 @@ exists("qdeclarative_enable_gcov") {
 
 include($$QT_SOURCE_TREE/src/qbase.pri)
 
+HEADERS += qtdeclarativeversion.h
+
 #INCLUDEPATH -= $$QMAKE_INCDIR_QT/$$TARGET
 #DESTDIR=.
 
diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h
index 07e37277b721977494146bcf3304cd05f8deb579..a5c979eabaf3185e6b8b7b5a69acbe1b2b6bbbd9 100644
--- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h
@@ -70,7 +70,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextInputPrivate : public QDeclarativeImplic
 {
     Q_DECLARE_PUBLIC(QDeclarativeTextInput)
 public:
-    QDeclarativeTextInputPrivate() : control(new QLineControl(QString())),
+    QDeclarativeTextInputPrivate() : control(new QLineControl),
                  color((QRgb)0), style(QDeclarativeText::Normal),
                  styleColor((QRgb)0), hAlign(QDeclarativeTextInput::AlignLeft),
                  mouseSelectionMode(QDeclarativeTextInput::SelectCharacters), inputMethodHints(Qt::ImhNone),
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index 073e1d411919d6baedb3337d56ca5cdfe1491baa..80845b4c813011577e46899ad499fc95c66c63fe 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -72,6 +72,7 @@
 #include "private/qdeclarativenotifier_p.h"
 #include "private/qdeclarativedebugtrace_p.h"
 #include "private/qdeclarativeapplication_p.h"
+#include "private/qjsdebugservice_p.h"
 
 #include <QtCore/qmetaobject.h>
 #include <QScriptClass>
@@ -126,7 +127,7 @@ QT_BEGIN_NAMESPACE
   \brief The QtObject element is the most basic element in QML.
 
   The QtObject element is a non-visual element which contains only the
-  objectName property. 
+  objectName property.
 
   It can be useful to create a QtObject if you need an extremely
   lightweight element to enclose a set of custom properties:
@@ -141,7 +142,7 @@ QT_BEGIN_NAMESPACE
   This property holds the QObject::objectName for this specific object instance.
 
   This allows a C++ application to locate an item within a QML component
-  using the QObject::findChild() method. For example, the following C++ 
+  using the QObject::findChild() method. For example, the following C++
   application locates the child \l Rectangle item and dynamically changes its
   \c color value:
 
@@ -155,7 +156,7 @@ QT_BEGIN_NAMESPACE
 
         Rectangle {
             anchors.fill: parent
-            color: "red" 
+            color: "red"
             objectName: "myRect"
         }
     }
@@ -169,7 +170,7 @@ QT_BEGIN_NAMESPACE
     view.show();
 
     QDeclarativeItem *item = view.rootObject()->findChild<QDeclarativeItem*>("myRect");
-    if (item) 
+    if (item)
         item->setProperty("color", QColor(Qt::yellow));
     \endcode
 */
@@ -205,7 +206,7 @@ void QDeclarativeEnginePrivate::defineModule()
 
 \keyword QmlGlobalQtObject
 
-\brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files. 
+\brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
 
 The \c Qt object is a global object with utility functions, properties and enums.
 
@@ -594,6 +595,7 @@ void QDeclarativeEnginePrivate::init()
         QDeclarativeEngineDebugServer::isDebuggingEnabled()) {
         isDebugging = true;
         QDeclarativeEngineDebugServer::instance()->addEngine(q);
+        QJSDebugService::instance()->addEngine(q);
     }
 }
 
@@ -656,8 +658,9 @@ QDeclarativeEngine::QDeclarativeEngine(QObject *parent)
 QDeclarativeEngine::~QDeclarativeEngine()
 {
     Q_D(QDeclarativeEngine);
-    if (d->isDebugging)
+    if (d->isDebugging) {
         QDeclarativeEngineDebugServer::instance()->remEngine(this);
+    }
 
     // if we are the parent of any of the qobject module api instances,
     // we need to remove them from our internal list, in order to prevent
@@ -784,7 +787,7 @@ QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const
 /*!
 
   Sets the \a provider to use for images requested via the \e
-  image: url scheme, with host \a providerId. The QDeclarativeEngine 
+  image: url scheme, with host \a providerId. The QDeclarativeEngine
   takes ownership of \a provider.
 
   Image providers enable support for pixmap and threaded image
@@ -1105,7 +1108,7 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool cre
 
     rv = pf(const_cast<QObject *>(object));
 
-    if (rv) 
+    if (rv)
         data->attachedProperties()->insert(id, rv);
 
     return rv;
@@ -1297,7 +1300,7 @@ Returns a \l Component object created using the QML file at the specified \a url
 or \c null if an empty string was given.
 
 The returned component's \l Component::status property indicates whether the
-component was successfully created. If the status is \c Component.Error, 
+component was successfully created. If the status is \c Component.Error,
 see \l Component::errorString() for an error description.
 
 Call \l {Component::createObject()}{Component.createObject()} on the returned
@@ -1659,7 +1662,7 @@ QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScr
             return engine->newVariant(QVariant::fromValue(date.toString(format)));
         } else if (formatArg.isNumber()) {
             enumFormat = Qt::DateFormat(formatArg.toUInt32());
-        } else { 
+        } else {
             return ctxt->throwError(QLatin1String("Qt.formatDateTime(): Invalid datetime format"));
         }
     }
@@ -1724,7 +1727,7 @@ QScriptValue QDeclarativeEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine
 }
 
 /*!
-\qmlmethod rect Qt::rect(int x, int y, int width, int height) 
+\qmlmethod rect Qt::rect(int x, int y, int width, int height)
 
 Returns a \c rect with the top-left corner at \c x, \c y and the specified \c width and \c height.
 
@@ -1893,7 +1896,7 @@ Binary to ASCII - this function returns a base64 encoding of \c data.
 */
 QScriptValue QDeclarativeEnginePrivate::btoa(QScriptContext *ctxt, QScriptEngine *)
 {
-    if (ctxt->argumentCount() != 1) 
+    if (ctxt->argumentCount() != 1)
         return ctxt->throwError(QLatin1String("Qt.btoa(): Invalid arguments"));
 
     QByteArray data = ctxt->argument(0).toString().toUtf8();
@@ -1908,7 +1911,7 @@ ASCII to binary - this function returns a base64 decoding of \c data.
 
 QScriptValue QDeclarativeEnginePrivate::atob(QScriptContext *ctxt, QScriptEngine *)
 {
-    if (ctxt->argumentCount() != 1) 
+    if (ctxt->argumentCount() != 1)
         return ctxt->throwError(QLatin1String("Qt.atob(): Invalid arguments"));
 
     QByteArray data = ctxt->argument(0).toString().toUtf8();
@@ -2412,7 +2415,7 @@ QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObj
     }
 }
 
-QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion, 
+QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion,
                                                                   QDeclarativeError &error)
 {
     QList<QDeclarativeType *> types;
@@ -2421,7 +2424,7 @@ QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeTy
 
     const QMetaObject *metaObject = type->metaObject();
     while (metaObject) {
-        QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(), 
+        QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(),
                                                             type->majorVersion(), minorVersion);
         if (t) {
             maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
@@ -2465,7 +2468,7 @@ QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeTy
 
     // Signals override:
     //    * other signals and methods of the same name.
-    //    * properties named on<Signal Name> 
+    //    * properties named on<Signal Name>
     //    * automatic <property name>Changed notify signals
 
     // Methods override:
@@ -2490,7 +2493,7 @@ QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeTy
         QDeclarativePropertyCache::Data *current = d;
         while (!overloadError && current) {
             current = d->overrideData(current);
-            if (current && raw->isAllowedInRevision(current)) 
+            if (current && raw->isAllowedInRevision(current))
                 overloadError = true;
         }
     }
@@ -2498,7 +2501,7 @@ QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeTy
 
     if (overloadError) {
         if (hasCopied) raw->release();
-            
+
         error.setDescription(QLatin1String("Type ") + QString::fromUtf8(type->qmlTypeName()) + QLatin1String(" ") + QString::number(type->majorVersion()) + QLatin1String(".") + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\".  This is an error in the type's implementation."));
         return 0;
     }
diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h
index fadedf41dd23d53d84c9eb55dc4ef56e43965eb9..58a852b3eb25a07684a57ff3f0127d2c2412d42c 100644
--- a/src/declarative/qml/qdeclarativeengine_p.h
+++ b/src/declarative/qml/qdeclarativeengine_p.h
@@ -98,7 +98,6 @@ class QDeclarativeScarceResourceScriptClass;
 class ScarceResourceData;
 class QDeclarativeTypeNameScriptClass;
 class QDeclarativeValueTypeScriptClass;
-class QScriptEngineDebugger;
 class QNetworkReply;
 class QNetworkAccessManager;
 class QDeclarativeNetworkAccessManagerFactory;
@@ -353,14 +352,14 @@ public:
 /*!
 Returns a QDeclarativePropertyCache for \a obj if one is available.
 
-If \a obj is null, being deleted or contains a dynamic meta object 0 
+If \a obj is null, being deleted or contains a dynamic meta object 0
 is returned.
 
 The returned cache is not referenced, so if it is to be stored, call addref().
 */
-QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QObject *obj) 
+QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QObject *obj)
 {
-    if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted) 
+    if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
         return 0;
 
     const QMetaObject *mo = obj->metaObject();
@@ -370,10 +369,10 @@ QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QObject *obj)
 }
 
 /*!
-Returns a QDeclarativePropertyCache for \a metaObject.  
+Returns a QDeclarativePropertyCache for \a metaObject.
 
 As the cache is persisted for the life of the engine, \a metaObject must be
-a static "compile time" meta-object, or a meta-object that is otherwise known to 
+a static "compile time" meta-object, or a meta-object that is otherwise known to
 exist for the lifetime of the QDeclarativeEngine.
 
 The returned cache is not referenced, so if it is to be stored, call addref().
diff --git a/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp
index e24f80f1d2bf46e2f2d7386e852476c5030c8b0a..628c82c90e69407b91a9731df52685bc62d846ae 100644
--- a/src/declarative/util/qdeclarativeview.cpp
+++ b/src/declarative/util/qdeclarativeview.cpp
@@ -49,6 +49,7 @@
 #include <qdeclarativeguard_p.h>
 
 #include <private/qdeclarativedebugtrace_p.h>
+#include <private/qdeclarativeobserverservice_p.h>
 
 #include <qscriptvalueiterator.h>
 #include <qdebug.h>
@@ -299,6 +300,8 @@ void QDeclarativeViewPrivate::init()
     q->viewport()->setAttribute(Qt::WA_OpaquePaintEvent);
     q->viewport()->setAttribute(Qt::WA_NoSystemBackground);
 #endif
+
+    QDeclarativeObserverService::instance()->addView(q);
 }
 
 /*!
@@ -306,6 +309,7 @@ void QDeclarativeViewPrivate::init()
  */
 QDeclarativeView::~QDeclarativeView()
 {
+    QDeclarativeObserverService::instance()->removeView(this);
 }
 
 /*! \property QDeclarativeView::source
@@ -558,7 +562,6 @@ void QDeclarativeView::continueExecute()
     emit statusChanged(status());
 }
 
-
 /*!
   \internal
 */
diff --git a/src/plugins/qmltooling/declarativeobserver/declarativeobserver.pro b/src/plugins/qmltooling/declarativeobserver/declarativeobserver.pro
new file mode 100644
index 0000000000000000000000000000000000000000..6c11efbc9e6df0bc6135a2bccdd676b410705b3f
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/declarativeobserver.pro
@@ -0,0 +1,55 @@
+load(qt_module)
+
+TARGET = declarativeobserver
+QT       += declarative-private
+
+include($$QT_SOURCE_TREE/src/plugins/qpluginbase.pri)
+
+DESTDIR  = $$QT.declarative.plugins/qmltooling
+QTDIR_build:REQUIRES += "contains(QT_CONFIG, declarative)"
+
+SOURCES += \
+    qdeclarativeobserverplugin.cpp \
+    qdeclarativeviewobserver.cpp \
+    editor/abstractliveedittool.cpp \
+    editor/liveselectiontool.cpp \
+    editor/livelayeritem.cpp \
+    editor/livesingleselectionmanipulator.cpp \
+    editor/liverubberbandselectionmanipulator.cpp \
+    editor/liveselectionrectangle.cpp \
+    editor/liveselectionindicator.cpp \
+    editor/boundingrecthighlighter.cpp \
+    editor/subcomponenteditortool.cpp \
+    editor/subcomponentmasklayeritem.cpp \
+    editor/zoomtool.cpp \
+    editor/colorpickertool.cpp \
+    editor/qmltoolbar.cpp \
+    editor/toolbarcolorbox.cpp
+
+HEADERS += \
+    qdeclarativeobserverplugin.h \
+    qdeclarativeobserverprotocol.h \
+    qdeclarativeviewobserver_p.h \
+    qdeclarativeviewobserver_p_p.h \
+    qmlobserverconstants_p.h \
+    editor/abstractliveedittool_p.h \
+    editor/liveselectiontool_p.h \
+    editor/livelayeritem_p.h \
+    editor/livesingleselectionmanipulator_p.h \
+    editor/liverubberbandselectionmanipulator_p.h \
+    editor/liveselectionrectangle_p.h \
+    editor/liveselectionindicator_p.h \
+    editor/boundingrecthighlighter_p.h \
+    editor/subcomponenteditortool_p.h \
+    editor/subcomponentmasklayeritem_p.h \
+    editor/zoomtool_p.h \
+    editor/colorpickertool_p.h \
+    editor/qmltoolbar_p.h \
+    editor/toolbarcolorbox_p.h
+
+RESOURCES += editor/editor.qrc
+
+target.path += $$[QT_INSTALL_PLUGINS]/qmltooling
+INSTALLS += target
+
+symbian:TARGET.UID3=0x20031E90
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/abstractliveedittool.cpp b/src/plugins/qmltooling/declarativeobserver/editor/abstractliveedittool.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b3ed22e3729a432c1f40f0c9fe8d2ef3f42aa5cd
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/abstractliveedittool.cpp
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractliveedittool_p.h"
+#include "../qdeclarativeviewobserver_p_p.h"
+
+#include <QDeclarativeEngine>
+
+#include <QtDebug>
+#include <QGraphicsItem>
+#include <QDeclarativeItem>
+
+QT_BEGIN_NAMESPACE
+
+AbstractLiveEditTool::AbstractLiveEditTool(QDeclarativeViewObserver *editorView)
+    : QObject(editorView), m_observer(editorView)
+{
+}
+
+
+AbstractLiveEditTool::~AbstractLiveEditTool()
+{
+}
+
+QDeclarativeViewObserver *AbstractLiveEditTool::observer() const
+{
+    return m_observer;
+}
+
+QDeclarativeView *AbstractLiveEditTool::view() const
+{
+    return m_observer->declarativeView();
+}
+
+QGraphicsScene* AbstractLiveEditTool::scene() const
+{
+    return view()->scene();
+}
+
+void AbstractLiveEditTool::updateSelectedItems()
+{
+    selectedItemsChanged(items());
+}
+
+QList<QGraphicsItem*> AbstractLiveEditTool::items() const
+{
+    return observer()->selectedItems();
+}
+
+void AbstractLiveEditTool::enterContext(QGraphicsItem *itemToEnter)
+{
+    observer()->data->enterContext(itemToEnter);
+}
+
+bool AbstractLiveEditTool::topItemIsMovable(const QList<QGraphicsItem*> & itemList)
+{
+    QGraphicsItem *firstSelectableItem = topMovableGraphicsItem(itemList);
+    if (firstSelectableItem == 0)
+        return false;
+    if (toQDeclarativeItem(firstSelectableItem) != 0)
+        return true;
+
+    return false;
+
+}
+
+bool AbstractLiveEditTool::topSelectedItemIsMovable(const QList<QGraphicsItem*> &itemList)
+{
+    QList<QGraphicsItem*> selectedItems = observer()->selectedItems();
+
+    foreach (QGraphicsItem *item, itemList) {
+        QDeclarativeItem *declarativeItem = toQDeclarativeItem(item);
+        if (declarativeItem
+                && selectedItems.contains(declarativeItem)
+                /*&& (declarativeItem->qmlItemNode().hasShowContent() || selectNonContentItems)*/)
+            return true;
+    }
+
+    return false;
+
+}
+
+bool AbstractLiveEditTool::topItemIsResizeHandle(const QList<QGraphicsItem*> &/*itemList*/)
+{
+    return false;
+}
+
+QDeclarativeItem *AbstractLiveEditTool::toQDeclarativeItem(QGraphicsItem *item)
+{
+    return qobject_cast<QDeclarativeItem*>(item->toGraphicsObject());
+}
+
+QGraphicsItem *AbstractLiveEditTool::topMovableGraphicsItem(const QList<QGraphicsItem*> &itemList)
+{
+    foreach (QGraphicsItem *item, itemList) {
+        if (item->flags().testFlag(QGraphicsItem::ItemIsMovable))
+            return item;
+    }
+    return 0;
+}
+
+QDeclarativeItem *AbstractLiveEditTool::topMovableDeclarativeItem(const QList<QGraphicsItem*>
+                                                                  &itemList)
+{
+    foreach (QGraphicsItem *item, itemList) {
+        QDeclarativeItem *declarativeItem = toQDeclarativeItem(item);
+        if (declarativeItem /*&& (declarativeItem->qmlItemNode().hasShowContent())*/)
+            return declarativeItem;
+    }
+
+    return 0;
+}
+
+QList<QGraphicsObject*> AbstractLiveEditTool::toGraphicsObjectList(const QList<QGraphicsItem*>
+                                                                   &itemList)
+{
+    QList<QGraphicsObject*> gfxObjects;
+    foreach (QGraphicsItem *item, itemList) {
+        QGraphicsObject *obj = item->toGraphicsObject();
+        if (obj)
+            gfxObjects << obj;
+    }
+
+    return gfxObjects;
+}
+
+QString AbstractLiveEditTool::titleForItem(QGraphicsItem *item)
+{
+    QString className(QLatin1String("QGraphicsItem"));
+    QString objectStringId;
+
+    QString constructedName;
+
+    QGraphicsObject *gfxObject = item->toGraphicsObject();
+    if (gfxObject) {
+        className = QLatin1String(gfxObject->metaObject()->className());
+
+        className.remove(QRegExp(QLatin1String("_QMLTYPE_\\d+")));
+        className.remove(QRegExp(QLatin1String("_QML_\\d+")));
+        if (className.startsWith(QLatin1String("QDeclarative")))
+            className = className.remove(QLatin1String("QDeclarative"));
+
+        QDeclarativeItem *declarativeItem = qobject_cast<QDeclarativeItem*>(gfxObject);
+        if (declarativeItem) {
+            objectStringId = m_observer->idStringForObject(declarativeItem);
+        }
+
+        if (!objectStringId.isEmpty()) {
+            constructedName = objectStringId + QLatin1String(" (") + className + QLatin1Char(')');
+        } else {
+            if (!gfxObject->objectName().isEmpty()) {
+                constructedName = gfxObject->objectName() + QLatin1String(" (") + className + QLatin1Char(')');
+            } else {
+                constructedName = className;
+            }
+        }
+    }
+
+    return constructedName;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/abstractliveedittool_p.h b/src/plugins/qmltooling/declarativeobserver/editor/abstractliveedittool_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..1dbc323ebb1a37b48cbd3a2ed4af14b3ba817837
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/abstractliveedittool_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTLIVEEDITTOOL_H
+#define ABSTRACTLIVEEDITTOOL_H
+
+#include <QtCore/QList>
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+class QMouseEvent;
+class QGraphicsItem;
+class QDeclarativeItem;
+class QKeyEvent;
+class QGraphicsScene;
+class QGraphicsObject;
+class QWheelEvent;
+class QDeclarativeView;
+QT_END_NAMESPACE
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserver;
+
+class AbstractLiveEditTool : public QObject
+{
+    Q_OBJECT
+public:
+    AbstractLiveEditTool(QDeclarativeViewObserver *observer);
+
+    virtual ~AbstractLiveEditTool();
+
+    virtual void mousePressEvent(QMouseEvent *event) = 0;
+    virtual void mouseMoveEvent(QMouseEvent *event) = 0;
+    virtual void mouseReleaseEvent(QMouseEvent *event) = 0;
+    virtual void mouseDoubleClickEvent(QMouseEvent *event) = 0;
+
+    virtual void hoverMoveEvent(QMouseEvent *event) = 0;
+    virtual void wheelEvent(QWheelEvent *event) = 0;
+
+    virtual void keyPressEvent(QKeyEvent *event) = 0;
+    virtual void keyReleaseEvent(QKeyEvent *keyEvent) = 0;
+    virtual void itemsAboutToRemoved(const QList<QGraphicsItem*> &itemList) = 0;
+
+    virtual void clear() = 0;
+
+    void updateSelectedItems();
+    QList<QGraphicsItem*> items() const;
+
+    void enterContext(QGraphicsItem *itemToEnter);
+
+    bool topItemIsMovable(const QList<QGraphicsItem*> &itemList);
+    bool topItemIsResizeHandle(const QList<QGraphicsItem*> &itemList);
+    bool topSelectedItemIsMovable(const QList<QGraphicsItem*> &itemList);
+
+    QString titleForItem(QGraphicsItem *item);
+
+    static QList<QGraphicsObject*> toGraphicsObjectList(const QList<QGraphicsItem*> &itemList);
+    static QGraphicsItem* topMovableGraphicsItem(const QList<QGraphicsItem*> &itemList);
+    static QDeclarativeItem* topMovableDeclarativeItem(const QList<QGraphicsItem*> &itemList);
+    static QDeclarativeItem *toQDeclarativeItem(QGraphicsItem *item);
+
+protected:
+    virtual void selectedItemsChanged(const QList<QGraphicsItem*> &objectList) = 0;
+
+    QDeclarativeViewObserver *observer() const;
+    QDeclarativeView *view() const;
+    QGraphicsScene *scene() const;
+
+private:
+    QDeclarativeViewObserver *m_observer;
+    QList<QGraphicsItem*> m_itemList;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTLIVEEDITTOOL_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/boundingrecthighlighter.cpp b/src/plugins/qmltooling/declarativeobserver/editor/boundingrecthighlighter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..98dbc4fca9b319bc729eff4ccc7e3df10d126047
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/boundingrecthighlighter.cpp
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "boundingrecthighlighter_p.h"
+
+#include "../qdeclarativeviewobserver_p.h"
+#include "../qmlobserverconstants_p.h"
+
+#include <QtGui/QGraphicsPolygonItem>
+
+#include <QtCore/QTimer>
+#include <QtCore/QObject>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+const qreal AnimDelta = 0.025f;
+const int AnimInterval = 30;
+const int AnimFrames = 10;
+
+BoundingBox::BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem,
+                         QObject *parent)
+    : QObject(parent),
+      highlightedObject(itemToHighlight),
+      highlightPolygon(0),
+      highlightPolygonEdge(0)
+{
+    highlightPolygon = new BoundingBoxPolygonItem(parentItem);
+    highlightPolygonEdge = new BoundingBoxPolygonItem(parentItem);
+
+    highlightPolygon->setPen(QPen(QColor(0, 22, 159)));
+    highlightPolygonEdge->setPen(QPen(QColor(158, 199, 255)));
+
+    highlightPolygon->setFlag(QGraphicsItem::ItemIsSelectable, false);
+    highlightPolygonEdge->setFlag(QGraphicsItem::ItemIsSelectable, false);
+}
+
+BoundingBox::~BoundingBox()
+{
+    highlightedObject.clear();
+}
+
+BoundingBoxPolygonItem::BoundingBoxPolygonItem(QGraphicsItem *item) : QGraphicsPolygonItem(item)
+{
+    QPen pen;
+    pen.setColor(QColor(108, 141, 221));
+    pen.setWidth(1);
+    setPen(pen);
+}
+
+int BoundingBoxPolygonItem::type() const
+{
+    return Constants::EditorItemType;
+}
+
+BoundingRectHighlighter::BoundingRectHighlighter(QDeclarativeViewObserver *view) :
+    LiveLayerItem(view->declarativeView()->scene()),
+    m_view(view),
+    m_animFrame(0)
+{
+    m_animTimer = new QTimer(this);
+    m_animTimer->setInterval(AnimInterval);
+    connect(m_animTimer, SIGNAL(timeout()), SLOT(animTimeout()));
+}
+
+BoundingRectHighlighter::~BoundingRectHighlighter()
+{
+
+}
+
+void BoundingRectHighlighter::animTimeout()
+{
+    ++m_animFrame;
+    if (m_animFrame == AnimFrames) {
+        m_animTimer->stop();
+    }
+
+    qreal alpha = m_animFrame / float(AnimFrames);
+
+    foreach (BoundingBox *box, m_boxes) {
+        box->highlightPolygonEdge->setOpacity(alpha);
+    }
+}
+
+void BoundingRectHighlighter::clear()
+{
+    if (m_boxes.length()) {
+        m_animTimer->stop();
+
+        foreach (BoundingBox *box, m_boxes) {
+            freeBoundingBox(box);
+        }
+    }
+}
+
+BoundingBox *BoundingRectHighlighter::boxFor(QGraphicsObject *item) const
+{
+    foreach (BoundingBox *box, m_boxes) {
+        if (box->highlightedObject.data() == item) {
+            return box;
+        }
+    }
+    return 0;
+}
+
+void BoundingRectHighlighter::highlight(QList<QGraphicsObject*> items)
+{
+    if (items.isEmpty())
+        return;
+
+    bool animate = false;
+
+    QList<BoundingBox *> newBoxes;
+    foreach (QGraphicsObject *itemToHighlight, items) {
+        BoundingBox *box = boxFor(itemToHighlight);
+        if (!box) {
+            box = createBoundingBox(itemToHighlight);
+            animate = true;
+        }
+
+        newBoxes << box;
+    }
+    qSort(newBoxes);
+
+    if (newBoxes != m_boxes) {
+        clear();
+        m_boxes << newBoxes;
+    }
+
+    highlightAll(animate);
+}
+
+void BoundingRectHighlighter::highlight(QGraphicsObject* itemToHighlight)
+{
+    if (!itemToHighlight)
+        return;
+
+    bool animate = false;
+
+    BoundingBox *box = boxFor(itemToHighlight);
+    if (!box) {
+        box = createBoundingBox(itemToHighlight);
+        m_boxes << box;
+        animate = true;
+        qSort(m_boxes);
+    }
+
+    highlightAll(animate);
+}
+
+BoundingBox *BoundingRectHighlighter::createBoundingBox(QGraphicsObject *itemToHighlight)
+{
+    if (!m_freeBoxes.isEmpty()) {
+        BoundingBox *box = m_freeBoxes.last();
+        if (box->highlightedObject.isNull()) {
+            box->highlightedObject = itemToHighlight;
+            box->highlightPolygon->show();
+            box->highlightPolygonEdge->show();
+            m_freeBoxes.removeLast();
+            return box;
+        }
+    }
+
+    BoundingBox *box = new BoundingBox(itemToHighlight, this, this);
+
+    connect(itemToHighlight, SIGNAL(xChanged()), this, SLOT(refresh()));
+    connect(itemToHighlight, SIGNAL(yChanged()), this, SLOT(refresh()));
+    connect(itemToHighlight, SIGNAL(widthChanged()), this, SLOT(refresh()));
+    connect(itemToHighlight, SIGNAL(heightChanged()), this, SLOT(refresh()));
+    connect(itemToHighlight, SIGNAL(rotationChanged()), this, SLOT(refresh()));
+    connect(itemToHighlight, SIGNAL(destroyed(QObject*)), this, SLOT(itemDestroyed(QObject*)));
+
+    return box;
+}
+
+void BoundingRectHighlighter::removeBoundingBox(BoundingBox *box)
+{
+    delete box;
+    box = 0;
+}
+
+void BoundingRectHighlighter::freeBoundingBox(BoundingBox *box)
+{
+    if (!box->highlightedObject.isNull()) {
+        disconnect(box->highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh()));
+        disconnect(box->highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh()));
+        disconnect(box->highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh()));
+        disconnect(box->highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh()));
+        disconnect(box->highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh()));
+    }
+
+    box->highlightedObject.clear();
+    box->highlightPolygon->hide();
+    box->highlightPolygonEdge->hide();
+    m_boxes.removeOne(box);
+    m_freeBoxes << box;
+}
+
+void BoundingRectHighlighter::itemDestroyed(QObject *obj)
+{
+    foreach (BoundingBox *box, m_boxes) {
+        if (box->highlightedObject.data() == obj) {
+            freeBoundingBox(box);
+            break;
+        }
+    }
+}
+
+void BoundingRectHighlighter::highlightAll(bool animate)
+{
+    foreach (BoundingBox *box, m_boxes) {
+        if (box && box->highlightedObject.isNull()) {
+            // clear all highlights
+            clear();
+            return;
+        }
+        QGraphicsObject *item = box->highlightedObject.data();
+        QRectF itemAndChildRect = item->boundingRect() | item->childrenBoundingRect();
+
+        QPolygonF boundingRectInSceneSpace(item->mapToScene(itemAndChildRect));
+        QPolygonF boundingRectInLayerItemSpace = mapFromScene(boundingRectInSceneSpace);
+        QRectF bboxRect
+                = m_view->adjustToScreenBoundaries(boundingRectInLayerItemSpace.boundingRect());
+        QRectF edgeRect = bboxRect;
+        edgeRect.adjust(-1, -1, 1, 1);
+
+        box->highlightPolygon->setPolygon(QPolygonF(bboxRect));
+        box->highlightPolygonEdge->setPolygon(QPolygonF(edgeRect));
+
+        if (animate)
+            box->highlightPolygonEdge->setOpacity(0);
+    }
+
+    if (animate) {
+        m_animFrame = 0;
+        m_animTimer->start();
+    }
+}
+
+void BoundingRectHighlighter::refresh()
+{
+    if (!m_boxes.isEmpty())
+        highlightAll(true);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/boundingrecthighlighter_p.h b/src/plugins/qmltooling/declarativeobserver/editor/boundingrecthighlighter_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..c1beed8d4f487afa816af0f96db4b1db028cc32f
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/boundingrecthighlighter_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BOUNDINGRECTHIGHLIGHTER_H
+#define BOUNDINGRECTHIGHLIGHTER_H
+
+#include "livelayeritem_p.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QWeakPointer>
+
+QT_FORWARD_DECLARE_CLASS(QGraphicsItem)
+QT_FORWARD_DECLARE_CLASS(QPainter)
+QT_FORWARD_DECLARE_CLASS(QWidget)
+QT_FORWARD_DECLARE_CLASS(QStyleOptionGraphicsItem)
+QT_FORWARD_DECLARE_CLASS(QTimer)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserver;
+class BoundingBox;
+
+class BoundingRectHighlighter : public LiveLayerItem
+{
+    Q_OBJECT
+public:
+    explicit BoundingRectHighlighter(QDeclarativeViewObserver *view);
+    ~BoundingRectHighlighter();
+    void clear();
+    void highlight(QList<QGraphicsObject*> items);
+    void highlight(QGraphicsObject* item);
+
+private slots:
+    void refresh();
+    void animTimeout();
+    void itemDestroyed(QObject *);
+
+private:
+    BoundingBox *boxFor(QGraphicsObject *item) const;
+    void highlightAll(bool animate);
+    BoundingBox *createBoundingBox(QGraphicsObject *itemToHighlight);
+    void removeBoundingBox(BoundingBox *box);
+    void freeBoundingBox(BoundingBox *box);
+
+private:
+    Q_DISABLE_COPY(BoundingRectHighlighter)
+
+    QDeclarativeViewObserver *m_view;
+    QList<BoundingBox* > m_boxes;
+    QList<BoundingBox* > m_freeBoxes;
+    QTimer *m_animTimer;
+    qreal m_animScale;
+    int m_animFrame;
+
+};
+
+class BoundingBox : public QObject
+{
+    Q_OBJECT
+public:
+    explicit BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem,
+                         QObject *parent = 0);
+    ~BoundingBox();
+    QWeakPointer<QGraphicsObject> highlightedObject;
+    QGraphicsPolygonItem *highlightPolygon;
+    QGraphicsPolygonItem *highlightPolygonEdge;
+
+private:
+    Q_DISABLE_COPY(BoundingBox)
+
+};
+
+class BoundingBoxPolygonItem : public QGraphicsPolygonItem
+{
+public:
+    explicit BoundingBoxPolygonItem(QGraphicsItem *item);
+    int type() const;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // BOUNDINGRECTHIGHLIGHTER_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/colorpickertool.cpp b/src/plugins/qmltooling/declarativeobserver/editor/colorpickertool.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a71e4088cd368c82731d9ee7eb9626072015a93e
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/colorpickertool.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "colorpickertool_p.h"
+
+#include "../qdeclarativeviewobserver_p.h"
+
+#include <QtGui/QMouseEvent>
+#include <QtGui/QKeyEvent>
+#include <QtCore/QRectF>
+#include <QtGui/QRgb>
+#include <QtGui/QImage>
+#include <QtGui/QApplication>
+#include <QtGui/QPalette>
+
+QT_BEGIN_NAMESPACE
+
+ColorPickerTool::ColorPickerTool(QDeclarativeViewObserver *view) :
+    AbstractLiveEditTool(view)
+{
+    m_selectedColor.setRgb(0,0,0);
+}
+
+ColorPickerTool::~ColorPickerTool()
+{
+
+}
+
+void ColorPickerTool::mousePressEvent(QMouseEvent * /*event*/)
+{
+}
+
+void ColorPickerTool::mouseMoveEvent(QMouseEvent *event)
+{
+    pickColor(event->pos());
+}
+
+void ColorPickerTool::mouseReleaseEvent(QMouseEvent *event)
+{
+    pickColor(event->pos());
+}
+
+void ColorPickerTool::mouseDoubleClickEvent(QMouseEvent * /*event*/)
+{
+}
+
+
+void ColorPickerTool::hoverMoveEvent(QMouseEvent * /*event*/)
+{
+}
+
+void ColorPickerTool::keyPressEvent(QKeyEvent * /*event*/)
+{
+}
+
+void ColorPickerTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
+{
+}
+void ColorPickerTool::wheelEvent(QWheelEvent * /*event*/)
+{
+}
+
+void ColorPickerTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
+{
+}
+
+void ColorPickerTool::clear()
+{
+    view()->setCursor(Qt::CrossCursor);
+}
+
+void ColorPickerTool::selectedItemsChanged(const QList<QGraphicsItem*> &/*itemList*/)
+{
+}
+
+void ColorPickerTool::pickColor(const QPoint &pos)
+{
+    QRgb fillColor = view()->backgroundBrush().color().rgb();
+    if (view()->backgroundBrush().style() == Qt::NoBrush)
+        fillColor = view()->palette().color(QPalette::Base).rgb();
+
+    QRectF target(0,0, 1, 1);
+    QRect source(pos.x(), pos.y(), 1, 1);
+    QImage img(1, 1, QImage::Format_ARGB32);
+    img.fill(fillColor);
+    QPainter painter(&img);
+    view()->render(&painter, target, source);
+    m_selectedColor = QColor::fromRgb(img.pixel(0, 0));
+
+    emit selectedColorChanged(m_selectedColor);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/colorpickertool_p.h b/src/plugins/qmltooling/declarativeobserver/editor/colorpickertool_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..86a8893f0daad8433913ff61fba96306c289b297
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/colorpickertool_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef COLORPICKERTOOL_H
+#define COLORPICKERTOOL_H
+
+#include "abstractliveedittool_p.h"
+
+#include <QtGui/QColor>
+
+QT_FORWARD_DECLARE_CLASS(QPoint)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class ColorPickerTool : public AbstractLiveEditTool
+{
+    Q_OBJECT
+public:
+    explicit ColorPickerTool(QDeclarativeViewObserver *view);
+
+    virtual ~ColorPickerTool();
+
+    void mousePressEvent(QMouseEvent *event);
+    void mouseMoveEvent(QMouseEvent *event);
+    void mouseReleaseEvent(QMouseEvent *event);
+    void mouseDoubleClickEvent(QMouseEvent *event);
+
+    void hoverMoveEvent(QMouseEvent *event);
+
+    void keyPressEvent(QKeyEvent *event);
+    void keyReleaseEvent(QKeyEvent *keyEvent);
+
+    void wheelEvent(QWheelEvent *event);
+
+    void itemsAboutToRemoved(const QList<QGraphicsItem*> &itemList);
+
+    void clear();
+
+signals:
+    void selectedColorChanged(const QColor &color);
+
+protected:
+
+    void selectedItemsChanged(const QList<QGraphicsItem*> &itemList);
+
+private:
+    void pickColor(const QPoint &pos);
+
+private:
+    QColor m_selectedColor;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // COLORPICKERTOOL_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/editor.qrc b/src/plugins/qmltooling/declarativeobserver/editor/editor.qrc
new file mode 100644
index 0000000000000000000000000000000000000000..77744d57bb45ce241337d49465d297bdaa342c2f
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/editor.qrc
@@ -0,0 +1,24 @@
+<RCC>
+    <qresource prefix="/qml">
+        <file>images/resize_handle.png</file>
+        <file>images/select.png</file>
+        <file>images/select-marquee.png</file>
+        <file>images/color-picker.png</file>
+        <file>images/play.png</file>
+        <file>images/pause.png</file>
+        <file>images/from-qml.png</file>
+        <file>images/to-qml.png</file>
+        <file>images/color-picker-hicontrast.png</file>
+        <file>images/zoom.png</file>
+        <file>images/color-picker-24.png</file>
+        <file>images/from-qml-24.png</file>
+        <file>images/pause-24.png</file>
+        <file>images/play-24.png</file>
+        <file>images/to-qml-24.png</file>
+        <file>images/zoom-24.png</file>
+        <file>images/select-24.png</file>
+        <file>images/select-marquee-24.png</file>
+        <file>images/observermode.png</file>
+        <file>images/observermode-24.png</file>
+    </qresource>
+</RCC>
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker-24.png
new file mode 100644
index 0000000000000000000000000000000000000000..cff47212a4f031c73791286788ed0a69c27618ea
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker-24.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker-hicontrast.png b/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker-hicontrast.png
new file mode 100644
index 0000000000000000000000000000000000000000..b953d08a689588cce464430e039d0b1bb0086bec
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker-hicontrast.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker.png b/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker.png
new file mode 100644
index 0000000000000000000000000000000000000000..026c31b3e1ddaaf4697b077ac693f3ad576b7023
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/from-qml-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/from-qml-24.png
new file mode 100644
index 0000000000000000000000000000000000000000..0ad21f3dbbf6e57d86351f2f472889e105186b61
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/from-qml-24.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/from-qml.png b/src/plugins/qmltooling/declarativeobserver/editor/images/from-qml.png
new file mode 100644
index 0000000000000000000000000000000000000000..666382c06dde13aae6cf433729da5cb155cf095b
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/from-qml.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/observermode-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/observermode-24.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e74d867c0a62eece4fd0986d950572814551e16
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/observermode-24.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/observermode.png b/src/plugins/qmltooling/declarativeobserver/editor/images/observermode.png
new file mode 100644
index 0000000000000000000000000000000000000000..daed21c9448aa789ed398125fb4d46d8f4d6dda0
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/observermode.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/pause-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/pause-24.png
new file mode 100644
index 0000000000000000000000000000000000000000..d9a2f6f814bd547536dd452462829fdc3014a6c4
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/pause-24.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/pause.png b/src/plugins/qmltooling/declarativeobserver/editor/images/pause.png
new file mode 100644
index 0000000000000000000000000000000000000000..114d89b12bdca29a40dd90d6004b53d00d323257
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/pause.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/play-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/play-24.png
new file mode 100644
index 0000000000000000000000000000000000000000..e2b9fbcf5126db709e54878dac3b1065e118c9c0
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/play-24.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/play.png b/src/plugins/qmltooling/declarativeobserver/editor/images/play.png
new file mode 100644
index 0000000000000000000000000000000000000000..011598a746fda2fb68de10ee4233429e474b7908
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/play.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/reload.png b/src/plugins/qmltooling/declarativeobserver/editor/images/reload.png
new file mode 100644
index 0000000000000000000000000000000000000000..7042bec9ae9f1076acd08e9fa72fda4f51118cfe
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/reload.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/resize_handle.png b/src/plugins/qmltooling/declarativeobserver/editor/images/resize_handle.png
new file mode 100644
index 0000000000000000000000000000000000000000..2934f25b7436ea36065f0ef5c249db9e87b04906
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/resize_handle.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/select-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/select-24.png
new file mode 100644
index 0000000000000000000000000000000000000000..5388a9d16ab38432cb9ec8039e8005297ad71104
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/select-24.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/select-marquee-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/select-marquee-24.png
new file mode 100644
index 0000000000000000000000000000000000000000..0111ddae458399551c52279e273334322bfeabf2
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/select-marquee-24.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/select-marquee.png b/src/plugins/qmltooling/declarativeobserver/editor/images/select-marquee.png
new file mode 100644
index 0000000000000000000000000000000000000000..92fe40d1adc99326c9edb2c31d3dd7a042a04f0d
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/select-marquee.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/select.png b/src/plugins/qmltooling/declarativeobserver/editor/images/select.png
new file mode 100644
index 0000000000000000000000000000000000000000..672285582b5cc30d0cfe457a20c2982e1b056a99
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/select.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/to-qml-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/to-qml-24.png
new file mode 100644
index 0000000000000000000000000000000000000000..b72450ddd47a39ff5d9c87e7964c320b7f25ebd5
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/to-qml-24.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/to-qml.png b/src/plugins/qmltooling/declarativeobserver/editor/images/to-qml.png
new file mode 100644
index 0000000000000000000000000000000000000000..2ab951fd082096b1b3838d4e2342d302ce23518d
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/to-qml.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/zoom-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/zoom-24.png
new file mode 100644
index 0000000000000000000000000000000000000000..03462001ecb1b4b6214358f65876eb62602af514
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/zoom-24.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/zoom.png b/src/plugins/qmltooling/declarativeobserver/editor/images/zoom.png
new file mode 100644
index 0000000000000000000000000000000000000000..17f0da6d64f983dcf256801dd4113e6a075d9a59
Binary files /dev/null and b/src/plugins/qmltooling/declarativeobserver/editor/images/zoom.png differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/livelayeritem.cpp b/src/plugins/qmltooling/declarativeobserver/editor/livelayeritem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7b508a4c5e87ce35e8637ad9338a834587b5647d
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/livelayeritem.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "livelayeritem_p.h"
+
+#include "../qmlobserverconstants_p.h"
+
+#include <QGraphicsScene>
+
+QT_BEGIN_NAMESPACE
+
+LiveLayerItem::LiveLayerItem(QGraphicsScene* scene)
+    : QGraphicsObject()
+{
+    scene->addItem(this);
+    setZValue(1);
+    setFlag(QGraphicsItem::ItemIsMovable, false);
+}
+
+LiveLayerItem::~LiveLayerItem()
+{
+}
+
+void LiveLayerItem::paint(QPainter * /*painter*/, const QStyleOptionGraphicsItem * /*option*/,
+                          QWidget * /*widget*/)
+{
+}
+
+int LiveLayerItem::type() const
+{
+    return Constants::EditorItemType;
+}
+
+QRectF LiveLayerItem::boundingRect() const
+{
+    return childrenBoundingRect();
+}
+
+QList<QGraphicsItem*> LiveLayerItem::findAllChildItems() const
+{
+    return findAllChildItems(this);
+}
+
+QList<QGraphicsItem*> LiveLayerItem::findAllChildItems(const QGraphicsItem *item) const
+{
+    QList<QGraphicsItem*> itemList(item->childItems());
+
+    foreach (QGraphicsItem *childItem, item->childItems())
+        itemList += findAllChildItems(childItem);
+
+    return itemList;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/livelayeritem_p.h b/src/plugins/qmltooling/declarativeobserver/editor/livelayeritem_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..242e3650a8cde6a10f7b30ee4930690d9be45145
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/livelayeritem_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LIVELAYERITEM_H
+#define LIVELAYERITEM_H
+
+#include <QtGui/QGraphicsObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class LiveLayerItem : public QGraphicsObject
+{
+public:
+    LiveLayerItem(QGraphicsScene *scene);
+    ~LiveLayerItem();
+    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+                QWidget *widget = 0);
+    QRectF boundingRect() const;
+    int type() const;
+
+    QList<QGraphicsItem*> findAllChildItems() const;
+
+protected:
+    QList<QGraphicsItem*> findAllChildItems(const QGraphicsItem *item) const;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // LIVELAYERITEM_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liverubberbandselectionmanipulator.cpp b/src/plugins/qmltooling/declarativeobserver/editor/liverubberbandselectionmanipulator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6c37ba5a4b3e35a3db879ed3fd0675f1c1370061
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liverubberbandselectionmanipulator.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "liverubberbandselectionmanipulator_p.h"
+
+#include "../qdeclarativeviewobserver_p_p.h"
+
+#include <QtGui/QGraphicsItem>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+LiveRubberBandSelectionManipulator::LiveRubberBandSelectionManipulator(QGraphicsObject *layerItem,
+                                                                       QDeclarativeViewObserver *editorView)
+    : m_selectionRectangleElement(layerItem),
+      m_editorView(editorView),
+      m_beginFormEditorItem(0),
+      m_isActive(false)
+{
+    m_selectionRectangleElement.hide();
+}
+
+void LiveRubberBandSelectionManipulator::clear()
+{
+    m_selectionRectangleElement.clear();
+    m_isActive = false;
+    m_beginPoint = QPointF();
+    m_itemList.clear();
+    m_oldSelectionList.clear();
+}
+
+QGraphicsItem *LiveRubberBandSelectionManipulator::topFormEditorItem(const QList<QGraphicsItem*>
+                                                                     &itemList)
+{
+    if (itemList.isEmpty())
+        return 0;
+
+    return itemList.first();
+}
+
+void LiveRubberBandSelectionManipulator::begin(const QPointF &beginPoint)
+{
+    m_beginPoint = beginPoint;
+    m_selectionRectangleElement.setRect(m_beginPoint, m_beginPoint);
+    m_selectionRectangleElement.show();
+    m_isActive = true;
+    QDeclarativeViewObserverPrivate *observerPrivate
+            = QDeclarativeViewObserverPrivate::get(m_editorView);
+    m_beginFormEditorItem = topFormEditorItem(observerPrivate->selectableItems(beginPoint));
+    m_oldSelectionList = m_editorView->selectedItems();
+}
+
+void LiveRubberBandSelectionManipulator::update(const QPointF &updatePoint)
+{
+    m_selectionRectangleElement.setRect(m_beginPoint, updatePoint);
+}
+
+void LiveRubberBandSelectionManipulator::end()
+{
+    m_oldSelectionList.clear();
+    m_selectionRectangleElement.hide();
+    m_isActive = false;
+}
+
+void LiveRubberBandSelectionManipulator::select(SelectionType selectionType)
+{
+    QDeclarativeViewObserverPrivate *observerPrivate
+            = QDeclarativeViewObserverPrivate::get(m_editorView);
+    QList<QGraphicsItem*> itemList
+            = observerPrivate->selectableItems(m_selectionRectangleElement.rect(),
+                                               Qt::IntersectsItemShape);
+    QList<QGraphicsItem*> newSelectionList;
+
+    foreach (QGraphicsItem* item, itemList) {
+        if (item
+                && item->parentItem()
+                && !newSelectionList.contains(item)
+                //&& m_beginFormEditorItem->childItems().contains(item) // TODO activate this test
+                )
+        {
+            newSelectionList.append(item);
+        }
+    }
+
+    if (newSelectionList.isEmpty() && m_beginFormEditorItem)
+        newSelectionList.append(m_beginFormEditorItem);
+
+    QList<QGraphicsItem*> resultList;
+
+    switch (selectionType) {
+    case AddToSelection: {
+        resultList.append(m_oldSelectionList);
+        resultList.append(newSelectionList);
+    }
+        break;
+    case ReplaceSelection: {
+        resultList.append(newSelectionList);
+    }
+        break;
+    case RemoveFromSelection: {
+        QSet<QGraphicsItem*> oldSelectionSet(m_oldSelectionList.toSet());
+        QSet<QGraphicsItem*> newSelectionSet(newSelectionList.toSet());
+        resultList.append(oldSelectionSet.subtract(newSelectionSet).toList());
+    }
+    }
+
+    m_editorView->setSelectedItems(resultList);
+}
+
+
+void LiveRubberBandSelectionManipulator::setItems(const QList<QGraphicsItem*> &itemList)
+{
+    m_itemList = itemList;
+}
+
+QPointF LiveRubberBandSelectionManipulator::beginPoint() const
+{
+    return m_beginPoint;
+}
+
+bool LiveRubberBandSelectionManipulator::isActive() const
+{
+    return m_isActive;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liverubberbandselectionmanipulator_p.h b/src/plugins/qmltooling/declarativeobserver/editor/liverubberbandselectionmanipulator_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..8d15288299dbf99730c69ae637e588dfb2e27cc7
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liverubberbandselectionmanipulator_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RUBBERBANDSELECTIONMANIPULATOR_H
+#define RUBBERBANDSELECTIONMANIPULATOR_H
+
+#include "liveselectionrectangle_p.h"
+
+#include <QtCore/QPointF>
+
+QT_FORWARD_DECLARE_CLASS(QGraphicsItem)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserver;
+
+class LiveRubberBandSelectionManipulator
+{
+public:
+    enum SelectionType {
+        ReplaceSelection,
+        AddToSelection,
+        RemoveFromSelection
+    };
+
+    LiveRubberBandSelectionManipulator(QGraphicsObject *layerItem,
+                                       QDeclarativeViewObserver *editorView);
+
+    void setItems(const QList<QGraphicsItem*> &itemList);
+
+    void begin(const QPointF& beginPoint);
+    void update(const QPointF& updatePoint);
+    void end();
+
+    void clear();
+
+    void select(SelectionType selectionType);
+
+    QPointF beginPoint() const;
+
+    bool isActive() const;
+
+protected:
+    QGraphicsItem *topFormEditorItem(const QList<QGraphicsItem*> &itemList);
+
+private:
+    QList<QGraphicsItem*> m_itemList;
+    QList<QGraphicsItem*> m_oldSelectionList;
+    LiveSelectionRectangle m_selectionRectangleElement;
+    QPointF m_beginPoint;
+    QDeclarativeViewObserver *m_editorView;
+    QGraphicsItem *m_beginFormEditorItem;
+    bool m_isActive;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // RUBBERBANDSELECTIONMANIPULATOR_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liveselectionindicator.cpp b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionindicator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..96e9dbf0cbe43727b0b8e38f9c094e406eecbfa2
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionindicator.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "liveselectionindicator_p.h"
+
+#include "../qdeclarativeviewobserver_p_p.h"
+#include "../qmlobserverconstants_p.h"
+
+#include <QtCore/QDebug>
+
+#include <QtGui/QGraphicsPolygonItem>
+#include <QtGui/QGraphicsObject>
+#include <QtGui/QGraphicsScene>
+#include <QtGui/QPen>
+
+#include <cmath>
+
+QT_BEGIN_NAMESPACE
+
+LiveSelectionIndicator::LiveSelectionIndicator(QDeclarativeViewObserver *editorView,
+                                       QGraphicsObject *layerItem)
+    : m_layerItem(layerItem), m_view(editorView)
+{
+}
+
+LiveSelectionIndicator::~LiveSelectionIndicator()
+{
+    clear();
+}
+
+void LiveSelectionIndicator::show()
+{
+    foreach (QGraphicsPolygonItem *item, m_indicatorShapeHash.values())
+        item->show();
+}
+
+void LiveSelectionIndicator::hide()
+{
+    foreach (QGraphicsPolygonItem *item, m_indicatorShapeHash.values())
+        item->hide();
+}
+
+void LiveSelectionIndicator::clear()
+{
+    if (!m_layerItem.isNull()) {
+        QHashIterator<QGraphicsItem*, QGraphicsPolygonItem *> iter(m_indicatorShapeHash);
+        while (iter.hasNext()) {
+            iter.next();
+            m_layerItem.data()->scene()->removeItem(iter.value());
+            delete iter.value();
+        }
+    }
+
+    m_indicatorShapeHash.clear();
+
+}
+
+QPolygonF LiveSelectionIndicator::addBoundingRectToPolygon(QGraphicsItem *item, QPolygonF &polygon)
+{
+    // ### remove this if statement when QTBUG-12172 gets fixed
+    if (item->boundingRect() != QRectF(0,0,0,0)) {
+        QPolygonF bounding = item->mapToScene(item->boundingRect());
+        if (bounding.isClosed()) //avoid crashes if there is an infinite scale.
+            polygon = polygon.united(bounding);
+    }
+
+    foreach (QGraphicsItem *child, item->childItems()) {
+        if (!QDeclarativeViewObserverPrivate::get(m_view)->isEditorItem(child))
+            addBoundingRectToPolygon(child, polygon);
+    }
+    return polygon;
+}
+
+void LiveSelectionIndicator::setItems(const QList<QWeakPointer<QGraphicsObject> > &itemList)
+{
+    clear();
+
+    // set selections to also all children if they are not editor items
+
+    foreach (const QWeakPointer<QGraphicsObject> &object, itemList) {
+        if (object.isNull())
+            continue;
+
+        QGraphicsItem *item = object.data();
+
+        QGraphicsPolygonItem *newSelectionIndicatorGraphicsItem
+                = new QGraphicsPolygonItem(m_layerItem.data());
+        if (!m_indicatorShapeHash.contains(item)) {
+            m_indicatorShapeHash.insert(item, newSelectionIndicatorGraphicsItem);
+
+            QPolygonF boundingShapeInSceneSpace;
+            addBoundingRectToPolygon(item, boundingShapeInSceneSpace);
+
+            QRectF boundingRect
+                    = m_view->adjustToScreenBoundaries(boundingShapeInSceneSpace.boundingRect());
+            QPolygonF boundingRectInLayerItemSpace = m_layerItem.data()->mapFromScene(boundingRect);
+
+            QPen pen;
+            pen.setColor(QColor(108, 141, 221));
+            newSelectionIndicatorGraphicsItem->setData(Constants::EditorItemDataKey,
+                                                       QVariant(true));
+            newSelectionIndicatorGraphicsItem->setFlag(QGraphicsItem::ItemIsSelectable, false);
+            newSelectionIndicatorGraphicsItem->setPolygon(boundingRectInLayerItemSpace);
+            newSelectionIndicatorGraphicsItem->setPen(pen);
+        }
+    }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liveselectionindicator_p.h b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionindicator_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..da95955a9a2954b2147e002bc68393ddae28171f
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionindicator_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LIVESELECTIONINDICATOR_H
+#define LIVESELECTIONINDICATOR_H
+
+#include <QtCore/QWeakPointer>
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+class QGraphicsObject;
+class QGraphicsPolygonItem;
+class QGraphicsItem;
+class QPolygonF;
+QT_END_NAMESPACE
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserver;
+
+class LiveSelectionIndicator
+{
+public:
+    LiveSelectionIndicator(QDeclarativeViewObserver* editorView, QGraphicsObject *layerItem);
+    ~LiveSelectionIndicator();
+
+    void show();
+    void hide();
+
+    void clear();
+
+    void setItems(const QList<QWeakPointer<QGraphicsObject> > &itemList);
+
+private:
+    QPolygonF addBoundingRectToPolygon(QGraphicsItem *item, QPolygonF &polygon);
+
+private:
+    QHash<QGraphicsItem*, QGraphicsPolygonItem *> m_indicatorShapeHash;
+    QWeakPointer<QGraphicsObject> m_layerItem;
+    QDeclarativeViewObserver *m_view;
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // LIVESELECTIONINDICATOR_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liveselectionrectangle.cpp b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionrectangle.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2a1d39306a1d72e16477af082b8175612f8d43d4
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionrectangle.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "liveselectionrectangle_p.h"
+
+#include "../qmlobserverconstants_p.h"
+
+#include <QtGui/QPen>
+#include <QtGui/QGraphicsRectItem>
+#include <QtGui/QGraphicsObject>
+#include <QtGui/QGraphicsScene>
+
+#include <QtCore/QtDebug>
+
+#include <cmath>
+
+QT_BEGIN_NAMESPACE
+
+class SelectionRectShape : public QGraphicsRectItem
+{
+public:
+    SelectionRectShape(QGraphicsItem *parent = 0) : QGraphicsRectItem(parent) {}
+    int type() const { return Constants::EditorItemType; }
+};
+
+LiveSelectionRectangle::LiveSelectionRectangle(QGraphicsObject *layerItem)
+    : m_controlShape(new SelectionRectShape(layerItem)),
+      m_layerItem(layerItem)
+{
+    m_controlShape->setPen(QPen(Qt::black));
+    m_controlShape->setBrush(QColor(128, 128, 128, 50));
+}
+
+LiveSelectionRectangle::~LiveSelectionRectangle()
+{
+    if (m_layerItem)
+        m_layerItem.data()->scene()->removeItem(m_controlShape);
+}
+
+void LiveSelectionRectangle::clear()
+{
+    hide();
+}
+void LiveSelectionRectangle::show()
+{
+    m_controlShape->show();
+}
+
+void LiveSelectionRectangle::hide()
+{
+    m_controlShape->hide();
+}
+
+QRectF LiveSelectionRectangle::rect() const
+{
+    return m_controlShape->mapFromScene(m_controlShape->rect()).boundingRect();
+}
+
+void LiveSelectionRectangle::setRect(const QPointF &firstPoint,
+                                 const QPointF &secondPoint)
+{
+    double firstX = std::floor(firstPoint.x()) + 0.5;
+    double firstY = std::floor(firstPoint.y()) + 0.5;
+    double secondX = std::floor(secondPoint.x()) + 0.5;
+    double secondY = std::floor(secondPoint.y()) + 0.5;
+    QPointF topLeftPoint(firstX < secondX ? firstX : secondX,
+                         firstY < secondY ? firstY : secondY);
+    QPointF bottomRightPoint(firstX > secondX ? firstX : secondX,
+                             firstY > secondY ? firstY : secondY);
+
+    QRectF rect(topLeftPoint, bottomRightPoint);
+    m_controlShape->setRect(rect);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liveselectionrectangle_p.h b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionrectangle_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..d1bed7252bb5890d0ab6ea33186bc73c8f326e6d
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionrectangle_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LIVESELECTIONRECTANGLE_H
+#define LIVESELECTIONRECTANGLE_H
+
+#include <QtCore/QWeakPointer>
+
+QT_FORWARD_DECLARE_CLASS(QGraphicsObject)
+QT_FORWARD_DECLARE_CLASS(QGraphicsRectItem)
+QT_FORWARD_DECLARE_CLASS(QPointF)
+QT_FORWARD_DECLARE_CLASS(QRectF)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class LiveSelectionRectangle
+{
+public:
+    LiveSelectionRectangle(QGraphicsObject *layerItem);
+    ~LiveSelectionRectangle();
+
+    void show();
+    void hide();
+
+    void clear();
+
+    void setRect(const QPointF &firstPoint,
+                 const QPointF &secondPoint);
+
+    QRectF rect() const;
+
+private:
+    QGraphicsRectItem *m_controlShape;
+    QWeakPointer<QGraphicsObject> m_layerItem;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // LIVESELECTIONRECTANGLE_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liveselectiontool.cpp b/src/plugins/qmltooling/declarativeobserver/editor/liveselectiontool.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d85926e324efefc194303ba9549d99d9cfee491c
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liveselectiontool.cpp
@@ -0,0 +1,442 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "liveselectiontool_p.h"
+#include "livelayeritem_p.h"
+
+#include "../qdeclarativeviewobserver_p_p.h"
+
+#include <QtGui/QApplication>
+#include <QtGui/QWheelEvent>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QClipboard>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+#include <QtGui/QGraphicsObject>
+
+#include <QtDeclarative/QDeclarativeItem>
+#include <QtDeclarative/QDeclarativeEngine>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+LiveSelectionTool::LiveSelectionTool(QDeclarativeViewObserver *editorView) :
+    AbstractLiveEditTool(editorView),
+    m_rubberbandSelectionMode(false),
+    m_rubberbandSelectionManipulator(
+        QDeclarativeViewObserverPrivate::get(editorView)->manipulatorLayer, editorView),
+    m_singleSelectionManipulator(editorView),
+    m_selectionIndicator(editorView,
+        QDeclarativeViewObserverPrivate::get(editorView)->manipulatorLayer),
+    //m_resizeIndicator(editorView->manipulatorLayer()),
+    m_selectOnlyContentItems(true)
+{
+
+}
+
+LiveSelectionTool::~LiveSelectionTool()
+{
+}
+
+void LiveSelectionTool::setRubberbandSelectionMode(bool value)
+{
+    m_rubberbandSelectionMode = value;
+}
+
+LiveSingleSelectionManipulator::SelectionType LiveSelectionTool::getSelectionType(Qt::KeyboardModifiers
+                                                                          modifiers)
+{
+   LiveSingleSelectionManipulator::SelectionType selectionType
+            = LiveSingleSelectionManipulator::ReplaceSelection;
+    if (modifiers.testFlag(Qt::ControlModifier)) {
+        selectionType = LiveSingleSelectionManipulator::RemoveFromSelection;
+    } else if (modifiers.testFlag(Qt::ShiftModifier)) {
+        selectionType = LiveSingleSelectionManipulator::AddToSelection;
+    }
+    return selectionType;
+}
+
+bool LiveSelectionTool::alreadySelected(const QList<QGraphicsItem*> &itemList) const
+{
+    QDeclarativeViewObserverPrivate *observerPrivate
+            = QDeclarativeViewObserverPrivate::get(observer());
+    const QList<QGraphicsItem*> selectedItems = observerPrivate->selectedItems();
+
+    if (selectedItems.isEmpty())
+        return false;
+
+    foreach (QGraphicsItem *item, itemList)
+        if (selectedItems.contains(item))
+            return true;
+
+    return false;
+}
+
+void LiveSelectionTool::mousePressEvent(QMouseEvent *event)
+{
+    QDeclarativeViewObserverPrivate *observerPrivate
+            = QDeclarativeViewObserverPrivate::get(observer());
+    QList<QGraphicsItem*> itemList = observerPrivate->selectableItems(event->pos());
+    LiveSingleSelectionManipulator::SelectionType selectionType = getSelectionType(event->modifiers());
+
+    if (event->buttons() & Qt::LeftButton) {
+        m_mousePressTimer.start();
+
+        if (m_rubberbandSelectionMode) {
+            m_rubberbandSelectionManipulator.begin(event->pos());
+        } else {
+            m_singleSelectionManipulator.begin(event->pos());
+            m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
+        }
+    } else if (event->buttons() & Qt::RightButton) {
+        createContextMenu(itemList, event->globalPos());
+    }
+}
+
+void LiveSelectionTool::createContextMenu(QList<QGraphicsItem*> itemList, QPoint globalPos)
+{
+    if (!QDeclarativeViewObserverPrivate::get(observer())->mouseInsideContextItem())
+        return;
+
+    QMenu contextMenu;
+    connect(&contextMenu, SIGNAL(hovered(QAction*)),
+            this, SLOT(contextMenuElementHovered(QAction*)));
+
+    m_contextMenuItemList = itemList;
+
+    contextMenu.addAction(tr("Items"));
+    contextMenu.addSeparator();
+    int shortcutKey = Qt::Key_1;
+    bool addKeySequence = true;
+    int i = 0;
+
+    foreach (QGraphicsItem * const item, itemList) {
+        QString itemTitle = titleForItem(item);
+        QAction *elementAction = contextMenu.addAction(itemTitle, this,
+                                                       SLOT(contextMenuElementSelected()));
+
+        if (observer()->selectedItems().contains(item)) {
+            QFont boldFont = elementAction->font();
+            boldFont.setBold(true);
+            elementAction->setFont(boldFont);
+        }
+
+        elementAction->setData(i);
+        if (addKeySequence)
+            elementAction->setShortcut(QKeySequence(shortcutKey));
+
+        shortcutKey++;
+        if (shortcutKey > Qt::Key_9)
+            addKeySequence = false;
+
+        ++i;
+    }
+    // add root item separately
+    //    QString itemTitle = QString(tr("%1")).arg(titleForItem(view()->currentRootItem()));
+    //    contextMenu.addAction(itemTitle, this, SLOT(contextMenuElementSelected()));
+    //    m_contextMenuItemList.append(view()->currentRootItem());
+
+    contextMenu.exec(globalPos);
+    m_contextMenuItemList.clear();
+}
+
+void LiveSelectionTool::contextMenuElementSelected()
+{
+    QAction *senderAction = static_cast<QAction*>(sender());
+    int itemListIndex = senderAction->data().toInt();
+    if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) {
+
+        QPointF updatePt(0, 0);
+        QGraphicsItem *item = m_contextMenuItemList.at(itemListIndex);
+        m_singleSelectionManipulator.begin(updatePt);
+        m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::InvertSelection,
+                                            QList<QGraphicsItem*>() << item,
+                                            false);
+        m_singleSelectionManipulator.end(updatePt);
+        enterContext(item);
+    }
+}
+
+void LiveSelectionTool::contextMenuElementHovered(QAction *action)
+{
+    int itemListIndex = action->data().toInt();
+    if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) {
+        QGraphicsObject *item = m_contextMenuItemList.at(itemListIndex)->toGraphicsObject();
+        QDeclarativeViewObserverPrivate::get(observer())->highlight(item);
+    }
+}
+
+void LiveSelectionTool::mouseMoveEvent(QMouseEvent *event)
+{
+    if (m_singleSelectionManipulator.isActive()) {
+        QPointF mouseMovementVector = m_singleSelectionManipulator.beginPoint() - event->pos();
+
+        if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance)
+                && (m_mousePressTimer.elapsed() > Constants::DragStartTime))
+        {
+            m_singleSelectionManipulator.end(event->pos());
+            //view()->changeToMoveTool(m_singleSelectionManipulator.beginPoint());
+            return;
+        }
+    } else if (m_rubberbandSelectionManipulator.isActive()) {
+        QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos();
+
+        if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance)
+                && (m_mousePressTimer.elapsed() > Constants::DragStartTime)) {
+            m_rubberbandSelectionManipulator.update(event->pos());
+
+            if (event->modifiers().testFlag(Qt::ControlModifier))
+                m_rubberbandSelectionManipulator.select(
+                            LiveRubberBandSelectionManipulator::RemoveFromSelection);
+            else if (event->modifiers().testFlag(Qt::ShiftModifier))
+                m_rubberbandSelectionManipulator.select(
+                            LiveRubberBandSelectionManipulator::AddToSelection);
+            else
+                m_rubberbandSelectionManipulator.select(
+                            LiveRubberBandSelectionManipulator::ReplaceSelection);
+        }
+    }
+}
+
+void LiveSelectionTool::hoverMoveEvent(QMouseEvent * event)
+{
+// ### commented out until move tool is re-enabled
+//    QList<QGraphicsItem*> itemList = view()->items(event->pos());
+//    if (!itemList.isEmpty() && !m_rubberbandSelectionMode) {
+//
+//        foreach (QGraphicsItem *item, itemList) {
+//            if (item->type() == Constants::ResizeHandleItemType) {
+//                ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(item);
+//                if (resizeHandle)
+//                    view()->changeTool(Constants::ResizeToolMode);
+//                return;
+//            }
+//        }
+//        if (topSelectedItemIsMovable(itemList))
+//            view()->changeTool(Constants::MoveToolMode);
+//    }
+    QDeclarativeViewObserverPrivate *observerPrivate
+            = QDeclarativeViewObserverPrivate::get(observer());
+
+    QList<QGraphicsItem*> selectableItemList = observerPrivate->selectableItems(event->pos());
+    if (!selectableItemList.isEmpty()) {
+        QGraphicsObject *item = selectableItemList.first()->toGraphicsObject();
+        if (item)
+            QDeclarativeViewObserverPrivate::get(observer())->highlight(item);
+
+        return;
+    }
+
+    QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
+}
+
+void LiveSelectionTool::mouseReleaseEvent(QMouseEvent *event)
+{
+    if (m_singleSelectionManipulator.isActive()) {
+        m_singleSelectionManipulator.end(event->pos());
+    }
+    else if (m_rubberbandSelectionManipulator.isActive()) {
+
+        QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos();
+        if (mouseMovementVector.toPoint().manhattanLength() < Constants::DragStartDistance) {
+            m_singleSelectionManipulator.begin(event->pos());
+
+            if (event->modifiers().testFlag(Qt::ControlModifier))
+                m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::RemoveFromSelection,
+                                                    m_selectOnlyContentItems);
+            else if (event->modifiers().testFlag(Qt::ShiftModifier))
+                m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::AddToSelection,
+                                                    m_selectOnlyContentItems);
+            else
+                m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::InvertSelection,
+                                                    m_selectOnlyContentItems);
+
+            m_singleSelectionManipulator.end(event->pos());
+        } else {
+            m_rubberbandSelectionManipulator.update(event->pos());
+
+            if (event->modifiers().testFlag(Qt::ControlModifier))
+                m_rubberbandSelectionManipulator.select(
+                            LiveRubberBandSelectionManipulator::RemoveFromSelection);
+            else if (event->modifiers().testFlag(Qt::ShiftModifier))
+                m_rubberbandSelectionManipulator.select(
+                            LiveRubberBandSelectionManipulator::AddToSelection);
+            else
+                m_rubberbandSelectionManipulator.select(
+                            LiveRubberBandSelectionManipulator::ReplaceSelection);
+
+            m_rubberbandSelectionManipulator.end();
+        }
+    }
+}
+
+void LiveSelectionTool::mouseDoubleClickEvent(QMouseEvent * /*event*/)
+{
+}
+
+void LiveSelectionTool::keyPressEvent(QKeyEvent *event)
+{
+    switch (event->key()) {
+    case Qt::Key_Left:
+    case Qt::Key_Right:
+    case Qt::Key_Up:
+    case Qt::Key_Down:
+        // disabled for now, cannot move stuff yet.
+        //view()->changeTool(Constants::MoveToolMode);
+        //view()->currentTool()->keyPressEvent(event);
+        break;
+    }
+}
+
+void LiveSelectionTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
+{
+
+}
+
+void LiveSelectionTool::wheelEvent(QWheelEvent *event)
+{
+    if (event->orientation() == Qt::Horizontal || m_rubberbandSelectionMode)
+        return;
+
+    QDeclarativeViewObserverPrivate *observerPrivate
+            = QDeclarativeViewObserverPrivate::get(observer());
+    QList<QGraphicsItem*> itemList = observerPrivate->selectableItems(event->pos());
+
+    if (itemList.isEmpty())
+        return;
+
+    int selectedIdx = 0;
+    if (!observer()->selectedItems().isEmpty()) {
+        selectedIdx = itemList.indexOf(observer()->selectedItems().first());
+        if (selectedIdx >= 0) {
+            if (event->delta() > 0) {
+                selectedIdx++;
+                if (selectedIdx == itemList.length())
+                    selectedIdx = 0;
+            } else if (event->delta() < 0) {
+                selectedIdx--;
+                if (selectedIdx == -1)
+                    selectedIdx = itemList.length() - 1;
+            }
+        } else {
+            selectedIdx = 0;
+        }
+    }
+
+    QPointF updatePt(0, 0);
+    m_singleSelectionManipulator.begin(updatePt);
+    m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::ReplaceSelection,
+                                        QList<QGraphicsItem*>() << itemList.at(selectedIdx),
+                                        false);
+    m_singleSelectionManipulator.end(updatePt);
+
+}
+
+void LiveSelectionTool::setSelectOnlyContentItems(bool selectOnlyContentItems)
+{
+    m_selectOnlyContentItems = selectOnlyContentItems;
+}
+
+void LiveSelectionTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
+{
+}
+
+void LiveSelectionTool::clear()
+{
+    view()->setCursor(Qt::ArrowCursor);
+    m_rubberbandSelectionManipulator.clear(),
+            m_singleSelectionManipulator.clear();
+    m_selectionIndicator.clear();
+    //m_resizeIndicator.clear();
+}
+
+void LiveSelectionTool::selectedItemsChanged(const QList<QGraphicsItem*> &itemList)
+{
+    foreach (const QWeakPointer<QGraphicsObject> &obj, m_selectedItemList) {
+        if (!obj.isNull()) {
+            disconnect(obj.data(), SIGNAL(xChanged()), this, SLOT(repaintBoundingRects()));
+            disconnect(obj.data(), SIGNAL(yChanged()), this, SLOT(repaintBoundingRects()));
+            disconnect(obj.data(), SIGNAL(widthChanged()), this, SLOT(repaintBoundingRects()));
+            disconnect(obj.data(), SIGNAL(heightChanged()), this, SLOT(repaintBoundingRects()));
+            disconnect(obj.data(), SIGNAL(rotationChanged()), this, SLOT(repaintBoundingRects()));
+        }
+    }
+
+    QList<QGraphicsObject*> objects = toGraphicsObjectList(itemList);
+    m_selectedItemList.clear();
+
+    foreach (QGraphicsObject *obj, objects) {
+        m_selectedItemList.append(obj);
+        connect(obj, SIGNAL(xChanged()), this, SLOT(repaintBoundingRects()));
+        connect(obj, SIGNAL(yChanged()), this, SLOT(repaintBoundingRects()));
+        connect(obj, SIGNAL(widthChanged()), this, SLOT(repaintBoundingRects()));
+        connect(obj, SIGNAL(heightChanged()), this, SLOT(repaintBoundingRects()));
+        connect(obj, SIGNAL(rotationChanged()), this, SLOT(repaintBoundingRects()));
+    }
+
+    m_selectionIndicator.setItems(m_selectedItemList);
+    //m_resizeIndicator.setItems(toGraphicsObjectList(itemList));
+}
+
+void LiveSelectionTool::repaintBoundingRects()
+{
+    m_selectionIndicator.setItems(m_selectedItemList);
+}
+
+void LiveSelectionTool::selectUnderPoint(QMouseEvent *event)
+{
+    m_singleSelectionManipulator.begin(event->pos());
+
+    if (event->modifiers().testFlag(Qt::ControlModifier))
+        m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::RemoveFromSelection,
+                                            m_selectOnlyContentItems);
+    else if (event->modifiers().testFlag(Qt::ShiftModifier))
+        m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::AddToSelection,
+                                            m_selectOnlyContentItems);
+    else
+        m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::InvertSelection,
+                                            m_selectOnlyContentItems);
+
+    m_singleSelectionManipulator.end(event->pos());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liveselectiontool_p.h b/src/plugins/qmltooling/declarativeobserver/editor/liveselectiontool_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..3daac3d76c5db8c0b885feb9c2189a949cb24c40
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liveselectiontool_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LIVESELECTIONTOOL_H
+#define LIVESELECTIONTOOL_H
+
+#include "abstractliveedittool_p.h"
+#include "liverubberbandselectionmanipulator_p.h"
+#include "livesingleselectionmanipulator_p.h"
+#include "liveselectionindicator_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QTime>
+
+QT_FORWARD_DECLARE_CLASS(QGraphicsItem)
+QT_FORWARD_DECLARE_CLASS(QMouseEvent)
+QT_FORWARD_DECLARE_CLASS(QKeyEvent)
+QT_FORWARD_DECLARE_CLASS(QAction)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class LiveSelectionTool : public AbstractLiveEditTool
+{
+    Q_OBJECT
+
+public:
+    LiveSelectionTool(QDeclarativeViewObserver* editorView);
+    ~LiveSelectionTool();
+
+    void mousePressEvent(QMouseEvent *event);
+    void mouseMoveEvent(QMouseEvent *event);
+    void mouseReleaseEvent(QMouseEvent *event);
+    void mouseDoubleClickEvent(QMouseEvent *event);
+    void hoverMoveEvent(QMouseEvent *event);
+    void keyPressEvent(QKeyEvent *event);
+    void keyReleaseEvent(QKeyEvent *keyEvent);
+    void wheelEvent(QWheelEvent *event);
+
+    void itemsAboutToRemoved(const QList<QGraphicsItem*> &itemList);
+//    QVariant itemChange(const QList<QGraphicsItem*> &itemList,
+//                        QGraphicsItem::GraphicsItemChange change,
+//                        const QVariant &value );
+
+//    void update();
+
+    void clear();
+
+    void selectedItemsChanged(const QList<QGraphicsItem*> &itemList);
+
+    void selectUnderPoint(QMouseEvent *event);
+
+    void setSelectOnlyContentItems(bool selectOnlyContentItems);
+
+    void setRubberbandSelectionMode(bool value);
+
+private slots:
+    void contextMenuElementSelected();
+    void contextMenuElementHovered(QAction *action);
+    void repaintBoundingRects();
+
+private:
+    void createContextMenu(QList<QGraphicsItem*> itemList, QPoint globalPos);
+    LiveSingleSelectionManipulator::SelectionType getSelectionType(Qt::KeyboardModifiers modifiers);
+    bool alreadySelected(const QList<QGraphicsItem*> &itemList) const;
+
+private:
+    bool m_rubberbandSelectionMode;
+    LiveRubberBandSelectionManipulator m_rubberbandSelectionManipulator;
+    LiveSingleSelectionManipulator m_singleSelectionManipulator;
+    LiveSelectionIndicator m_selectionIndicator;
+    //ResizeIndicator m_resizeIndicator;
+    QTime m_mousePressTimer;
+    bool m_selectOnlyContentItems;
+
+    QList<QWeakPointer<QGraphicsObject> > m_selectedItemList;
+
+    QList<QGraphicsItem*> m_contextMenuItemList;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // LIVESELECTIONTOOL_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/livesingleselectionmanipulator.cpp b/src/plugins/qmltooling/declarativeobserver/editor/livesingleselectionmanipulator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e753b64931d85044a78393107fb9ee9eaf2cba7d
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/livesingleselectionmanipulator.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "livesingleselectionmanipulator_p.h"
+
+#include "../qdeclarativeviewobserver_p_p.h"
+
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+LiveSingleSelectionManipulator::LiveSingleSelectionManipulator(QDeclarativeViewObserver *editorView)
+    : m_editorView(editorView),
+      m_isActive(false)
+{
+}
+
+
+void LiveSingleSelectionManipulator::begin(const QPointF &beginPoint)
+{
+    m_beginPoint = beginPoint;
+    m_isActive = true;
+    m_oldSelectionList = QDeclarativeViewObserverPrivate::get(m_editorView)->selectedItems();
+}
+
+void LiveSingleSelectionManipulator::update(const QPointF &/*updatePoint*/)
+{
+    m_oldSelectionList.clear();
+}
+
+void LiveSingleSelectionManipulator::clear()
+{
+    m_beginPoint = QPointF();
+    m_oldSelectionList.clear();
+}
+
+
+void LiveSingleSelectionManipulator::end(const QPointF &/*updatePoint*/)
+{
+    m_oldSelectionList.clear();
+    m_isActive = false;
+}
+
+void LiveSingleSelectionManipulator::select(SelectionType selectionType,
+                                            const QList<QGraphicsItem*> &items,
+                                            bool /*selectOnlyContentItems*/)
+{
+    QGraphicsItem *selectedItem = 0;
+
+    foreach (QGraphicsItem* item, items)
+    {
+        //FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
+        if (item
+            /*&& !formEditorItem->qmlItemNode().isRootNode()
+               && (formEditorItem->qmlItemNode().hasShowContent() || !selectOnlyContentItems)*/)
+        {
+            selectedItem = item;
+            break;
+        }
+    }
+
+    QList<QGraphicsItem*> resultList;
+
+    switch (selectionType) {
+    case AddToSelection: {
+        resultList.append(m_oldSelectionList);
+        if (selectedItem && !m_oldSelectionList.contains(selectedItem))
+            resultList.append(selectedItem);
+    }
+        break;
+    case ReplaceSelection: {
+        if (selectedItem)
+            resultList.append(selectedItem);
+    }
+        break;
+    case RemoveFromSelection: {
+        resultList.append(m_oldSelectionList);
+        if (selectedItem)
+            resultList.removeAll(selectedItem);
+    }
+        break;
+    case InvertSelection: {
+        if (selectedItem
+                && !m_oldSelectionList.contains(selectedItem))
+        {
+            resultList.append(selectedItem);
+        }
+    }
+    }
+
+    m_editorView->setSelectedItems(resultList);
+}
+
+void LiveSingleSelectionManipulator::select(SelectionType selectionType, bool selectOnlyContentItems)
+{
+    QDeclarativeViewObserverPrivate *observerPrivate =
+            QDeclarativeViewObserverPrivate::get(m_editorView);
+    QList<QGraphicsItem*> itemList = observerPrivate->selectableItems(m_beginPoint);
+    select(selectionType, itemList, selectOnlyContentItems);
+}
+
+
+bool LiveSingleSelectionManipulator::isActive() const
+{
+    return m_isActive;
+}
+
+QPointF LiveSingleSelectionManipulator::beginPoint() const
+{
+    return m_beginPoint;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/livesingleselectionmanipulator_p.h b/src/plugins/qmltooling/declarativeobserver/editor/livesingleselectionmanipulator_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..68329e5a024d43fed92e4262117fe7de43353460
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/livesingleselectionmanipulator_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LIVESINGLESELECTIONMANIPULATOR_H
+#define LIVESINGLESELECTIONMANIPULATOR_H
+
+#include <QtCore/QPointF>
+#include <QtCore/QList>
+
+QT_FORWARD_DECLARE_CLASS(QGraphicsItem)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserver;
+
+class LiveSingleSelectionManipulator
+{
+public:
+    LiveSingleSelectionManipulator(QDeclarativeViewObserver *editorView);
+
+    enum SelectionType {
+        ReplaceSelection,
+        AddToSelection,
+        RemoveFromSelection,
+        InvertSelection
+    };
+
+    void begin(const QPointF& beginPoint);
+    void update(const QPointF& updatePoint);
+    void end(const QPointF& updatePoint);
+
+    void select(SelectionType selectionType, const QList<QGraphicsItem*> &items,
+                bool selectOnlyContentItems);
+    void select(SelectionType selectionType, bool selectOnlyContentItems);
+
+    void clear();
+
+    QPointF beginPoint() const;
+
+    bool isActive() const;
+
+private:
+    QList<QGraphicsItem*> m_oldSelectionList;
+    QPointF m_beginPoint;
+    QDeclarativeViewObserver *m_editorView;
+    bool m_isActive;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // LIVESINGLESELECTIONMANIPULATOR_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/qmltoolbar.cpp b/src/plugins/qmltooling/declarativeobserver/editor/qmltoolbar.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..359e9ef75077c388de9460b1b51511c92fa6dfa9
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/qmltoolbar.cpp
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmltoolbar_p.h"
+#include "toolbarcolorbox_p.h"
+
+#include <QtGui/QLabel>
+#include <QtGui/QIcon>
+#include <QtGui/QAction>
+#include <QtGui/QMenu>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QmlToolBar::QmlToolBar(QWidget *parent)
+    : QToolBar(parent)
+    , m_emitSignals(true)
+    , m_paused(false)
+    , m_animationSpeed(1.0f)
+    , ui(new Ui)
+{
+    ui->playIcon = QIcon(QLatin1String(":/qml/images/play-24.png"));
+    ui->pauseIcon = QIcon(QLatin1String(":/qml/images/pause-24.png"));
+
+    ui->designmode = new QAction(QIcon(QLatin1String(":/qml/images/observermode-24.png")),
+                                 tr("Observer Mode"), this);
+    ui->play = new QAction(ui->pauseIcon, tr("Play/Pause Animations"), this);
+    ui->select = new QAction(QIcon(QLatin1String(":/qml/images/select-24.png")), tr("Select"), this);
+    ui->selectMarquee = new QAction(QIcon(QLatin1String(":/qml/images/select-marquee-24.png")),
+                                    tr("Select (Marquee)"), this);
+    ui->zoom = new QAction(QIcon(QLatin1String(":/qml/images/zoom-24.png")), tr("Zoom"), this);
+    ui->colorPicker = new QAction(QIcon(QLatin1String(":/qml/images/color-picker-24.png")),
+                                  tr("Color Picker"), this);
+    ui->toQml = new QAction(QIcon(QLatin1String(":/qml/images/to-qml-24.png")),
+                            tr("Apply Changes to QML Viewer"), this);
+    ui->fromQml = new QAction(QIcon(QLatin1String(":/qml/images/from-qml-24.png")),
+                              tr("Apply Changes to Document"), this);
+    ui->designmode->setCheckable(true);
+    ui->designmode->setChecked(false);
+
+    ui->play->setCheckable(false);
+    ui->select->setCheckable(true);
+    ui->selectMarquee->setCheckable(true);
+    ui->zoom->setCheckable(true);
+    ui->colorPicker->setCheckable(true);
+
+    setWindowTitle(tr("Tools"));
+
+    addAction(ui->designmode);
+    addAction(ui->play);
+    addSeparator();
+
+    addAction(ui->select);
+    // disabled because multi selection does not do anything useful without design mode
+    //addAction(ui->selectMarquee);
+    addSeparator();
+    addAction(ui->zoom);
+    addAction(ui->colorPicker);
+    //addAction(ui->fromQml);
+
+    ui->colorBox = new ToolBarColorBox(this);
+    ui->colorBox->setMinimumSize(24, 24);
+    ui->colorBox->setMaximumSize(28, 28);
+    ui->colorBox->setColor(Qt::black);
+    addWidget(ui->colorBox);
+
+    setWindowFlags(Qt::Tool);
+
+    QMenu *playSpeedMenu = new QMenu(this);
+    ui->playSpeedMenuActions = new QActionGroup(this);
+    ui->playSpeedMenuActions->setExclusive(true);
+
+    QAction *speedAction = playSpeedMenu->addAction(tr("1x"), this, SLOT(changeAnimationSpeed()));
+    speedAction->setCheckable(true);
+    speedAction->setChecked(true);
+    speedAction->setData(1.0f);
+    ui->playSpeedMenuActions->addAction(speedAction);
+
+    speedAction = playSpeedMenu->addAction(tr("0.5x"), this, SLOT(changeAnimationSpeed()));
+    speedAction->setCheckable(true);
+    speedAction->setData(2.0f);
+    ui->playSpeedMenuActions->addAction(speedAction);
+
+    speedAction = playSpeedMenu->addAction(tr("0.25x"), this, SLOT(changeAnimationSpeed()));
+    speedAction->setCheckable(true);
+    speedAction->setData(4.0f);
+    ui->playSpeedMenuActions->addAction(speedAction);
+
+    speedAction = playSpeedMenu->addAction(tr("0.125x"), this, SLOT(changeAnimationSpeed()));
+    speedAction->setCheckable(true);
+    speedAction->setData(8.0f);
+    ui->playSpeedMenuActions->addAction(speedAction);
+
+    speedAction = playSpeedMenu->addAction(tr("0.1x"), this, SLOT(changeAnimationSpeed()));
+    speedAction->setCheckable(true);
+    speedAction->setData(10.0f);
+    ui->playSpeedMenuActions->addAction(speedAction);
+
+    ui->play->setMenu(playSpeedMenu);
+
+    connect(ui->designmode, SIGNAL(toggled(bool)), SLOT(setDesignModeBehaviorOnClick(bool)));
+
+    connect(ui->colorPicker, SIGNAL(triggered()), SLOT(activateColorPickerOnClick()));
+
+    connect(ui->play, SIGNAL(triggered()), SLOT(activatePlayOnClick()));
+
+    connect(ui->zoom, SIGNAL(triggered()), SLOT(activateZoomOnClick()));
+    connect(ui->colorPicker, SIGNAL(triggered()), SLOT(activateColorPickerOnClick()));
+    connect(ui->select, SIGNAL(triggered()), SLOT(activateSelectToolOnClick()));
+    connect(ui->selectMarquee, SIGNAL(triggered()), SLOT(activateMarqueeSelectToolOnClick()));
+
+    connect(ui->toQml, SIGNAL(triggered()), SLOT(activateToQml()));
+    connect(ui->fromQml, SIGNAL(triggered()), SLOT(activateFromQml()));
+}
+
+QmlToolBar::~QmlToolBar()
+{
+    delete ui;
+}
+
+void QmlToolBar::activateColorPicker()
+{
+    m_emitSignals = false;
+    activateColorPickerOnClick();
+    m_emitSignals = true;
+}
+
+void QmlToolBar::activateSelectTool()
+{
+    m_emitSignals = false;
+    activateSelectToolOnClick();
+    m_emitSignals = true;
+}
+
+void QmlToolBar::activateMarqueeSelectTool()
+{
+    m_emitSignals = false;
+    activateMarqueeSelectToolOnClick();
+    m_emitSignals = true;
+}
+
+void QmlToolBar::activateZoom()
+{
+    m_emitSignals = false;
+    activateZoomOnClick();
+    m_emitSignals = true;
+}
+
+void QmlToolBar::setAnimationSpeed(qreal slowDownFactor)
+{
+    if (m_animationSpeed == slowDownFactor)
+        return;
+
+    m_emitSignals = false;
+    m_animationSpeed = slowDownFactor;
+
+    foreach (QAction *action, ui->playSpeedMenuActions->actions()) {
+        if (action->data().toReal() == slowDownFactor) {
+            action->setChecked(true);
+            break;
+        }
+    }
+
+    m_emitSignals = true;
+}
+
+void QmlToolBar::setAnimationPaused(bool paused)
+{
+    if (m_paused == paused)
+        return;
+
+    m_paused = paused;
+    updatePlayAction();
+}
+
+void QmlToolBar::changeAnimationSpeed()
+{
+    QAction *action = qobject_cast<QAction*>(sender());
+    m_animationSpeed = action->data().toReal();
+    emit animationSpeedChanged(m_animationSpeed);
+}
+
+void QmlToolBar::setDesignModeBehavior(bool inDesignMode)
+{
+    m_emitSignals = false;
+    ui->designmode->setChecked(inDesignMode);
+    setDesignModeBehaviorOnClick(inDesignMode);
+    m_emitSignals = true;
+}
+
+void QmlToolBar::setDesignModeBehaviorOnClick(bool checked)
+{
+    ui->select->setEnabled(checked);
+    ui->selectMarquee->setEnabled(checked);
+    ui->zoom->setEnabled(checked);
+    ui->colorPicker->setEnabled(checked);
+    ui->toQml->setEnabled(checked);
+    ui->fromQml->setEnabled(checked);
+
+    if (m_emitSignals)
+        emit designModeBehaviorChanged(checked);
+}
+
+void QmlToolBar::setColorBoxColor(const QColor &color)
+{
+    ui->colorBox->setColor(color);
+}
+
+void QmlToolBar::activatePlayOnClick()
+{
+    m_paused = !m_paused;
+    emit animationPausedChanged(m_paused);
+    updatePlayAction();
+}
+
+void QmlToolBar::updatePlayAction()
+{
+    ui->play->setIcon(m_paused ? ui->playIcon : ui->pauseIcon);
+}
+
+void QmlToolBar::activateColorPickerOnClick()
+{
+    ui->zoom->setChecked(false);
+    ui->select->setChecked(false);
+    ui->selectMarquee->setChecked(false);
+
+    ui->colorPicker->setChecked(true);
+    if (m_activeTool != Constants::ColorPickerMode) {
+        m_activeTool = Constants::ColorPickerMode;
+        if (m_emitSignals)
+            emit colorPickerSelected();
+    }
+}
+
+void QmlToolBar::activateSelectToolOnClick()
+{
+    ui->zoom->setChecked(false);
+    ui->selectMarquee->setChecked(false);
+    ui->colorPicker->setChecked(false);
+
+    ui->select->setChecked(true);
+    if (m_activeTool != Constants::SelectionToolMode) {
+        m_activeTool = Constants::SelectionToolMode;
+        if (m_emitSignals)
+            emit selectToolSelected();
+    }
+}
+
+void QmlToolBar::activateMarqueeSelectToolOnClick()
+{
+    ui->zoom->setChecked(false);
+    ui->select->setChecked(false);
+    ui->colorPicker->setChecked(false);
+
+    ui->selectMarquee->setChecked(true);
+    if (m_activeTool != Constants::MarqueeSelectionToolMode) {
+        m_activeTool = Constants::MarqueeSelectionToolMode;
+        if (m_emitSignals)
+            emit marqueeSelectToolSelected();
+    }
+}
+
+void QmlToolBar::activateZoomOnClick()
+{
+    ui->select->setChecked(false);
+    ui->selectMarquee->setChecked(false);
+    ui->colorPicker->setChecked(false);
+
+    ui->zoom->setChecked(true);
+    if (m_activeTool != Constants::ZoomMode) {
+        m_activeTool = Constants::ZoomMode;
+        if (m_emitSignals)
+            emit zoomToolSelected();
+    }
+}
+
+void QmlToolBar::activateFromQml()
+{
+    if (m_emitSignals)
+        emit applyChangesFromQmlFileSelected();
+}
+
+void QmlToolBar::activateToQml()
+{
+    if (m_emitSignals)
+        emit applyChangesToQmlFileSelected();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/qmltoolbar_p.h b/src/plugins/qmltooling/declarativeobserver/editor/qmltoolbar_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..459eafdbb89eb6c25496997b4490f432f2625bca
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/qmltoolbar_p.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTOOLBAR_H
+#define QMLTOOLBAR_H
+
+#include <QtGui/QToolBar>
+#include <QtGui/QIcon>
+
+#include "../qmlobserverconstants_p.h"
+
+QT_FORWARD_DECLARE_CLASS(QActionGroup)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class ToolBarColorBox;
+
+class QmlToolBar : public QToolBar
+{
+    Q_OBJECT
+
+public:
+    explicit QmlToolBar(QWidget *parent = 0);
+    ~QmlToolBar();
+
+public slots:
+    void setDesignModeBehavior(bool inDesignMode);
+    void setColorBoxColor(const QColor &color);
+    void activateColorPicker();
+    void activateSelectTool();
+    void activateMarqueeSelectTool();
+    void activateZoom();
+
+    void setAnimationSpeed(qreal slowDownFactor);
+    void setAnimationPaused(bool paused);
+
+signals:
+    void animationSpeedChanged(qreal factor);
+    void animationPausedChanged(bool paused);
+
+    void designModeBehaviorChanged(bool inDesignMode);
+    void colorPickerSelected();
+    void selectToolSelected();
+    void marqueeSelectToolSelected();
+    void zoomToolSelected();
+
+    void applyChangesToQmlFileSelected();
+    void applyChangesFromQmlFileSelected();
+
+private slots:
+    void setDesignModeBehaviorOnClick(bool inDesignMode);
+    void activatePlayOnClick();
+    void activateColorPickerOnClick();
+    void activateSelectToolOnClick();
+    void activateMarqueeSelectToolOnClick();
+    void activateZoomOnClick();
+
+    void activateFromQml();
+    void activateToQml();
+
+    void changeAnimationSpeed();
+
+    void updatePlayAction();
+
+private:
+    class Ui {
+    public:
+        QAction *designmode;
+        QAction *play;
+        QAction *select;
+        QAction *selectMarquee;
+        QAction *zoom;
+        QAction *colorPicker;
+        QAction *toQml;
+        QAction *fromQml;
+        QIcon playIcon;
+        QIcon pauseIcon;
+        ToolBarColorBox *colorBox;
+
+        QActionGroup *playSpeedMenuActions;
+    };
+
+    bool m_emitSignals;
+    bool m_paused;
+    qreal m_animationSpeed;
+
+    Constants::DesignTool m_activeTool;
+
+    Ui *ui;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLTOOLBAR_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/subcomponenteditortool.cpp b/src/plugins/qmltooling/declarativeobserver/editor/subcomponenteditortool.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ab7729645cd3a0aa5f11dd0961a70b9c0fb48938
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/subcomponenteditortool.cpp
@@ -0,0 +1,364 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "subcomponenteditortool_p.h"
+#include "subcomponentmasklayeritem_p.h"
+#include "livelayeritem_p.h"
+
+#include "../qdeclarativeviewobserver_p_p.h"
+
+#include <QtGui/QGraphicsItem>
+#include <QtGui/QGraphicsObject>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QKeyEvent>
+
+#include <QtCore/QTimer>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+const qreal MaxOpacity = 0.5f;
+
+SubcomponentEditorTool::SubcomponentEditorTool(QDeclarativeViewObserver *view)
+    : AbstractLiveEditTool(view),
+      m_animIncrement(0.05f),
+      m_animTimer(new QTimer(this))
+{
+    QDeclarativeViewObserverPrivate *observerPrivate =
+            QDeclarativeViewObserverPrivate::get(view);
+    m_mask = new SubcomponentMaskLayerItem(view, observerPrivate->manipulatorLayer);
+    connect(m_animTimer, SIGNAL(timeout()), SLOT(animate()));
+    m_animTimer->setInterval(20);
+}
+
+SubcomponentEditorTool::~SubcomponentEditorTool()
+{
+
+}
+
+void SubcomponentEditorTool::mousePressEvent(QMouseEvent * /*event*/)
+{
+
+}
+
+void SubcomponentEditorTool::mouseMoveEvent(QMouseEvent * /*event*/)
+{
+
+}
+
+bool SubcomponentEditorTool::containsCursor(const QPoint &mousePos) const
+{
+    if (!m_currentContext.size())
+        return false;
+
+    QPointF scenePos = view()->mapToScene(mousePos);
+    QRectF itemRect = m_currentContext.top()->boundingRect()
+            | m_currentContext.top()->childrenBoundingRect();
+    QRectF polyRect = m_currentContext.top()->mapToScene(itemRect).boundingRect();
+
+    return polyRect.contains(scenePos);
+}
+
+void SubcomponentEditorTool::mouseReleaseEvent(QMouseEvent * /*event*/)
+{
+
+}
+
+void SubcomponentEditorTool::mouseDoubleClickEvent(QMouseEvent *event)
+{
+    if (event->buttons() & Qt::LeftButton
+            && !containsCursor(event->pos())
+            && m_currentContext.size() > 1)
+    {
+        aboutToPopContext();
+    }
+}
+
+void SubcomponentEditorTool::hoverMoveEvent(QMouseEvent *event)
+{
+    if (!containsCursor(event->pos()) && m_currentContext.size() > 1) {
+        QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
+    }
+}
+
+void SubcomponentEditorTool::wheelEvent(QWheelEvent * /*event*/)
+{
+
+}
+
+void SubcomponentEditorTool::keyPressEvent(QKeyEvent * /*event*/)
+{
+
+}
+
+void SubcomponentEditorTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
+{
+
+}
+
+void SubcomponentEditorTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
+{
+
+}
+
+void SubcomponentEditorTool::animate()
+{
+    if (m_animIncrement > 0) {
+        if (m_mask->opacity() + m_animIncrement < MaxOpacity) {
+            m_mask->setOpacity(m_mask->opacity() + m_animIncrement);
+        } else {
+            m_animTimer->stop();
+            m_mask->setOpacity(MaxOpacity);
+        }
+    } else {
+        if (m_mask->opacity() + m_animIncrement > 0) {
+            m_mask->setOpacity(m_mask->opacity() + m_animIncrement);
+        } else {
+            m_animTimer->stop();
+            m_mask->setOpacity(0);
+            popContext();
+            emit contextPathChanged(m_path);
+        }
+    }
+
+}
+
+void SubcomponentEditorTool::clear()
+{
+    m_currentContext.clear();
+    m_mask->setCurrentItem(0);
+    m_animTimer->stop();
+    m_mask->hide();
+    m_path.clear();
+
+    emit contextPathChanged(m_path);
+    emit cleared();
+}
+
+void SubcomponentEditorTool::selectedItemsChanged(const QList<QGraphicsItem*> &/*itemList*/)
+{
+
+}
+
+void SubcomponentEditorTool::setCurrentItem(QGraphicsItem* contextItem)
+{
+    if (!contextItem)
+        return;
+
+    QGraphicsObject *gfxObject = contextItem->toGraphicsObject();
+    if (!gfxObject)
+        return;
+
+    //QString parentClassName = gfxObject->metaObject()->className();
+    //if (parentClassName.contains(QRegExp("_QMLTYPE_\\d+")))
+
+    bool containsSelectableItems = false;
+    foreach (QGraphicsItem *item, gfxObject->childItems()) {
+        if (item->type() == Constants::EditorItemType
+                || item->type() == Constants::ResizeHandleItemType)
+        {
+            continue;
+        }
+        containsSelectableItems = true;
+        break;
+    }
+
+    if (containsSelectableItems) {
+        m_mask->setCurrentItem(gfxObject);
+        m_mask->setOpacity(0);
+        m_mask->show();
+        m_animIncrement = 0.05f;
+        m_animTimer->start();
+
+        QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
+        observer()->setSelectedItems(QList<QGraphicsItem*>());
+
+        pushContext(gfxObject);
+    }
+}
+
+QGraphicsItem *SubcomponentEditorTool::firstChildOfContext(QGraphicsItem *item) const
+{
+    if (!item)
+        return 0;
+
+    if (isDirectChildOfContext(item))
+        return item;
+
+    QGraphicsItem *parent = item->parentItem();
+    while (parent) {
+        if (isDirectChildOfContext(parent))
+            return parent;
+        parent = parent->parentItem();
+    }
+
+    return 0;
+}
+
+bool SubcomponentEditorTool::isChildOfContext(QGraphicsItem *item) const
+{
+    return (firstChildOfContext(item) != 0);
+}
+
+bool SubcomponentEditorTool::isDirectChildOfContext(QGraphicsItem *item) const
+{
+    return (item->parentItem() == m_currentContext.top());
+}
+
+bool SubcomponentEditorTool::itemIsChildOfQmlSubComponent(QGraphicsItem *item) const
+{
+    if (item->parentItem() && item->parentItem() != m_currentContext.top()) {
+        QGraphicsObject *parent = item->parentItem()->toGraphicsObject();
+        QString parentClassName = QLatin1String(parent->metaObject()->className());
+
+        if (parentClassName.contains(QRegExp(QLatin1String("_QMLTYPE_\\d+")))) {
+            return true;
+        } else {
+            return itemIsChildOfQmlSubComponent(parent);
+        }
+    }
+
+    return false;
+}
+
+void SubcomponentEditorTool::pushContext(QGraphicsObject *contextItem)
+{
+    connect(contextItem, SIGNAL(destroyed(QObject*)), this, SLOT(contextDestroyed(QObject*)));
+    connect(contextItem, SIGNAL(xChanged()), this, SLOT(resizeMask()));
+    connect(contextItem, SIGNAL(yChanged()), this, SLOT(resizeMask()));
+    connect(contextItem, SIGNAL(widthChanged()), this, SLOT(resizeMask()));
+    connect(contextItem, SIGNAL(heightChanged()), this, SLOT(resizeMask()));
+    connect(contextItem, SIGNAL(rotationChanged()), this, SLOT(resizeMask()));
+
+    m_currentContext.push(contextItem);
+    QString title = titleForItem(contextItem);
+    emit contextPushed(title);
+
+    m_path << title;
+    emit contextPathChanged(m_path);
+}
+
+void SubcomponentEditorTool::aboutToPopContext()
+{
+    if (m_currentContext.size() > 2) {
+        popContext();
+        emit contextPathChanged(m_path);
+    } else {
+        m_animIncrement = -0.05f;
+        m_animTimer->start();
+    }
+}
+
+QGraphicsObject *SubcomponentEditorTool::popContext()
+{
+    QGraphicsObject *popped = m_currentContext.pop();
+    m_path.removeLast();
+
+    emit contextPopped();
+
+    disconnect(popped, SIGNAL(xChanged()), this, SLOT(resizeMask()));
+    disconnect(popped, SIGNAL(yChanged()), this, SLOT(resizeMask()));
+    disconnect(popped, SIGNAL(scaleChanged()), this, SLOT(resizeMask()));
+    disconnect(popped, SIGNAL(widthChanged()), this, SLOT(resizeMask()));
+    disconnect(popped, SIGNAL(heightChanged()), this, SLOT(resizeMask()));
+
+    if (m_currentContext.size() > 1) {
+        QGraphicsObject *item = m_currentContext.top();
+        m_mask->setCurrentItem(item);
+        m_mask->setOpacity(MaxOpacity);
+        m_mask->setVisible(true);
+    } else {
+        m_mask->setVisible(false);
+    }
+
+    return popped;
+}
+
+void SubcomponentEditorTool::resizeMask()
+{
+    QGraphicsObject *item = m_currentContext.top();
+    m_mask->setCurrentItem(item);
+}
+
+QGraphicsObject *SubcomponentEditorTool::currentRootItem() const
+{
+    return m_currentContext.top();
+}
+
+void SubcomponentEditorTool::contextDestroyed(QObject *contextToDestroy)
+{
+    disconnect(contextToDestroy, SIGNAL(destroyed(QObject*)),
+               this, SLOT(contextDestroyed(QObject*)));
+
+    // pop out the whole context - it might not be safe anymore.
+    while (m_currentContext.size() > 1) {
+        m_currentContext.pop();
+        m_path.removeLast();
+        emit contextPopped();
+    }
+    m_mask->setVisible(false);
+
+    emit contextPathChanged(m_path);
+}
+
+QGraphicsObject *SubcomponentEditorTool::setContext(int contextIndex)
+{
+    Q_ASSERT(contextIndex >= 0);
+
+    // sometimes we have to delete the context while user was still clicking around,
+    // so just bail out.
+    if (contextIndex >= m_currentContext.size() -1)
+        return 0;
+
+    while (m_currentContext.size() - 1 > contextIndex) {
+        popContext();
+    }
+    emit contextPathChanged(m_path);
+
+    return m_currentContext.top();
+}
+
+int SubcomponentEditorTool::contextIndex() const
+{
+    return m_currentContext.size() - 1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/subcomponenteditortool_p.h b/src/plugins/qmltooling/declarativeobserver/editor/subcomponenteditortool_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..15217eb779df711df31d2e1ba15730d9e7a85a92
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/subcomponenteditortool_p.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SUBCOMPONENTEDITORTOOL_H
+#define SUBCOMPONENTEDITORTOOL_H
+
+#include "abstractliveedittool_p.h"
+
+#include <QtCore/QStack>
+#include <QtCore/QStringList>
+
+QT_FORWARD_DECLARE_CLASS(QGraphicsObject)
+QT_FORWARD_DECLARE_CLASS(QPoint)
+QT_FORWARD_DECLARE_CLASS(QTimer)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class SubcomponentMaskLayerItem;
+
+class SubcomponentEditorTool : public AbstractLiveEditTool
+{
+    Q_OBJECT
+
+public:
+    SubcomponentEditorTool(QDeclarativeViewObserver *view);
+    ~SubcomponentEditorTool();
+
+    void mousePressEvent(QMouseEvent *event);
+    void mouseMoveEvent(QMouseEvent *event);
+    void mouseReleaseEvent(QMouseEvent *event);
+    void mouseDoubleClickEvent(QMouseEvent *event);
+
+    void hoverMoveEvent(QMouseEvent *event);
+    void wheelEvent(QWheelEvent *event);
+
+    void keyPressEvent(QKeyEvent *event);
+    void keyReleaseEvent(QKeyEvent *keyEvent);
+    void itemsAboutToRemoved(const QList<QGraphicsItem*> &itemList);
+
+    void clear();
+
+    bool containsCursor(const QPoint &mousePos) const;
+    bool itemIsChildOfQmlSubComponent(QGraphicsItem *item) const;
+
+    bool isChildOfContext(QGraphicsItem *item) const;
+    bool isDirectChildOfContext(QGraphicsItem *item) const;
+    QGraphicsItem *firstChildOfContext(QGraphicsItem *item) const;
+
+    void setCurrentItem(QGraphicsItem *contextObject);
+
+    void pushContext(QGraphicsObject *contextItem);
+
+    QGraphicsObject *currentRootItem() const;
+    QGraphicsObject *setContext(int contextIndex);
+    int contextIndex() const;
+
+signals:
+    void exitContextRequested();
+    void cleared();
+    void contextPushed(const QString &contextTitle);
+    void contextPopped();
+    void contextPathChanged(const QStringList &path);
+
+protected:
+    void selectedItemsChanged(const QList<QGraphicsItem*> &itemList);
+
+private slots:
+    void animate();
+    void contextDestroyed(QObject *context);
+    void resizeMask();
+
+private:
+    QGraphicsObject *popContext();
+    void aboutToPopContext();
+
+private:
+    QStack<QGraphicsObject *> m_currentContext;
+    QStringList m_path;
+
+    qreal m_animIncrement;
+    SubcomponentMaskLayerItem *m_mask;
+    QTimer *m_animTimer;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // SUBCOMPONENTEDITORTOOL_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/subcomponentmasklayeritem.cpp b/src/plugins/qmltooling/declarativeobserver/editor/subcomponentmasklayeritem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..15d2a2c64f622d9448065bcbec50d27a80ef901a
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/subcomponentmasklayeritem.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "subcomponentmasklayeritem_p.h"
+
+#include "../qmlobserverconstants_p.h"
+#include "../qdeclarativeviewobserver_p.h"
+
+#include <QtGui/QPolygonF>
+
+QT_BEGIN_NAMESPACE
+
+SubcomponentMaskLayerItem::SubcomponentMaskLayerItem(QDeclarativeViewObserver *observer,
+                                                     QGraphicsItem *parentItem) :
+    QGraphicsPolygonItem(parentItem),
+    m_observer(observer),
+    m_currentItem(0),
+    m_borderRect(new QGraphicsRectItem(this))
+{
+    m_borderRect->setRect(0,0,0,0);
+    m_borderRect->setPen(QPen(QColor(60, 60, 60), 1));
+    m_borderRect->setData(Constants::EditorItemDataKey, QVariant(true));
+
+    setBrush(QBrush(QColor(160,160,160)));
+    setPen(Qt::NoPen);
+}
+
+int SubcomponentMaskLayerItem::type() const
+{
+    return Constants::EditorItemType;
+}
+
+static QRectF resizeRect(const QRectF &newRect, const QRectF &oldRect)
+{
+    QRectF result = newRect;
+    if (oldRect.left() < newRect.left())
+        result.setLeft(oldRect.left());
+
+    if (oldRect.top() < newRect.top())
+        result.setTop(oldRect.top());
+
+    if (oldRect.right() > newRect.right())
+        result.setRight(oldRect.right());
+
+    if (oldRect.bottom() > newRect.bottom())
+        result.setBottom(oldRect.bottom());
+
+    return result;
+}
+
+
+void SubcomponentMaskLayerItem::setCurrentItem(QGraphicsItem *item)
+{
+    QGraphicsItem *prevItem = m_currentItem;
+    m_currentItem = item;
+
+    if (!m_currentItem)
+        return;
+
+    QPolygonF viewPoly(QRectF(m_observer->declarativeView()->rect()));
+    viewPoly = m_observer->declarativeView()->mapToScene(viewPoly.toPolygon());
+
+    QRectF itemRect = item->boundingRect() | item->childrenBoundingRect();
+    QPolygonF itemPoly(itemRect);
+    itemPoly = item->mapToScene(itemPoly);
+
+    // if updating the same item as before, resize the rectangle only bigger, not smaller.
+    if (prevItem == item && prevItem != 0) {
+        m_itemPolyRect = resizeRect(itemPoly.boundingRect(), m_itemPolyRect);
+    } else {
+        m_itemPolyRect = itemPoly.boundingRect();
+    }
+    QRectF borderRect = m_itemPolyRect;
+    borderRect.adjust(-1, -1, 1, 1);
+    m_borderRect->setRect(borderRect);
+
+    itemPoly = viewPoly.subtracted(QPolygonF(m_itemPolyRect));
+    setPolygon(itemPoly);
+}
+
+QGraphicsItem *SubcomponentMaskLayerItem::currentItem() const
+{
+    return m_currentItem;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/subcomponentmasklayeritem_p.h b/src/plugins/qmltooling/declarativeobserver/editor/subcomponentmasklayeritem_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0b892da3d7a9134ef9253276256557154e134a5
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/subcomponentmasklayeritem_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SUBCOMPONENTMASKLAYERITEM_H
+#define SUBCOMPONENTMASKLAYERITEM_H
+
+#include <QtGui/QGraphicsPolygonItem>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserver;
+
+class SubcomponentMaskLayerItem : public QGraphicsPolygonItem
+{
+public:
+    explicit SubcomponentMaskLayerItem(QDeclarativeViewObserver *observer,
+                                       QGraphicsItem *parentItem = 0);
+    int type() const;
+    void setCurrentItem(QGraphicsItem *item);
+    void setBoundingBox(const QRectF &boundingBox);
+    QGraphicsItem *currentItem() const;
+    QRectF itemRect() const;
+
+private:
+    QDeclarativeViewObserver *m_observer;
+    QGraphicsItem *m_currentItem;
+    QGraphicsRectItem *m_borderRect;
+    QRectF m_itemPolyRect;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // SUBCOMPONENTMASKLAYERITEM_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/toolbarcolorbox.cpp b/src/plugins/qmltooling/declarativeobserver/editor/toolbarcolorbox.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..35582fb5423f3b37b9686dabc0a4e00396aebbea
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/toolbarcolorbox.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "toolbarcolorbox_p.h"
+
+#include "../qmlobserverconstants_p.h"
+
+#include <QtGui/QPixmap>
+#include <QtGui/QPainter>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QClipboard>
+#include <QtGui/QApplication>
+#include <QtGui/QColorDialog>
+#include <QtGui/QDrag>
+
+#include <QtCore/QMimeData>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+ToolBarColorBox::ToolBarColorBox(QWidget *parent) :
+    QLabel(parent)
+{
+    m_copyHexColor = new QAction(QIcon(QLatin1String(":/qml/images/color-picker-hicontrast.png")),
+                                 tr("Copy Color"), this);
+    connect(m_copyHexColor, SIGNAL(triggered()), SLOT(copyColorToClipboard()));
+    setScaledContents(false);
+}
+
+void ToolBarColorBox::setColor(const QColor &color)
+{
+    m_color = color;
+
+    QPixmap pix = createDragPixmap(width());
+    setPixmap(pix);
+    update();
+}
+
+void ToolBarColorBox::mousePressEvent(QMouseEvent *event)
+{
+    m_dragBeginPoint = event->pos();
+    m_dragStarted = false;
+}
+
+void ToolBarColorBox::mouseMoveEvent(QMouseEvent *event)
+{
+
+    if (event->buttons() & Qt::LeftButton
+            && (QPoint(event->pos() - m_dragBeginPoint).manhattanLength()
+                > Constants::DragStartDistance)
+            && !m_dragStarted)
+    {
+        m_dragStarted = true;
+        QDrag *drag = new QDrag(this);
+        QMimeData *mimeData = new QMimeData;
+
+        mimeData->setText(m_color.name());
+        drag->setMimeData(mimeData);
+        drag->setPixmap(createDragPixmap());
+
+        drag->exec();
+    }
+}
+
+QPixmap ToolBarColorBox::createDragPixmap(int size) const
+{
+    QPixmap pix(size, size);
+    QPainter p(&pix);
+
+    QColor borderColor1 = QColor(143, 143 ,143);
+    QColor borderColor2 = QColor(43, 43, 43);
+
+    p.setBrush(QBrush(m_color));
+    p.setPen(QPen(QBrush(borderColor2),1));
+
+    p.fillRect(0, 0, size, size, borderColor1);
+    p.drawRect(1,1, size - 3, size - 3);
+    return pix;
+}
+
+void ToolBarColorBox::contextMenuEvent(QContextMenuEvent *ev)
+{
+    QMenu contextMenu;
+    contextMenu.addAction(m_copyHexColor);
+    contextMenu.exec(ev->globalPos());
+}
+
+void ToolBarColorBox::copyColorToClipboard()
+{
+    QClipboard *clipboard = QApplication::clipboard();
+    clipboard->setText(m_color.name());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/toolbarcolorbox_p.h b/src/plugins/qmltooling/declarativeobserver/editor/toolbarcolorbox_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..d4914fa00aa56fdfef21d1df6f7b0bbebbed3c37
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/toolbarcolorbox_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOOLBARCOLORBOX_H
+#define TOOLBARCOLORBOX_H
+
+#include <QtGui/QLabel>
+#include <QtGui/QColor>
+#include <QtCore/QPoint>
+
+QT_FORWARD_DECLARE_CLASS(QContextMenuEvent)
+QT_FORWARD_DECLARE_CLASS(QAction)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class ToolBarColorBox : public QLabel
+{
+    Q_OBJECT
+
+public:
+    explicit ToolBarColorBox(QWidget *parent = 0);
+    void setColor(const QColor &color);
+
+protected:
+    void contextMenuEvent(QContextMenuEvent *ev);
+    void mousePressEvent(QMouseEvent *ev);
+    void mouseMoveEvent(QMouseEvent *ev);
+private slots:
+    void copyColorToClipboard();
+
+private:
+    QPixmap createDragPixmap(int size = 24) const;
+
+private:
+    bool m_dragStarted;
+    QPoint m_dragBeginPoint;
+    QAction *m_copyHexColor;
+    QColor m_color;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // TOOLBARCOLORBOX_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/zoomtool.cpp b/src/plugins/qmltooling/declarativeobserver/editor/zoomtool.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b70cda5ba4f7b16a38c48306647b879e2c02deaf
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/zoomtool.cpp
@@ -0,0 +1,336 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "zoomtool_p.h"
+
+#include "../qdeclarativeviewobserver_p_p.h"
+
+#include <QtGui/QMouseEvent>
+#include <QtGui/QWheelEvent>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+
+#include <QtCore/QRectF>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+ZoomTool::ZoomTool(QDeclarativeViewObserver *view) :
+    AbstractLiveEditTool(view),
+    m_rubberbandManipulator(),
+    m_smoothZoomMultiplier(0.05f),
+    m_currentScale(1.0f)
+{
+    m_zoomTo100Action = new QAction(tr("Zoom to &100%"), this);
+    m_zoomInAction = new QAction(tr("Zoom In"), this);
+    m_zoomOutAction = new QAction(tr("Zoom Out"), this);
+    m_zoomInAction->setShortcut(QKeySequence(Qt::Key_Plus));
+    m_zoomOutAction->setShortcut(QKeySequence(Qt::Key_Minus));
+
+
+    LiveLayerItem *layerItem = QDeclarativeViewObserverPrivate::get(view)->manipulatorLayer;
+    QGraphicsObject *layerObject = reinterpret_cast<QGraphicsObject *>(layerItem);
+    m_rubberbandManipulator = new LiveRubberBandSelectionManipulator(layerObject, view);
+
+
+    connect(m_zoomTo100Action, SIGNAL(triggered()), SLOT(zoomTo100()));
+    connect(m_zoomInAction, SIGNAL(triggered()), SLOT(zoomIn()));
+    connect(m_zoomOutAction, SIGNAL(triggered()), SLOT(zoomOut()));
+}
+
+ZoomTool::~ZoomTool()
+{
+    delete m_rubberbandManipulator;
+}
+
+void ZoomTool::mousePressEvent(QMouseEvent *event)
+{
+    m_mousePos = event->pos();
+
+    QPointF scenePos = view()->mapToScene(event->pos());
+
+    if (event->buttons() & Qt::RightButton) {
+        QMenu contextMenu;
+        contextMenu.addAction(m_zoomTo100Action);
+        contextMenu.addSeparator();
+        contextMenu.addAction(m_zoomInAction);
+        contextMenu.addAction(m_zoomOutAction);
+        contextMenu.exec(event->globalPos());
+    } else if (event->buttons() & Qt::LeftButton) {
+        m_dragBeginPos = scenePos;
+        m_dragStarted = false;
+    }
+}
+
+void ZoomTool::mouseMoveEvent(QMouseEvent *event)
+{
+    m_mousePos = event->pos();
+
+    QPointF scenePos = view()->mapToScene(event->pos());
+
+    if (event->buttons() & Qt::LeftButton
+            && (QPointF(scenePos - m_dragBeginPos).manhattanLength()
+                > Constants::DragStartDistance / 3)
+            && !m_dragStarted)
+    {
+        m_dragStarted = true;
+        m_rubberbandManipulator->begin(m_dragBeginPos);
+        return;
+    }
+
+    if (m_dragStarted)
+        m_rubberbandManipulator->update(scenePos);
+
+}
+
+void ZoomTool::mouseReleaseEvent(QMouseEvent *event)
+{
+    m_mousePos = event->pos();
+    QPointF scenePos = view()->mapToScene(event->pos());
+
+    if (m_dragStarted) {
+        m_rubberbandManipulator->end();
+
+        int x1 = qMin(scenePos.x(), m_rubberbandManipulator->beginPoint().x());
+        int x2 = qMax(scenePos.x(), m_rubberbandManipulator->beginPoint().x());
+        int y1 = qMin(scenePos.y(), m_rubberbandManipulator->beginPoint().y());
+        int y2 = qMax(scenePos.y(), m_rubberbandManipulator->beginPoint().y());
+
+        QPointF scenePosTopLeft = QPoint(x1, y1);
+        QPointF scenePosBottomRight = QPoint(x2, y2);
+
+        QRectF sceneArea(scenePosTopLeft, scenePosBottomRight);
+
+        m_currentScale = qMin(view()->rect().width() / sceneArea.width(),
+                              view()->rect().height() / sceneArea.height());
+
+
+        QTransform transform;
+        transform.scale(m_currentScale, m_currentScale);
+
+        view()->setTransform(transform);
+        view()->setSceneRect(sceneArea);
+    } else {
+        Qt::KeyboardModifier modifierKey = Qt::ControlModifier;
+#ifdef Q_WS_MAC
+        modifierKey = Qt::AltModifier;
+#endif
+        if (event->modifiers() & modifierKey) {
+            zoomOut();
+        } else {
+            zoomIn();
+        }
+    }
+}
+
+void ZoomTool::zoomIn()
+{
+    m_currentScale = nextZoomScale(ZoomIn);
+    scaleView(view()->mapToScene(m_mousePos));
+}
+
+void ZoomTool::zoomOut()
+{
+    m_currentScale = nextZoomScale(ZoomOut);
+    scaleView(view()->mapToScene(m_mousePos));
+}
+
+void ZoomTool::mouseDoubleClickEvent(QMouseEvent *event)
+{
+    m_mousePos = event->pos();
+}
+
+
+void ZoomTool::hoverMoveEvent(QMouseEvent *event)
+{
+    m_mousePos = event->pos();
+}
+
+
+void ZoomTool::keyPressEvent(QKeyEvent * /*event*/)
+{
+}
+
+void ZoomTool::wheelEvent(QWheelEvent *event)
+{
+    if (event->orientation() != Qt::Vertical)
+        return;
+
+    Qt::KeyboardModifier smoothZoomModifier = Qt::ControlModifier;
+    if (event->modifiers() & smoothZoomModifier) {
+        int numDegrees = event->delta() / 8;
+        m_currentScale += m_smoothZoomMultiplier * (numDegrees / 15.0f);
+
+        scaleView(view()->mapToScene(m_mousePos));
+
+    } else if (!event->modifiers()) {
+        if (event->delta() > 0) {
+            m_currentScale = nextZoomScale(ZoomIn);
+        } else if (event->delta() < 0) {
+            m_currentScale = nextZoomScale(ZoomOut);
+        }
+        scaleView(view()->mapToScene(m_mousePos));
+    }
+}
+
+void ZoomTool::keyReleaseEvent(QKeyEvent *event)
+{
+    switch (event->key()) {
+    case Qt::Key_Plus:
+        zoomIn();
+        break;
+    case Qt::Key_Minus:
+        zoomOut();
+        break;
+    case Qt::Key_1:
+    case Qt::Key_2:
+    case Qt::Key_3:
+    case Qt::Key_4:
+    case Qt::Key_5:
+    case Qt::Key_6:
+    case Qt::Key_7:
+    case Qt::Key_8:
+    case Qt::Key_9:
+    {
+        m_currentScale = ((event->key() - Qt::Key_0) * 1.0f);
+        scaleView(view()->mapToScene(m_mousePos)); // view()->mapToScene(view()->rect().center())
+        break;
+    }
+
+    default:
+        break;
+    }
+
+}
+
+void ZoomTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
+{
+}
+
+void ZoomTool::clear()
+{
+    view()->setCursor(Qt::ArrowCursor);
+}
+
+void ZoomTool::selectedItemsChanged(const QList<QGraphicsItem*> &/*itemList*/)
+{
+}
+
+void ZoomTool::scaleView(const QPointF &centerPos)
+{
+
+    QTransform transform;
+    transform.scale(m_currentScale, m_currentScale);
+    view()->setTransform(transform);
+
+    QPointF adjustedCenterPos = centerPos;
+    QSize rectSize(view()->rect().width() / m_currentScale,
+                   view()->rect().height() / m_currentScale);
+
+    QRectF sceneRect;
+    if (qAbs(m_currentScale - 1.0f) < Constants::ZoomSnapDelta) {
+        adjustedCenterPos.rx() = rectSize.width() / 2;
+        adjustedCenterPos.ry() = rectSize.height() / 2;
+    }
+
+    if (m_currentScale < 1.0f) {
+        adjustedCenterPos.rx() = rectSize.width() / 2;
+        adjustedCenterPos.ry() = rectSize.height() / 2;
+        sceneRect.setRect(view()->rect().width() / 2 -rectSize.width() / 2,
+                          view()->rect().height() / 2 -rectSize.height() / 2,
+                          rectSize.width(),
+                          rectSize.height());
+    } else {
+        sceneRect.setRect(adjustedCenterPos.x() - rectSize.width() / 2,
+                          adjustedCenterPos.y() - rectSize.height() / 2,
+                          rectSize.width(),
+                          rectSize.height());
+    }
+
+    view()->setSceneRect(sceneRect);
+}
+
+void ZoomTool::zoomTo100()
+{
+    m_currentScale = 1.0f;
+    scaleView(view()->mapToScene(view()->rect().center()));
+}
+
+qreal ZoomTool::nextZoomScale(ZoomDirection direction) const
+{
+    static QList<qreal> zoomScales =
+            QList<qreal>()
+            << 0.125f
+            << 1.0f / 6.0f
+            << 0.25f
+            << 1.0f / 3.0f
+            << 0.5f
+            << 2.0f / 3.0f
+            << 1.0f
+            << 2.0f
+            << 3.0f
+            << 4.0f
+            << 5.0f
+            << 6.0f
+            << 7.0f
+            << 8.0f
+            << 12.0f
+            << 16.0f
+            << 32.0f
+            << 48.0f;
+
+    if (direction == ZoomIn) {
+        for (int i = 0; i < zoomScales.length(); ++i) {
+            if (zoomScales[i] > m_currentScale || i == zoomScales.length() - 1)
+                return zoomScales[i];
+        }
+    } else {
+        for (int i = zoomScales.length() - 1; i >= 0; --i) {
+            if (zoomScales[i] < m_currentScale || i == 0)
+                return zoomScales[i];
+        }
+    }
+
+    return 1.0f;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/zoomtool_p.h b/src/plugins/qmltooling/declarativeobserver/editor/zoomtool_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..6734cf9ffdb74808b83018c46305e98866648b4a
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/zoomtool_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ZOOMTOOL_H
+#define ZOOMTOOL_H
+
+#include "abstractliveedittool_p.h"
+#include "liverubberbandselectionmanipulator_p.h"
+
+QT_FORWARD_DECLARE_CLASS(QAction)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class ZoomTool : public AbstractLiveEditTool
+{
+    Q_OBJECT
+
+public:
+    enum ZoomDirection {
+        ZoomIn,
+        ZoomOut
+    };
+
+    explicit ZoomTool(QDeclarativeViewObserver *view);
+
+    virtual ~ZoomTool();
+
+    void mousePressEvent(QMouseEvent *event);
+    void mouseMoveEvent(QMouseEvent *event);
+    void mouseReleaseEvent(QMouseEvent *event);
+    void mouseDoubleClickEvent(QMouseEvent *event);
+
+    void hoverMoveEvent(QMouseEvent *event);
+    void wheelEvent(QWheelEvent *event);
+
+    void keyPressEvent(QKeyEvent *event);
+    void keyReleaseEvent(QKeyEvent *keyEvent);
+    void itemsAboutToRemoved(const QList<QGraphicsItem*> &itemList);
+
+    void clear();
+
+protected:
+    void selectedItemsChanged(const QList<QGraphicsItem*> &itemList);
+
+private slots:
+    void zoomTo100();
+    void zoomIn();
+    void zoomOut();
+
+private:
+    qreal nextZoomScale(ZoomDirection direction) const;
+    void scaleView(const QPointF &centerPos);
+
+private:
+    bool m_dragStarted;
+    QPoint m_mousePos; // in view coords
+    QPointF m_dragBeginPos;
+    QAction *m_zoomTo100Action;
+    QAction *m_zoomInAction;
+    QAction *m_zoomOutAction;
+    LiveRubberBandSelectionManipulator *m_rubberbandManipulator;
+
+    qreal m_smoothZoomMultiplier;
+    qreal m_currentScale;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ZOOMTOOL_H
diff --git a/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverplugin.cpp b/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverplugin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..458b7ef4612f74c50853a4946ce84c41ba5a4887
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverplugin.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativeobserverplugin.h"
+
+#include "qdeclarativeviewobserver_p.h"
+
+#include <QtCore/qplugin.h>
+#include <QtDeclarative/private/qdeclarativeobserverservice_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QDeclarativeObserverPlugin::QDeclarativeObserverPlugin() :
+    m_observer(0)
+{
+}
+
+QDeclarativeObserverPlugin::~QDeclarativeObserverPlugin()
+{
+    delete m_observer;
+}
+
+void QDeclarativeObserverPlugin::activate()
+{
+    QDeclarativeObserverService *service = QDeclarativeObserverService::instance();
+    QList<QDeclarativeView*> views = service->views();
+    if (views.isEmpty())
+        return;
+
+    // TODO: Support multiple views
+    QDeclarativeView *view = service->views().at(0);
+    m_observer = new QDeclarativeViewObserver(view, view);
+}
+
+void QDeclarativeObserverPlugin::deactivate()
+{
+    delete m_observer;
+}
+
+Q_EXPORT_PLUGIN2(declarativeobserver, QDeclarativeObserverPlugin)
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverplugin.h b/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverplugin.h
new file mode 100644
index 0000000000000000000000000000000000000000..82d3dbcf98c8abc5f3ffd23e2e62780cdd743671
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverplugin.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEOBSERVERPLUGIN_H
+#define QDECLARATIVEOBSERVERPLUGIN_H
+
+#include <QtCore/QPointer>
+#include <QtDeclarative/private/qdeclarativeobserverinterface_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeViewObserver;
+
+class QDeclarativeObserverPlugin : public QObject, public QDeclarativeObserverInterface
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(QDeclarativeObserverPlugin)
+    Q_INTERFACES(QDeclarativeObserverInterface)
+
+public:
+    QDeclarativeObserverPlugin();
+    ~QDeclarativeObserverPlugin();
+
+    void activate();
+    void deactivate();
+
+private:
+    QPointer<QDeclarativeViewObserver> m_observer;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEOBSERVERPLUGIN_H
diff --git a/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverprotocol.h b/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverprotocol.h
new file mode 100644
index 0000000000000000000000000000000000000000..eb46693aab882791aaa9828e347570c32dba03e0
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverprotocol.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEOBSERVERPROTOCOL_H
+#define QDECLARATIVEOBSERVERPROTOCOL_H
+
+#include <QtCore/QDebug>
+#include <QtCore/QMetaType>
+#include <QtCore/QMetaEnum>
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class ObserverProtocol : public QObject
+{
+    Q_OBJECT
+    Q_ENUMS(Message Tool)
+
+public:
+    enum Message {
+        AnimationSpeedChanged  = 0,
+        AnimationPausedChanged = 19, // highest value
+        ChangeTool             = 1,
+        ClearComponentCache    = 2,
+        ColorChanged           = 3,
+        ContextPathUpdated     = 4,
+        CreateObject           = 5,
+        CurrentObjectsChanged  = 6,
+        DestroyObject          = 7,
+        MoveObject             = 8,
+        ObjectIdList           = 9,
+        Reload                 = 10,
+        Reloaded               = 11,
+        SetAnimationSpeed      = 12,
+        SetAnimationPaused     = 18,
+        SetContextPathIdx      = 13,
+        SetCurrentObjects      = 14,
+        SetDesignMode          = 15,
+        ShowAppOnTop           = 16,
+        ToolChanged            = 17
+    };
+
+    enum Tool {
+        ColorPickerTool,
+        SelectMarqueeTool,
+        SelectTool,
+        ZoomTool
+    };
+
+    static inline QString toString(Message message)
+    {
+        return QLatin1String(staticMetaObject.enumerator(0).valueToKey(message));
+    }
+
+    static inline QString toString(Tool tool)
+    {
+        return QLatin1String(staticMetaObject.enumerator(1).valueToKey(tool));
+    }
+};
+
+inline QDataStream & operator<< (QDataStream &stream, ObserverProtocol::Message message)
+{
+    return stream << static_cast<quint32>(message);
+}
+
+inline QDataStream & operator>> (QDataStream &stream, ObserverProtocol::Message &message)
+{
+    quint32 i;
+    stream >> i;
+    message = static_cast<ObserverProtocol::Message>(i);
+    return stream;
+}
+
+inline QDebug operator<< (QDebug dbg, ObserverProtocol::Message message)
+{
+    dbg << ObserverProtocol::toString(message);
+    return dbg;
+}
+
+inline QDataStream & operator<< (QDataStream &stream, ObserverProtocol::Tool tool)
+{
+    return stream << static_cast<quint32>(tool);
+}
+
+inline QDataStream & operator>> (QDataStream &stream, ObserverProtocol::Tool &tool)
+{
+    quint32 i;
+    stream >> i;
+    tool = static_cast<ObserverProtocol::Tool>(i);
+    return stream;
+}
+
+inline QDebug operator<< (QDebug dbg, ObserverProtocol::Tool tool)
+{
+    dbg << ObserverProtocol::toString(tool);
+    return dbg;
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEOBSERVERPROTOCOL_H
diff --git a/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver.cpp b/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..22869908129eaf437a06bd4e65d7178e29edb917
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver.cpp
@@ -0,0 +1,1167 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtDeclarative/private/qdeclarativeobserverservice_p.h"
+#include "QtDeclarative/private/qdeclarativedebughelper_p.h"
+
+#include "qdeclarativeviewobserver_p.h"
+#include "qdeclarativeviewobserver_p_p.h"
+#include "qdeclarativeobserverprotocol.h"
+
+#include "editor/liveselectiontool_p.h"
+#include "editor/zoomtool_p.h"
+#include "editor/colorpickertool_p.h"
+#include "editor/livelayeritem_p.h"
+#include "editor/boundingrecthighlighter_p.h"
+#include "editor/subcomponenteditortool_p.h"
+#include "editor/qmltoolbar_p.h"
+
+#include <QtDeclarative/QDeclarativeItem>
+#include <QtDeclarative/QDeclarativeEngine>
+#include <QtDeclarative/QDeclarativeContext>
+#include <QtDeclarative/QDeclarativeExpression>
+#include <QtGui/QWidget>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QGraphicsObject>
+#include <QtGui/QApplication>
+#include <QtCore/QSettings>
+
+static inline void initEditorResource() { Q_INIT_RESOURCE(editor); }
+
+QT_BEGIN_NAMESPACE
+
+const char * const KEY_TOOLBOX_GEOMETRY = "toolBox/geometry";
+
+const int SceneChangeUpdateInterval = 5000;
+
+
+class ToolBox : public QWidget
+{
+    Q_OBJECT
+
+public:
+    ToolBox(QWidget *parent = 0);
+    ~ToolBox();
+
+    QmlToolBar *toolBar() const { return m_toolBar; }
+
+private:
+    QSettings m_settings;
+    QmlToolBar *m_toolBar;
+};
+
+ToolBox::ToolBox(QWidget *parent)
+    : QWidget(parent, Qt::Tool)
+    , m_settings(QLatin1String("Nokia"), QLatin1String("QmlObserver"), this)
+    , m_toolBar(new QmlToolBar)
+{
+    setWindowFlags((windowFlags() & ~Qt::WindowCloseButtonHint) | Qt::CustomizeWindowHint);
+    setWindowTitle(tr("Qt Quick Toolbox"));
+
+    QVBoxLayout *verticalLayout = new QVBoxLayout;
+    verticalLayout->setMargin(0);
+    verticalLayout->addWidget(m_toolBar);
+    setLayout(verticalLayout);
+
+    restoreGeometry(m_settings.value(QLatin1String(KEY_TOOLBOX_GEOMETRY)).toByteArray());
+}
+
+ToolBox::~ToolBox()
+{
+    m_settings.setValue(QLatin1String(KEY_TOOLBOX_GEOMETRY), saveGeometry());
+}
+
+
+QDeclarativeViewObserverPrivate::QDeclarativeViewObserverPrivate(QDeclarativeViewObserver *q) :
+    q(q),
+    designModeBehavior(false),
+    showAppOnTop(false),
+    animationPaused(false),
+    slowDownFactor(1.0f),
+    toolBox(0)
+{
+}
+
+QDeclarativeViewObserverPrivate::~QDeclarativeViewObserverPrivate()
+{
+}
+
+QDeclarativeViewObserver::QDeclarativeViewObserver(QDeclarativeView *view,
+                                                   QObject *parent) :
+    QObject(parent),
+    data(new QDeclarativeViewObserverPrivate(this))
+{
+    initEditorResource();
+
+    data->view = view;
+    data->manipulatorLayer = new LiveLayerItem(view->scene());
+    data->selectionTool = new LiveSelectionTool(this);
+    data->zoomTool = new ZoomTool(this);
+    data->colorPickerTool = new ColorPickerTool(this);
+    data->boundingRectHighlighter = new BoundingRectHighlighter(this);
+    data->subcomponentEditorTool = new SubcomponentEditorTool(this);
+    data->currentTool = data->selectionTool;
+
+    // to capture ChildRemoved event when viewport changes
+    data->view->installEventFilter(this);
+
+    data->setViewport(data->view->viewport());
+
+    data->debugService = QDeclarativeObserverService::instance();
+    connect(data->debugService, SIGNAL(gotMessage(QByteArray)),
+            this, SLOT(handleMessage(QByteArray)));
+
+    connect(data->view, SIGNAL(statusChanged(QDeclarativeView::Status)),
+            data.data(), SLOT(_q_onStatusChanged(QDeclarativeView::Status)));
+
+    connect(data->colorPickerTool, SIGNAL(selectedColorChanged(QColor)),
+            SIGNAL(selectedColorChanged(QColor)));
+    connect(data->colorPickerTool, SIGNAL(selectedColorChanged(QColor)),
+            this, SLOT(sendColorChanged(QColor)));
+
+    connect(data->subcomponentEditorTool, SIGNAL(cleared()), SIGNAL(inspectorContextCleared()));
+    connect(data->subcomponentEditorTool, SIGNAL(contextPushed(QString)),
+            SIGNAL(inspectorContextPushed(QString)));
+    connect(data->subcomponentEditorTool, SIGNAL(contextPopped()),
+            SIGNAL(inspectorContextPopped()));
+    connect(data->subcomponentEditorTool, SIGNAL(contextPathChanged(QStringList)),
+            this, SLOT(sendContextPathUpdated(QStringList)));
+
+    data->_q_changeToSingleSelectTool();
+}
+
+QDeclarativeViewObserver::~QDeclarativeViewObserver()
+{
+}
+
+void QDeclarativeViewObserver::setObserverContext(int contextIndex)
+{
+    if (data->subcomponentEditorTool->contextIndex() != contextIndex) {
+        QGraphicsObject *object = data->subcomponentEditorTool->setContext(contextIndex);
+        if (object)
+            setSelectedItems(QList<QGraphicsItem*>() << object);
+    }
+}
+
+void QDeclarativeViewObserverPrivate::_q_setToolBoxVisible(bool visible)
+{
+#if !defined(Q_OS_SYMBIAN) && !defined(Q_WS_MAEMO_5) && !defined(Q_WS_SIMULATOR)
+    if (!toolBox && visible)
+        createToolBox();
+    if (toolBox)
+        toolBox->setVisible(visible);
+#else
+    Q_UNUSED(visible)
+#endif
+}
+
+void QDeclarativeViewObserverPrivate::_q_reloadView()
+{
+    subcomponentEditorTool->clear();
+    clearHighlight();
+    emit q->reloadRequested();
+}
+
+void QDeclarativeViewObserverPrivate::setViewport(QWidget *widget)
+{
+    if (viewport.data() == widget)
+        return;
+
+    if (viewport)
+        viewport.data()->removeEventFilter(q);
+
+    viewport = widget;
+    if (viewport) {
+        // make sure we get mouse move events
+        viewport.data()->setMouseTracking(true);
+        viewport.data()->installEventFilter(q);
+    }
+}
+
+void QDeclarativeViewObserverPrivate::clearEditorItems()
+{
+    clearHighlight();
+    setSelectedItems(QList<QGraphicsItem*>());
+}
+
+bool QDeclarativeViewObserver::eventFilter(QObject *obj, QEvent *event)
+{
+    if (obj == data->view) {
+        // Event from view
+        if (event->type() == QEvent::ChildRemoved) {
+            // Might mean that viewport has changed
+            if (data->view->viewport() != data->viewport.data())
+                data->setViewport(data->view->viewport());
+        }
+        return QObject::eventFilter(obj, event);
+    }
+
+    // Event from viewport
+    switch (event->type()) {
+    case QEvent::Leave: {
+        if (leaveEvent(event))
+            return true;
+        break;
+    }
+    case QEvent::MouseButtonPress: {
+        if (mousePressEvent(static_cast<QMouseEvent*>(event)))
+            return true;
+        break;
+    }
+    case QEvent::MouseMove: {
+        if (mouseMoveEvent(static_cast<QMouseEvent*>(event)))
+            return true;
+        break;
+    }
+    case QEvent::MouseButtonRelease: {
+        if (mouseReleaseEvent(static_cast<QMouseEvent*>(event)))
+            return true;
+        break;
+    }
+    case QEvent::KeyPress: {
+        if (keyPressEvent(static_cast<QKeyEvent*>(event)))
+            return true;
+        break;
+    }
+    case QEvent::KeyRelease: {
+        if (keyReleaseEvent(static_cast<QKeyEvent*>(event)))
+            return true;
+        break;
+    }
+    case QEvent::MouseButtonDblClick: {
+        if (mouseDoubleClickEvent(static_cast<QMouseEvent*>(event)))
+            return true;
+        break;
+    }
+    case QEvent::Wheel: {
+        if (wheelEvent(static_cast<QWheelEvent*>(event)))
+            return true;
+        break;
+    }
+    default: {
+        break;
+    }
+    } //switch
+
+    // standard event processing
+    return QObject::eventFilter(obj, event);
+}
+
+bool QDeclarativeViewObserver::leaveEvent(QEvent * /*event*/)
+{
+    if (!data->designModeBehavior)
+        return false;
+    data->clearHighlight();
+    return true;
+}
+
+bool QDeclarativeViewObserver::mousePressEvent(QMouseEvent *event)
+{
+    if (!data->designModeBehavior)
+        return false;
+    data->cursorPos = event->pos();
+    data->currentTool->mousePressEvent(event);
+    return true;
+}
+
+bool QDeclarativeViewObserver::mouseMoveEvent(QMouseEvent *event)
+{
+    if (!data->designModeBehavior) {
+        data->clearEditorItems();
+        return false;
+    }
+    data->cursorPos = event->pos();
+
+    QList<QGraphicsItem*> selItems = data->selectableItems(event->pos());
+    if (!selItems.isEmpty()) {
+        declarativeView()->setToolTip(data->currentTool->titleForItem(selItems.first()));
+    } else {
+        declarativeView()->setToolTip(QString());
+    }
+    if (event->buttons()) {
+        data->subcomponentEditorTool->mouseMoveEvent(event);
+        data->currentTool->mouseMoveEvent(event);
+    } else {
+        data->subcomponentEditorTool->hoverMoveEvent(event);
+        data->currentTool->hoverMoveEvent(event);
+    }
+    return true;
+}
+
+bool QDeclarativeViewObserver::mouseReleaseEvent(QMouseEvent *event)
+{
+    if (!data->designModeBehavior)
+        return false;
+    data->subcomponentEditorTool->mouseReleaseEvent(event);
+
+    data->cursorPos = event->pos();
+    data->currentTool->mouseReleaseEvent(event);
+    return true;
+}
+
+bool QDeclarativeViewObserver::keyPressEvent(QKeyEvent *event)
+{
+    if (!data->designModeBehavior)
+        return false;
+
+    data->currentTool->keyPressEvent(event);
+    return true;
+}
+
+bool QDeclarativeViewObserver::keyReleaseEvent(QKeyEvent *event)
+{
+    if (!data->designModeBehavior)
+        return false;
+
+    switch (event->key()) {
+    case Qt::Key_V:
+        data->_q_changeToSingleSelectTool();
+        break;
+// disabled because multiselection does not do anything useful without design mode
+//    case Qt::Key_M:
+//        data->_q_changeToMarqueeSelectTool();
+//        break;
+    case Qt::Key_I:
+        data->_q_changeToColorPickerTool();
+        break;
+    case Qt::Key_Z:
+        data->_q_changeToZoomTool();
+        break;
+    case Qt::Key_Enter:
+    case Qt::Key_Return:
+        if (!data->selectedItems().isEmpty())
+            data->subcomponentEditorTool->setCurrentItem(data->selectedItems().first());
+        break;
+    case Qt::Key_Space:
+        setAnimationPaused(!data->animationPaused);
+        break;
+    default:
+        break;
+    }
+
+    data->currentTool->keyReleaseEvent(event);
+    return true;
+}
+
+void QDeclarativeViewObserverPrivate::_q_createQmlObject(const QString &qml, QObject *parent,
+                                                         const QStringList &importList,
+                                                         const QString &filename)
+{
+    if (!parent)
+        return;
+
+    QString imports;
+    foreach (const QString &s, importList) {
+        imports += s;
+        imports += QLatin1Char('\n');
+    }
+
+    QDeclarativeContext *parentContext = view->engine()->contextForObject(parent);
+    QDeclarativeComponent component(view->engine(), q);
+    QByteArray constructedQml = QString(imports + qml).toLatin1();
+
+    component.setData(constructedQml, QUrl::fromLocalFile(filename));
+    QObject *newObject = component.create(parentContext);
+    if (newObject) {
+        newObject->setParent(parent);
+        QDeclarativeItem *parentItem = qobject_cast<QDeclarativeItem*>(parent);
+        QDeclarativeItem *newItem    = qobject_cast<QDeclarativeItem*>(newObject);
+        if (parentItem && newItem)
+            newItem->setParentItem(parentItem);
+    }
+}
+
+void QDeclarativeViewObserverPrivate::_q_reparentQmlObject(QObject *object, QObject *newParent)
+{
+    if (!newParent)
+        return;
+
+    object->setParent(newParent);
+    QDeclarativeItem *newParentItem = qobject_cast<QDeclarativeItem*>(newParent);
+    QDeclarativeItem *item    = qobject_cast<QDeclarativeItem*>(object);
+    if (newParentItem && item)
+        item->setParentItem(newParentItem);
+}
+
+void QDeclarativeViewObserverPrivate::_q_clearComponentCache()
+{
+    view->engine()->clearComponentCache();
+}
+
+void QDeclarativeViewObserverPrivate::_q_removeFromSelection(QObject *obj)
+{
+    QList<QGraphicsItem*> items = selectedItems();
+    if (QGraphicsItem *item = qobject_cast<QGraphicsObject*>(obj))
+        items.removeOne(item);
+    setSelectedItems(items);
+}
+
+QGraphicsItem *QDeclarativeViewObserverPrivate::currentRootItem() const
+{
+    return subcomponentEditorTool->currentRootItem();
+}
+
+bool QDeclarativeViewObserver::mouseDoubleClickEvent(QMouseEvent *event)
+{
+    if (!data->designModeBehavior)
+        return false;
+
+    if (data->currentToolMode != Constants::SelectionToolMode
+            && data->currentToolMode != Constants::MarqueeSelectionToolMode)
+        return true;
+
+    QGraphicsItem *itemToEnter = 0;
+    QList<QGraphicsItem*> itemList = data->view->items(event->pos());
+    data->filterForSelection(itemList);
+
+    if (data->selectedItems().isEmpty() && !itemList.isEmpty()) {
+        itemToEnter = itemList.first();
+    } else if (!data->selectedItems().isEmpty() && !itemList.isEmpty()) {
+        itemToEnter = itemList.first();
+    }
+
+    if (itemToEnter)
+        itemToEnter = data->subcomponentEditorTool->firstChildOfContext(itemToEnter);
+
+    data->subcomponentEditorTool->setCurrentItem(itemToEnter);
+    data->subcomponentEditorTool->mouseDoubleClickEvent(event);
+
+    if ((event->buttons() & Qt::LeftButton) && itemToEnter) {
+        if (QGraphicsObject *objectToEnter = itemToEnter->toGraphicsObject())
+            setSelectedItems(QList<QGraphicsItem*>() << objectToEnter);
+    }
+
+    return true;
+}
+
+bool QDeclarativeViewObserver::wheelEvent(QWheelEvent *event)
+{
+    if (!data->designModeBehavior)
+        return false;
+    data->currentTool->wheelEvent(event);
+    return true;
+}
+
+void QDeclarativeViewObserverPrivate::enterContext(QGraphicsItem *itemToEnter)
+{
+    QGraphicsItem *itemUnderCurrentContext = itemToEnter;
+    if (itemUnderCurrentContext)
+        itemUnderCurrentContext = subcomponentEditorTool->firstChildOfContext(itemToEnter);
+
+    if (itemUnderCurrentContext)
+        subcomponentEditorTool->setCurrentItem(itemToEnter);
+}
+
+void QDeclarativeViewObserver::setDesignModeBehavior(bool value)
+{
+    emit designModeBehaviorChanged(value);
+
+    if (data->toolBox)
+        data->toolBox->toolBar()->setDesignModeBehavior(value);
+    sendDesignModeBehavior(value);
+
+    data->designModeBehavior = value;
+    if (data->subcomponentEditorTool) {
+        data->subcomponentEditorTool->clear();
+        data->clearHighlight();
+        data->setSelectedItems(QList<QGraphicsItem*>());
+
+        if (data->view->rootObject())
+            data->subcomponentEditorTool->pushContext(data->view->rootObject());
+    }
+
+    if (!data->designModeBehavior)
+        data->clearEditorItems();
+}
+
+bool QDeclarativeViewObserver::designModeBehavior()
+{
+    return data->designModeBehavior;
+}
+
+bool QDeclarativeViewObserver::showAppOnTop() const
+{
+    return data->showAppOnTop;
+}
+
+void QDeclarativeViewObserver::setShowAppOnTop(bool appOnTop)
+{
+    if (data->view) {
+        QWidget *window = data->view->window();
+        Qt::WindowFlags flags = window->windowFlags();
+        if (appOnTop)
+            flags |= Qt::WindowStaysOnTopHint;
+        else
+            flags &= ~Qt::WindowStaysOnTopHint;
+
+        window->setWindowFlags(flags);
+        window->show();
+    }
+
+    data->showAppOnTop = appOnTop;
+    sendShowAppOnTop(appOnTop);
+
+    emit showAppOnTopChanged(appOnTop);
+}
+
+void QDeclarativeViewObserverPrivate::changeTool(Constants::DesignTool tool,
+                                                 Constants::ToolFlags /*flags*/)
+{
+    switch (tool) {
+    case Constants::SelectionToolMode:
+        _q_changeToSingleSelectTool();
+        break;
+    case Constants::NoTool:
+    default:
+        currentTool = 0;
+        break;
+    }
+}
+
+void QDeclarativeViewObserverPrivate::setSelectedItemsForTools(QList<QGraphicsItem *> items)
+{
+    foreach (const QWeakPointer<QGraphicsObject> &obj, currentSelection) {
+        if (QGraphicsItem *item = obj.data()) {
+            if (!items.contains(item)) {
+                QObject::disconnect(obj.data(), SIGNAL(destroyed(QObject*)),
+                                    this, SLOT(_q_removeFromSelection(QObject*)));
+                currentSelection.removeOne(obj);
+            }
+        }
+    }
+
+    foreach (QGraphicsItem *item, items) {
+        if (item) {
+            if (QGraphicsObject *obj = item->toGraphicsObject()) {
+                QObject::connect(obj, SIGNAL(destroyed(QObject*)),
+                                 this, SLOT(_q_removeFromSelection(QObject*)));
+                currentSelection.append(obj);
+            }
+        }
+    }
+
+    currentTool->updateSelectedItems();
+}
+
+void QDeclarativeViewObserverPrivate::setSelectedItems(QList<QGraphicsItem *> items)
+{
+    QList<QWeakPointer<QGraphicsObject> > oldList = currentSelection;
+    setSelectedItemsForTools(items);
+    if (oldList != currentSelection) {
+        QList<QObject*> objectList;
+        foreach (const QWeakPointer<QGraphicsObject> &graphicsObject, currentSelection) {
+            if (graphicsObject)
+                objectList << graphicsObject.data();
+        }
+
+        q->sendCurrentObjects(objectList);
+    }
+}
+
+QList<QGraphicsItem *> QDeclarativeViewObserverPrivate::selectedItems() const
+{
+    QList<QGraphicsItem *> selection;
+    foreach (const QWeakPointer<QGraphicsObject> &selectedObject, currentSelection) {
+        if (selectedObject.data())
+            selection << selectedObject.data();
+    }
+
+    return selection;
+}
+
+void QDeclarativeViewObserver::setSelectedItems(QList<QGraphicsItem *> items)
+{
+    data->setSelectedItems(items);
+}
+
+QList<QGraphicsItem *> QDeclarativeViewObserver::selectedItems() const
+{
+    return data->selectedItems();
+}
+
+QDeclarativeView *QDeclarativeViewObserver::declarativeView()
+{
+    return data->view;
+}
+
+void QDeclarativeViewObserverPrivate::clearHighlight()
+{
+    boundingRectHighlighter->clear();
+}
+
+void QDeclarativeViewObserverPrivate::highlight(QGraphicsObject * item, ContextFlags flags)
+{
+    highlight(QList<QGraphicsObject*>() << item, flags);
+}
+
+void QDeclarativeViewObserverPrivate::highlight(QList<QGraphicsObject *> items, ContextFlags flags)
+{
+    if (items.isEmpty())
+        return;
+
+    QList<QGraphicsObject*> objectList;
+    foreach (QGraphicsItem *item, items) {
+        QGraphicsItem *child = item;
+        if (flags & ContextSensitive)
+            child = subcomponentEditorTool->firstChildOfContext(item);
+
+        if (child) {
+            QGraphicsObject *childObject = child->toGraphicsObject();
+            if (childObject)
+                objectList << childObject;
+        }
+    }
+
+    boundingRectHighlighter->highlight(objectList);
+}
+
+bool QDeclarativeViewObserverPrivate::mouseInsideContextItem() const
+{
+    return subcomponentEditorTool->containsCursor(cursorPos.toPoint());
+}
+
+QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::selectableItems(
+    const QPointF &scenePos) const
+{
+    QList<QGraphicsItem*> itemlist = view->scene()->items(scenePos);
+    return filterForCurrentContext(itemlist);
+}
+
+QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::selectableItems(const QPoint &pos) const
+{
+    QList<QGraphicsItem*> itemlist = view->items(pos);
+    return filterForCurrentContext(itemlist);
+}
+
+QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::selectableItems(
+    const QRectF &sceneRect, Qt::ItemSelectionMode selectionMode) const
+{
+    QList<QGraphicsItem*> itemlist = view->scene()->items(sceneRect, selectionMode);
+
+    return filterForCurrentContext(itemlist);
+}
+
+void QDeclarativeViewObserverPrivate::_q_changeToSingleSelectTool()
+{
+    currentToolMode = Constants::SelectionToolMode;
+    selectionTool->setRubberbandSelectionMode(false);
+
+    changeToSelectTool();
+
+    emit q->selectToolActivated();
+    q->sendCurrentTool(Constants::SelectionToolMode);
+}
+
+void QDeclarativeViewObserverPrivate::changeToSelectTool()
+{
+    if (currentTool == selectionTool)
+        return;
+
+    currentTool->clear();
+    currentTool = selectionTool;
+    currentTool->clear();
+    currentTool->updateSelectedItems();
+}
+
+void QDeclarativeViewObserverPrivate::_q_changeToMarqueeSelectTool()
+{
+    changeToSelectTool();
+    currentToolMode = Constants::MarqueeSelectionToolMode;
+    selectionTool->setRubberbandSelectionMode(true);
+
+    emit q->marqueeSelectToolActivated();
+    q->sendCurrentTool(Constants::MarqueeSelectionToolMode);
+}
+
+void QDeclarativeViewObserverPrivate::_q_changeToZoomTool()
+{
+    currentToolMode = Constants::ZoomMode;
+    currentTool->clear();
+    currentTool = zoomTool;
+    currentTool->clear();
+
+    emit q->zoomToolActivated();
+    q->sendCurrentTool(Constants::ZoomMode);
+}
+
+void QDeclarativeViewObserverPrivate::_q_changeToColorPickerTool()
+{
+    if (currentTool == colorPickerTool)
+        return;
+
+    currentToolMode = Constants::ColorPickerMode;
+    currentTool->clear();
+    currentTool = colorPickerTool;
+    currentTool->clear();
+
+    emit q->colorPickerActivated();
+    q->sendCurrentTool(Constants::ColorPickerMode);
+}
+
+void QDeclarativeViewObserverPrivate::_q_changeContextPathIndex(int index)
+{
+    subcomponentEditorTool->setContext(index);
+}
+
+void QDeclarativeViewObserver::setAnimationSpeed(qreal slowDownFactor)
+{
+    Q_ASSERT(slowDownFactor > 0);
+    if (data->slowDownFactor == slowDownFactor)
+        return;
+
+    animationSpeedChangeRequested(slowDownFactor);
+    sendAnimationSpeed(slowDownFactor);
+}
+
+void QDeclarativeViewObserver::setAnimationPaused(bool paused)
+{
+    if (data->animationPaused == paused)
+        return;
+
+    animationPausedChangeRequested(paused);
+    sendAnimationPaused(paused);
+}
+
+void QDeclarativeViewObserver::animationSpeedChangeRequested(qreal factor)
+{
+    if (data->slowDownFactor != factor) {
+        data->slowDownFactor = factor;
+        emit animationSpeedChanged(factor);
+    }
+
+    const float effectiveFactor = data->animationPaused ? 0 : factor;
+    QDeclarativeDebugHelper::setAnimationSlowDownFactor(effectiveFactor);
+}
+
+void QDeclarativeViewObserver::animationPausedChangeRequested(bool paused)
+{
+    if (data->animationPaused != paused) {
+        data->animationPaused = paused;
+        emit animationPausedChanged(paused);
+    }
+
+    const float effectiveFactor = paused ? 0 : data->slowDownFactor;
+    QDeclarativeDebugHelper::setAnimationSlowDownFactor(effectiveFactor);
+}
+
+
+void QDeclarativeViewObserverPrivate::_q_applyChangesFromClient()
+{
+}
+
+
+QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::filterForSelection(
+    QList<QGraphicsItem*> &itemlist) const
+{
+    foreach (QGraphicsItem *item, itemlist) {
+        if (isEditorItem(item) || !subcomponentEditorTool->isChildOfContext(item))
+            itemlist.removeOne(item);
+    }
+
+    return itemlist;
+}
+
+QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::filterForCurrentContext(
+    QList<QGraphicsItem*> &itemlist) const
+{
+    foreach (QGraphicsItem *item, itemlist) {
+
+        if (isEditorItem(item) || !subcomponentEditorTool->isDirectChildOfContext(item)) {
+
+            // if we're a child, but not directly, replace with the parent that is directly in context.
+            if (QGraphicsItem *contextParent = subcomponentEditorTool->firstChildOfContext(item)) {
+                if (contextParent != item) {
+                    if (itemlist.contains(contextParent)) {
+                        itemlist.removeOne(item);
+                    } else {
+                        itemlist.replace(itemlist.indexOf(item), contextParent);
+                    }
+                }
+            } else {
+                itemlist.removeOne(item);
+            }
+        }
+    }
+
+    return itemlist;
+}
+
+bool QDeclarativeViewObserverPrivate::isEditorItem(QGraphicsItem *item) const
+{
+    return (item->type() == Constants::EditorItemType
+            || item->type() == Constants::ResizeHandleItemType
+            || item->data(Constants::EditorItemDataKey).toBool());
+}
+
+void QDeclarativeViewObserverPrivate::_q_onStatusChanged(QDeclarativeView::Status status)
+{
+    if (status == QDeclarativeView::Ready) {
+        if (view->rootObject()) {
+            if (subcomponentEditorTool->contextIndex() != -1)
+                subcomponentEditorTool->clear();
+            subcomponentEditorTool->pushContext(view->rootObject());
+        }
+        q->sendReloaded();
+    }
+}
+
+void QDeclarativeViewObserverPrivate::_q_onCurrentObjectsChanged(QList<QObject*> objects)
+{
+    QList<QGraphicsItem*> items;
+    QList<QGraphicsObject*> gfxObjects;
+    foreach (QObject *obj, objects) {
+        QDeclarativeItem* declarativeItem = qobject_cast<QDeclarativeItem*>(obj);
+        if (declarativeItem) {
+            items << declarativeItem;
+            if (QGraphicsObject *gfxObj = declarativeItem->toGraphicsObject())
+                gfxObjects << gfxObj;
+        }
+    }
+    if (designModeBehavior) {
+        setSelectedItemsForTools(items);
+        clearHighlight();
+        highlight(gfxObjects, QDeclarativeViewObserverPrivate::IgnoreContext);
+    }
+}
+
+// adjusts bounding boxes on edges of screen to be visible
+QRectF QDeclarativeViewObserver::adjustToScreenBoundaries(const QRectF &boundingRectInSceneSpace)
+{
+    int marginFromEdge = 1;
+    QRectF boundingRect(boundingRectInSceneSpace);
+    if (qAbs(boundingRect.left()) - 1 < 2)
+        boundingRect.setLeft(marginFromEdge);
+
+    QRect rect = data->view->rect();
+
+    if (boundingRect.right() >= rect.right())
+        boundingRect.setRight(rect.right() - marginFromEdge);
+
+    if (qAbs(boundingRect.top()) - 1 < 2)
+        boundingRect.setTop(marginFromEdge);
+
+    if (boundingRect.bottom() >= rect.bottom())
+        boundingRect.setBottom(rect.bottom() - marginFromEdge);
+
+    return boundingRect;
+}
+
+void QDeclarativeViewObserverPrivate::createToolBox()
+{
+    toolBox = new ToolBox(q->declarativeView());
+
+    QmlToolBar *toolBar = toolBox->toolBar();
+
+    QObject::connect(q, SIGNAL(selectedColorChanged(QColor)),
+                     toolBar, SLOT(setColorBoxColor(QColor)));
+
+    QObject::connect(q, SIGNAL(designModeBehaviorChanged(bool)),
+                     toolBar, SLOT(setDesignModeBehavior(bool)));
+
+    QObject::connect(toolBar, SIGNAL(designModeBehaviorChanged(bool)),
+                     q, SLOT(setDesignModeBehavior(bool)));
+    QObject::connect(toolBar, SIGNAL(animationSpeedChanged(qreal)), q, SLOT(setAnimationSpeed(qreal)));
+    QObject::connect(toolBar, SIGNAL(animationPausedChanged(bool)), q, SLOT(setAnimationPaused(bool)));
+    QObject::connect(toolBar, SIGNAL(colorPickerSelected()), this, SLOT(_q_changeToColorPickerTool()));
+    QObject::connect(toolBar, SIGNAL(zoomToolSelected()), this, SLOT(_q_changeToZoomTool()));
+    QObject::connect(toolBar, SIGNAL(selectToolSelected()), this, SLOT(_q_changeToSingleSelectTool()));
+    QObject::connect(toolBar, SIGNAL(marqueeSelectToolSelected()),
+                     this, SLOT(_q_changeToMarqueeSelectTool()));
+
+    QObject::connect(toolBar, SIGNAL(applyChangesFromQmlFileSelected()),
+                     this, SLOT(_q_applyChangesFromClient()));
+
+    QObject::connect(q, SIGNAL(animationSpeedChanged(qreal)), toolBar, SLOT(setAnimationSpeed(qreal)));
+    QObject::connect(q, SIGNAL(animationPausedChanged(bool)), toolBar, SLOT(setAnimationPaused(bool)));
+
+    QObject::connect(q, SIGNAL(selectToolActivated()), toolBar, SLOT(activateSelectTool()));
+
+    // disabled features
+    //connect(d->m_toolBar, SIGNAL(applyChangesToQmlFileSelected()), SLOT(applyChangesToClient()));
+    //connect(q, SIGNAL(resizeToolActivated()), d->m_toolBar, SLOT(activateSelectTool()));
+    //connect(q, SIGNAL(moveToolActivated()),   d->m_toolBar, SLOT(activateSelectTool()));
+
+    QObject::connect(q, SIGNAL(colorPickerActivated()), toolBar, SLOT(activateColorPicker()));
+    QObject::connect(q, SIGNAL(zoomToolActivated()), toolBar, SLOT(activateZoom()));
+    QObject::connect(q, SIGNAL(marqueeSelectToolActivated()),
+                     toolBar, SLOT(activateMarqueeSelectTool()));
+}
+
+void QDeclarativeViewObserver::handleMessage(const QByteArray &message)
+{
+    QDataStream ds(message);
+
+    ObserverProtocol::Message type;
+    ds >> type;
+
+    switch (type) {
+    case ObserverProtocol::SetCurrentObjects: {
+        int itemCount = 0;
+        ds >> itemCount;
+
+        QList<QObject*> selectedObjects;
+        for (int i = 0; i < itemCount; ++i) {
+            int debugId = -1;
+            ds >> debugId;
+            QObject *obj = QDeclarativeDebugService::objectForId(debugId);
+
+            if (obj)
+                selectedObjects << obj;
+        }
+
+        data->_q_onCurrentObjectsChanged(selectedObjects);
+        break;
+    }
+    case ObserverProtocol::Reload: {
+        data->_q_reloadView();
+        break;
+    }
+    case ObserverProtocol::SetAnimationSpeed: {
+        qreal speed;
+        ds >> speed;
+        animationSpeedChangeRequested(speed);
+        break;
+    }
+    case ObserverProtocol::SetAnimationPaused: {
+        bool paused;
+        ds >> paused;
+        animationPausedChangeRequested(paused);
+        break;
+    }
+    case ObserverProtocol::ChangeTool: {
+        ObserverProtocol::Tool tool;
+        ds >> tool;
+        switch (tool) {
+        case ObserverProtocol::ColorPickerTool:
+            data->_q_changeToColorPickerTool();
+            break;
+        case ObserverProtocol::SelectTool:
+            data->_q_changeToSingleSelectTool();
+            break;
+        case ObserverProtocol::SelectMarqueeTool:
+            data->_q_changeToMarqueeSelectTool();
+            break;
+        case ObserverProtocol::ZoomTool:
+            data->_q_changeToZoomTool();
+            break;
+        default:
+            qWarning() << "Warning: Unhandled tool:" << tool;
+        }
+        break;
+    }
+    case ObserverProtocol::SetDesignMode: {
+        bool inDesignMode;
+        ds >> inDesignMode;
+        setDesignModeBehavior(inDesignMode);
+        break;
+    }
+    case ObserverProtocol::ShowAppOnTop: {
+        bool showOnTop;
+        ds >> showOnTop;
+        setShowAppOnTop(showOnTop);
+        break;
+    }
+    case ObserverProtocol::CreateObject: {
+        QString qml;
+        int parentId;
+        QString filename;
+        QStringList imports;
+        ds >> qml >> parentId >> imports >> filename;
+        data->_q_createQmlObject(qml, QDeclarativeDebugService::objectForId(parentId),
+                                 imports, filename);
+        break;
+    }
+    case ObserverProtocol::DestroyObject: {
+        int debugId;
+        ds >> debugId;
+        if (QObject* obj = QDeclarativeDebugService::objectForId(debugId))
+            obj->deleteLater();
+        break;
+    }
+    case ObserverProtocol::MoveObject: {
+        int debugId, newParent;
+        ds >> debugId >> newParent;
+        data->_q_reparentQmlObject(QDeclarativeDebugService::objectForId(debugId),
+                                   QDeclarativeDebugService::objectForId(newParent));
+        break;
+    }
+    case ObserverProtocol::ObjectIdList: {
+        int itemCount;
+        ds >> itemCount;
+        data->stringIdForObjectId.clear();
+        for (int i = 0; i < itemCount; ++i) {
+            int itemDebugId;
+            QString itemIdString;
+            ds >> itemDebugId
+               >> itemIdString;
+
+            data->stringIdForObjectId.insert(itemDebugId, itemIdString);
+        }
+        break;
+    }
+    case ObserverProtocol::SetContextPathIdx: {
+        int contextPathIndex;
+        ds >> contextPathIndex;
+        data->_q_changeContextPathIndex(contextPathIndex);
+        break;
+    }
+    case ObserverProtocol::ClearComponentCache: {
+        data->_q_clearComponentCache();
+        break;
+    }
+    default:
+        qWarning() << "Warning: Not handling message:" << type;
+    }
+}
+
+void QDeclarativeViewObserver::sendDesignModeBehavior(bool inDesignMode)
+{
+    QByteArray message;
+    QDataStream ds(&message, QIODevice::WriteOnly);
+
+    ds << ObserverProtocol::SetDesignMode
+       << inDesignMode;
+
+    data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendCurrentObjects(QList<QObject*> objects)
+{
+    QByteArray message;
+    QDataStream ds(&message, QIODevice::WriteOnly);
+
+    ds << ObserverProtocol::CurrentObjectsChanged
+       << objects.length();
+
+    foreach (QObject *object, objects) {
+        int id = QDeclarativeDebugService::idForObject(object);
+        ds << id;
+    }
+
+    data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendCurrentTool(Constants::DesignTool toolId)
+{
+    QByteArray message;
+    QDataStream ds(&message, QIODevice::WriteOnly);
+
+    ds << ObserverProtocol::ToolChanged
+       << toolId;
+
+    data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendAnimationSpeed(qreal slowDownFactor)
+{
+    QByteArray message;
+    QDataStream ds(&message, QIODevice::WriteOnly);
+
+    ds << ObserverProtocol::AnimationSpeedChanged
+       << slowDownFactor;
+
+    data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendAnimationPaused(bool paused)
+{
+    QByteArray message;
+    QDataStream ds(&message, QIODevice::WriteOnly);
+
+    ds << ObserverProtocol::AnimationPausedChanged
+       << paused;
+
+    data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendReloaded()
+{
+    QByteArray message;
+    QDataStream ds(&message, QIODevice::WriteOnly);
+
+    ds << ObserverProtocol::Reloaded;
+
+    data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendShowAppOnTop(bool showAppOnTop)
+{
+    QByteArray message;
+    QDataStream ds(&message, QIODevice::WriteOnly);
+
+    ds << ObserverProtocol::ShowAppOnTop << showAppOnTop;
+
+    data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendColorChanged(const QColor &color)
+{
+    QByteArray message;
+    QDataStream ds(&message, QIODevice::WriteOnly);
+
+    ds << ObserverProtocol::ColorChanged
+       << color;
+
+    data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendContextPathUpdated(const QStringList &contextPath)
+{
+    QByteArray message;
+    QDataStream ds(&message, QIODevice::WriteOnly);
+
+    ds << ObserverProtocol::ContextPathUpdated
+       << contextPath;
+
+    data->debugService->sendMessage(message);
+}
+
+QString QDeclarativeViewObserver::idStringForObject(QObject *obj) const
+{
+    int id = QDeclarativeDebugService::idForObject(obj);
+    QString idString = data->stringIdForObjectId.value(id, QString());
+    return idString;
+}
+
+QT_END_NAMESPACE
+
+#include "qdeclarativeviewobserver.moc"
diff --git a/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver_p.h b/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..6e986c2738e16465666a16f25af453c873981dfb
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver_p.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEVIEWOBSERVER_P_H
+#define QDECLARATIVEVIEWOBSERVER_P_H
+
+#include <private/qdeclarativeglobal_p.h>
+#include "qmlobserverconstants_p.h"
+
+#include <QtCore/QScopedPointer>
+#include <QtDeclarative/QDeclarativeView>
+
+QT_FORWARD_DECLARE_CLASS(QDeclarativeItem)
+QT_FORWARD_DECLARE_CLASS(QMouseEvent)
+QT_FORWARD_DECLARE_CLASS(QToolBar)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserverPrivate;
+
+class QDeclarativeViewObserver : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit QDeclarativeViewObserver(QDeclarativeView *view, QObject *parent = 0);
+    ~QDeclarativeViewObserver();
+
+    void setSelectedItems(QList<QGraphicsItem *> items);
+    QList<QGraphicsItem *> selectedItems() const;
+
+    QDeclarativeView *declarativeView();
+
+    QRectF adjustToScreenBoundaries(const QRectF &boundingRectInSceneSpace);
+
+    bool showAppOnTop() const;
+
+    void sendDesignModeBehavior(bool inDesignMode);
+    void sendCurrentObjects(QList<QObject*> items);
+    void sendAnimationSpeed(qreal slowDownFactor);
+    void sendAnimationPaused(bool paused);
+    void sendCurrentTool(Constants::DesignTool toolId);
+    void sendReloaded();
+    void sendShowAppOnTop(bool showAppOnTop);
+
+    QString idStringForObject(QObject *obj) const;
+
+public Q_SLOTS:
+    void sendColorChanged(const QColor &color);
+    void sendContextPathUpdated(const QStringList &contextPath);
+
+    void setDesignModeBehavior(bool value);
+    bool designModeBehavior();
+
+    void setShowAppOnTop(bool appOnTop);
+
+    void setAnimationSpeed(qreal factor);
+    void setAnimationPaused(bool paused);
+
+    void setObserverContext(int contextIndex);
+
+Q_SIGNALS:
+    void designModeBehaviorChanged(bool inDesignMode);
+    void showAppOnTopChanged(bool showAppOnTop);
+    void reloadRequested();
+    void marqueeSelectToolActivated();
+    void selectToolActivated();
+    void zoomToolActivated();
+    void colorPickerActivated();
+    void selectedColorChanged(const QColor &color);
+
+    void animationSpeedChanged(qreal factor);
+    void animationPausedChanged(bool paused);
+
+    void inspectorContextCleared();
+    void inspectorContextPushed(const QString &contextTitle);
+    void inspectorContextPopped();
+
+protected:
+    bool eventFilter(QObject *obj, QEvent *event);
+
+    bool leaveEvent(QEvent *);
+    bool mousePressEvent(QMouseEvent *event);
+    bool mouseMoveEvent(QMouseEvent *event);
+    bool mouseReleaseEvent(QMouseEvent *event);
+    bool keyPressEvent(QKeyEvent *event);
+    bool keyReleaseEvent(QKeyEvent *keyEvent);
+    bool mouseDoubleClickEvent(QMouseEvent *event);
+    bool wheelEvent(QWheelEvent *event);
+
+    void setSelectedItemsForTools(QList<QGraphicsItem *> items);
+
+private slots:
+    void handleMessage(const QByteArray &message);
+
+    void animationSpeedChangeRequested(qreal factor);
+    void animationPausedChangeRequested(bool paused);
+
+private:
+    Q_DISABLE_COPY(QDeclarativeViewObserver)
+
+    inline QDeclarativeViewObserverPrivate *d_func() { return data.data(); }
+    QScopedPointer<QDeclarativeViewObserverPrivate> data;
+    friend class QDeclarativeViewObserverPrivate;
+    friend class AbstractLiveEditTool;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEVIEWOBSERVER_P_H
diff --git a/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver_p_p.h b/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver_p_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..60225554ede257680833622d2119ec4d132e6591
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver_p_p.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEVIEWOBSERVER_P_P_H
+#define QDECLARATIVEVIEWOBSERVER_P_P_H
+
+#include "qdeclarativeviewobserver_p.h"
+
+#include <QtCore/QWeakPointer>
+#include <QtCore/QPointF>
+
+#include "QtDeclarative/private/qdeclarativeobserverservice_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserver;
+class LiveSelectionTool;
+class ZoomTool;
+class ColorPickerTool;
+class LiveLayerItem;
+class BoundingRectHighlighter;
+class SubcomponentEditorTool;
+class ToolBox;
+class AbstractLiveEditTool;
+
+class QDeclarativeViewObserverPrivate : public QObject
+{
+    Q_OBJECT
+public:
+    enum ContextFlags {
+        IgnoreContext,
+        ContextSensitive
+    };
+
+    QDeclarativeViewObserverPrivate(QDeclarativeViewObserver *);
+    ~QDeclarativeViewObserverPrivate();
+
+    QDeclarativeView *view;
+    QDeclarativeViewObserver *q;
+    QDeclarativeObserverService *debugService;
+    QWeakPointer<QWidget> viewport;
+    QHash<int, QString> stringIdForObjectId;
+
+    QPointF cursorPos;
+    QList<QWeakPointer<QGraphicsObject> > currentSelection;
+
+    Constants::DesignTool currentToolMode;
+    AbstractLiveEditTool *currentTool;
+
+    LiveSelectionTool *selectionTool;
+    ZoomTool *zoomTool;
+    ColorPickerTool *colorPickerTool;
+    SubcomponentEditorTool *subcomponentEditorTool;
+    LiveLayerItem *manipulatorLayer;
+
+    BoundingRectHighlighter *boundingRectHighlighter;
+
+    bool designModeBehavior;
+    bool showAppOnTop;
+
+    bool animationPaused;
+    qreal slowDownFactor;
+
+    ToolBox *toolBox;
+
+    void setViewport(QWidget *widget);
+
+    void clearEditorItems();
+    void createToolBox();
+    void changeToSelectTool();
+    QList<QGraphicsItem*> filterForCurrentContext(QList<QGraphicsItem*> &itemlist) const;
+    QList<QGraphicsItem*> filterForSelection(QList<QGraphicsItem*> &itemlist) const;
+
+    QList<QGraphicsItem*> selectableItems(const QPoint &pos) const;
+    QList<QGraphicsItem*> selectableItems(const QPointF &scenePos) const;
+    QList<QGraphicsItem*> selectableItems(const QRectF &sceneRect, Qt::ItemSelectionMode selectionMode) const;
+
+    void setSelectedItemsForTools(QList<QGraphicsItem *> items);
+    void setSelectedItems(QList<QGraphicsItem *> items);
+    QList<QGraphicsItem *> selectedItems() const;
+
+    void changeTool(Constants::DesignTool tool,
+                    Constants::ToolFlags flags = Constants::NoToolFlags);
+
+    void clearHighlight();
+    void highlight(QList<QGraphicsObject *> item, ContextFlags flags = ContextSensitive);
+    void highlight(QGraphicsObject *item, ContextFlags flags = ContextSensitive);
+
+    bool mouseInsideContextItem() const;
+    bool isEditorItem(QGraphicsItem *item) const;
+
+    QGraphicsItem *currentRootItem() const;
+
+    void enterContext(QGraphicsItem *itemToEnter);
+
+public slots:
+    void _q_setToolBoxVisible(bool visible);
+
+    void _q_reloadView();
+    void _q_onStatusChanged(QDeclarativeView::Status status);
+    void _q_onCurrentObjectsChanged(QList<QObject*> objects);
+    void _q_applyChangesFromClient();
+    void _q_createQmlObject(const QString &qml, QObject *parent,
+                            const QStringList &imports, const QString &filename = QString());
+    void _q_reparentQmlObject(QObject *, QObject *);
+
+    void _q_changeToSingleSelectTool();
+    void _q_changeToMarqueeSelectTool();
+    void _q_changeToZoomTool();
+    void _q_changeToColorPickerTool();
+    void _q_changeContextPathIndex(int index);
+    void _q_clearComponentCache();
+    void _q_removeFromSelection(QObject *);
+
+public:
+    static QDeclarativeViewObserverPrivate *get(QDeclarativeViewObserver *v) { return v->d_func(); }
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEVIEWOBSERVER_P_P_H
diff --git a/src/plugins/qmltooling/declarativeobserver/qmlobserverconstants_p.h b/src/plugins/qmltooling/declarativeobserver/qmlobserverconstants_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..353e235c46e7b5873c7c97f42a281e117d7a8efd
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/qmlobserverconstants_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLOBSERVERCONSTANTS_H
+#define QMLOBSERVERCONSTANTS_H
+
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+namespace Constants {
+
+enum DesignTool {
+    NoTool = 0,
+    SelectionToolMode = 1,
+    MarqueeSelectionToolMode = 2,
+    MoveToolMode = 3,
+    ResizeToolMode = 4,
+    ColorPickerMode = 5,
+    ZoomMode = 6
+};
+
+enum ToolFlags {
+    NoToolFlags = 0,
+    UseCursorPos = 1
+};
+
+static const int DragStartTime = 50;
+
+static const int DragStartDistance = 20;
+
+static const double ZoomSnapDelta = 0.04;
+
+static const int EditorItemDataKey = 1000;
+
+enum GraphicsItemTypes {
+    EditorItemType = 0xEAAA,
+    ResizeHandleItemType = 0xEAEA
+};
+
+
+} // namespace Constants
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLOBSERVERCONSTANTS_H
diff --git a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp
index 1c91c3455a827ee2d23448d6289a2ea46b129916..ac32081a9b878866d962333b095e0169637ec546 100644
--- a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp
+++ b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp
@@ -109,6 +109,12 @@ void QmlOstPlugin::disconnect()
     d->protocol = 0;
 }
 
+bool QmlOstPlugin::waitForMessage()
+{
+    Q_D(QmlOstPlugin);
+    return d->protocol->waitForReadyRead(-1);
+}
+
 void QmlOstPlugin::setPort(int port, bool block)
 {
     Q_UNUSED(port);
diff --git a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h
index eee6ee179b40b781d3480c5fbe54a1607ed675eb..b4ff377fbd527492b1707f4163ffbc4d3ddb6e3a 100644
--- a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h
+++ b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h
@@ -68,6 +68,7 @@ public:
     bool isConnected() const;
     void send(const QByteArray &message);
     void disconnect();
+    bool waitForMessage();
 
 private Q_SLOTS:
     void readyRead();
diff --git a/src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp b/src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp
index 21b0169c81e7518917cd50d68f997d5514c9043e..d3b2661a27f29fb9fe543ef40ddefca1b08eb526 100644
--- a/src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp
+++ b/src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp
@@ -57,6 +57,8 @@ public:
         Cancel();
     }
 
+    TInt& AoFlags() { return ((TInt*)&iStatus)[1]; }
+
 private:
     void RunL();
     void DoCancel();
@@ -65,6 +67,7 @@ private:
     RUsbOstComm ost;
     TBuf8<4096> readBuf;
     QByteArray dataBuf;
+    TBool inReadyRead;
 };
 
 QOstDevice::QOstDevice(QObject *parent) :
@@ -116,7 +119,11 @@ void QOstDevicePrivate::RunL()
         ost.ReadMessage(iStatus, readBuf);
         SetActive();
 
-        emit q->readyRead();
+        if (!inReadyRead) {
+            inReadyRead = true;
+            emit q->readyRead();
+            inReadyRead = false;
+        }
     } else {
         q->setErrorString(QString("Error %1 from RUsbOstComm::ReadMessage()").arg(iStatus.Int()));
     }
@@ -178,3 +185,36 @@ qint64 QOstDevice::bytesAvailable() const
     Q_D(const QOstDevice);
     return d->dataBuf.length();
 }
+
+bool QOstDevice::waitForReadyRead(int msecs)
+{
+    Q_D(QOstDevice);
+    if (msecs >= 0) {
+        RTimer timer;
+        TInt err = timer.CreateLocal();
+        if (err) return false;
+        TRequestStatus timeoutStat;
+        timer.After(timeoutStat, msecs*1000);
+        User::WaitForRequest(timeoutStat, d->iStatus);
+        if (timeoutStat != KRequestPending) {
+            // Timed out
+            timer.Close();
+            return false;
+        } else {
+            // We got data, so cancel timer
+            timer.Cancel();
+            User::WaitForRequest(timeoutStat);
+            timer.Close();
+            // And drop through
+        }
+    } else {
+        // Just wait forever for data
+        User::WaitForRequest(d->iStatus);
+    }
+
+    // If we get here we have data
+    TInt err = d->iStatus.Int();
+    d->AoFlags() &= ~3; // This is necessary to clean up the scheduler as you're not supposed to bypass it like this
+    TRAP_IGNORE(d->RunL());
+    return err == KErrNone;
+}
diff --git a/src/plugins/qmltooling/qmldbg_ost/qostdevice.h b/src/plugins/qmltooling/qmldbg_ost/qostdevice.h
index 2c26ff707df1a26aaaf5a5c8e1e12cd18da2be62..200e6079ccca3904343ccc7f3944098afb13478c 100644
--- a/src/plugins/qmltooling/qmldbg_ost/qostdevice.h
+++ b/src/plugins/qmltooling/qmldbg_ost/qostdevice.h
@@ -61,10 +61,12 @@ public:
     bool open(int ostProtocolId);
     void close();
 
+    bool waitForReadyRead(int msecs);
+    qint64 bytesAvailable() const;
+
 protected:
     qint64 readData(char *data, qint64 maxSize);
     qint64 writeData(const char *data, qint64 maxSize);
-    qint64 bytesAvailable() const;
 
 private:
     QOstDevicePrivate* d_ptr;
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
index 437c4061b1440d350ac228e0c4ea1746508e12f0..7cd3d734a8d95a690e2cf5adf1e292c0b842e446 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
@@ -41,6 +41,7 @@
 
 #include "qtcpserverconnection.h"
 
+#include <QtCore/qplugin.h>
 #include <QtNetwork/qtcpserver.h>
 #include <QtNetwork/qtcpsocket.h>
 
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
index 1c972b5dd75ff425e809a87e1dc2d99366c4fcbc..dd5a5ec31a9088581619f92e5e9f07ac1da8e9ab 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
@@ -42,7 +42,6 @@
 #ifndef QTCPSERVERCONNECTION_H
 #define QTCPSERVERCONNECTION_H
 
-#include <QtGui/QStylePlugin>
 #include <QtDeclarative/private/qdeclarativedebugserverconnection_p.h>
 
 QT_BEGIN_NAMESPACE
diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro
index 9b3346fb36f06f6861553ddf0e2a8ecf22d40a7a..0d60eb17ffeb156a6b1e4943f50197074fffd845 100644
--- a/src/plugins/qmltooling/qmltooling.pro
+++ b/src/plugins/qmltooling/qmltooling.pro
@@ -1,4 +1,4 @@
 TEMPLATE = subdirs
 
-SUBDIRS = qmldbg_tcp
+SUBDIRS = qmldbg_tcp declarativeobserver
 symbian:SUBDIRS += qmldbg_ost
diff --git a/sync.profile b/sync.profile
index 5ec72304d026cf04896c2e11cc801e69effb379a..e1c0ef4d914b334849f38c540b8500d49e558860 100644
--- a/sync.profile
+++ b/sync.profile
@@ -5,6 +5,7 @@
 %moduleheaders = ( # restrict the module headers to those found in relative path
 );
 %classnames = (
+    "qtdeclarativeversion.h" => "QtDeclarativeVersion",
 );
 %mastercontent = (
     "gui" => "#include <QtGui/QtGui>\n",