diff options
author | Lasse Holmstedt <lasse.holmstedt@nokia.com> | 2010-08-13 14:18:10 +0200 |
---|---|---|
committer | Lasse Holmstedt <lasse.holmstedt@nokia.com> | 2010-08-13 14:20:39 +0200 |
commit | b71c3c62ba3b4264de05e0e18ab68fd0a8e8ba52 (patch) | |
tree | 8503c49137889f97724165d44e94b9d7970d8962 | |
parent | 5de57ddad398e2da73dc5c2542270e3a64c3690c (diff) | |
download | qt-creator-b71c3c62ba3b4264de05e0e18ab68fd0a8e8ba52.tar.gz |
QML Debugger refactoring
Now, QmlEngine creates the connection to the inferior (debuggee), and
notifies QmlInspector when a connection is established. Before,
inspector created the debugger engin, which was wrong.
QmlEngine's responsibilities are connecting to the debuggee and basic
QML/JS debugging features like locals & watchers, breakpoints etc.
QmlInspector takes care of Live Preview and other fancy inspection
features.
Reviewed-by: hjk
24 files changed, 820 insertions, 642 deletions
diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index 0d6de6c154..6149403215 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -112,7 +112,12 @@ include(cdb/cdb.pri) include(gdb/gdb.pri) include(script/script.pri) include(pdb/pdb.pri) -include(qml/qml.pri) + +contains(QT_CONFIG, declarative) { + QT += declarative + include(qml/qml.pri) +} + include(tcf/tcf.pri) include(shared/shared.pri) diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index 8c3eb12c5f..d3ea885112 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -76,6 +76,10 @@ public: bool breakAtMain; QString crashParameter; // for AttachCrashedExternal + // for qml debugging + QString qmlServerAddress; + quint16 qmlServerPort; + // for remote debugging QString remoteChannel; QString remoteArchitecture; diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 6d6fed29eb..f2e6eb8d7f 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -331,7 +331,7 @@ void DebuggerRunControl::createEngine(const DebuggerStartParameters &sp) QString errorMessage; QString settingsIdHint; - if (sp.executable.endsWith(_("qmlviewer"))) + if (sp.executable.endsWith(_("qmlviewer")) || sp.executable.endsWith(_("qmlobserver"))) engineType = QmlEngineType; else if (sp.executable.endsWith(_(".js"))) engineType = ScriptEngineType; diff --git a/src/plugins/debugger/qml/qml.pri b/src/plugins/debugger/qml/qml.pri index df58969fbf..2bc5e8ebd4 100644 --- a/src/plugins/debugger/qml/qml.pri +++ b/src/plugins/debugger/qml/qml.pri @@ -1,4 +1,12 @@ +include($$PWD/../../../libs/qmljsdebugclient/qmljsdebugclient-lib.pri) -HEADERS += $$PWD/qmlengine.h -SOURCES += $$PWD/qmlengine.cpp +HEADERS += \ + $$PWD/qmlengine.h \ + $$PWD/qmladapter.h \ + $$PWD/qmldebuggerclient.h \ + $$PWD/qmljsprivateapi.h +SOURCES += \ + $$PWD/qmlengine.cpp \ + $$PWD/qmladapter.cpp \ + $$PWD/qmldebuggerclient.cpp diff --git a/src/plugins/debugger/qml/qmladapter.cpp b/src/plugins/debugger/qml/qmladapter.cpp new file mode 100644 index 0000000000..85f429b83e --- /dev/null +++ b/src/plugins/debugger/qml/qmladapter.cpp @@ -0,0 +1,204 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "qmladapter.h" +#include "qmldebuggerclient.h" +#include "qmljsprivateapi.h" + +#include "debuggerengine.h" + +#include <QAbstractSocket> +#include <QTimer> +#include <QDebug> + +namespace Debugger { +namespace Internal { + +QmlAdapter::QmlAdapter(DebuggerEngine *engine, QObject *parent) + : QObject(parent) + , m_engine(engine) + , m_qmlClient(0) + , m_mainClient(0) + , m_connectionTimer(new QTimer(this)) + , m_connectionAttempts(0) + , m_conn(0) + +{ + connect(m_connectionTimer, SIGNAL(timeout()), SLOT(pollInferior())); +} + +void QmlAdapter::beginConnection() +{ + m_connectionTimer->start(); +} + +void QmlAdapter::pollInferior() +{ + ++m_connectionAttempts; + + if (connectToViewer()) { + m_connectionTimer->stop(); + m_connectionAttempts = 0; + } else if (m_connectionAttempts == m_maxConnectionAttempts) { + emit connectionStartupFailed(); + m_connectionTimer->stop(); + m_connectionAttempts = 0; + } +} + +bool QmlAdapter::connectToViewer() +{ + if (m_engine.isNull() || (m_conn && m_conn->state() != QAbstractSocket::UnconnectedState)) + return false; + + m_conn = new QDeclarativeDebugConnection(this); + connect(m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)), + SLOT(connectionStateChanged())); + connect(m_conn, SIGNAL(error(QAbstractSocket::SocketError)), + SLOT(connectionErrorOccurred())); + + QString address = m_engine.data()->startParameters().qmlServerAddress; + QString port = QString::number(m_engine.data()->startParameters().qmlServerPort); + showConnectionStatusMessage(tr("Connect to debug server %1:%2").arg(address).arg(port)); + m_conn->connectToHost(m_engine.data()->startParameters().qmlServerAddress, + m_engine.data()->startParameters().qmlServerPort); + + // blocks until connected; if no connection is available, will fail immediately + if (!m_conn->waitForConnected()) + return false; + + return true; +} + +void QmlAdapter::connectionErrorOccurred() +{ + showConnectionErrorMessage(tr("Error: (%1) %2", "%1=error code, %2=error message") + .arg(m_conn->error()).arg(m_conn->errorString())); + + // this is only an error if we are already connected and something goes wrong. + if (isConnected()) + emit connectionError(); +} + +void QmlAdapter::connectionStateChanged() +{ + switch (m_conn->state()) { + case QAbstractSocket::UnconnectedState: + { + showConnectionStatusMessage(tr("disconnected.\n\n")); + emit disconnected(); + + break; + } + case QAbstractSocket::HostLookupState: + showConnectionStatusMessage(tr("resolving host...")); + break; + case QAbstractSocket::ConnectingState: + showConnectionStatusMessage(tr("connecting to debug server...")); + break; + case QAbstractSocket::ConnectedState: + { + showConnectionStatusMessage(tr("connected.\n")); + + if (!m_mainClient) { + m_mainClient = new QDeclarativeEngineDebug(m_conn, this); + } + + createDebuggerClient(); + //reloadEngines(); + emit connected(); + break; + } + case QAbstractSocket::ClosingState: + showConnectionStatusMessage(tr("closing...")); + break; + case QAbstractSocket::BoundState: + case QAbstractSocket::ListeningState: + break; + } +} + +void QmlAdapter::createDebuggerClient() +{ + m_qmlClient = new QmlDebuggerClient(m_conn); + + connect(m_engine.data(), SIGNAL(sendMessage(QByteArray)), + m_qmlClient, SLOT(slotSendMessage(QByteArray))); + connect(m_qmlClient, SIGNAL(messageWasReceived(QByteArray)), + m_engine.data(), SLOT(messageReceived(QByteArray))); + + //engine->startSuccessful(); // FIXME: AAA: port to new debugger states +} + +bool QmlAdapter::isConnected() const +{ + return m_conn && m_qmlClient && m_conn->state() == QAbstractSocket::ConnectedState; +} + +bool QmlAdapter::isUnconnected() const +{ + return !m_conn || m_conn->state() == QAbstractSocket::UnconnectedState; +} + +QDeclarativeEngineDebug *QmlAdapter::client() const +{ + return m_mainClient; +} + +QDeclarativeDebugConnection *QmlAdapter::connection() const +{ + if (!isConnected()) + return 0; + + return m_conn; +} + +void QmlAdapter::showConnectionStatusMessage(const QString &message) +{ + if (!m_engine.isNull()) + m_engine.data()->showMessage(QLatin1String("QmlJSDebugger: ") + message, LogStatus); +} + +void QmlAdapter::showConnectionErrorMessage(const QString &message) +{ + if (!m_engine.isNull()) + m_engine.data()->showMessage(QLatin1String("QmlJSDebugger: ") + message, LogError); +} + +void QmlAdapter::setMaxConnectionAttempts(int maxAttempts) +{ + m_maxConnectionAttempts = maxAttempts; +} +void QmlAdapter::setConnectionAttemptInterval(int interval) +{ + m_connectionAttemptInterval = interval; +} + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/qml/qmladapter.h b/src/plugins/debugger/qml/qmladapter.h new file mode 100644 index 0000000000..df63707dad --- /dev/null +++ b/src/plugins/debugger/qml/qmladapter.h @@ -0,0 +1,98 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QMLADAPTER_H +#define QMLADAPTER_H + +#include <QObject> +#include <QWeakPointer> + +#include "qmljsprivateapi.h" +#include "debugger_global.h" + +QT_FORWARD_DECLARE_CLASS(QTimer) + +namespace Debugger { +namespace Internal { +class DebuggerEngine; +class QmlDebuggerClient; + +class DEBUGGER_EXPORT QmlAdapter : public QObject +{ + Q_OBJECT +public: + explicit QmlAdapter(DebuggerEngine *engine, QObject *parent = 0); + void beginConnection(); + + bool isConnected() const; + bool isUnconnected() const; + + QDeclarativeEngineDebug *client() const; + QDeclarativeDebugConnection *connection() const; + + // TODO move to private API b/w engine and adapter + void setMaxConnectionAttempts(int maxAttempts); + void setConnectionAttemptInterval(int interval); + +signals: + void aboutToDisconnect(); + void connected(); + void disconnected(); + void connectionStartupFailed(); + void connectionError(); + +private slots: + void connectionErrorOccurred(); + void connectionStateChanged(); + void pollInferior(); + +private: + bool connectToViewer(); + void createDebuggerClient(); + void showConnectionStatusMessage(const QString &message); + void showConnectionErrorMessage(const QString &message); + +private: + QWeakPointer<DebuggerEngine> m_engine; + QmlDebuggerClient *m_qmlClient; + QDeclarativeEngineDebug *m_mainClient; + + QTimer *m_connectionTimer; + int m_connectionAttempts; + int m_maxConnectionAttempts; + int m_connectionAttemptInterval; + + QDeclarativeDebugConnection *m_conn; + +}; + +} // namespace Internal +} // namespace Debugger + +#endif // QMLADAPTER_H diff --git a/src/plugins/qmljsinspector/qmljsdebuggerclient.cpp b/src/plugins/debugger/qml/qmldebuggerclient.cpp index 2745048266..a4d852fb93 100644 --- a/src/plugins/qmljsinspector/qmljsdebuggerclient.cpp +++ b/src/plugins/debugger/qml/qmldebuggerclient.cpp @@ -26,29 +26,33 @@ ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ -#include "qmljsdebuggerclient.h" +#include "qmldebuggerclient.h" #include <extensionsystem/pluginmanager.h> #include <utils/qtcassert.h> -using namespace QmlJSInspector::Internal; +namespace Debugger { +namespace Internal { -DebuggerClient::DebuggerClient(QDeclarativeDebugConnection* client) +QmlDebuggerClient::QmlDebuggerClient(QmlJsDebugClient::QDeclarativeDebugConnection* client) : QDeclarativeDebugClient(QLatin1String("JSDebugger"), client) { setEnabled(true); } -DebuggerClient::~DebuggerClient() +QmlDebuggerClient::~QmlDebuggerClient() { } -void DebuggerClient::messageReceived(const QByteArray &data) +void QmlDebuggerClient::messageReceived(const QByteArray &data) { emit messageWasReceived(data); } -void DebuggerClient::slotSendMessage(const QByteArray &message) +void QmlDebuggerClient::slotSendMessage(const QByteArray &message) { QDeclarativeDebugClient::sendMessage(message); } + +} // Internal +} // Debugger diff --git a/src/plugins/qmljsinspector/qmljsdebuggerclient.h b/src/plugins/debugger/qml/qmldebuggerclient.h index 4daf16fe6e..191e3570d5 100644 --- a/src/plugins/qmljsinspector/qmljsdebuggerclient.h +++ b/src/plugins/debugger/qml/qmldebuggerclient.h @@ -32,16 +32,16 @@ #include "qmljsprivateapi.h" -namespace QmlJSInspector { +namespace Debugger { namespace Internal { -class DebuggerClient : public QDeclarativeDebugClient +class QmlDebuggerClient : public QDeclarativeDebugClient { Q_OBJECT public: - DebuggerClient(QDeclarativeDebugConnection *client); - virtual ~DebuggerClient(); + QmlDebuggerClient(QmlJsDebugClient::QDeclarativeDebugConnection *client); + virtual ~QmlDebuggerClient(); signals: void messageWasReceived(const QByteArray &data); diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 5a40f7dc42..8b3c177ab8 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -28,6 +28,7 @@ **************************************************************************/ #include "qmlengine.h" +#include "qmladapter.h" #include "debuggerconstants.h" #include "debuggerplugin.h" @@ -42,6 +43,7 @@ #include "watchhandler.h" #include "watchutils.h" +#include <extensionsystem/pluginmanager.h> #include <projectexplorer/environment.h> #include <utils/qtcassert.h> @@ -70,7 +72,10 @@ #endif # define XSDEBUG(s) qDebug() << s - +enum { + MaxConnectionAttempts = 50, + ConnectionAttemptDefaultInterval = 75 +}; namespace Debugger { namespace Internal { @@ -96,8 +101,12 @@ QDataStream& operator>>(QDataStream& s, WatchData &data) /////////////////////////////////////////////////////////////////////// QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters) - : DebuggerEngine(startParameters), m_ping(0) + : DebuggerEngine(startParameters) + , m_ping(0) + , m_adapter(new QmlAdapter(this)) + , m_addedAdapterToObjectPool(false) { + } QmlEngine::~QmlEngine() @@ -107,32 +116,91 @@ QmlEngine::~QmlEngine() void QmlEngine::setupInferior() { QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); - attemptBreakpointSynchronization(); + + connect(&m_applicationLauncher, SIGNAL(processExited(int)), SLOT(disconnected())); + m_applicationLauncher.setEnvironment(startParameters().environment); + m_applicationLauncher.setWorkingDirectory(startParameters().workingDirectory); + notifyInferiorSetupOk(); } +void QmlEngine::connectionEstablished() +{ + attemptBreakpointSynchronization(); + + ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance(); + pluginManager->addObject(m_adapter); + m_addedAdapterToObjectPool = true; + + plugin()->showMessage(tr("QML Debugger connected."), StatusBar); + + notifyEngineRunAndInferiorRunOk(); +} + +void QmlEngine::connectionStartupFailed() +{ + QMessageBox::critical(0, + tr("Failed to connect to debugger"), + tr("Could not connect to debugger server.") ); + notifyEngineRunFailed(); +} + +void QmlEngine::connectionError() +{ + // do nothing for now - only exit the debugger when inferior exits. +} + void QmlEngine::runEngine() { QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); - notifyEngineRunAndInferiorRunOk(); + + // ### TODO for non-qmlproject apps, start in a different way + m_applicationLauncher.start(ProjectExplorer::ApplicationLauncher::Gui, + startParameters().executable, + startParameters().processArgs); + + m_adapter->beginConnection(); + plugin()->showMessage(tr("QML Debugger connecting..."), StatusBar); } void QmlEngine::shutdownInferior() { QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); + if (!m_applicationLauncher.isRunning()) { + showMessage(tr("Trying to stop while process is no longer running."), LogError); + } else { + disconnect(&m_applicationLauncher, SIGNAL(processExited(int)), this, SLOT(disconnected())); + m_applicationLauncher.stop(); + } notifyInferiorShutdownOk(); } void QmlEngine::shutdownEngine() { QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); + + if (m_addedAdapterToObjectPool) { + ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance(); + pluginManager->removeObject(m_adapter); + } + + if (m_applicationLauncher.isRunning()) { + // should only happen if engine is ill + disconnect(&m_applicationLauncher, SIGNAL(processExited(int)), this, SLOT(disconnected())); + m_applicationLauncher.stop(); + } + notifyEngineShutdownOk(); } -const int serverPort = 3768; - void QmlEngine::setupEngine() { + m_adapter->setMaxConnectionAttempts(MaxConnectionAttempts); + m_adapter->setConnectionAttemptInterval(ConnectionAttemptDefaultInterval); + connect(m_adapter, SIGNAL(connectionError()), SLOT(connectionError())); + connect(m_adapter, SIGNAL(connected()), SLOT(connectionEstablished())); + connect(m_adapter, SIGNAL(connectionStartupFailed()), SLOT(connectionStartupFailed())); + notifyEngineSetupOk(); } @@ -368,8 +436,6 @@ void QmlEngine::sendPing() sendMessage(reply); } - - DebuggerEngine *createQmlEngine(const DebuggerStartParameters &sp) { return new QmlEngine(sp); @@ -520,6 +586,7 @@ void QmlEngine::messageReceived(const QByteArray &message) void QmlEngine::disconnected() { + plugin()->showMessage(tr("QML Debugger disconnected."), StatusBar); notifyInferiorExited(); } diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index 9520fe360d..9c77d2e4df 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -44,12 +44,14 @@ #include <QtNetwork/QAbstractSocket> #include <QtNetwork/QTcpSocket> +#include <projectexplorer/applicationlauncher.h> namespace Debugger { namespace Internal { class ScriptAgent; class WatchData; +class QmlAdapter; class QmlResponse; class QmlDebuggerClient; @@ -57,7 +59,6 @@ class DEBUGGER_EXPORT QmlEngine : public DebuggerEngine { Q_OBJECT - int m_ping; public: explicit QmlEngine(const DebuggerStartParameters &startParameters); ~QmlEngine(); @@ -112,9 +113,21 @@ private: signals: void sendMessage(const QByteArray &msg); +private slots: + void connectionEstablished(); + void connectionStartupFailed(); + void connectionError(); + private: + void expandObject(const QByteArray &iname, quint64 objectId); void sendPing(); + +private: + int m_ping; + QmlAdapter *m_adapter; + ProjectExplorer::ApplicationLauncher m_applicationLauncher; + bool m_addedAdapterToObjectPool; }; } // namespace Internal diff --git a/src/plugins/qmljsinspector/qmljsinspectorcontext.h b/src/plugins/debugger/qml/qmljsprivateapi.h index 7a4e1dd244..33be55e2b9 100644 --- a/src/plugins/qmljsinspector/qmljsinspectorcontext.h +++ b/src/plugins/debugger/qml/qmljsprivateapi.h @@ -26,51 +26,12 @@ ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ +#ifndef QMLJSPRIVATEAPI_H +#define QMLJSPRIVATEAPI_H -#ifndef QMLJSINSPECTORCONTEXT_H -#define QMLJSINSPECTORCONTEXT_H +#include <qmljsdebugclient/qdeclarativedebug_p.h> +#include <qmljsdebugclient/qdeclarativedebugclient_p.h> -#include <coreplugin/icontext.h> -#include <QList> - -QT_BEGIN_NAMESPACE -class QWidget; -QT_END_NAMESPACE - -namespace QmlJSInspector { -namespace Internal { - -class ObjectPropertiesView; -class ObjectTree; -class DesignModeWidget; - -class InspectorContext : public Core::IContext -{ - Q_OBJECT - -public: - InspectorContext(QWidget *widget); - virtual ~InspectorContext(); - - // Core::IContext interface - virtual Core::Context context() const; - virtual QWidget *widget(); - virtual QString contextHelpId() const; - - static QString contextHelpIdForProperty(const QString &itemName, const QString &propName); - static QString contextHelpIdForItem(const QString &itemName); - -public slots: - void setContextHelpId(const QString &helpId); - -private: - QWidget *m_widget; - Core::Context m_context; - QString m_contextHelpId; -}; - -} // Internal -} // QmlInspector - -#endif +using namespace QmlJsDebugClient; +#endif // QMLJSPRIVATEAPI_H diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 24a14f049b..0e6f2338d5 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -35,12 +35,13 @@ SUBDIRS = plugin_coreplugin \ plugin_qmljseditor \ plugin_mercurial \ plugin_classview \ - plugin_qmljsinspector \ debugger/dumper.pro contains(QT_CONFIG, declarative) { - SUBDIRS += plugin_qmlprojectmanager + SUBDIRS += \ + plugin_qmlprojectmanager \ + plugin_qmljsinspector include(../private_headers.pri) exists($${QT_PRIVATE_HEADERS}/QtDeclarative/private/qdeclarativecontext_p.h) { diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.cpp b/src/plugins/qmljsinspector/qmljsclientproxy.cpp index 7d419d55b1..ddbe6e45e4 100644 --- a/src/plugins/qmljsinspector/qmljsclientproxy.cpp +++ b/src/plugins/qmljsinspector/qmljsclientproxy.cpp @@ -28,13 +28,13 @@ **************************************************************************/ #include "qmljsclientproxy.h" -#include "qmljsdebuggerclient.h" #include "qmljsprivateapi.h" #include "qmljsdesigndebugclient.h" #include <debugger/debuggerplugin.h> #include <debugger/debuggerrunner.h> #include <debugger/qml/qmlengine.h> +#include <debugger/qml/qmladapter.h> #include <extensionsystem/pluginmanager.h> #include <utils/qtcassert.h> @@ -44,33 +44,54 @@ using namespace QmlJSInspector::Internal; -ClientProxy *ClientProxy::m_instance = 0; - -ClientProxy::ClientProxy(QObject *parent) : - QObject(parent), - m_conn(0), - m_client(0), - m_designClient(0), - m_engineQuery(0), - m_contextQuery(0), - m_objectTreeQuery(0) +ClientProxy::ClientProxy(Debugger::Internal::QmlAdapter *adapter, QObject *parent) + : QObject(parent) + , m_adapter(adapter) + , m_client(m_adapter->client()) + , m_designClient(0) + , m_engineQuery(0) + , m_contextQuery(0) + , m_objectTreeQuery(0) +{ + + connect(m_adapter, SIGNAL(aboutToDisconnect()), SLOT(disconnectFromServer())); + connectToServer(); +} + +void ClientProxy::connectToServer() +{ + m_designClient = new QmlJSDesignDebugClient(m_adapter->connection(), this); + emit connected(); + + connect(m_designClient, SIGNAL(currentObjectsChanged(QList<int>)), + SLOT(onCurrentObjectsChanged(QList<int>))); + connect(m_designClient, SIGNAL(colorPickerActivated()), + SIGNAL(colorPickerActivated())); + connect(m_designClient, SIGNAL(zoomToolActivated()), + SIGNAL(zoomToolActivated())); + connect(m_designClient, SIGNAL(selectToolActivated()), + SIGNAL(selectToolActivated())); + connect(m_designClient, SIGNAL(selectMarqueeToolActivated()), + SIGNAL(selectMarqueeToolActivated())); + connect(m_designClient, SIGNAL(animationSpeedChanged(qreal)), + SIGNAL(animationSpeedChanged(qreal))); + connect(m_designClient, SIGNAL(designModeBehaviorChanged(bool)), + SIGNAL(designModeBehaviorChanged(bool))); + connect(m_designClient, SIGNAL(reloaded()), this, + SIGNAL(serverReloaded())); + connect(m_designClient, SIGNAL(selectedColorChanged(QColor)), + SIGNAL(selectedColorChanged(QColor))); + connect(m_designClient, SIGNAL(contextPathUpdated(QStringList)), + SIGNAL(contextPathUpdated(QStringList))); + connect(m_designClient, SIGNAL(treeRefreshRequested()), + SLOT(refreshObjectTree())); + + reloadEngines(); +} + +void ClientProxy::disconnectFromServer() { - Q_ASSERT(! m_instance); - m_instance = this; -} - -ClientProxy *ClientProxy::instance() -{ - return m_instance; -} - -bool ClientProxy::connectToViewer(const QString &host, quint16 port) -{ - if (m_conn && m_conn->state() != QAbstractSocket::UnconnectedState) - return false; - if (m_designClient) { - disconnect(m_designClient, SIGNAL(currentObjectsChanged(QList<int>)), this, SLOT(onCurrentObjectsChanged(QList<int>))); disconnect(m_designClient, SIGNAL(colorPickerActivated()), @@ -92,36 +113,22 @@ bool ClientProxy::connectToViewer(const QString &host, quint16 port) disconnect(m_designClient, SIGNAL(treeRefreshRequested()), this, SLOT(refreshObjectTree())); - emit aboutToDisconnect(); - - delete m_client; - m_client = 0; - delete m_designClient; m_designClient = 0; } - if (m_conn) { - m_conn->disconnectFromHost(); - delete m_conn; - m_conn = 0; - } - - m_conn = new QDeclarativeDebugConnection(this); - connect(m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)), - SLOT(connectionStateChanged())); - connect(m_conn, SIGNAL(error(QAbstractSocket::SocketError)), - SLOT(connectionError())); - - emit connectionStatusMessage(tr("[Inspector] set to connect to debug server %1:%2").arg(host).arg(port)); - m_conn->connectToHost(host, port); - + if (m_engineQuery) + delete m_engineQuery; + m_engineQuery = 0; - // blocks until connected; if no connection is available, will fail immediately - if (!m_conn->waitForConnected()) - return false; + if (m_contextQuery) + delete m_contextQuery; + m_contextQuery = 0; - return true; + if (m_objectTreeQuery) { + delete m_objectTreeQuery; + m_objectTreeQuery = 0; + } } void ClientProxy::refreshObjectTree() @@ -173,134 +180,6 @@ void ClientProxy::onCurrentObjectsChanged(const QList<int> &debugIds) } } -void ClientProxy::disconnectFromViewer() -{ - m_conn->disconnectFromHost(); - emit disconnected(); -} - -void ClientProxy::connectionError() -{ - emit connectionStatusMessage(tr("[Inspector] error: (%1) %2", "%1=error code, %2=error message") - .arg(m_conn->error()).arg(m_conn->errorString())); -} - -void ClientProxy::connectionStateChanged() -{ - switch (m_conn->state()) { - case QAbstractSocket::UnconnectedState: - { - emit connectionStatusMessage(tr("[Inspector] disconnected.\n\n")); - - delete m_engineQuery; - m_engineQuery = 0; - delete m_contextQuery; - m_contextQuery = 0; - - if (m_objectTreeQuery) { - delete m_objectTreeQuery; - m_objectTreeQuery = 0; - } - - emit disconnected(); - - break; - } - case QAbstractSocket::HostLookupState: - emit connectionStatusMessage(tr("[Inspector] resolving host...")); - break; - case QAbstractSocket::ConnectingState: - emit connectionStatusMessage(tr("[Inspector] connecting to debug server...")); - break; - case QAbstractSocket::ConnectedState: - { - emit connectionStatusMessage(tr("[Inspector] connected.\n")); - - if (!m_client) { - m_client = new QDeclarativeEngineDebug(m_conn, this); - m_designClient = new QmlJSDesignDebugClient(m_conn, this); - emit connected(m_client); - - connect(m_designClient, SIGNAL(currentObjectsChanged(QList<int>)), - SLOT(onCurrentObjectsChanged(QList<int>))); - connect(m_designClient, SIGNAL(colorPickerActivated()), - SIGNAL(colorPickerActivated())); - connect(m_designClient, SIGNAL(zoomToolActivated()), - SIGNAL(zoomToolActivated())); - connect(m_designClient, SIGNAL(selectToolActivated()), - SIGNAL(selectToolActivated())); - connect(m_designClient, SIGNAL(selectMarqueeToolActivated()), - SIGNAL(selectMarqueeToolActivated())); - connect(m_designClient, SIGNAL(animationSpeedChanged(qreal)), - SIGNAL(animationSpeedChanged(qreal))); - connect(m_designClient, SIGNAL(designModeBehaviorChanged(bool)), - SIGNAL(designModeBehaviorChanged(bool))); - connect(m_designClient, SIGNAL(reloaded()), this, - SIGNAL(serverReloaded())); - connect(m_designClient, SIGNAL(selectedColorChanged(QColor)), - SIGNAL(selectedColorChanged(QColor))); - connect(m_designClient, SIGNAL(contextPathUpdated(QStringList)), - SIGNAL(contextPathUpdated(QStringList))); - connect(m_designClient, SIGNAL(treeRefreshRequested()), - SLOT(refreshObjectTree())); - } - - createDebuggerClient(); - reloadEngines(); - - break; - } - case QAbstractSocket::ClosingState: - emit connectionStatusMessage(tr("[Inspector] closing...")); - break; - case QAbstractSocket::BoundState: - case QAbstractSocket::ListeningState: - break; - } -} - -void ClientProxy::createDebuggerClient() -{ - DebuggerClient *debuggerClient = new DebuggerClient(m_conn); - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - const QList<Debugger::DebuggerRunControlFactory *> factories = - pm->getObjects<Debugger::DebuggerRunControlFactory>(); - ProjectExplorer::RunControl *runControl = 0; - - Debugger::DebuggerStartParameters sp; - sp.startMode = Debugger::StartExternal; - sp.executable = "qmlviewer"; //FIXME - runControl = factories.first()->create(sp); - Debugger::DebuggerRunControl* debuggerRunControl = - qobject_cast<Debugger::DebuggerRunControl *>(runControl); - - QTC_ASSERT(debuggerRunControl, return); - Debugger::Internal::QmlEngine *engine = - qobject_cast<Debugger::Internal::QmlEngine *>(debuggerRunControl->engine()); - QTC_ASSERT(engine, return); - - engine->Debugger::Internal::DebuggerEngine::startDebugger(debuggerRunControl); - - connect(engine, SIGNAL(sendMessage(QByteArray)), - debuggerClient, SLOT(slotSendMessage(QByteArray))); - connect(debuggerClient, SIGNAL(messageWasReceived(QByteArray)), - engine, SLOT(messageReceived(QByteArray))); - connect(m_conn, SIGNAL(disconnected()), - engine, SLOT(disconnected())); - - //engine->startSuccessful(); // FIXME: AAA: port to new debugger states -} - -bool ClientProxy::isConnected() const -{ - return m_conn && m_client && m_conn->state() == QAbstractSocket::ConnectedState; -} - -bool ClientProxy::isUnconnected() const -{ - return !m_conn || m_conn->state() == QAbstractSocket::UnconnectedState; -} - void ClientProxy::setSelectedItemsByObjectId(const QList<QDeclarativeDebugObjectReference> &objectRefs) { if (isConnected() && m_designClient) @@ -317,7 +196,6 @@ QDeclarativeDebugObjectReference QmlJSInspector::Internal::ClientProxy::rootObje return m_rootObject; } - QDeclarativeDebugObjectReference ClientProxy::objectReferenceForId(int debugId, const QDeclarativeDebugObjectReference &objectRef) const { @@ -527,7 +405,7 @@ void ClientProxy::setContextPathIndex(int contextIndex) bool ClientProxy::isDesignClientConnected() const { - return (m_designClient && m_conn->isConnected()); + return (m_designClient && m_adapter->isConnected()); } void ClientProxy::reloadEngines() @@ -560,3 +438,13 @@ void ClientProxy::updateEngineList() emit enginesChanged(); } + +Debugger::Internal::QmlAdapter *ClientProxy::qmlAdapter() const +{ + return m_adapter; +} + +bool ClientProxy::isConnected() const +{ + return m_adapter->isConnected(); +} diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.h b/src/plugins/qmljsinspector/qmljsclientproxy.h index 04f1bb6a5f..d3539ad1f3 100644 --- a/src/plugins/qmljsinspector/qmljsclientproxy.h +++ b/src/plugins/qmljsinspector/qmljsclientproxy.h @@ -35,6 +35,12 @@ QT_FORWARD_DECLARE_CLASS(QUrl) +namespace Debugger { +namespace Internal { +class QmlAdapter; +} +} + namespace QmlJSInspector { namespace Internal { @@ -46,7 +52,7 @@ class ClientProxy : public QObject Q_OBJECT public: - static ClientProxy *instance(); + explicit ClientProxy(Debugger::Internal::QmlAdapter *adapter, QObject *parent = 0); bool setBindingForObject(int objectDebugId, const QString &propertyName, @@ -63,15 +69,13 @@ public: QDeclarativeDebugObjectReference rootObjectReference() const; bool isConnected() const; - bool isUnconnected() const; void setSelectedItemsByObjectId(const QList<QDeclarativeDebugObjectReference> &objectRefs); - bool connectToViewer(const QString &host, quint16 port); - void disconnectFromViewer(); - QList<QDeclarativeDebugEngineReference> engines() const; + Debugger::Internal::QmlAdapter *qmlAdapter() const; + signals: void objectTreeUpdated(const QDeclarativeDebugObjectReference &rootObject); void connectionStatusMessage(const QString &text); @@ -81,7 +85,7 @@ signals: void selectedItemsChanged(const QList<QDeclarativeDebugObjectReference> &selectedItems); - void connected(QDeclarativeEngineDebug *client); + void connected(); void aboutToDisconnect(); void disconnected(); @@ -112,9 +116,10 @@ public slots: void setContextPathIndex(int contextIndex); private slots: + void disconnectFromServer(); + void connectToServer(); + void contextChanged(); - void connectionStateChanged(); - void connectionError(); void onCurrentObjectsChanged(const QList<int> &debugIds); void updateEngineList(); @@ -123,17 +128,14 @@ private slots: private: bool isDesignClientConnected() const; void reloadEngines(); - void createDebuggerClient(); + QList<QDeclarativeDebugObjectReference> objectReferences(const QUrl &url, const QDeclarativeDebugObjectReference &objectRef) const; QDeclarativeDebugObjectReference objectReferenceForId(int debugId, const QDeclarativeDebugObjectReference &ref) const; private: - explicit ClientProxy(QObject *parent = 0); Q_DISABLE_COPY(ClientProxy); - static ClientProxy *m_instance; - - QDeclarativeDebugConnection *m_conn; + Debugger::Internal::QmlAdapter *m_adapter; QDeclarativeEngineDebug *m_client; QmlJSDesignDebugClient *m_designClient; @@ -143,8 +145,6 @@ private: QDeclarativeDebugObjectReference m_rootObject; QList<QDeclarativeDebugEngineReference> m_engines; - - friend class QmlJSInspector::Internal::InspectorPlugin; }; } // namespace Internal diff --git a/src/plugins/qmljsinspector/qmljsinspector.cpp b/src/plugins/qmljsinspector/qmljsinspector.cpp index e6a5b7e8d8..3fa5fc1dc4 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.cpp +++ b/src/plugins/qmljsinspector/qmljsinspector.cpp @@ -28,8 +28,8 @@ **************************************************************************/ #include "qmljsinspectorconstants.h" #include "qmljsinspector.h" +#include "qmlinspectortoolbar.h" #include "qmljsclientproxy.h" -#include "qmljsinspectorcontext.h" #include "qmljslivetextpreview.h" #include "qmljsprivateapi.h" #include "qmljscontextcrumblepath.h" @@ -113,58 +113,98 @@ enum { ConnectionAttemptSimultaneousInterval = 500 }; -Inspector *Inspector::m_instance = 0; +InspectorUi *InspectorUi::m_instance = 0; -Inspector::Inspector(QObject *parent) - : QObject(parent), - m_connectionTimer(new QTimer(this)), - m_connectionAttempts(0), - m_listeningToEditorManager(false), - m_settings(new InspectorSettings(this)), - m_debugProject(0) +QmlJS::ModelManagerInterface *modelManager() { - m_clientProxy = ClientProxy::instance(); - m_instance = this; -//#warning set up the context widget - QWidget *contextWidget = 0; - m_context = new InspectorContext(contextWidget); - - connect(m_clientProxy, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)), - SLOT(setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference>))); - - connect(m_clientProxy, SIGNAL(connectionStatusMessage(QString)), SIGNAL(statusMessage(QString))); - connect(m_clientProxy, SIGNAL(connected(QDeclarativeEngineDebug*)), SLOT(connected(QDeclarativeEngineDebug*))); - connect(m_clientProxy, SIGNAL(disconnected()), SLOT(disconnected())); - connect(m_clientProxy, SIGNAL(enginesChanged()), SLOT(updateEngineList())); - connect(m_clientProxy, SIGNAL(serverReloaded()), this, SLOT(serverReloaded())); - - connect(m_connectionTimer, SIGNAL(timeout()), SLOT(pollInspector())); + return ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>(); } +InspectorUi::InspectorUi(QObject *parent) + : QObject(parent) + , m_listeningToEditorManager(false) + , m_settings(new InspectorSettings(this)) + , m_clientProxy(0) + , m_debugProject(0) +{ + m_instance = this; + m_toolbar = new QmlInspectorToolbar(this); +} -Inspector::~Inspector() +InspectorUi::~InspectorUi() { +} +void InspectorUi::setupUi() +{ + setupDockWidgets(); + m_toolbar->createActions(Core::Context(Constants::C_INSPECTOR)); + restoreSettings(); } -void Inspector::saveSettings() const +void InspectorUi::saveSettings() const { m_settings->saveSettings(Core::ICore::instance()->settings()); } -void Inspector::restoreSettings() +void InspectorUi::restoreSettings() { m_settings->restoreSettings(Core::ICore::instance()->settings()); } -void Inspector::disconnected() +void InspectorUi::connected(ClientProxy *clientProxy) +{ + m_clientProxy = clientProxy; + + connect(m_clientProxy, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)), + SLOT(setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference>))); + + connect(m_clientProxy, SIGNAL(enginesChanged()), SLOT(updateEngineList())); + connect(m_clientProxy, SIGNAL(serverReloaded()), this, SLOT(serverReloaded())); + connect(m_clientProxy, SIGNAL(contextPathUpdated(QStringList)), + m_crumblePath, SLOT(updateContextPath(QStringList))); + + m_debugProject = ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject(); + connect(m_debugProject, SIGNAL(destroyed()), SLOT(currentDebugProjectRemoved())); + + setupToolbar(true); + resetViews(); + + initializeDocuments(); + + QHashIterator<QString, QmlJSLiveTextPreview *> iter(m_textPreviews); + while(iter.hasNext()) { + iter.next(); + iter.value()->setClientProxy(m_clientProxy); + } +} + +void InspectorUi::disconnected() { + disconnect(m_clientProxy, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)), + this, SLOT(setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference>))); + + disconnect(m_clientProxy, SIGNAL(enginesChanged()), this, SLOT(updateEngineList())); + disconnect(m_clientProxy, SIGNAL(serverReloaded()), this, SLOT(serverReloaded())); + disconnect(m_clientProxy, SIGNAL(contextPathUpdated(QStringList)), + m_crumblePath, SLOT(updateContextPath(QStringList))); + m_debugProject = 0; resetViews(); + + setupToolbar(false); applyChangesToQmlObserverHelper(false); + + QHashIterator<QString, QmlJSLiveTextPreview *> iter(m_textPreviews); + while(iter.hasNext()) { + iter.next(); + iter.value()->setClientProxy(0); + } + + m_clientProxy = 0; } -void Inspector::updateEngineList() +void InspectorUi::updateEngineList() { const QList<QDeclarativeDebugEngineReference> engines = m_clientProxy->engines(); @@ -178,40 +218,14 @@ void Inspector::updateEngineList() } } -void Inspector::changeSelectedItems(const QList<QDeclarativeDebugObjectReference> &objects) +void InspectorUi::changeSelectedItems(const QList<QDeclarativeDebugObjectReference> &objects) { m_clientProxy->setSelectedItemsByObjectId(objects); } -void Inspector::pollInspector() +void InspectorUi::initializeDocuments() { - ++m_connectionAttempts; - - const QString host = m_runConfigurationDebugData.serverAddress; - const quint16 port = quint16(m_runConfigurationDebugData.serverPort); - - if (m_clientProxy->connectToViewer(host, port)) { - initializeDocuments(); - m_connectionTimer->stop(); - m_connectionAttempts = 0; - } else if (m_connectionAttempts == MaxConnectionAttempts) { - m_connectionTimer->stop(); - m_connectionAttempts = 0; - - QMessageBox::critical(0, - tr("Failed to connect to debugger"), - tr("Could not connect to debugger server.") ); - } -} - -QmlJS::ModelManagerInterface *Inspector::modelManager() -{ - return ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>(); -} - -void Inspector::initializeDocuments() -{ - if (!modelManager()) + if (!modelManager() || !m_clientProxy) return; Core::EditorManager *em = Core::EditorManager::instance(); @@ -231,7 +245,7 @@ void Inspector::initializeDocuments() applyChangesToQmlObserverHelper(true); } -void Inspector::serverReloaded() +void InspectorUi::serverReloaded() { QmlJS::Snapshot snapshot = modelManager()->snapshot(); m_loadedSnapshot = snapshot; @@ -240,22 +254,24 @@ void Inspector::serverReloaded() Document::Ptr doc = snapshot.document(it.key()); it.value()->resetInitialDoc(doc); } - ClientProxy::instance()->queryEngineContext(0); - //ClientProxy::instance()->refreshObjectTree(); + m_clientProxy->queryEngineContext(0); } -void Inspector::removePreviewForEditor(Core::IEditor *oldEditor) +void InspectorUi::removePreviewForEditor(Core::IEditor *oldEditor) { if (QmlJSLiveTextPreview *preview = m_textPreviews.value(oldEditor->file()->fileName())) { preview->unassociateEditor(oldEditor); } } -void Inspector::createPreviewForEditor(Core::IEditor *newEditor) +void InspectorUi::createPreviewForEditor(Core::IEditor *newEditor) { - if (newEditor && newEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID - && m_clientProxy->isConnected()) + if (m_clientProxy + && m_clientProxy->isConnected() + && newEditor + && newEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID + ) { QString filename = newEditor->file()->fileName(); QmlJS::Document::Ptr doc = modelManager()->snapshot().document(filename); @@ -268,7 +284,7 @@ void Inspector::createPreviewForEditor(Core::IEditor *newEditor) if (m_textPreviews.contains(filename)) { m_textPreviews.value(filename)->associateEditor(newEditor); } else { - QmlJSLiveTextPreview *preview = new QmlJSLiveTextPreview(doc, initdoc, this); + QmlJSLiveTextPreview *preview = new QmlJSLiveTextPreview(doc, initdoc, m_clientProxy, this); connect(preview, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)), SLOT(changeSelectedItems(QList<QDeclarativeDebugObjectReference>))); @@ -282,55 +298,23 @@ void Inspector::createPreviewForEditor(Core::IEditor *newEditor) } } -bool Inspector::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 Inspector::startQmlProjectDebugger() -{ - m_connectionTimer->start(); -} - -void Inspector::currentDebugProjectRemoved() +void InspectorUi::currentDebugProjectRemoved() { m_debugProject = 0; } -void Inspector::resetViews() +void InspectorUi::resetViews() { m_crumblePath->updateContextPath(QStringList()); } -void Inspector::connected(QDeclarativeEngineDebug *client) -{ - m_debugProject = ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject(); - connect(m_debugProject, SIGNAL(destroyed()), SLOT(currentDebugProjectRemoved())); - m_client = client; - resetViews(); -} - -void Inspector::reloadQmlViewer() +void InspectorUi::reloadQmlViewer() { - m_clientProxy->reloadQmlViewer(); + if (m_clientProxy) + m_clientProxy->reloadQmlViewer(); } -void Inspector::setSimpleDockWidgetArrangement() +void InspectorUi::setSimpleDockWidgetArrangement() { Utils::FancyMainWindow *mainWindow = Debugger::DebuggerUISwitcher::instance()->mainWindow(); @@ -342,13 +326,13 @@ void Inspector::setSimpleDockWidgetArrangement() mainWindow->setTrackingEnabled(true); } -void Inspector::setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference> objectReferences) +void InspectorUi::setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference> objectReferences) { if (objectReferences.length()) gotoObjectReferenceDefinition(objectReferences.first()); } -void Inspector::gotoObjectReferenceDefinition(const QDeclarativeDebugObjectReference &obj) +void InspectorUi::gotoObjectReferenceDefinition(const QDeclarativeDebugObjectReference &obj) { Q_UNUSED(obj); @@ -369,22 +353,7 @@ void Inspector::gotoObjectReferenceDefinition(const QDeclarativeDebugObjectRefer } } -QDeclarativeDebugExpressionQuery *Inspector::executeExpression(int objectDebugId, const QString &objectId, - const QString &propertyName, const QVariant &value) -{ - if (objectId.length()) { - QString quoteWrappedValue = value.toString(); - if (addQuotesForData(value)) - quoteWrappedValue = QString("'%1'").arg(quoteWrappedValue); // ### FIXME this code is wrong! - - QString constructedExpression = objectId + "." + propertyName + "=" + quoteWrappedValue; - return m_client.data()->queryExpressionResult(objectDebugId, constructedExpression, this); - } - - return 0; -} - -bool Inspector::addQuotesForData(const QVariant &value) const +bool InspectorUi::addQuotesForData(const QVariant &value) const { switch (value.type()) { case QVariant::String: @@ -398,7 +367,7 @@ bool Inspector::addQuotesForData(const QVariant &value) const return false; } -void Inspector::createDockWidgets() +void InspectorUi::setupDockWidgets() { m_crumblePath = new ContextCrumblePath; m_crumblePath->setObjectName("QmlContextPath"); @@ -409,43 +378,42 @@ void Inspector::createDockWidgets() m_crumblePath, Qt::BottomDockWidgetArea); m_crumblePathDock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); m_crumblePathDock->setTitleBarWidget(new QWidget(m_crumblePathDock)); - connect(m_clientProxy, SIGNAL(contextPathUpdated(QStringList)), m_crumblePath, SLOT(updateContextPath(QStringList))); } -void Inspector::crumblePathElementClicked(int pathIndex) +void InspectorUi::crumblePathElementClicked(int pathIndex) { - if (m_clientProxy->isConnected() && !m_crumblePath->isEmpty()) { + if (m_clientProxy && m_clientProxy->isConnected() && !m_crumblePath->isEmpty()) { m_clientProxy->setContextPathIndex(pathIndex); } } -bool Inspector::showExperimentalWarning() +bool InspectorUi::showExperimentalWarning() { return m_settings->showLivePreviewWarning(); } -void Inspector::setShowExperimentalWarning(bool value) +void InspectorUi::setShowExperimentalWarning(bool value) { m_settings->setShowLivePreviewWarning(value); } -Inspector *Inspector::instance() +InspectorUi *InspectorUi::instance() { return m_instance; } -ProjectExplorer::Project *Inspector::debugProject() const +ProjectExplorer::Project *InspectorUi::debugProject() const { return m_debugProject; } -void Inspector::setApplyChangesToQmlObserver(bool applyChanges) +void InspectorUi::setApplyChangesToQmlObserver(bool applyChanges) { emit livePreviewActivated(applyChanges); applyChangesToQmlObserverHelper(applyChanges); } -void Inspector::applyChangesToQmlObserverHelper(bool applyChanges) +void InspectorUi::applyChangesToQmlObserverHelper(bool applyChanges) { QHashIterator<QString, QmlJSLiveTextPreview *> iter(m_textPreviews); while(iter.hasNext()) { @@ -454,7 +422,58 @@ void Inspector::applyChangesToQmlObserverHelper(bool applyChanges) } } -void Inspector::disableLivePreview() +void InspectorUi::disableLivePreview() { setApplyChangesToQmlObserver(false); } + +void InspectorUi::setupToolbar(bool doConnect) +{ + if (doConnect) { + connect(m_clientProxy, SIGNAL(connected()), m_toolbar, SLOT(enable())); + connect(m_clientProxy, SIGNAL(disconnected()), m_toolbar, SLOT(disable())); + + connect(m_toolbar, SIGNAL(designModeSelected(bool)), m_clientProxy, SLOT(setDesignModeBehavior(bool))); + connect(m_toolbar, SIGNAL(reloadSelected()), m_clientProxy, SLOT(reloadQmlViewer())); + connect(m_toolbar, SIGNAL(animationSpeedChanged(qreal)), m_clientProxy, SLOT(setAnimationSpeed(qreal))); + connect(m_toolbar, SIGNAL(colorPickerSelected()), m_clientProxy, SLOT(changeToColorPickerTool())); + connect(m_toolbar, SIGNAL(zoomToolSelected()), m_clientProxy, SLOT(changeToZoomTool())); + connect(m_toolbar, SIGNAL(selectToolSelected()), m_clientProxy, SLOT(changeToSelectTool())); + connect(m_toolbar, SIGNAL(marqueeSelectToolSelected()), m_clientProxy, SLOT(changeToSelectMarqueeTool())); + connect(m_toolbar, SIGNAL(applyChangesFromQmlFileTriggered(bool)), this, SLOT(setApplyChangesToQmlObserver(bool))); + + connect(this, SIGNAL(livePreviewActivated(bool)), m_toolbar, SLOT(setLivePreviewChecked(bool))); + connect(m_clientProxy, SIGNAL(colorPickerActivated()), m_toolbar, SLOT(activateColorPicker())); + connect(m_clientProxy, SIGNAL(selectToolActivated()), m_toolbar, SLOT(activateSelectTool())); + connect(m_clientProxy, SIGNAL(selectMarqueeToolActivated()), m_toolbar, SLOT(activateMarqueeSelectTool())); + connect(m_clientProxy, SIGNAL(zoomToolActivated()), m_toolbar, SLOT(activateZoomTool())); + connect(m_clientProxy, SIGNAL(designModeBehaviorChanged(bool)), m_toolbar, SLOT(setDesignModeBehavior(bool))); + connect(m_clientProxy, SIGNAL(selectedColorChanged(QColor)), m_toolbar, SLOT(setSelectedColor(QColor))); + + connect(m_clientProxy, SIGNAL(animationSpeedChanged(qreal)), m_toolbar, SLOT(changeAnimationSpeed(qreal))); + m_toolbar->enable(); + } else { + disconnect(m_clientProxy, SIGNAL(connected()), m_toolbar, SLOT(enable())); + disconnect(m_clientProxy, SIGNAL(disconnected()), m_toolbar, SLOT(disable())); + + disconnect(m_toolbar, SIGNAL(designModeSelected(bool)), m_clientProxy, SLOT(setDesignModeBehavior(bool))); + disconnect(m_toolbar, SIGNAL(reloadSelected()), m_clientProxy, SLOT(reloadQmlViewer())); + disconnect(m_toolbar, SIGNAL(animationSpeedChanged(qreal)), m_clientProxy, SLOT(setAnimationSpeed(qreal))); + disconnect(m_toolbar, SIGNAL(colorPickerSelected()), m_clientProxy, SLOT(changeToColorPickerTool())); + disconnect(m_toolbar, SIGNAL(zoomToolSelected()), m_clientProxy, SLOT(changeToZoomTool())); + disconnect(m_toolbar, SIGNAL(selectToolSelected()), m_clientProxy, SLOT(changeToSelectTool())); + disconnect(m_toolbar, SIGNAL(marqueeSelectToolSelected()), m_clientProxy, SLOT(changeToSelectMarqueeTool())); + disconnect(m_toolbar, SIGNAL(applyChangesFromQmlFileTriggered(bool)), this, SLOT(setApplyChangesToQmlObserver(bool))); + + disconnect(this, SIGNAL(livePreviewActivated(bool)), m_toolbar, SLOT(setLivePreviewChecked(bool))); + disconnect(m_clientProxy, SIGNAL(colorPickerActivated()), m_toolbar, SLOT(activateColorPicker())); + disconnect(m_clientProxy, SIGNAL(selectToolActivated()), m_toolbar, SLOT(activateSelectTool())); + disconnect(m_clientProxy, SIGNAL(selectMarqueeToolActivated()), m_toolbar, SLOT(activateMarqueeSelectTool())); + disconnect(m_clientProxy, SIGNAL(zoomToolActivated()), m_toolbar, SLOT(activateZoomTool())); + disconnect(m_clientProxy, SIGNAL(designModeBehaviorChanged(bool)), m_toolbar, SLOT(setDesignModeBehavior(bool))); + disconnect(m_clientProxy, SIGNAL(selectedColorChanged(QColor)), m_toolbar, SLOT(setSelectedColor(QColor))); + + disconnect(m_clientProxy, SIGNAL(animationSpeedChanged(qreal)), m_toolbar, SLOT(changeAnimationSpeed(qreal))); + m_toolbar->disable(); + } +} diff --git a/src/plugins/qmljsinspector/qmljsinspector.h b/src/plugins/qmljsinspector/qmljsinspector.h index 6e9e7e4ce6..b7b5020a2a 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.h +++ b/src/plugins/qmljsinspector/qmljsinspector.h @@ -59,13 +59,13 @@ QT_FORWARD_DECLARE_CLASS(QDockWidget) namespace QmlJSInspector { namespace Internal { +class QmlInspectorToolbar; class ClientProxy; -class InspectorContext; class InspectorSettings; class ContextCrumblePath; class QmlJSLiveTextPreview; -class Inspector : public QObject +class InspectorUi : public QObject { Q_OBJECT @@ -76,33 +76,23 @@ public: QmlProjectWithCppPlugins }; public: - Inspector(QObject *parent = 0); - virtual ~Inspector(); + InspectorUi(QObject *parent = 0); + virtual ~InspectorUi(); - bool connectToViewer(); // using host, port from widgets - - // returns false if project is not debuggable. - bool setDebugConfigurationDataFromProject(ProjectExplorer::Project *projectToDebug); - void startQmlProjectDebugger(); - - QDeclarativeDebugExpressionQuery *executeExpression(int objectDebugId, const QString &objectId, - const QString &propertyName, const QVariant &value); - - QDeclarativeDebugExpressionQuery *setBindingForObject(int objectDebugId, const QString &objectId, - const QString &propertyName, const QVariant &value, - bool isLiteralValue); void saveSettings() const; void restoreSettings(); bool showExperimentalWarning(); void setShowExperimentalWarning(bool value); - static Inspector *instance(); + static InspectorUi *instance(); // returns the project being currently debugged, or 0 if not debugging anything ProjectExplorer::Project *debugProject() const; - void createDockWidgets(); + void setupUi(); + void connected(ClientProxy *clientProxy); + void disconnected(); signals: void statusMessage(const QString &text); @@ -117,15 +107,11 @@ public slots: private slots: void gotoObjectReferenceDefinition(const QDeclarativeDebugObjectReference &obj); - void pollInspector(); - void setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference> objectReferences); void changeSelectedItems(const QList<QDeclarativeDebugObjectReference> &objects); - void connected(QDeclarativeEngineDebug *client); void updateEngineList(); - void disconnected(); void removePreviewForEditor(Core::IEditor *newEditor); void createPreviewForEditor(Core::IEditor *newEditor); @@ -139,32 +125,29 @@ private: bool addQuotesForData(const QVariant &value) const; void resetViews(); - - QmlJS::ModelManagerInterface *modelManager(); void initializeDocuments(); void applyChangesToQmlObserverHelper(bool applyChanges); + void setupToolbar(bool doConnect); + void setupDockWidgets(); private: QWeakPointer<QDeclarativeEngineDebug> m_client; - QmlProjectManager::QmlProjectRunConfigurationDebugData m_runConfigurationDebugData; - InspectorContext *m_context; - QTimer *m_connectionTimer; - int m_connectionAttempts; - ClientProxy *m_clientProxy; bool m_listeningToEditorManager; + QmlInspectorToolbar *m_toolbar; ContextCrumblePath *m_crumblePath; QDockWidget *m_crumblePathDock; InspectorSettings *m_settings; + ClientProxy *m_clientProxy; // Qml/JS integration QHash<QString, QmlJSLiveTextPreview *> m_textPreviews; QmlJS::Snapshot m_loadedSnapshot; //the snapshot loaded by the viewer ProjectExplorer::Project *m_debugProject; - static Inspector *m_instance; + static InspectorUi *m_instance; }; } // Internal diff --git a/src/plugins/qmljsinspector/qmljsinspector.pro b/src/plugins/qmljsinspector/qmljsinspector.pro index 5f96f765da..31b405eb7c 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.pro +++ b/src/plugins/qmljsinspector/qmljsinspector.pro @@ -8,10 +8,8 @@ DEFINES += QMLJSINSPECTOR_LIBRARY HEADERS += \ qmljsprivateapi.h \ -qmljsdebuggerclient.h \ qmljsinspector_global.h \ qmljsinspectorconstants.h \ -qmljsinspectorcontext.h \ qmljsinspectorplugin.h \ qmljsclientproxy.h \ qmljsinspector.h \ @@ -23,8 +21,6 @@ qmljscontextcrumblepath.h \ qmljsinspectorsettings.h SOURCES += \ -qmljsdebuggerclient.cpp \ -qmljsinspectorcontext.cpp \ qmljsinspectorplugin.cpp \ qmljsclientproxy.cpp \ qmljsinspector.cpp \ diff --git a/src/plugins/qmljsinspector/qmljsinspectorcontext.cpp b/src/plugins/qmljsinspector/qmljsinspectorcontext.cpp deleted file mode 100644 index 3a687adf5c..0000000000 --- a/src/plugins/qmljsinspector/qmljsinspectorcontext.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** Commercial Usage -** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** -**************************************************************************/ - -#include "qmljsinspectorcontext.h" -#include "qmljsinspectorconstants.h" - -#include <coreplugin/icore.h> -#include <QtGui/QWidget> -#include <QtCore/QDebug> - -using namespace QmlJSInspector::Internal; -using namespace QmlJSInspector::Constants; - -InspectorContext::InspectorContext(QWidget *widget) - : IContext(widget), - m_widget(widget), - m_context(C_INSPECTOR) -{ -} - -InspectorContext::~InspectorContext() -{ -} - -Core::Context InspectorContext::context() const -{ - return m_context; -} - -QWidget *InspectorContext::widget() -{ - return m_widget; -} - -void InspectorContext::setContextHelpId(const QString &helpId) -{ - m_contextHelpId = helpId; -} - -QString InspectorContext::contextHelpId() const -{ - return m_contextHelpId; -} - -QString InspectorContext::contextHelpIdForProperty(const QString &itemName, const QString &propName) -{ - // TODO this functionality is not supported yet as we don't have help id's for - // properties. - return QString("QML.").append(itemName).append(".").append(propName); -} - -QString InspectorContext::contextHelpIdForItem(const QString &itemName) -{ - return QString("QML.").append(itemName); -} - diff --git a/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp b/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp index b28614f9c7..211a55f325 100644 --- a/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp +++ b/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp @@ -35,25 +35,16 @@ #include <debugger/debuggeruiswitcher.h> #include <debugger/debuggerconstants.h> +#include <debugger/qml/qmladapter.h> #include <qmlprojectmanager/qmlproject.h> #include <qmljseditor/qmljseditorconstants.h> #include <extensionsystem/pluginmanager.h> -#include <projectexplorer/projectexplorer.h> -#include <projectexplorer/runconfiguration.h> -#include <projectexplorer/projectexplorer.h> -#include <projectexplorer/projectexplorerconstants.h> -#include <projectexplorer/project.h> - -#include <coreplugin/modemanager.h> -#include <coreplugin/imode.h> #include <coreplugin/icore.h> #include <coreplugin/icontext.h> #include <coreplugin/coreconstants.h> -#include <coreplugin/actionmanager/actionmanager.h> -#include <coreplugin/actionmanager/command.h> #include <QtCore/QStringList> #include <QtCore/QtPlugin> @@ -71,23 +62,16 @@ namespace { InspectorPlugin *g_instance = 0; // the global QML/JS inspector instance -QToolButton *createToolButton(QAction *action) -{ - QToolButton *button = new QToolButton; - button->setDefaultAction(action); - return button; -} - } // end of anonymous namespace InspectorPlugin::InspectorPlugin() + : IPlugin() + , m_clientProxy(0) { Q_ASSERT(! g_instance); g_instance = this; - m_clientProxy = new ClientProxy(this); - m_inspector = new Inspector(this); - m_toolbar = new QmlInspectorToolbar(this); + m_inspectorUi = new InspectorUi(this); } InspectorPlugin::~InspectorPlugin() @@ -99,24 +83,19 @@ QmlJS::ModelManagerInterface *InspectorPlugin::modelManager() const return ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>(); } -ClientProxy *InspectorPlugin::clientProxy() const -{ - return m_clientProxy; -} - InspectorPlugin *InspectorPlugin::instance() { return g_instance; } -Inspector *InspectorPlugin::inspector() const +InspectorUi *InspectorPlugin::inspector() const { - return m_inspector; + return m_inspectorUi; } ExtensionSystem::IPlugin::ShutdownFlag InspectorPlugin::aboutToShutdown() { - m_inspector->saveSettings(); + m_inspectorUi->saveSettings(); return SynchronousShutdown; } @@ -125,95 +104,51 @@ bool InspectorPlugin::initialize(const QStringList &arguments, QString *errorStr Q_UNUSED(arguments); Q_UNUSED(errorString); - connect(Core::ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)), - SLOT(prepareDebugger(Core::IMode*))); - ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance(); Debugger::DebuggerUISwitcher *uiSwitcher = pluginManager->getObject<Debugger::DebuggerUISwitcher>(); uiSwitcher->addLanguage(LANG_QML, Core::Context(C_INSPECTOR)); - m_inspector->createDockWidgets(); - return true; } void InspectorPlugin::extensionsInitialized() { ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance(); - Debugger::DebuggerUISwitcher *uiSwitcher = pluginManager->getObject<Debugger::DebuggerUISwitcher>(); + Debugger::DebuggerUISwitcher *uiSwitcher = pluginManager->getObject<Debugger::DebuggerUISwitcher>(); connect(uiSwitcher, SIGNAL(dockArranged(QString)), SLOT(setDockWidgetArrangement(QString))); - if (ProjectExplorer::ProjectExplorerPlugin *pex = ProjectExplorer::ProjectExplorerPlugin::instance()) { - connect(pex, SIGNAL(aboutToExecuteProject(ProjectExplorer::Project*, QString)), - SLOT(activateDebuggerForProject(ProjectExplorer::Project*, QString))); - } - m_toolbar->createActions(Core::Context(C_INSPECTOR)); - - connect(m_clientProxy, SIGNAL(connected(QDeclarativeEngineDebug*)), m_toolbar, SLOT(enable())); - connect(m_clientProxy, SIGNAL(disconnected()), m_toolbar, SLOT(disable())); - - connect(m_toolbar, SIGNAL(designModeSelected(bool)), m_clientProxy, SLOT(setDesignModeBehavior(bool))); - connect(m_toolbar, SIGNAL(reloadSelected()), m_clientProxy, SLOT(reloadQmlViewer())); - connect(m_toolbar, SIGNAL(animationSpeedChanged(qreal)), m_clientProxy, SLOT(setAnimationSpeed(qreal))); - connect(m_toolbar, SIGNAL(colorPickerSelected()), m_clientProxy, SLOT(changeToColorPickerTool())); - connect(m_toolbar, SIGNAL(zoomToolSelected()), m_clientProxy, SLOT(changeToZoomTool())); - connect(m_toolbar, SIGNAL(selectToolSelected()), m_clientProxy, SLOT(changeToSelectTool())); - connect(m_toolbar, SIGNAL(marqueeSelectToolSelected()), m_clientProxy, SLOT(changeToSelectMarqueeTool())); - connect(m_toolbar, SIGNAL(applyChangesFromQmlFileTriggered(bool)), m_inspector, SLOT(setApplyChangesToQmlObserver(bool))); - - connect(m_inspector, SIGNAL(livePreviewActivated(bool)), m_toolbar, SLOT(setLivePreviewChecked(bool))); - connect(m_clientProxy, SIGNAL(colorPickerActivated()), m_toolbar, SLOT(activateColorPicker())); - connect(m_clientProxy, SIGNAL(selectToolActivated()), m_toolbar, SLOT(activateSelectTool())); - connect(m_clientProxy, SIGNAL(selectMarqueeToolActivated()), m_toolbar, SLOT(activateMarqueeSelectTool())); - connect(m_clientProxy, SIGNAL(zoomToolActivated()), m_toolbar, SLOT(activateZoomTool())); - connect(m_clientProxy, SIGNAL(designModeBehaviorChanged(bool)), m_toolbar, SLOT(setDesignModeBehavior(bool))); - connect(m_clientProxy, SIGNAL(selectedColorChanged(QColor)), m_toolbar, SLOT(setSelectedColor(QColor))); - - connect(m_clientProxy, SIGNAL(animationSpeedChanged(qreal)), m_toolbar, SLOT(changeAnimationSpeed(qreal))); - - m_inspector->restoreSettings(); + connect(pluginManager, SIGNAL(objectAdded(QObject*)), SLOT(objectAdded(QObject*))); + connect(pluginManager, SIGNAL(aboutToRemoveObject(QObject*)), SLOT(aboutToRemoveObject(QObject*))); + + m_inspectorUi->setupUi(); } -void InspectorPlugin::activateDebuggerForProject(ProjectExplorer::Project *project, const QString &runMode) +void InspectorPlugin::setDockWidgetArrangement(const QString &activeLanguage) { - Q_UNUSED(project); - Q_UNUSED(runMode); - - if (runMode == QLatin1String(ProjectExplorer::Constants::DEBUGMODE)) { -#ifdef __GNUC__ -# warning start a QML/JS debugging session using the information stored in the current project -#endif - - // FIXME we probably want to activate the debugger for other projects than QmlProjects, - // if they contain Qml files. Some kind of options should exist for this behavior. - if (QmlProjectManager::QmlProject *qmlproj = qobject_cast<QmlProjectManager::QmlProject*>(project)) { - if (m_inspector->setDebugConfigurationDataFromProject(qmlproj)) - m_inspector->startQmlProjectDebugger(); - } - } + if (activeLanguage == QmlJSInspector::Constants::LANG_QML || activeLanguage.isEmpty()) + m_inspectorUi->setSimpleDockWidgetArrangement(); } -void InspectorPlugin::prepareDebugger(Core::IMode *mode) +// The adapter object is only added to the pool with a succesful connection, +// so we can immediately init our stuff. +void InspectorPlugin::objectAdded(QObject *object) { - if (mode->id() != QLatin1String(Debugger::Constants::MODE_DEBUG)) - return; - - ProjectExplorer::ProjectExplorerPlugin *pex = ProjectExplorer::ProjectExplorerPlugin::instance(); - - if (pex->startupProject() && pex->startupProject()->id() == QLatin1String("QmlProjectManager.QmlProject")) { - ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance(); - Debugger::DebuggerUISwitcher *uiSwitcher = pluginManager->getObject<Debugger::DebuggerUISwitcher>(); - uiSwitcher->setActiveLanguage(LANG_QML); + Debugger::Internal::QmlAdapter *adapter = qobject_cast<Debugger::Internal::QmlAdapter *>(object); + if (adapter) { + m_clientProxy = new ClientProxy(adapter); + m_inspectorUi->connected(m_clientProxy); } } -void InspectorPlugin::setDockWidgetArrangement(const QString &activeLanguage) +void InspectorPlugin::aboutToRemoveObject(QObject *obj) { - if (activeLanguage == QmlJSInspector::Constants::LANG_QML || activeLanguage.isEmpty()) - m_inspector->setSimpleDockWidgetArrangement(); + if (m_clientProxy && m_clientProxy->qmlAdapter() == obj) { + m_inspectorUi->disconnected(); + delete m_clientProxy; + m_clientProxy = 0; + } } - Q_EXPORT_PLUGIN(InspectorPlugin) diff --git a/src/plugins/qmljsinspector/qmljsinspectorplugin.h b/src/plugins/qmljsinspector/qmljsinspectorplugin.h index 9ce481266f..9849f2a8a8 100644 --- a/src/plugins/qmljsinspector/qmljsinspectorplugin.h +++ b/src/plugins/qmljsinspector/qmljsinspectorplugin.h @@ -49,9 +49,8 @@ namespace ProjectExplorer { namespace QmlJSInspector { namespace Internal { -class QmlInspectorToolbar; class ClientProxy; -class Inspector; +class InspectorUi; class InspectorPlugin : public ExtensionSystem::IPlugin { @@ -64,8 +63,7 @@ public: static InspectorPlugin *instance(); QmlJS::ModelManagerInterface *modelManager() const; - ClientProxy *clientProxy() const; - Inspector *inspector() const; + InspectorUi *inspector() const; // ExtensionSystem::IPlugin interface virtual bool initialize(const QStringList &arguments, QString *errorString); @@ -73,19 +71,19 @@ public: virtual ExtensionSystem::IPlugin::ShutdownFlag aboutToShutdown(); public slots: - void activateDebuggerForProject(ProjectExplorer::Project *project, const QString &runMode); void setDockWidgetArrangement(const QString &activeLanguage); private slots: void prepareDebugger(Core::IMode *mode); + void objectAdded(QObject *object); + void aboutToRemoveObject(QObject *obj); private: void createActions(); private: ClientProxy *m_clientProxy; - Inspector *m_inspector; - QmlInspectorToolbar *m_toolbar; + InspectorUi *m_inspectorUi; }; } // end of namespace Internal diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp index 4dbd6468d8..2e66d4e112 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp @@ -167,19 +167,27 @@ void QmlJSLiveTextPreview::unassociateEditor(Core::IEditor *oldEditor) } } -QmlJSLiveTextPreview::QmlJSLiveTextPreview(const QmlJS::Document::Ptr &doc, const QmlJS::Document::Ptr &initDoc, QObject* parent) : - QObject(parent), m_previousDoc(doc), m_initialDoc(initDoc), m_applyChangesToQmlObserver(true) +QmlJSLiveTextPreview::QmlJSLiveTextPreview(const QmlJS::Document::Ptr &doc, + const QmlJS::Document::Ptr &initDoc, + ClientProxy *clientProxy, + QObject* parent) + : QObject(parent) + , m_previousDoc(doc) + , m_initialDoc(initDoc) + , m_applyChangesToQmlObserver(true) + , m_clientProxy(clientProxy) { Q_ASSERT(doc->fileName() == initDoc->fileName()); - ClientProxy *clientProxy = ClientProxy::instance(); m_filename = doc->fileName(); connect(modelManager(), SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)), SLOT(documentChanged(QmlJS::Document::Ptr))); - connect(clientProxy, - SIGNAL(objectTreeUpdated(QDeclarativeDebugObjectReference)), - SLOT(updateDebugIds(QDeclarativeDebugObjectReference))); + if (m_clientProxy.data()) { + connect(m_clientProxy.data(), + SIGNAL(objectTreeUpdated(QDeclarativeDebugObjectReference)), + SLOT(updateDebugIds(QDeclarativeDebugObjectReference))); + } } void QmlJSLiveTextPreview::resetInitialDoc(const QmlJS::Document::Ptr &doc) @@ -209,14 +217,12 @@ QList<int> QmlJSLiveTextPreview::objectReferencesForOffset(quint32 offset) const void QmlJSLiveTextPreview::changeSelectedElements(QList<int> offsets, const QString &wordAtCursor) { - if (m_editors.isEmpty() || !m_previousDoc) + if (m_editors.isEmpty() || !m_previousDoc || !m_clientProxy) return; - ClientProxy *clientProxy = ClientProxy::instance(); - QDeclarativeDebugObjectReference objectRefUnderCursor; if (!wordAtCursor.isEmpty() && wordAtCursor[0].isUpper()) { - QList<QDeclarativeDebugObjectReference> refs = clientProxy->objectReferences(); + QList<QDeclarativeDebugObjectReference> refs = m_clientProxy.data()->objectReferences(); foreach (const QDeclarativeDebugObjectReference &ref, refs) { if (ref.idString() == wordAtCursor) { objectRefUnderCursor = ref; @@ -431,7 +437,7 @@ protected: Q_UNUSED(scriptBinding); checkUnsyncronizableElementChanges(parentDefinition); appliedChangesToViewer = true; - ClientProxy::instance()->setMethodBodyForObject(debugId, methodName, methodBody); + m_clientProxy->setMethodBodyForObject(debugId, methodName, methodBody); } virtual void updateScriptBinding(DebugId debugId, @@ -453,19 +459,19 @@ protected: if (isLiteral) expr = castToLiteral(scriptCode, scriptBinding); appliedChangesToViewer = true; - ClientProxy::instance()->setBindingForObject(debugId, propertyName, expr, isLiteral); + m_clientProxy->setBindingForObject(debugId, propertyName, expr, isLiteral); } virtual void resetBindingForObject(int debugId, const QString &propertyName) { appliedChangesToViewer = true; - ClientProxy::instance()->resetBindingForObject(debugId, propertyName); + m_clientProxy->resetBindingForObject(debugId, propertyName); } virtual void removeObject(int debugId) { appliedChangesToViewer = true; - ClientProxy::instance()->destroyQmlObject(debugId); + m_clientProxy->destroyQmlObject(debugId); } virtual void createObject(const QString& qmlText, DebugId ref, @@ -473,7 +479,7 @@ protected: { appliedChangesToViewer = true; referenceRefreshRequired = true; - ClientProxy::instance()->createQmlObject(qmlText, ref, importList, filename); + m_clientProxy->createQmlObject(qmlText, ref, importList, filename); } void checkUnsyncronizableElementChanges(UiObjectDefinition *parentDefinition) @@ -513,19 +519,27 @@ protected: } public: - UpdateObserver() : appliedChangesToViewer(false), referenceRefreshRequired(false), unsyncronizableChanges(QmlJSLiveTextPreview::NoUnsyncronizableChanges) {} + UpdateObserver(ClientProxy *clientProxy) + : appliedChangesToViewer(false) + , referenceRefreshRequired(false) + , unsyncronizableChanges(QmlJSLiveTextPreview::NoUnsyncronizableChanges) + , m_clientProxy(clientProxy) + { + + } bool appliedChangesToViewer; bool referenceRefreshRequired; QString unsyncronizableElementName; QmlJSLiveTextPreview::UnsyncronizableChangeType unsyncronizableChanges; unsigned unsyncronizableChangeLine; unsigned unsyncronizableChangeColumn; + ClientProxy *m_clientProxy; }; void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) { - if (doc->fileName() != m_previousDoc->fileName()) + if (doc->fileName() != m_previousDoc->fileName() || !m_clientProxy) return; Core::ICore *core = Core::ICore::instance(); @@ -534,7 +548,7 @@ void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) if (!core->hasContext(dbgcontext)) return; - if (ProjectExplorer::Project *debugProject = Inspector::instance()->debugProject()) { + if (ProjectExplorer::Project *debugProject = InspectorUi::instance()->debugProject()) { QStringList files = debugProject->files(ProjectExplorer::Project::ExcludeGeneratedFiles); if (!files.contains(doc->fileName())) return; @@ -548,16 +562,16 @@ void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) if (doc && m_previousDoc && doc->fileName() == m_previousDoc->fileName() && doc->qmlProgram() && m_previousDoc->qmlProgram()) { - UpdateObserver delta; + UpdateObserver delta(m_clientProxy.data()); m_debugIds = delta(m_previousDoc, doc, m_debugIds); if (delta.referenceRefreshRequired) - ClientProxy::instance()->refreshObjectTree(); + m_clientProxy.data()->refreshObjectTree(); - if (Inspector::instance()->showExperimentalWarning() && delta.appliedChangesToViewer) { + if (InspectorUi::instance()->showExperimentalWarning() && delta.appliedChangesToViewer) { showExperimentalWarning(); experimentalWarningShown = true; - Inspector::instance()->setShowExperimentalWarning(false); + InspectorUi::instance()->setShowExperimentalWarning(false); } if (delta.unsyncronizableChanges != NoUnsyncronizableChanges && !experimentalWarningShown) @@ -568,7 +582,7 @@ void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) if (!delta.newObjects.isEmpty()) m_createdObjects[doc] += delta.newObjects; - ClientProxy::instance()->clearComponentCache(); + m_clientProxy.data()->clearComponentCache(); } } else { m_docWithUnappliedChanges = doc; @@ -634,5 +648,23 @@ void QmlJSLiveTextPreview::setApplyChangesToQmlObserver(bool applyChanges) m_applyChangesToQmlObserver = applyChanges; } +void QmlJSLiveTextPreview::setClientProxy(ClientProxy *clientProxy) +{ + if (m_clientProxy.data()) { + disconnect(m_clientProxy.data(), + SIGNAL(objectTreeUpdated(QDeclarativeDebugObjectReference)), + this, + SLOT(updateDebugIds(QDeclarativeDebugObjectReference))); + } + + m_clientProxy = clientProxy; + + if (m_clientProxy.data()) { + connect(m_clientProxy.data(), + SIGNAL(objectTreeUpdated(QDeclarativeDebugObjectReference)), + SLOT(updateDebugIds(QDeclarativeDebugObjectReference))); + } +} + } // namespace Internal } // namespace QmlJSInspector diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.h b/src/plugins/qmljsinspector/qmljslivetextpreview.h index 8d1fda0ea0..63f471cc55 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.h +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.h @@ -56,12 +56,17 @@ namespace Internal { namespace QmlJSInspector { namespace Internal { +class ClientProxy; + class QmlJSLiveTextPreview : public QObject { Q_OBJECT public: - explicit QmlJSLiveTextPreview(const QmlJS::Document::Ptr &doc, const QmlJS::Document::Ptr &initDoc, QObject *parent = 0); + explicit QmlJSLiveTextPreview(const QmlJS::Document::Ptr &doc, + const QmlJS::Document::Ptr &initDoc, + ClientProxy *clientProxy, + QObject *parent = 0); //void updateDocuments(); void associateEditor(Core::IEditor *editor); @@ -70,6 +75,8 @@ public: void mapObjectToQml(const QDeclarativeDebugObjectReference &object); void resetInitialDoc(const QmlJS::Document::Ptr &doc); + void setClientProxy(ClientProxy *clientProxy); + enum UnsyncronizableChangeType { NoUnsyncronizableChanges, AttributeChangeWarning, @@ -111,6 +118,7 @@ private: bool m_applyChangesToQmlObserver; QmlJS::Document::Ptr m_docWithUnappliedChanges; + QWeakPointer<ClientProxy> m_clientProxy; }; diff --git a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp index a495503084..8f48010557 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp @@ -37,8 +37,11 @@ #include <projectexplorer/applicationlauncher.h> #include <utils/qtcassert.h> +#include <debugger/debuggerrunner.h> +#include <debugger/debuggerplugin.h> #include <debugger/debuggerconstants.h> #include <debugger/debuggeruiswitcher.h> +#include <debugger/debuggerengine.h> #include <qmljsinspector/qmljsinspectorconstants.h> #include <QDir> @@ -143,16 +146,27 @@ bool QmlRunControlFactory::canRun(RunConfiguration *runConfiguration, QmlProjectRunConfiguration *config = qobject_cast<QmlProjectRunConfiguration*>(runConfiguration); if (mode == ProjectExplorer::Constants::RUNMODE) { return config != 0; - } else { - return (config != 0) && Debugger::DebuggerUISwitcher::instance()->supportedLanguages().contains(QmlProjectManager::Constants::LANG_QML); + } else if (mode == ProjectExplorer::Constants::DEBUGMODE) { + bool qmlDebugSupportInstalled = Debugger::DebuggerUISwitcher::instance()->supportedLanguages().contains(QmlProjectManager::Constants::LANG_QML); + return (config != 0) && qmlDebugSupportInstalled; } + + return false; } RunControl *QmlRunControlFactory::create(RunConfiguration *runConfiguration, const QString &mode) { QTC_ASSERT(canRun(runConfiguration, mode), return 0); - return new QmlRunControl(qobject_cast<QmlProjectRunConfiguration *>(runConfiguration), mode); + + QmlProjectRunConfiguration *config = qobject_cast<QmlProjectRunConfiguration *>(runConfiguration); + RunControl *runControl = 0; + if (mode == ProjectExplorer::Constants::RUNMODE) { + runControl = new QmlRunControl(config, mode); + } else { + runControl = createDebugRunControl(config); + } + return runControl; } QString QmlRunControlFactory::displayName() const @@ -166,6 +180,25 @@ QWidget *QmlRunControlFactory::createConfigurationWidget(RunConfiguration *runCo return new QLabel("TODO add Configuration widget"); } +ProjectExplorer::RunControl *QmlRunControlFactory::createDebugRunControl(QmlProjectRunConfiguration *runConfig) +{ + ProjectExplorer::Environment environment = ProjectExplorer::Environment::systemEnvironment(); + environment.set(QmlProjectManager::Constants::E_QML_DEBUG_SERVER_PORT, QString::number(runConfig->debugServerPort())); + + Debugger::DebuggerStartParameters params; + params.startMode = Debugger::StartInternal; + params.executable = runConfig->viewerPath(); + params.qmlServerAddress = runConfig->debugServerAddress(); + params.qmlServerPort = runConfig->debugServerPort(); + params.processArgs = runConfig->viewerArguments(); + params.workingDirectory = runConfig->workingDirectory(); + params.environment = environment.toStringList(); + params.displayName = runConfig->displayName(); + + Debugger::DebuggerRunControl *debuggerRunControl = Debugger::DebuggerPlugin::createDebugger(params, runConfig); + return debuggerRunControl; +} + } // namespace Internal } // namespace QmlProjectManager diff --git a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h index 7e85370a6e..8a1bc940a2 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h +++ b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h @@ -75,6 +75,9 @@ public: virtual ProjectExplorer::RunControl *create(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode); virtual QString displayName() const; virtual QWidget *createConfigurationWidget(ProjectExplorer::RunConfiguration *runConfiguration); + +private: + ProjectExplorer::RunControl *createDebugRunControl(QmlProjectRunConfiguration *runConfig); }; } // namespace Internal |