OSDN Git Service

Merge remote branch 'origin/2.1'
[qt-creator-jp/qt-creator-jp.git] / src / plugins / debugger / qml / qmlengine.cpp
index 0d456ae..9e1599a 100644 (file)
 **************************************************************************/
 
 #include "qmlengine.h"
+#include "qmladapter.h"
 
+#include "debuggeractions.h"
+#include "debuggertooltip.h"
 #include "debuggerconstants.h"
 #include "debuggerplugin.h"
 #include "debuggerdialogs.h"
 #include "debuggerstringutils.h"
+#include "debuggeruiswitcher.h"
+#include "debuggerrunner.h"
 
 #include "breakhandler.h"
 #include "moduleshandler.h"
 #include "watchhandler.h"
 #include "watchutils.h"
 
-#include "canvasframerate.h"
-
-#include <projectexplorer/environment.h>
+#include <extensionsystem/pluginmanager.h>
+#include <projectexplorer/applicationlauncher.h>
 
+#include <utils/environment.h>
 #include <utils/qtcassert.h>
 
 #include <QtCore/QDateTime>
 #include <QtGui/QMainWindow>
 #include <QtGui/QMessageBox>
 #include <QtGui/QToolTip>
+#include <QtGui/QTextDocument>
 
 #include <QtNetwork/QTcpSocket>
 #include <QtNetwork/QHostAddress>
 
-#include <private/qdeclarativedebug_p.h>
-#include <private/qdeclarativedebugclient_p.h>
-
 #define DEBUG_QML 1
 #if DEBUG_QML
 #   define SDEBUG(s) qDebug() << s
 #endif
 # define XSDEBUG(s) qDebug() << s
 
-#define CB(callback) &QmlEngine::callback, STRINGIFY(callback)
-
-//#define USE_CONGESTION_CONTROL
-
+enum {
+    MaxConnectionAttempts = 50,
+    ConnectionAttemptDefaultInterval = 200
+};
 
 namespace Debugger {
 namespace Internal {
@@ -88,258 +91,258 @@ QDataStream& operator>>(QDataStream& s, WatchData &data)
     QString type;
     bool hasChildren;
     s >> data.exp >> data.name >> value >> type >> hasChildren >> data.objectId;
-    data.setType(type, false);
+    data.setType(type.toUtf8(), false);
     data.setValue(value);
     data.setHasChildren(hasChildren);
     data.setAllUnneeded();
     return s;
 }
 
-class QmlResponse
-{
-public:
-    QmlResponse() {}
-    QmlResponse(const QByteArray &data_) : data(data_) {}
+} // namespace Internal
 
-    QString toString() const { return data; }
+struct QmlEnginePrivate {
+    explicit QmlEnginePrivate(QmlEngine *q);
 
-    QByteArray data;
+    int m_ping;
+    QmlAdapter *m_adapter;
+    ProjectExplorer::ApplicationLauncher m_applicationLauncher;
+    bool m_addedAdapterToObjectPool;
+    bool m_attachToRunningExternalApp;
+    bool m_hasShutdown;
 };
 
+QmlEnginePrivate::QmlEnginePrivate(QmlEngine *q) :
+  m_ping(0)
+, m_adapter(new QmlAdapter(q))
+, m_addedAdapterToObjectPool(false)
+, m_attachToRunningExternalApp(false)
+, m_hasShutdown(false)
+{
+}
+
 ///////////////////////////////////////////////////////////////////////
 //
-// QmlDebuggerClient
+// QmlEngine
 //
 ///////////////////////////////////////////////////////////////////////
 
-#if 0 //QmlJSInspector does that for us now.
-class QmlDebuggerClient : public QDeclarativeDebugClient
+QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters)
+    : DebuggerEngine(startParameters), d(new QmlEnginePrivate(this))
 {
-    Q_OBJECT
+    setObjectName(QLatin1String("QmlEngine"));
+}
 
-public:
-    QmlDebuggerClient(QDeclarativeDebugConnection *connection, QmlEngine *engine)
-        : QDeclarativeDebugClient(QLatin1String("QDeclarativeEngine"), connection)
-        , m_connection(connection), m_engine(engine)
-    {
-        setEnabled(true);
-    }
+QmlEngine::~QmlEngine()
+{
+}
 
-    void sendMessage(const QByteArray &msg)
-    {
-        QTC_kASSERT(isConnected(), /**/);
-        qDebug() << "SENDING: " << quoteUnprintableLatin1(msg);
-        QDeclarativeDebugClient::sendMessage(msg);
-    }
+void QmlEngine::setAttachToRunningExternalApp(bool value)
+{
+    d->m_attachToRunningExternalApp = value;
+}
 
-    void messageReceived(const QByteArray &data)
-    {
-        m_engine->messageReceived(data);
-    }
+void QmlEngine::pauseConnection()
+{
+    d->m_adapter->pauseConnection();
+}
 
+void QmlEngine::gotoLocation(const QString &fileName, int lineNumber, bool setMarker)
+{
+    QString processedFilename = fileName;
 
-    QDeclarativeDebugConnection *m_connection;
-    QmlEngine *m_engine;
-};
+    if (isShadowBuildProject())
+        processedFilename = fromShadowBuildFilename(fileName);
 
+    DebuggerEngine::gotoLocation(processedFilename, lineNumber, setMarker);
+}
 
-class QmlFrameRateClient : public QDeclarativeDebugClient
+void QmlEngine::gotoLocation(const Internal::StackFrame &frame, bool setMarker)
 {
-    Q_OBJECT
+    Internal::StackFrame adjustedFrame = frame;
+    if (isShadowBuildProject())
+        adjustedFrame.file = fromShadowBuildFilename(frame.file);
 
-public:
-    QmlFrameRateClient(QDeclarativeDebugConnection *connection, QmlEngine *engine)
-        : QDeclarativeDebugClient(QLatin1String("CanvasFrameRate"), connection)
-        , m_connection(connection), m_engine(engine)
-    {
-        setEnabled(true);
-    }
+    DebuggerEngine::gotoLocation(adjustedFrame, setMarker);
+}
 
-    void messageReceived(const QByteArray &data)
-    {
-        Q_UNUSED(data);
-        // FIXME
-        //qDebug() << "CANVAS FRAME RATE: " << data.size();
-        //m_engine->messageReceived(data);
-    }
+void QmlEngine::setupInferior()
+{
+    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
 
+    if (startParameters().startMode == AttachToRemote) {
+        emit remoteStartupRequested();
+    } else {
+        connect(&d->m_applicationLauncher, SIGNAL(processExited(int)),
+                this, SLOT(disconnected()));
+        connect(&d->m_applicationLauncher, SIGNAL(appendMessage(QString,bool)),
+                runControl(), SLOT(emitAppendMessage(QString,bool)));
+        connect(&d->m_applicationLauncher, SIGNAL(appendOutput(QString, bool)),
+                runControl(), SLOT(emitAddToOutputWindow(QString, bool)));
+        connect(&d->m_applicationLauncher, SIGNAL(bringToForegroundRequested(qint64)),
+                runControl(), SLOT(bringApplicationToForeground(qint64)));
 
-    QDeclarativeDebugConnection *m_connection;
-    QmlEngine *m_engine;
-};
-#endif
+        d->m_applicationLauncher.setEnvironment(startParameters().environment);
+        d->m_applicationLauncher.setWorkingDirectory(startParameters().workingDirectory);
 
-///////////////////////////////////////////////////////////////////////
-//
-// QmlEngine
-//
-///////////////////////////////////////////////////////////////////////
+        notifyInferiorSetupOk();
+    }
+}
 
-QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters)
-    : DebuggerEngine(startParameters)
+void QmlEngine::connectionEstablished()
 {
-/*
-    m_conn = 0;
-    m_client = 0;
-    m_engineDebugInterface = 0;
-    m_frameRate = 0;
-
-    m_watchTableModel = new Internal::WatchTableModel(0, this);
-
-    m_objectTreeWidget = new Internal::ObjectTree;
-    m_propertiesWidget = new Internal::ObjectPropertiesView(m_watchTableModel);
-    m_watchTableView = new Internal::WatchTableView(m_watchTableModel);
-    m_expressionWidget = new Internal::ExpressionQueryWidget(Internal::ExpressionQueryWidget::SeparateEntryMode);
-//    m_frameRateWidget = new Internal::CanvasFrameRate;
-//    m_frameRateWidget->setObjectName(QLatin1String("QmlDebugFrameRate"));
+    attemptBreakpointSynchronization();
 
-    connect(Debugger::DebuggerPlugin::instance(),
-        SIGNAL(stateChanged(int)), this, SLOT(debuggerStateChanged(int)));
+    ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance();
+    pluginManager->addObject(d->m_adapter);
+    pluginManager->addObject(this);
+    d->m_addedAdapterToObjectPool = true;
 
-    m_editablePropertyTypes = QStringList() << "qreal" << "bool" << "QString"
-                                            << "int" << "QVariant" << "QUrl" << "QColor";
+    plugin()->showMessage(tr("QML Debugger connected."), StatusBar);
 
-    connect(m_connectionTimer, SIGNAL(timeout()), SLOT(pollInspector()));
-    */
+    notifyEngineRunAndInferiorRunOk();
 }
 
-QmlEngine::~QmlEngine()
+void QmlEngine::connectionStartupFailed()
 {
+    QMessageBox::critical(0,
+                          tr("Failed to connect to debugger"),
+                          tr("Could not connect to QML debugger server at %1:%2.")
+                          .arg(startParameters().qmlServerAddress)
+                          .arg(startParameters().qmlServerPort));
+    notifyEngineRunFailed();
 }
 
-void QmlEngine::executeDebuggerCommand(const QString &command)
+void QmlEngine::connectionError(QAbstractSocket::SocketError socketError)
 {
-    QByteArray cmd = command.toUtf8();
-    cmd = cmd.mid(cmd.indexOf(' ') + 1);
-    QByteArray null;
-    null.append('\0');
-    // FIXME: works for single-digit escapes only
-    cmd.replace("\\0", null);
-    cmd.replace("\\1", "\1");
-    cmd.replace("\\3", "\3");
-    //QmlCommand tcf;
-    //tcf.command = cmd;
-    //enqueueCommand(tcf);
+    if (socketError ==QAbstractSocket::RemoteHostClosedError)
+        plugin()->showMessage(tr("QML Debugger: Remote host closed connection."), StatusBar);
 }
 
-void QmlEngine::setupInferior()
+
+void QmlEngine::serviceConnectionError(const QString &serviceName)
 {
-    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
-    attemptBreakpointSynchronization();
-    notifyInferiorSetupOk();
+    plugin()->showMessage(tr("QML Debugger: Couldn't connect to service '%1'.").arg(serviceName), StatusBar);
 }
 
 void QmlEngine::runEngine()
 {
     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
-    notifyEngineRunAndInferiorRunOk();
+
+    if (!d->m_attachToRunningExternalApp) {
+        d->m_applicationLauncher.start(ProjectExplorer::ApplicationLauncher::Gui,
+                                    startParameters().executable,
+                                    startParameters().processArgs);
+    }
+
+    d->m_adapter->beginConnection();
+    plugin()->showMessage(tr("QML Debugger connecting..."), StatusBar);
 }
 
-void QmlEngine::shutdownInferior()
+void QmlEngine::handleRemoteSetupDone()
 {
-    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
-    notifyInferiorShutdownOk();
+    notifyInferiorSetupOk();
 }
 
-void QmlEngine::shutdownEngine()
+void QmlEngine::handleRemoteSetupFailed(const QString &message)
 {
-    QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
-    //m_objectTreeWidget->saveSettings(m_settings);
-    //m_propertiesWidget->saveSettings(m_settings);
-    //m_settings.saveSettings(Core::ICore::instance()->settings());
+    QMessageBox::critical(0,tr("Failed to start application"),
+        tr("Application startup failed: %1").arg(message));
+    notifyInferiorSetupFailed();
 }
 
-const int serverPort = 3768;
-
-void QmlEngine::setupEngine()
+void QmlEngine::shutdownInferiorAsSlave()
 {
- #if 0
-    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
-    const DebuggerStartParameters &sp = startParameters();
-    const int pos = sp.remoteChannel.indexOf(QLatin1Char(':'));
-    const QString host = sp.remoteChannel.left(pos);
-    const quint16 port = sp.remoteChannel.mid(pos + 1).toInt();
-    qDebug() << "STARTING QML ENGINE" <<  host << port << sp.remoteChannel
-        << sp.executable << sp.processArgs << sp.workingDirectory;
-  
-    ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment(); // empty env by default
-    env.set("QML_DEBUG_SERVER_PORT", QString::number(serverPort));
-
-    connect(&m_proc, SIGNAL(error(QProcess::ProcessError)),
-        SLOT(handleProcError(QProcess::ProcessError)));
-    connect(&m_proc, SIGNAL(finished(int, QProcess::ExitStatus)),
-        SLOT(handleProcFinished(int, QProcess::ExitStatus)));
-    connect(&m_proc, SIGNAL(readyReadStandardOutput()),
-        SLOT(readProcStandardOutput()));
-    connect(&m_proc, SIGNAL(readyReadStandardError()),
-        SLOT(readProcStandardError()));
-
-    m_proc.setEnvironment(env.toStringList());
-    m_proc.setWorkingDirectory(sp.workingDirectory);
-    m_proc.start(sp.executable, sp.processArgs);
-
-    if (!m_proc.waitForStarted()) {
-        notifyEngineSetupFailed();
-        return;
-    }
-#endif
-    notifyEngineSetupOk();
+    resetLocation();
 
-    //m_frameRate = new CanvasFrameRate(0);
-    //m_frameRate->show();
+    // This can be issued in almost any state. We assume, though,
+    // that at this point of time the inferior is not running anymore,
+    // even if stop notification were not issued or got lost.
+    if (state() == InferiorRunOk) {
+        setState(InferiorStopRequested);
+        setState(InferiorStopOk);
+    }
+    setState(InferiorShutdownRequested);
+    setState(InferiorShutdownOk);
 }
 
-void QmlEngine::setupConnection()
+void QmlEngine::shutdownEngineAsSlave()
 {
-    #if 0
-    //the qmlviewer right now connected using QmlJSInspector::InternalInspectorPlugin::ClientProxy
-    QTC_ASSERT(m_conn == 0, /**/);
-    m_conn = new QDeclarativeDebugConnection(this);
+    if (d->m_hasShutdown)
+        return;
+
+    disconnect(d->m_adapter, SIGNAL(connectionStartupFailed()), this, SLOT(connectionStartupFailed()));
+    d->m_adapter->closeConnection();
 
-    connect(m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
-            SLOT(connectionStateChanged()));
-    connect(m_conn, SIGNAL(error(QAbstractSocket::SocketError)),
-            SLOT(connectionError()));
-    connect(m_conn, SIGNAL(connected()),
-            SLOT(connectionConnected()));
+    if (d->m_addedAdapterToObjectPool) {
+        ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance();
+        pluginManager->removeObject(d->m_adapter);
+        pluginManager->removeObject(this);
+    }
 
-    QTC_ASSERT(m_client == 0, /**/);
-    m_client = new QmlDebuggerClient(m_conn, this);
-    (void) new QmlFrameRateClient(m_conn, this);
+    if (d->m_attachToRunningExternalApp) {
+        setState(EngineShutdownRequested, true);
+        setState(EngineShutdownOk, true);
+        setState(DebuggerFinished, true);
+    } else {
+        if (d->m_applicationLauncher.isRunning()) {
+            // should only happen if engine is ill
+            disconnect(&d->m_applicationLauncher, SIGNAL(processExited(int)), this, SLOT(disconnected()));
+            d->m_applicationLauncher.stop();
+        }
+    }
+    d->m_hasShutdown = true;
+}
 
+void QmlEngine::shutdownInferior()
+{
+    // don't do normal shutdown if running as slave engine
+    if (d->m_attachToRunningExternalApp)
+        return;
 
-    QTC_ASSERT(m_engineDebugInterface == 0, /**/);
-    m_engineDebugInterface = new QDeclarativeEngineDebug(m_conn, this);
+    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
+    if (!d->m_applicationLauncher.isRunning()) {
+        showMessage(tr("Trying to stop while process is no longer running."), LogError);
+    } else {
+        disconnect(&d->m_applicationLauncher, SIGNAL(processExited(int)), this, SLOT(disconnected()));
+        if (!d->m_attachToRunningExternalApp)
+            d->m_applicationLauncher.stop();
+    }
+    notifyInferiorShutdownOk();
+}
 
-    //m_objectTreeWidget->setEngineDebug(m_engineDebugInterface);
-    //m_propertiesWidget->setEngineDebug(m_engineDebugInterface);
-    //m_watchTableModel->setEngineDebug(m_engineDebugInterface);
-    //m_expressionWidget->setEngineDebug(m_engineDebugInterface);
-    //resetViews();
-    //m_frameRateWidget->reset(m_conn);
+void QmlEngine::shutdownEngine()
+{
+    QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
 
-    QHostAddress ha(QHostAddress::LocalHost);
+    shutdownEngineAsSlave();
 
-    qDebug() << "CONNECTING TO " << ha.toString() << serverPort;
-    m_conn->connectToHost(ha, serverPort);
+    notifyEngineShutdownOk();
+    plugin()->showMessage(QString(), StatusBar);
+}
 
-    if (!m_conn->waitForConnected()) {
-        qDebug() << "CONNECTION FAILED";
-        notifyEngineSetupFailed();
-        return;
+void QmlEngine::setupEngine()
+{
+    if (!d->m_attachToRunningExternalApp
+     && !startParameters().qmlObserverAvailable
+     && Internal::theDebuggerBoolSetting(Internal::UseQmlObserver))
+    {
+        showQmlObserverToolWarning();
     }
- #endif
 
-    notifyEngineRunAndInferiorStopOk();
+    d->m_adapter->setMaxConnectionAttempts(MaxConnectionAttempts);
+    d->m_adapter->setConnectionAttemptInterval(ConnectionAttemptDefaultInterval);
+    connect(d->m_adapter, SIGNAL(connectionError(QAbstractSocket::SocketError)),
+            SLOT(connectionError(QAbstractSocket::SocketError)));
+    connect(d->m_adapter, SIGNAL(serviceConnectionError(QString)), SLOT(serviceConnectionError(QString)));
+    connect(d->m_adapter, SIGNAL(connected()), SLOT(connectionEstablished()));
+    connect(d->m_adapter, SIGNAL(connectionStartupFailed()), SLOT(connectionStartupFailed()));
 
-//    reloadEngines();
-//    continueInferior();
+    notifyEngineSetupOk();
 }
 
 void QmlEngine::continueInferior()
 {
     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
-    SDEBUG("QmlEngine::continueInferior()");
     QByteArray reply;
     QDataStream rs(&reply, QIODevice::WriteOnly);
     rs << QByteArray("CONTINUE");
@@ -355,11 +358,11 @@ void QmlEngine::interruptInferior()
     QDataStream rs(&reply, QIODevice::WriteOnly);
     rs << QByteArray("INTERRUPT");
     sendMessage(reply);
+    notifyInferiorStopOk();
 }
 
 void QmlEngine::executeStep()
 {
-    SDEBUG("QmlEngine::executeStep()");
     QByteArray reply;
     QDataStream rs(&reply, QIODevice::WriteOnly);
     rs << QByteArray("STEPINTO");
@@ -370,7 +373,6 @@ void QmlEngine::executeStep()
 
 void QmlEngine::executeStepI()
 {
-    SDEBUG("QmlEngine::executeStepI()");
     QByteArray reply;
     QDataStream rs(&reply, QIODevice::WriteOnly);
     rs << QByteArray("STEPINTO");
@@ -381,7 +383,6 @@ void QmlEngine::executeStepI()
 
 void QmlEngine::executeStepOut()
 {
-    SDEBUG("QmlEngine::executeStepOut()");
     QByteArray reply;
     QDataStream rs(&reply, QIODevice::WriteOnly);
     rs << QByteArray("STEPOUT");
@@ -398,7 +399,6 @@ void QmlEngine::executeNext()
     sendMessage(reply);
     notifyInferiorRunRequested();
     notifyInferiorRunOk();
-    SDEBUG("QmlEngine::nextExec()");
 }
 
 void QmlEngine::executeNextI()
@@ -446,12 +446,15 @@ void QmlEngine::selectThread(int index)
 
 void QmlEngine::attemptBreakpointSynchronization()
 {
-    BreakHandler *handler = breakHandler();
+    Internal::BreakHandler *handler = breakHandler();
     //bool updateNeeded = false;
     QSet< QPair<QString, qint32> > breakList;
     for (int index = 0; index != handler->size(); ++index) {
-        BreakpointData *data = handler->at(index);
-        breakList << qMakePair(data->fileName, data->lineNumber.toInt());
+        Internal::BreakpointData *data = handler->at(index);
+        QString processedFilename = data->fileName;
+        if (isShadowBuildProject())
+            processedFilename = toShadowBuildFilename(data->fileName);
+        breakList << qMakePair(processedFilename, data->lineNumber);
     }
 
     {
@@ -464,6 +467,11 @@ void QmlEngine::attemptBreakpointSynchronization()
     }
 }
 
+bool QmlEngine::acceptsBreakpoint(const Internal::BreakpointData *br)
+{
+    return (br->fileName.endsWith(QLatin1String("qml")) || br->fileName.endsWith(QLatin1String("js")));
+}
+
 void QmlEngine::loadSymbols(const QString &moduleName)
 {
     Q_UNUSED(moduleName)
@@ -482,30 +490,16 @@ void QmlEngine::requestModuleSymbols(const QString &moduleName)
     Q_UNUSED(moduleName)
 }
 
-#if 0 //this is currently a signal connected to the QmlJSInspector::Internal::DebuggerClient
-void QmlEngine::sendMessage(const QByteArray &msg)
-{
-    QTC_ASSERT(m_client, return);
-    m_client->sendMessage(msg);
-}
-#endif
-
-
 //////////////////////////////////////////////////////////////////////
 //
 // Tooltip specific stuff
 //
 //////////////////////////////////////////////////////////////////////
 
-static WatchData m_toolTip;
-static QPoint m_toolTipPos;
-static QHash<QString, WatchData> m_toolTipCache;
-
 void QmlEngine::setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos)
 {
-    Q_UNUSED(mousePos)
-    Q_UNUSED(editor)
-    Q_UNUSED(cursorPos)
+    // this is processed by QML inspector, which has deps to qml js editor. Makes life easier.
+    emit tooltipRequested(mousePos, editor, cursorPos);
 }
 
 //////////////////////////////////////////////////////////////////////
@@ -514,13 +508,25 @@ void QmlEngine::setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEd
 //
 //////////////////////////////////////////////////////////////////////
 
-void QmlEngine::assignValueInDebugger(const QString &expression,
-    const QString &value)
-{
-    XSDEBUG("ASSIGNING: " << expression + '=' + value);
+void QmlEngine::assignValueInDebugger(const Internal::WatchData *,
+                                      const QString &expression, const QVariant &valueV)
+{
+    QRegExp inObject("@([0-9a-fA-F]+)->(.+)");
+    if (inObject.exactMatch(expression)) {
+        bool ok = false;
+        quint64 objectId = inObject.cap(1).toULongLong(&ok, 16);
+        QString property = inObject.cap(2);
+        if (ok && objectId > 0 && !property.isEmpty()) {
+            QByteArray reply;
+            QDataStream rs(&reply, QIODevice::WriteOnly);
+            rs << QByteArray("SET_PROPERTY");
+            rs << expression.toUtf8() << objectId << property << valueV.toString();
+            sendMessage(reply);
+        }
+    }
 }
 
-void QmlEngine::updateWatchData(const WatchData &data)
+void QmlEngine::updateWatchData(const Internal::WatchData &data, const Internal::WatchUpdateFlags &)
 {
 //    qDebug() << "UPDATE WATCH DATA" << data.toString();
     //watchHandler()->rebuildModel();
@@ -534,9 +540,9 @@ void QmlEngine::updateWatchData(const WatchData &data)
         sendMessage(reply);
     }
 
-    if (!data.name.isEmpty() && data.isChildrenNeeded() && watchHandler()->isExpandedIName(data.iname)) {
+    if (!data.name.isEmpty() && data.isChildrenNeeded()
+            && watchHandler()->isExpandedIName(data.iname))
         expandObject(data.iname, data.objectId);
-    }
 
     {
         QByteArray reply;
@@ -545,6 +551,9 @@ void QmlEngine::updateWatchData(const WatchData &data)
         rs << watchHandler()->watchedExpressions();
         sendMessage(reply);
     }
+
+    if (!data.isSomethingNeeded())
+        watchHandler()->insertData(data);
 }
 
 void QmlEngine::expandObject(const QByteArray& iname, quint64 objectId)
@@ -556,11 +565,22 @@ void QmlEngine::expandObject(const QByteArray& iname, quint64 objectId)
     sendMessage(reply);
 }
 
+void QmlEngine::sendPing()
+{
+    d->m_ping++;
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    rs << QByteArray("PING");
+    rs << d->m_ping;
+    sendMessage(reply);
+}
 
+namespace Internal {
 DebuggerEngine *createQmlEngine(const DebuggerStartParameters &sp)
 {
     return new QmlEngine(sp);
 }
+} // namespace Internal
 
 unsigned QmlEngine::debuggerCapabilities() const
 {
@@ -584,19 +604,21 @@ void QmlEngine::messageReceived(const QByteArray &message)
     QByteArray command;
     stream >> command;
 
-    showMessage(_("RECEIVED RESPONSE: ") + quoteUnprintableLatin1(message));
+    showMessage(QLatin1String("RECEIVED RESPONSE: ") + Internal::quoteUnprintableLatin1(message));
     if (command == "STOPPED") {
-        notifyInferiorSpontaneousStop();
+        if (state() == InferiorRunOk) {
+            notifyInferiorSpontaneousStop();
+        }
 
         QList<QPair<QString, QPair<QString, qint32> > > backtrace;
-        QList<WatchData> watches;
-        QList<WatchData> locals;
+        QList<Internal::WatchData> watches;
+        QList<Internal::WatchData> locals;
         stream >> backtrace >> watches >> locals;
 
-        StackFrames stackFrames;
+        Internal::StackFrames stackFrames;
         typedef QPair<QString, QPair<QString, qint32> > Iterator;
         foreach (const Iterator &it, backtrace) {
-            StackFrame frame;
+            Internal::StackFrame frame;
             frame.file = it.second.first;
             frame.line = it.second.second;
             frame.function = it.first;
@@ -607,1005 +629,211 @@ void QmlEngine::messageReceived(const QByteArray &message)
         stackHandler()->setFrames(stackFrames);
 
         watchHandler()->beginCycle();
+        bool needPing = false;
 
-        foreach (WatchData data, watches) {
+        foreach (Internal::WatchData data, watches) {
             data.iname = watchHandler()->watcherName(data.exp);
             watchHandler()->insertData(data);
 
-            if (watchHandler()->expandedINames().contains(data.iname))
+            if (watchHandler()->expandedINames().contains(data.iname)) {
+                needPing = true;
                 expandObject(data.iname, data.objectId);
+            }
         }
 
-        foreach (WatchData data, locals) {
+        foreach (Internal::WatchData data, locals) {
             data.iname = "local." + data.exp;
             watchHandler()->insertData(data);
 
-            if (watchHandler()->expandedINames().contains(data.iname))
+            if (watchHandler()->expandedINames().contains(data.iname)) {
+                needPing = true;
                 expandObject(data.iname, data.objectId);
+            }
         }
 
-        watchHandler()->endCycle();
+        if (needPing)
+            sendPing();
+        else
+            watchHandler()->endCycle();
+
+        bool becauseOfException;
+        stream >> becauseOfException;
+        if (becauseOfException) {
+            QString error;
+            stream >> error;
+
+            QString msg =
+                tr("<p>An Uncaught Exception occured in <i>%1</i>:</p><p>%2</p>")
+                    .arg(stackFrames.value(0).file, Qt::escape(error));
+            showMessageBox(QMessageBox::Information, tr("Uncaught Exception"), msg);
+        } else {
+            //
+            // Make breakpoint non-pending
+            //
+            QString file;
+            int line = -1;
+
+            if (!stackFrames.isEmpty()) {
+                file = stackFrames.at(0).file;
+                line = stackFrames.at(0).line;
+
+                if (isShadowBuildProject()) {
+                    file = fromShadowBuildFilename(file);
+                }
+            }
+
+            Internal::BreakHandler *handler = breakHandler();
+            for (int index = 0; index != handler->size(); ++index) {
+                Internal::BreakpointData *data = handler->at(index);
+                QString processedFilename = data->fileName;
 
+                if (processedFilename == file
+                        && data->lineNumber == line) {
+                    data->pending = false;
+                    data->updateMarker();
+                }
+            }
+        }
     } else if (command == "RESULT") {
-        WatchData data;
+        Internal::WatchData data;
         QByteArray iname;
         stream >> iname >> data;
         data.iname = iname;
-        watchHandler()->insertData(data);
-
+        if (iname.startsWith("watch.")) {
+            watchHandler()->insertData(data);
+        } else if(iname == "console") {
+            plugin()->showMessage(data.value, ScriptConsoleOutput);
+        } else {
+            qWarning() << "QmlEngine: Unexcpected result: " << iname << data.value;
+        }
     } else if (command == "EXPANDED") {
-        QList<WatchData> result;
+        QList<Internal::WatchData> result;
         QByteArray iname;
         stream >> iname >> result;
-        foreach (WatchData data, result) {
+        bool needPing = false;
+        foreach (Internal::WatchData data, result) {
             data.iname = iname + '.' + data.exp;
             watchHandler()->insertData(data);
 
-            if (watchHandler()->expandedINames().contains(data.iname)) 
+            if (watchHandler()->expandedINames().contains(data.iname)) {
+                needPing = true;
                 expandObject(data.iname, data.objectId);
+            }
         }
+        if (needPing)
+            sendPing();
     } else if (command == "LOCALS") {
-        QList<WatchData> locals;
+        QList<Internal::WatchData> locals;
         int frameId;
         stream >> frameId >> locals;
         watchHandler()->beginCycle();
-        foreach (WatchData data, locals) {
+        bool needPing = false;
+        foreach (Internal::WatchData data, locals) {
             data.iname = "local." + data.exp;
             watchHandler()->insertData(data);
-            if (watchHandler()->expandedINames().contains(data.iname))
+            if (watchHandler()->expandedINames().contains(data.iname)) {
+                needPing = true;
                 expandObject(data.iname, data.objectId);
+            }
         }
-        watchHandler()->endCycle();
+        if (needPing)
+            sendPing();
+        else
+            watchHandler()->endCycle();
+
+    } else if (command == "PONG") {
+        int ping;
+        stream >> ping;
+        if (ping == d->m_ping)
+            watchHandler()->endCycle();
     } else {
         qDebug() << Q_FUNC_INFO << "Unknown command: " << command;
     }
 
 }
 
-
-#if 0
-class EngineComboBox : public QComboBox
-{
-    Q_OBJECT
-public:
-    struct EngineInfo
-    {
-        QString name;
-        int id;
-    };
-
-    EngineComboBox(QWidget *parent = 0);
-
-    void addEngine(int engine, const QString &name);
-    void clearEngines();
-
-protected:
-
-private:
-    QList<EngineInfo> m_engines;
-};
-
-EngineComboBox::EngineComboBox(QWidget *parent)
-    : QComboBox(parent)
-{
-    setEnabled(false);
-    setEditable(false);
-}
-
-void EngineComboBox::addEngine(int engine, const QString &name)
+void QmlEngine::disconnected()
 {
-    EngineInfo info;
-    info.id = engine;
-    if (name.isEmpty())
-        info.name = tr("Engine %1", "engine number").arg(engine);
-    else
-        info.name = name;
-    m_engines << info;
-
-    addItem(info.name);
+    plugin()->showMessage(tr("QML Debugger disconnected."), StatusBar);
+    notifyInferiorExited();
 }
 
-void EngineComboBox::clearEngines()
+void QmlEngine::executeDebuggerCommand(const QString& command)
 {
-    m_engines.clear();
-    clear();
-}
-
-
-bool QmlEngine::setDebugConfigurationDataFromProject(ProjectExplorer::Project *projectToDebug)
-{
-    if (!projectToDebug) {
-        emit statusMessage(tr("Invalid project, debugging canceled."));
-        return false;
-    }
-
-    QmlProjectManager::QmlProjectRunConfiguration* config =
-            qobject_cast<QmlProjectManager::QmlProjectRunConfiguration*>(projectToDebug->activeTarget()->activeRunConfiguration());
-    if (!config) {
-        emit statusMessage(tr("Cannot find project run configuration, debugging canceled."));
-        return false;
-    }
-    m_runConfigurationDebugData.serverAddress = config->debugServerAddress();
-    m_runConfigurationDebugData.serverPort = config->debugServerPort();
-    m_connectionTimer->setInterval(ConnectionAttemptDefaultInterval);
-
-    return true;
-}
-
-void QmlEngine::startQmlProjectDebugger()
-{
-    m_simultaneousCppAndQmlDebugMode = false;
-    m_connectionTimer->start();
-}
-
-bool QmlEngine::connectToViewer()
-{
-    if (m_conn && m_conn->state() != QAbstractSocket::UnconnectedState)
-        return false;
-
-    delete m_engineDebugInterface; m_engineDebugInterface = 0;
-
-    if (m_conn) {
-        m_conn->disconnectFromHost();
-        delete m_conn;
-        m_conn = 0;
-    }
-
-    QString host = m_runConfigurationDebugData.serverAddress;
-    quint16 port = quint16(m_runConfigurationDebugData.serverPort);
-
-    m_conn = new QDeclarativeDebugConnection(this);
-    connect(m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
-            SLOT(connectionStateChanged()));
-    connect(m_conn, SIGNAL(error(QAbstractSocket::SocketError)),
-            SLOT(connectionError()));
-
-    emit statusMessage(tr("[Inspector] set to connect to debug server %1:%2").arg(host).arg(port));
-    m_conn->connectToHost(host, port);
-    // blocks until connected; if no connection is available, will fail immediately
-
-    if (!m_conn->waitForConnected())
-        return false;
-
-    QTC_ASSERT(m_debuggerRunControl, return false);
-    QmlEngine *engine = qobject_cast<QmlEngine *>(m_debuggerRunControl->engine());
-    QTC_ASSERT(engine, return false);
-
-    (void) new DebuggerClient(m_conn, engine);
-
-    return true;
-}
-
-void QmlEngine::disconnectFromViewer()
-{
-    m_conn->disconnectFromHost();
-    updateMenuActions();
-}
-
-void QmlEngine::connectionStateChanged()
-{
-    switch (m_conn->state()) {
-        case QAbstractSocket::UnconnectedState:
-        {
-            emit statusMessage(tr("[Inspector] disconnected.\n\n"));
-            resetViews();
-            updateMenuActions();
-            break;
-        }
-        case QAbstractSocket::HostLookupState:
-            emit statusMessage(tr("[Inspector] resolving host..."));
-            break;
-        case QAbstractSocket::ConnectingState:
-            emit statusMessage(tr("[Inspector] connecting to debug server..."));
-            break;
-        case QAbstractSocket::ConnectedState:
-        {
-            emit statusMessage(tr("[Inspector] connected.\n"));
-
-            resetViews();
-//            m_frameRateWidget->reset(m_conn);
-
-            break;
-        }
-        case QAbstractSocket::ClosingState:
-            emit statusMessage(tr("[Inspector] closing..."));
-            break;
-        case QAbstractSocket::BoundState:
-        case QAbstractSocket::ListeningState:
-            break;
-    }
-}
-
-void QmlEngine::resetViews()
-{
-    m_objectTreeWidget->cleanup();
-    m_propertiesWidget->clear();
-    m_expressionWidget->clear();
-    m_watchTableModel->removeAllWatches();
-}
-
-void QmlEngine::createDockWidgets()
-{
-
-    m_engineComboBox = new Internal::EngineComboBox;
-    m_engineComboBox->setEnabled(false);
-    connect(m_engineComboBox, SIGNAL(currentIndexChanged(int)),
-            SLOT(queryEngineContext(int)));
-
-    // FancyMainWindow uses widgets' window titles for tab labels
-//    m_frameRateWidget->setWindowTitle(tr("Frame rate"));
-
-    Utils::StyledBar *treeOptionBar = new Utils::StyledBar;
-    QHBoxLayout *treeOptionBarLayout = new QHBoxLayout(treeOptionBar);
-    treeOptionBarLayout->setContentsMargins(5, 0, 5, 0);
-    treeOptionBarLayout->setSpacing(5);
-    treeOptionBarLayout->addWidget(new QLabel(tr("QML engine:")));
-    treeOptionBarLayout->addWidget(m_engineComboBox);
-
-    QWidget *treeWindow = new QWidget;
-    treeWindow->setObjectName(QLatin1String("QmlDebugTree"));
-    treeWindow->setWindowTitle(tr("Object Tree"));
-    QVBoxLayout *treeWindowLayout = new QVBoxLayout(treeWindow);
-    treeWindowLayout->setMargin(0);
-    treeWindowLayout->setSpacing(0);
-    treeWindowLayout->setContentsMargins(0,0,0,0);
-    treeWindowLayout->addWidget(treeOptionBar);
-    treeWindowLayout->addWidget(m_objectTreeWidget);
-
-
-    m_watchTableView->setModel(m_watchTableModel);
-    Internal::WatchTableHeaderView *header = new Internal::WatchTableHeaderView(m_watchTableModel);
-    m_watchTableView->setHorizontalHeader(header);
-
-    connect(m_objectTreeWidget, SIGNAL(activated(QDeclarativeDebugObjectReference)),
-            this, SLOT(treeObjectActivated(QDeclarativeDebugObjectReference)));
-
-    connect(m_objectTreeWidget, SIGNAL(currentObjectChanged(QDeclarativeDebugObjectReference)),
-            m_propertiesWidget, SLOT(reload(QDeclarativeDebugObjectReference)));
-
-    connect(m_objectTreeWidget, SIGNAL(expressionWatchRequested(QDeclarativeDebugObjectReference,QString)),
-            m_watchTableModel, SLOT(expressionWatchRequested(QDeclarativeDebugObjectReference,QString)));
-
-    connect(m_propertiesWidget, SIGNAL(watchToggleRequested(QDeclarativeDebugObjectReference,QDeclarativeDebugPropertyReference)),
-            m_watchTableModel, SLOT(togglePropertyWatch(QDeclarativeDebugObjectReference,QDeclarativeDebugPropertyReference)));
-
-    connect(m_watchTableModel, SIGNAL(watchCreated(QDeclarativeDebugWatch*)),
-            m_propertiesWidget, SLOT(watchCreated(QDeclarativeDebugWatch*)));
-
-    connect(m_watchTableModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
-            m_watchTableView, SLOT(scrollToBottom()));
-
-    connect(m_watchTableView, SIGNAL(objectActivated(int)),
-            m_objectTreeWidget, SLOT(setCurrentObject(int)));
-
-    connect(m_objectTreeWidget, SIGNAL(currentObjectChanged(QDeclarativeDebugObjectReference)),
-            m_expressionWidget, SLOT(setCurrentObject(QDeclarativeDebugObjectReference)));
-
-
-    Core::MiniSplitter *propSplitter = new Core::MiniSplitter(Qt::Horizontal);
-    Core::MiniSplitter *propWatcherSplitter = new Core::MiniSplitter(Qt::Vertical);
-    propWatcherSplitter->addWidget(m_propertiesWidget);
-    propWatcherSplitter->addWidget(m_watchTableView);
-    propWatcherSplitter->setStretchFactor(0, 2);
-    propWatcherSplitter->setStretchFactor(1, 1);
-    propWatcherSplitter->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
-
-    propSplitter->setWindowTitle(tr("Properties and Watchers"));
-    propSplitter->setObjectName(QLatin1String("QmlDebugProperties"));
-    propSplitter->addWidget(m_objectTreeWidget);
-    propSplitter->addWidget(propWatcherSplitter);
-    propSplitter->setStretchFactor(0, 1);
-    propSplitter->setStretchFactor(1, 3);
-
-    InspectorOutputWidget *inspectorOutput = new InspectorOutputWidget();
-    inspectorOutput->setObjectName(QLatin1String("QmlDebugInspectorOutput"));
-    connect(this, SIGNAL(statusMessage(QString)),
-            inspectorOutput, SLOT(addInspectorStatus(QString)));
-
-    Debugger::DebuggerUISwitcher *uiSwitcher = Debugger::DebuggerUISwitcher::instance();
-
-    m_watchTableView->hide();
-//    m_objectTreeDock = uiSwitcher->createDockWidget(Qml::Constants::LANG_QML,
-//                                                            treeWindow, Qt::BottomDockWidgetArea);
-//    m_frameRateDock = uiSwitcher->createDockWidget(Qml::Constants::LANG_QML,
-//                                                            m_frameRateWidget, Qt::BottomDockWidgetArea);
-    m_propertyWatcherDock = uiSwitcher->createDockWidget(Qml::Constants::LANG_QML,
-                                                            propSplitter, Qt::BottomDockWidgetArea);
-    m_inspectorOutputDock = uiSwitcher->createDockWidget(Qml::Constants::LANG_QML,
-                                                            inspectorOutput, Qt::BottomDockWidgetArea);
-
-    m_expressionWidget->setWindowTitle(tr("Script Console"));
-    m_expressionQueryDock = uiSwitcher->createDockWidget(Qml::Constants::LANG_QML,
-                                                         m_expressionWidget, Qt::BottomDockWidgetArea);
-
-    m_inspectorOutputDock->setToolTip(tr("Output of the QML inspector, such as information on connecting to the server."));
-
-    m_dockWidgets << /*m_objectTreeDock << *//*m_frameRateDock << */ m_propertyWatcherDock
-                  << m_inspectorOutputDock << m_expressionQueryDock;
-
-    m_context = new Internal::InspectorContext(m_objectTreeWidget);
-    m_propWatcherContext = new Internal::InspectorContext(m_propertyWatcherDock);
-
-    Core::ICore *core = Core::ICore::instance();
-    core->addContextObject(m_propWatcherContext);
-    core->addContextObject(m_context);
-
-    m_simultaneousDebugAction = new QAction(this);
-    m_simultaneousDebugAction->setText(tr("Start Debugging C++ and QML Simultaneously..."));
-    connect(m_simultaneousDebugAction, SIGNAL(triggered()),
-        this, SLOT(simultaneouslyDebugQmlCppApplication()));
-
-    Core::ActionManager *am = core->actionManager();
-    Core::ActionContainer *mstart = am->actionContainer(ProjectExplorer::Constants::M_DEBUG_STARTDEBUGGING);
-    Core::Command *cmd = am->registerAction(m_simultaneousDebugAction, Constants::M_DEBUG_SIMULTANEOUSLY,
-                                            m_context->context());
-    cmd->setAttribute(Core::Command::CA_Hide);
-    mstart->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
-
-    m_settings.readSettings(core->settings());
-    m_objectTreeWidget->readSettings(m_settings);
-    m_propertiesWidget->readSettings(m_settings);
-
-    connect(m_objectTreeWidget, SIGNAL(contextHelpIdChanged(QString)), m_context,
-            SLOT(setContextHelpId(QString)));
-    connect(m_watchTableView, SIGNAL(contextHelpIdChanged(QString)), m_propWatcherContext,
-            SLOT(setContextHelpId(QString)));
-    connect(m_propertiesWidget, SIGNAL(contextHelpIdChanged(QString)), m_propWatcherContext,
-            SLOT(setContextHelpId(QString)));
-    connect(m_expressionWidget, SIGNAL(contextHelpIdChanged(QString)), m_propWatcherContext,
-            SLOT(setContextHelpId(QString)));
-}
-
-void QmlEngine::simultaneouslyDebugQmlCppApplication()
-{
-    QString errorMessage;
-    ProjectExplorer::ProjectExplorerPlugin *pex = ProjectExplorer::ProjectExplorerPlugin::instance();
-    ProjectExplorer::Project *project = pex->startupProject();
-
-    if (!project)
-         errorMessage = QString(tr("No project was found."));
-    else {
-        if (project->id() == "QmlProjectManager.QmlProject")
-            errorMessage = attachToQmlViewerAsExternalApp(project);
-        else {
-            errorMessage = attachToExternalCppAppWithQml(project);
-        }
-    }
-
-    if (!errorMessage.isEmpty())
-        QMessageBox::warning(Core::ICore::instance()->mainWindow(), "Failed to debug C++ and QML", errorMessage);
-}
-
-QString QmlEngine::attachToQmlViewerAsExternalApp(ProjectExplorer::Project *project)
-{
-    m_debugMode = QmlProjectWithCppPlugins;
-
-    QmlProjectManager::QmlProjectRunConfiguration* runConfig =
-                qobject_cast<QmlProjectManager::QmlProjectRunConfiguration*>(project->activeTarget()->activeRunConfiguration());
-
-    if (!runConfig)
-        return QString(tr("No run configurations were found for the project '%1'.").arg(project->displayName()));
-
-    Internal::StartExternalQmlDialog dlg(Debugger::DebuggerUISwitcher::instance()->mainWindow());
-
-    QString importPathArgument = "-I";
-    QString execArgs;
-    if (runConfig->viewerArguments().contains(importPathArgument))
-        execArgs = runConfig->viewerArguments().join(" ");
-    else {
-        QFileInfo qmlFileInfo(runConfig->viewerArguments().last());
-        importPathArgument.append(" " + qmlFileInfo.absolutePath() + " ");
-        execArgs = importPathArgument + runConfig->viewerArguments().join(" ");
-    }
-
-
-    dlg.setPort(runConfig->debugServerPort());
-    dlg.setDebuggerUrl(runConfig->debugServerAddress());
-    dlg.setProjectDisplayName(project->displayName());
-    dlg.setDebugMode(Internal::StartExternalQmlDialog::QmlProjectWithCppPlugins);
-    dlg.setQmlViewerArguments(execArgs);
-    dlg.setQmlViewerPath(runConfig->viewerPath());
-
-    if (dlg.exec() != QDialog::Accepted)
-        return QString();
-
-    m_runConfigurationDebugData.serverAddress = dlg.debuggerUrl();
-    m_runConfigurationDebugData.serverPort = dlg.port();
-    m_settings.setExternalPort(dlg.port());
-    m_settings.setExternalUrl(dlg.debuggerUrl());
-
-    ProjectExplorer::Environment customEnv = ProjectExplorer::Environment::systemEnvironment(); // empty env by default
-    customEnv.set(QmlProjectManager::Constants::E_QML_DEBUG_SERVER_PORT, QString::number(m_settings.externalPort()));
-
-    Debugger::DebuggerRunControl *debuggableRunControl =
-     createDebuggerRunControl(runConfig, dlg.qmlViewerPath(), dlg.qmlViewerArguments());
-
-    return executeDebuggerRunControl(debuggableRunControl, &customEnv);
-}
-
-QString QmlEngine::attachToExternalCppAppWithQml(ProjectExplorer::Project *project)
-{
-    m_debugMode = CppProjectWithQmlEngines;
-
-    ProjectExplorer::LocalApplicationRunConfiguration* runConfig =
-                qobject_cast<ProjectExplorer::LocalApplicationRunConfiguration*>(project->activeTarget()->activeRunConfiguration());
-
-    if (!project->activeTarget() || !project->activeTarget()->activeRunConfiguration())
-        return QString(tr("No run configurations were found for the project '%1'.").arg(project->displayName()));
-    else if (!runConfig)
-        return QString(tr("No valid run configuration was found for the project %1. "
-                                  "Only locally runnable configurations are supported.\n"
-                                  "Please check your project settings.").arg(project->displayName()));
-
-    Internal::StartExternalQmlDialog dlg(Debugger::DebuggerUISwitcher::instance()->mainWindow());
-
-    dlg.setPort(m_settings.externalPort());
-    dlg.setDebuggerUrl(m_settings.externalUrl());
-    dlg.setProjectDisplayName(project->displayName());
-    dlg.setDebugMode(Internal::StartExternalQmlDialog::CppProjectWithQmlEngine);
-    if (dlg.exec() != QDialog::Accepted)
-        return QString();
-
-    m_runConfigurationDebugData.serverAddress = dlg.debuggerUrl();
-    m_runConfigurationDebugData.serverPort = dlg.port();
-    m_settings.setExternalPort(dlg.port());
-    m_settings.setExternalUrl(dlg.debuggerUrl());
-
-    ProjectExplorer::Environment customEnv = runConfig->environment();
-    customEnv.set(QmlProjectManager::Constants::E_QML_DEBUG_SERVER_PORT, QString::number(m_settings.externalPort()));
-    Debugger::DebuggerRunControl *debuggableRunControl = createDebuggerRunControl(runConfig);
-    return executeDebuggerRunControl(debuggableRunControl, &customEnv);
-}
-
-QString QmlEngine::executeDebuggerRunControl(Debugger::DebuggerRunControl *debuggableRunControl, ProjectExplorer::Environment *environment)
-{
-    ProjectExplorer::ProjectExplorerPlugin *pex = ProjectExplorer::ProjectExplorerPlugin::instance();
-
-    // to make sure we have a valid, debuggable run control, find the correct factory for it
-    if (debuggableRunControl) {
-
-        // modify the env
-        debuggableRunControl->setCustomEnvironment(*environment);
-
-        pex->startRunControl(debuggableRunControl, ProjectExplorer::Constants::DEBUGMODE);
-        m_simultaneousCppAndQmlDebugMode = true;
-
-        return QString();
-    }
-    return QString(tr("A valid run control was not registered in Qt Creator for this project run configuration."));;
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    rs << QByteArray("EXEC");
+    rs << QByteArray("console") << command;
+    sendMessage(reply);
 }
 
-Debugger::DebuggerRunControl *QmlEngine::createDebuggerRunControl(ProjectExplorer::RunConfiguration *runConfig,
-                                                                     const QString &executableFile, const QString &executableArguments)
+bool QmlEngine::isShadowBuildProject() const
 {
-    ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
-    const QList<Debugger::DebuggerRunControlFactory *> factories = pm->getObjects<Debugger::DebuggerRunControlFactory>();
-    ProjectExplorer::RunControl *runControl = 0;
-
-    if (m_debugMode == QmlProjectWithCppPlugins) {
-        Debugger::DebuggerStartParameters sp;
-        sp.startMode = Debugger::StartExternal;
-        sp.executable = executableFile;
-        sp.processArgs = executableArguments.split(QLatin1Char(' '));
-        runControl = factories.first()->create(sp);
-        return qobject_cast<Debugger::DebuggerRunControl *>(runControl);
-    }
-
-    if (m_debugMode == CppProjectWithQmlEngines) {
-        if (factories.length() && factories.first()->canRun(runConfig, ProjectExplorer::Constants::DEBUGMODE)) {
-            runControl = factories.first()->create(runConfig, ProjectExplorer::Constants::DEBUGMODE);
-            return qobject_cast<Debugger::DebuggerRunControl *>(runControl);
-        }
+    if (!startParameters().projectBuildDir.isEmpty()
+        && (startParameters().projectDir != startParameters().projectBuildDir))
+    {
+        return true;
     }
-
-    return 0;
-}
-
-void QmlEngine::updateMenuActions()
-{
-
-    bool enabled = true;
-    if (m_simultaneousCppAndQmlDebugMode)
-        enabled = (m_cppDebuggerState == Debugger::DebuggerNotReady && (!m_conn || m_conn->state() == QAbstractSocket::UnconnectedState));
-    else
-        enabled = (!m_conn || m_conn->state() == QAbstractSocket::UnconnectedState);
-
-    m_simultaneousDebugAction->setEnabled(enabled);
+    return false;
 }
 
-
-void QmlEngine::debuggerStateChanged(int newState)
+QString QmlEngine::qmlImportPath() const
 {
-    if (m_simultaneousCppAndQmlDebugMode) {
-
-        switch(newState) {
-        case Debugger::EngineSetupRequested:
-            {
-                m_connectionInitialized = false;
-                break;
-            }
-        case Debugger::AdapterStartFailed:
-        case Debugger::InferiorSetupFailed:
-            emit statusMessage(QString(tr("Debugging failed: could not start C++ debugger.")));
-            break;
-        case Debugger::InferiorRunRequested:
-            {
-                if (m_cppDebuggerState == Debugger::InferiorStopOk) {
-                    // re-enable UI again
-                    m_objectTreeWidget->setEnabled(true);
-                    m_propertiesWidget->setEnabled(true);
-                    m_expressionWidget->setEnabled(true);
-                }
-                break;
-            }
-        case Debugger::InferiorRunOk:
-            {
-                if (!m_connectionInitialized) {
-                    m_connectionInitialized = true;
-                    m_connectionTimer->setInterval(ConnectionAttemptSimultaneousInterval);
-                    m_connectionTimer->start();
-                }
-                break;
-            }
-        case Debugger::InferiorStopOk:
-            {
-                m_objectTreeWidget->setEnabled(false);
-                m_propertiesWidget->setEnabled(false);
-                m_expressionWidget->setEnabled(false);
-                break;
-            }
-        case Debugger::EngineShutdownRequested:
-            {
-                m_connectionInitialized = false;
-                // here it's safe to enable the debugger windows again -
-                // disabled ones look ugly.
-                m_objectTreeWidget->setEnabled(true);
-                m_propertiesWidget->setEnabled(true);
-                m_expressionWidget->setEnabled(true);
-                m_simultaneousCppAndQmlDebugMode = false;
-                break;
-            }
-        default:
+    QString result;
+    const QString qmlImportPathPrefix("QML_IMPORT_PATH=");
+    QStringList env = startParameters().environment;
+    foreach(const QString &envStr, env) {
+        if (envStr.startsWith(qmlImportPathPrefix)) {
+            result = envStr.mid(qmlImportPathPrefix.length());
             break;
         }
     }
-
-    m_cppDebuggerState = newState;
-    updateMenuActions();
+    return result;
 }
 
-
-void QmlEngine::setSimpleDockWidgetArrangement()
+QString QmlEngine::toShadowBuildFilename(const QString &filename) const
 {
-    Utils::FancyMainWindow *mainWindow = Debugger::DebuggerUISwitcher::instance()->mainWindow();
-
-    mainWindow->setTrackingEnabled(false);
-    QList<QDockWidget *> dockWidgets = mainWindow->dockWidgets();
-    foreach (QDockWidget *dockWidget, dockWidgets) {
-        if (m_dockWidgets.contains(dockWidget)) {
-            dockWidget->setFloating(false);
-            mainWindow->removeDockWidget(dockWidget);
-        }
-    }
+    QString newFilename = filename;
+    QString importPath = qmlImportPath();
 
-    foreach (QDockWidget *dockWidget, dockWidgets) {
-        if (m_dockWidgets.contains(dockWidget)) {
-            mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
-            dockWidget->show();
-        }
+    newFilename = mangleFilenamePaths(filename, startParameters().projectDir, startParameters().projectBuildDir);
+    if (newFilename == filename && !importPath.isEmpty()) {
+        newFilename = mangleFilenamePaths(filename, startParameters().projectDir, importPath);
     }
-    mainWindow->splitDockWidget(mainWindow->toolBarDockWidget(), m_propertyWatcherDock, Qt::Vertical);
-    //mainWindow->tabifyDockWidget(m_frameRateDock, m_propertyWatcherDock);
-    mainWindow->tabifyDockWidget(m_propertyWatcherDock, m_expressionQueryDock);
-    mainWindow->tabifyDockWidget(m_propertyWatcherDock, m_inspectorOutputDock);
-    m_propertyWatcherDock->raise();
 
-    m_inspectorOutputDock->setVisible(false);
-
-    mainWindow->setTrackingEnabled(true);
-}
-#endif
-#if 0
-void QmlEngine::reloadEngines()
-{
-    //m_engineComboBox->setEnabled(false);
-
-    QDeclarativeDebugEnginesQuery *query =
-           m_engineDebugInterface->queryAvailableEngines(this);
-    if (!query->isWaiting())
-        enginesChanged(query);
-    else
-        QObject::connect(query, SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
-                         this, SLOT(enginesChanged()));
-}
-
-void QmlEngine::enginesChanged()
-{
-    enginesChanged(qobject_cast<QDeclarativeDebugEnginesQuery *>(sender()));
+    return newFilename;
 }
 
-void QmlEngine::enginesChanged(QDeclarativeDebugEnginesQuery *query)
+QString QmlEngine::mangleFilenamePaths(const QString &filename, const QString &oldBasePath, const QString &newBasePath) const
 {
-    //m_engineComboBox->clearEngines();
-    QList<QDeclarativeDebugEngineReference> engines = query->engines();
-    if (engines.isEmpty())
-        qWarning("QMLDEBUGGER: NO ENGINES FOUND!");
-
-    //m_engineComboBox->setEnabled(true);
-
-    for (int i = 0; i < engines.count(); ++i)
-        qDebug() << "ENGINE: "  <<  engines.at(i).debugId() << engines.at(i).name();
-    //    m_engineComboBox->addEngine(engines.at(i).debugId(), engines.at(i).name());
+    QDir oldBaseDir(oldBasePath);
+    QDir newBaseDir(newBasePath);
+    QFileInfo fileInfo(filename);
 
-    if (engines.count() > 0) {
-    //    m_engineComboBox->setCurrentIndex(engines.at(0).debugId());
-        queryEngineContext(engines.at(0));
-    }
-}
+    if (oldBaseDir.exists() && newBaseDir.exists() && fileInfo.exists()) {
+        if (fileInfo.absoluteFilePath().startsWith(oldBaseDir.canonicalPath())) {
+            QString fileRelativePath = fileInfo.canonicalFilePath().mid(oldBasePath.length());
+            QFileInfo projectFile(newBaseDir.canonicalPath() + QLatin1Char('/') + fileRelativePath);
 
-void QmlEngine::queryEngineContext(const QDeclarativeDebugEngineReference &engine)
-{
-    QDeclarativeDebugRootContextQuery *query =
-        m_engineDebugInterface->queryRootContexts(engine, this);
-
-    if (!query->isWaiting())
-        contextChanged();
-    else
-        QObject::connect(query, SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
-                         this, SLOT(contextChanged()));
-}
-
-void QmlEngine::contextChanged()
-{
-    contextChanged(qobject_cast<QDeclarativeDebugRootContextQuery *>(sender()));
-}
-
-void QmlEngine::contextChanged(QDeclarativeDebugRootContextQuery *query)
-{
-    QTC_ASSERT(query, return);
-    //dump(query->rootContext(), 0);
-    foreach (const QDeclarativeDebugObjectReference &object, query->rootContext().objects())
-        reloadObject(object);
-}
-
-void QmlEngine::reloadObject(const QDeclarativeDebugObjectReference &object)
-{
-    qDebug() << "RELOAD OBJECT: " << object.debugId() << object.idString()
-            << object.className();
-    QDeclarativeDebugObjectQuery *query =
-        m_engineDebugInterface->queryObjectRecursive(object, this);
-    if (!query->isWaiting())
-        objectFetched(query, QDeclarativeDebugQuery::Completed);
-    else
-        QObject::connect(query, SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
-                         this, SLOT(objectFetched(QDeclarativeDebugQuery::State)));
-}
-
-void QmlEngine::objectFetched(QDeclarativeDebugQuery::State state)
-{
-    objectFetched(qobject_cast<QDeclarativeDebugObjectQuery *>(sender()), state);
-}
-
-void QmlEngine::objectFetched(QDeclarativeDebugObjectQuery *query,
-    QDeclarativeDebugQuery::State state)
-{
-    QTC_ASSERT(query, return);
-    QTC_ASSERT(state == QDeclarativeDebugQuery::Completed, return);
-    //dump(m_query->object(), 0);
-
-    m_watches.clear();
-    buildTree(query->object(), "local");
-
-    qDebug() << "WATCHES CREATED: " << m_watches.size();
-    //watchHandler()->beginCycle();
-    //watchHandler()->insertBulkData(list);
-    //watchHandler()->endCycle();
-    //setCurrentItem(topLevelItem(0));
-
-    // this ugly hack is needed if user wants to see internal structs
-    // on startup - debugger does not load them until towards the end,
-    // so essentially loading twice gives us the full list as everything
-    // is already loaded.
-    //if (m_showUninspectableItems && !m_showUninspectableOnInitDone) {
-    //    m_showUninspectableOnInitDone = true;
-    //    reloadObject(m_currentObjectDebugId);
-    //}
-}
-
-void QmlEngine::buildTree(const QDeclarativeDebugObjectReference &obj,
-    const QByteArray &iname)
-{
-    //QTC_ASSERT(obj.contextDebugId() >= 0, return);
-    WatchData data;
-    data.iname = iname;
-
-    if (obj.idString().isEmpty())
-        data.name = QString("<%1>").arg(obj.className());
-    else
-        data.name = obj.idString();
-
-    data.value = "?";
-    data.type = "?";
-    data.setHasChildren(!obj.children().isEmpty());
-    data.setAllUnneeded();
-    qDebug() << "CREATED ITEM " << data.iname << data.name;
-    m_watches.append(m_engineDebugInterface->addWatch(obj, data.name, 0));
-    //QDeclarativeDebugPropertyWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebugPropertyReference &property, QObject *parent)
-
-    //data.userRole = qVariantFromValue(obj);
-    /*
-    if (parent && obj.contextDebugId() >= 0
-            && obj.contextDebugId() != parent->data(0, Qt::UserRole
-                    ).value<QDeclarativeDebugObjectReference>().contextDebugId())
-    {
-
-        QDeclarativeDebugFileReference source = obj.source();
-        if (!source.url().isEmpty()) {
-            QString toolTipString = QLatin1String("URL: ") + source.url().toString();
-            item->setToolTip(0, toolTipString);
+            if (projectFile.exists())
+                return projectFile.canonicalFilePath();
         }
-
-    } else {
-        item->setExpanded(true);
     }
-
-    if (obj.contextDebugId() < 0)
-        item->setHasValidDebugId(false);
-*/
-
-    for (int i = 0; i < obj.children().size(); ++i)
-        buildTree(obj.children().at(i), iname + '.' + QByteArray::number(i));
-}
-#endif
-#if 0
-void QmlEngine::treeObjectActivated(const QDeclarativeDebugObjectReference &obj)
-{
-    QDeclarativeDebugFileReference source = obj.source();
-    QString fileName = source.url().toLocalFile();
-
-    if (source.lineNumber() < 0 || !QFile::exists(fileName))
-        return;
-
-    Core::EditorManager *editorManager = Core::EditorManager::instance();
-    Core::IEditor *editor = editorManager->openEditor(fileName, QString(), Core::EditorManager::NoModeSwitch);
-    TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor*>(editor);
-
-    if (textEditor) {
-        editorManager->addCurrentPositionToNavigationHistory();
-        textEditor->gotoLine(source.lineNumber());
-        textEditor->widget()->setFocus();
-    }
-}
-
-bool QmlEngine::canEditProperty(const QString &propertyType)
-{
-    return m_editablePropertyTypes.contains(propertyType);
-}
-
-QDeclarativeDebugExpressionQuery *QmlEngine::executeExpression(int objectDebugId, const QString &objectId,
-                                                                  const QString &propertyName, const QVariant &value)
-{
-    //qDebug() << entity.property << entity.title << entity.objectId;
-    if (objectId.length()) {
-
-        QString quoteWrappedValue = value.toString();
-        if (addQuotesForData(value))
-            quoteWrappedValue = QString("'%1'").arg(quoteWrappedValue);
-
-        QString constructedExpression = objectId + "." + propertyName + "=" + quoteWrappedValue;
-        //qDebug() << "EXPRESSION:" << constructedExpression;
-        return m_client->queryExpressionResult(objectDebugId, constructedExpression, this);
-    }
-
-    return 0;
-}
-
-bool QmlEngine::addQuotesForData(const QVariant &value) const
-{
-    switch (value.type()) {
-    case QVariant::String:
-    case QVariant::Color:
-    case QVariant::Date:
-        return true;
-    default:
-        break;
-    }
-
-    return false;
-}
-
-ObjectTree::ObjectTree(QDeclarativeEngineDebug *client, QWidget *parent)
-    : QTreeWidget(parent),
-      m_client(client),
-      m_query(0), m_clickedItem(0), m_showUninspectableItems(false),
-      m_currentObjectDebugId(0), m_showUninspectableOnInitDone(false)
-{
-    setAttribute(Qt::WA_MacShowFocusRect, false);
-    setFrameStyle(QFrame::NoFrame);
-    setHeaderHidden(true);
-    setExpandsOnDoubleClick(false);
-
-    m_addWatchAction = new QAction(tr("Add watch expression..."), this);
-    m_toggleUninspectableItemsAction = new QAction(tr("Show uninspectable items"), this);
-    m_toggleUninspectableItemsAction->setCheckable(true);
-    m_goToFileAction = new QAction(tr("Go to file"), this);
-    connect(m_toggleUninspectableItemsAction, SIGNAL(triggered()), SLOT(toggleUninspectableItems()));
-    connect(m_addWatchAction, SIGNAL(triggered()), SLOT(addWatch()));
-    connect(m_goToFileAction, SIGNAL(triggered()), SLOT(goToFile()));
-
-    connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
-            SLOT(currentItemChanged(QTreeWidgetItem *)));
-    connect(this, SIGNAL(itemActivated(QTreeWidgetItem *, int)),
-            SLOT(activated(QTreeWidgetItem *)));
-    connect(this, SIGNAL(itemSelectionChanged()), SLOT(selectionChanged()));
-}
-
-void ObjectTree::readSettings(const InspectorSettings &settings)
-{
-    if (settings.showUninspectableItems() != m_showUninspectableItems)
-        toggleUninspectableItems();
-}
-void ObjectTree::saveSettings(InspectorSettings &settings)
-{
-    settings.setShowUninspectableItems(m_showUninspectableItems);
-}
-
-void ObjectTree::setEngineDebug(QDeclarativeEngineDebug *client)
-{
-    m_client = client;
-}
-
-void ObjectTree::toggleUninspectableItems()
-{
-    m_showUninspectableItems = !m_showUninspectableItems;
-    m_toggleUninspectableItemsAction->setChecked(m_showUninspectableItems);
-    reload(m_currentObjectDebugId);
-}
-
-void ObjectTree::selectionChanged()
-{
-    if (selectedItems().isEmpty())
-        return;
-
-    QTreeWidgetItem *item = selectedItems().first();
-    if (item)
-        emit contextHelpIdChanged(InspectorContext::contextHelpIdForItem(item->text(0)));
-}
-
-
-void ObjectTree::setCurrentObject(int debugId)
-{
-    QTreeWidgetItem *item = findItemByObjectId(debugId);
-    if (item) {
-        setCurrentItem(item);
-        scrollToItem(item);
-        item->setExpanded(true);
-    }
-
-
+    return filename;
 }
 
+QString QmlEngine::fromShadowBuildFilename(const QString &filename) const
 {
-    if (!item)
-        return;
+    QString newFilename = filename;
+    QString importPath = qmlImportPath();
 
-    QDeclarativeDebugObjectReference obj = item->data(0, Qt::UserRole).value<QDeclarativeDebugObjectReference>();
-    if (obj.debugId() >= 0)
-        emit currentObjectChanged(obj);
-}
-
-void ObjectTree::activated(QTreeWidgetItem *item)
-{
-    if (!item)
-        return;
-
-    QDeclarativeDebugObjectReference obj = item->data(0, Qt::UserRole).value<QDeclarativeDebugObjectReference>();
-    if (obj.debugId() >= 0)
-        emit activated(obj);
-}
-
-void ObjectTree::cleanup()
-{
-    m_showUninspectableOnInitDone = false;
-    clear();
-}
-
-void ObjectTree::dump(const QDeclarativeDebugContextReference &ctxt, int ind)
-{
-    QByteArray indent(ind * 4, ' ');
-    qWarning().nospace() << indent.constData() << ctxt.debugId() << " "
-                         << qPrintable(ctxt.name());
-
-    for (int ii = 0; ii < ctxt.contexts().count(); ++ii)
-        dump(ctxt.contexts().at(ii), ind + 1);
-
-    for (int ii = 0; ii < ctxt.objects().count(); ++ii)
-        dump(ctxt.objects().at(ii), ind);
-}
-
-void ObjectTree::dump(const QDeclarativeDebugObjectReference &obj, int ind)
-{
-    QByteArray indent(ind * 4, ' ');
-    qWarning().nospace() << indent.constData() << qPrintable(obj.className())
-                         << " " << qPrintable(obj.idString()) << " "
-                         << obj.debugId();
-
-    for (int ii = 0; ii < obj.children().count(); ++ii)
-        dump(obj.children().at(ii), ind + 1);
-}
-
-QTreeWidgetItem *ObjectTree::findItemByObjectId(int debugId) const
-{
-    for (int i=0; i<topLevelItemCount(); ++i) {
-        QTreeWidgetItem *item = findItem(topLevelItem(i), debugId);
-        if (item)
-            return item;
+    newFilename = mangleFilenamePaths(filename, startParameters().projectBuildDir, startParameters().projectDir);
+    if (newFilename == filename && !importPath.isEmpty()) {
+        newFilename = mangleFilenamePaths(filename, startParameters().projectBuildDir, importPath);
     }
 
-    return 0;
+    return newFilename;
 }
 
-QTreeWidgetItem *ObjectTree::findItem(QTreeWidgetItem *item, int debugId) const
-{
-    if (item->data(0, Qt::UserRole).value<QDeclarativeDebugObjectReference>().debugId() == debugId)
-        return item;
-
-    QTreeWidgetItem *child;
-    for (int i=0; i<item->childCount(); ++i) {
-        child = findItem(item->child(i), debugId);
-        if (child)
-            return child;
-    }
-
-    return 0;
-}
-
-void ObjectTree::addWatch()
-{
-    QDeclarativeDebugObjectReference obj =
-            currentItem()->data(0, Qt::UserRole).value<QDeclarativeDebugObjectReference>();
-
-    bool ok = false;
-    QString watch = QInputDialog::getText(this, tr("Watch expression"),
-            tr("Expression:"), QLineEdit::Normal, QString(), &ok);
-    if (ok && !watch.isEmpty())
-        emit expressionWatchRequested(obj, watch);
-
-}
-
-void ObjectTree::goToFile()
-{
-    QDeclarativeDebugObjectReference obj =
-            currentItem()->data(0, Qt::UserRole).value<QDeclarativeDebugObjectReference>();
-
-    if (obj.debugId() >= 0)
-        emit activated(obj);
-}
-
-void ObjectTree::contextMenuEvent(QContextMenuEvent *event)
-{
-
-    m_clickedItem = itemAt(QPoint(event->pos().x(),
-                                  event->pos().y() ));
-    if (!m_clickedItem)
-        return;
-
-    QMenu menu;
-    menu.addAction(m_addWatchAction);
-    menu.addAction(m_goToFileAction);
-    if (m_currentObjectDebugId) {
-        menu.addSeparator();
-        menu.addAction(m_toggleUninspectableItemsAction);
-    }
-
-    menu.exec(event->globalPos());
-}
-
-} // Internal
-} // Qml
-#endif
-
-} // namespace Internal
 } // namespace Debugger
 
-#include "qmlengine.moc"