Merge QML inspector into debugger plugin
Merge QmlJSInspector plugin into the debugger. Also merge the extra Inspector window with the Locals & Watchers: It now shows the QML object tree in the running state. Change-Id: I59ae0c1b970a48ba10ecda92ed3ba765d94b1d9c Reviewed-by: Aurindam Jana <aurindam.jana@nokia.com>
@@ -55,7 +55,6 @@ Project {
|
|||||||
"src/plugins/projectexplorer/projectexplorer.qbs",
|
"src/plugins/projectexplorer/projectexplorer.qbs",
|
||||||
"src/plugins/qmldesigner/qmldesigner.qbs",
|
"src/plugins/qmldesigner/qmldesigner.qbs",
|
||||||
"src/plugins/qmljseditor/qmljseditor.qbs",
|
"src/plugins/qmljseditor/qmljseditor.qbs",
|
||||||
"src/plugins/qmljsinspector/qmljsinspector.qbs",
|
|
||||||
"src/plugins/qmljstools/qmljstools.qbs",
|
"src/plugins/qmljstools/qmljstools.qbs",
|
||||||
"src/plugins/qmlprofiler/qmlprofiler.qbs",
|
"src/plugins/qmlprofiler/qmlprofiler.qbs",
|
||||||
"src/plugins/qmlprojectmanager/qmlprojectmanager.qbs",
|
"src/plugins/qmlprojectmanager/qmlprojectmanager.qbs",
|
||||||
|
@@ -348,14 +348,16 @@ quint32 BaseEngineDebugClient::queryObjectRecursive(const QmlDebugObjectReferenc
|
|||||||
}
|
}
|
||||||
|
|
||||||
quint32 BaseEngineDebugClient::queryExpressionResult(int objectDebugId,
|
quint32 BaseEngineDebugClient::queryExpressionResult(int objectDebugId,
|
||||||
const QString &expr)
|
const QString &expr,
|
||||||
|
int engineId)
|
||||||
{
|
{
|
||||||
quint32 id = 0;
|
quint32 id = 0;
|
||||||
if (status() == QmlDebugClient::Enabled && objectDebugId != -1) {
|
if (status() == QmlDebugClient::Enabled && objectDebugId != -1) {
|
||||||
id = getId();
|
id = getId();
|
||||||
QByteArray message;
|
QByteArray message;
|
||||||
QDataStream ds(&message, QIODevice::WriteOnly);
|
QDataStream ds(&message, QIODevice::WriteOnly);
|
||||||
ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr;
|
ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr
|
||||||
|
<< engineId;
|
||||||
sendMessage(message);
|
sendMessage(message);
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
|
@@ -66,7 +66,7 @@ public:
|
|||||||
quint32 queryObject(const QmlDebugObjectReference &object);
|
quint32 queryObject(const QmlDebugObjectReference &object);
|
||||||
quint32 queryObjectRecursive(const QmlDebugObjectReference &object);
|
quint32 queryObjectRecursive(const QmlDebugObjectReference &object);
|
||||||
quint32 queryExpressionResult(int objectDebugId,
|
quint32 queryExpressionResult(int objectDebugId,
|
||||||
const QString &expr);
|
const QString &expr, int engineId = -1);
|
||||||
virtual quint32 setBindingForObject(int objectDebugId, const QString &propertyName,
|
virtual quint32 setBindingForObject(int objectDebugId, const QString &propertyName,
|
||||||
const QVariant &bindingExpression,
|
const QVariant &bindingExpression,
|
||||||
bool isLiteralValue,
|
bool isLiteralValue,
|
||||||
@@ -116,7 +116,7 @@ class QmlDebugEngineReference
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QmlDebugEngineReference() : m_debugId(-1) {}
|
QmlDebugEngineReference() : m_debugId(-1) {}
|
||||||
QmlDebugEngineReference(int id) : m_debugId(id) {}
|
explicit QmlDebugEngineReference(int id) : m_debugId(id) {}
|
||||||
|
|
||||||
int debugId() const { return m_debugId; }
|
int debugId() const { return m_debugId; }
|
||||||
QString name() const { return m_name; }
|
QString name() const { return m_name; }
|
||||||
@@ -133,7 +133,7 @@ class QmlDebugObjectReference
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QmlDebugObjectReference() : m_debugId(-1), m_parentId(-1), m_contextDebugId(-1), m_needsMoreData(false) {}
|
QmlDebugObjectReference() : m_debugId(-1), m_parentId(-1), m_contextDebugId(-1), m_needsMoreData(false) {}
|
||||||
QmlDebugObjectReference(int id) : m_debugId(id), m_parentId(-1), m_contextDebugId(-1), m_needsMoreData(false) {}
|
explicit QmlDebugObjectReference(int id) : m_debugId(id), m_parentId(-1), m_contextDebugId(-1), m_needsMoreData(false) {}
|
||||||
|
|
||||||
int debugId() const { return m_debugId; }
|
int debugId() const { return m_debugId; }
|
||||||
int parentId() const { return m_parentId; }
|
int parentId() const { return m_parentId; }
|
||||||
@@ -148,18 +148,18 @@ public:
|
|||||||
QList<QmlDebugPropertyReference> properties() const { return m_properties; }
|
QList<QmlDebugPropertyReference> properties() const { return m_properties; }
|
||||||
QList<QmlDebugObjectReference> children() const { return m_children; }
|
QList<QmlDebugObjectReference> children() const { return m_children; }
|
||||||
|
|
||||||
bool insertObjectInTree(const QmlDebugObjectReference &obj)
|
int insertObjectInTree(const QmlDebugObjectReference &obj)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_children.count(); i++) {
|
for (int i = 0; i < m_children.count(); i++) {
|
||||||
if (m_children[i].debugId() == obj.debugId()) {
|
if (m_children[i].debugId() == obj.debugId()) {
|
||||||
m_children.replace(i, obj);
|
m_children.replace(i, obj);
|
||||||
return true;
|
return debugId();
|
||||||
} else {
|
} else {
|
||||||
if (m_children[i].insertObjectInTree(obj))
|
if (m_children[i].insertObjectInTree(obj))
|
||||||
return true;
|
return debugId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator ==(const QmlDebugObjectReference &obj)
|
bool operator ==(const QmlDebugObjectReference &obj)
|
||||||
@@ -229,4 +229,20 @@ Q_DECLARE_METATYPE(QmlDebug::QmlDebugEngineReference)
|
|||||||
Q_DECLARE_METATYPE(QmlDebug::QmlDebugEngineReferenceList)
|
Q_DECLARE_METATYPE(QmlDebug::QmlDebugEngineReferenceList)
|
||||||
Q_DECLARE_METATYPE(QmlDebug::QmlDebugContextReference)
|
Q_DECLARE_METATYPE(QmlDebug::QmlDebugContextReference)
|
||||||
|
|
||||||
|
inline QDebug operator<<(QDebug dbg, const QmlDebug::QmlDebugEngineReference &ref) {
|
||||||
|
dbg.nospace() << "(Engine " << ref.debugId() << "/" << ref.name() << ")";
|
||||||
|
return dbg.space();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QDebug operator<<(QDebug dbg, const QmlDebug::QmlDebugContextReference &ref) {
|
||||||
|
dbg.nospace() << "(Context " << ref.debugId() << "/" << ref.name() << ")";
|
||||||
|
return dbg.space();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QDebug operator<<(QDebug dbg, const QmlDebug::QmlDebugObjectReference &ref) {
|
||||||
|
dbg.nospace() << "(Object " << ref.debugId() << "/"
|
||||||
|
<< (ref.idString().isEmpty() ? ref.idString() : ref.className()) << ")";
|
||||||
|
return dbg.space();
|
||||||
|
}
|
||||||
|
|
||||||
#endif // BASEENGINEDEBUGCLIENT_H
|
#endif // BASEENGINEDEBUGCLIENT_H
|
||||||
|
@@ -31,10 +31,9 @@
|
|||||||
|
|
||||||
#include "basetoolsclient.h"
|
#include "basetoolsclient.h"
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
namespace QmlDebug {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
BaseToolsClient::BaseToolsClient(QmlDebug::QmlDebugConnection* client, QLatin1String clientName)
|
BaseToolsClient::BaseToolsClient(QmlDebugConnection* client, QLatin1String clientName)
|
||||||
: QmlDebugClient(clientName, client)
|
: QmlDebugClient(clientName, client)
|
||||||
{
|
{
|
||||||
setObjectName(clientName);
|
setObjectName(clientName);
|
||||||
@@ -45,14 +44,13 @@ void BaseToolsClient::statusChanged(Status status)
|
|||||||
emit connectedStatusChanged(status);
|
emit connectedStatusChanged(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseToolsClient::recurseObjectIdList(const QmlDebug::QmlDebugObjectReference &ref,
|
void BaseToolsClient::recurseObjectIdList(const QmlDebugObjectReference &ref,
|
||||||
QList<int> &debugIds, QList<QString> &objectIds)
|
QList<int> &debugIds, QList<QString> &objectIds)
|
||||||
{
|
{
|
||||||
debugIds << ref.debugId();
|
debugIds << ref.debugId();
|
||||||
objectIds << ref.idString();
|
objectIds << ref.idString();
|
||||||
foreach (const QmlDebug::QmlDebugObjectReference &child, ref.children())
|
foreach (const QmlDebugObjectReference &child, ref.children())
|
||||||
recurseObjectIdList(child, debugIds, objectIds);
|
recurseObjectIdList(child, debugIds, objectIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace QmlDebug
|
||||||
} // namespace QmlJSInspector
|
|
@@ -32,17 +32,16 @@
|
|||||||
#ifndef BASETOOLSCLIENT_H
|
#ifndef BASETOOLSCLIENT_H
|
||||||
#define BASETOOLSCLIENT_H
|
#define BASETOOLSCLIENT_H
|
||||||
|
|
||||||
#include <qmldebug/qmldebugclient.h>
|
#include "qmldebugclient.h"
|
||||||
#include <qmldebug/baseenginedebugclient.h>
|
#include "baseenginedebugclient.h"
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
namespace QmlDebug {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class BaseToolsClient : public QmlDebug::QmlDebugClient
|
class QMLDEBUG_EXPORT BaseToolsClient : public QmlDebugClient
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
BaseToolsClient(QmlDebug::QmlDebugConnection* client, QLatin1String clientName);
|
BaseToolsClient(QmlDebugConnection *client, QLatin1String clientName);
|
||||||
|
|
||||||
virtual void setCurrentObjects(const QList<int> &debugIds) = 0;
|
virtual void setCurrentObjects(const QList<int> &debugIds) = 0;
|
||||||
virtual void reloadViewer() = 0;
|
virtual void reloadViewer() = 0;
|
||||||
@@ -67,7 +66,7 @@ public:
|
|||||||
|
|
||||||
// ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's
|
// ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's
|
||||||
virtual void setObjectIdList(
|
virtual void setObjectIdList(
|
||||||
const QList<QmlDebug::QmlDebugObjectReference> &objectRoots) = 0;
|
const QList<QmlDebugObjectReference> &objectRoots) = 0;
|
||||||
|
|
||||||
virtual void clearComponentCache() = 0;
|
virtual void clearComponentCache() = 0;
|
||||||
|
|
||||||
@@ -89,7 +88,7 @@ signals:
|
|||||||
protected:
|
protected:
|
||||||
void statusChanged(Status);
|
void statusChanged(Status);
|
||||||
|
|
||||||
void recurseObjectIdList(const QmlDebug::QmlDebugObjectReference &ref,
|
void recurseObjectIdList(const QmlDebugObjectReference &ref,
|
||||||
QList<int> &debugIds, QList<QString> &objectIds);
|
QList<int> &debugIds, QList<QString> &objectIds);
|
||||||
protected:
|
protected:
|
||||||
enum LogDirection {
|
enum LogDirection {
|
||||||
@@ -98,7 +97,6 @@ protected:
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace QmlDebug
|
||||||
} // namespace QmlJSInspector
|
|
||||||
|
|
||||||
#endif // BASETOOLSCLIENT_H
|
#endif // BASETOOLSCLIENT_H
|
@@ -30,16 +30,114 @@
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "declarativetoolsclient.h"
|
#include "declarativetoolsclient.h"
|
||||||
#include "qmljsclientproxy.h"
|
#include <QMetaEnum>
|
||||||
#include "qmljsinspectorconstants.h"
|
#include <QStringList>
|
||||||
|
|
||||||
using namespace QmlJSDebugger;
|
namespace QmlDebug {
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
namespace Constants {
|
||||||
|
|
||||||
|
enum DesignTool {
|
||||||
|
NoTool = 0,
|
||||||
|
SelectionToolMode = 1,
|
||||||
|
MarqueeSelectionToolMode = 2,
|
||||||
|
MoveToolMode = 3,
|
||||||
|
ResizeToolMode = 4,
|
||||||
|
ZoomMode = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class InspectorProtocol : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_ENUMS(Message Tool)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Message {
|
||||||
|
AnimationSpeedChanged = 0,
|
||||||
|
AnimationPausedChanged = 19, // highest value
|
||||||
|
ChangeTool = 1,
|
||||||
|
ClearComponentCache = 2,
|
||||||
|
ColorChanged = 3,
|
||||||
|
CreateObject = 5,
|
||||||
|
CurrentObjectsChanged = 6,
|
||||||
|
DestroyObject = 7,
|
||||||
|
MoveObject = 8,
|
||||||
|
ObjectIdList = 9,
|
||||||
|
Reload = 10,
|
||||||
|
Reloaded = 11,
|
||||||
|
SetAnimationSpeed = 12,
|
||||||
|
SetAnimationPaused = 18,
|
||||||
|
SetCurrentObjects = 14,
|
||||||
|
SetDesignMode = 15,
|
||||||
|
ShowAppOnTop = 16,
|
||||||
|
ToolChanged = 17
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Tool {
|
||||||
|
ColorPickerTool,
|
||||||
|
SelectMarqueeTool,
|
||||||
|
SelectTool,
|
||||||
|
ZoomTool
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline QString toString(Message message)
|
||||||
|
{
|
||||||
|
return staticMetaObject.enumerator(0).valueToKey(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline QString toString(Tool tool)
|
||||||
|
{
|
||||||
|
return staticMetaObject.enumerator(1).valueToKey(tool);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDataStream & operator<< (QDataStream &stream, InspectorProtocol::Message message)
|
||||||
|
{
|
||||||
|
return stream << static_cast<quint32>(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QDataStream & operator>> (QDataStream &stream, InspectorProtocol::Message &message)
|
||||||
|
{
|
||||||
|
quint32 i;
|
||||||
|
stream >> i;
|
||||||
|
message = static_cast<InspectorProtocol::Message>(i);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, InspectorProtocol::Message message)
|
||||||
|
{
|
||||||
|
dbg << InspectorProtocol::toString(message);
|
||||||
|
return dbg;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QDataStream & operator<< (QDataStream &stream, InspectorProtocol::Tool tool)
|
||||||
|
{
|
||||||
|
return stream << static_cast<quint32>(tool);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QDataStream & operator>> (QDataStream &stream, InspectorProtocol::Tool &tool)
|
||||||
|
{
|
||||||
|
quint32 i;
|
||||||
|
stream >> i;
|
||||||
|
tool = static_cast<InspectorProtocol::Tool>(i);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, InspectorProtocol::Tool tool)
|
||||||
|
{
|
||||||
|
dbg << InspectorProtocol::toString(tool);
|
||||||
|
return dbg;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // internal
|
||||||
|
|
||||||
|
using namespace Internal;
|
||||||
|
|
||||||
DeclarativeToolsClient::DeclarativeToolsClient(QmlDebugConnection *client)
|
DeclarativeToolsClient::DeclarativeToolsClient(QmlDebugConnection *client)
|
||||||
: BaseToolsClient(client,QLatin1String(Constants::QDECLARATIVE_OBSERVER_MODE)),
|
: BaseToolsClient(client,QLatin1String("QDeclarativeObserverMode")),
|
||||||
m_connection(client)
|
m_connection(client)
|
||||||
{
|
{
|
||||||
setObjectName(name());
|
setObjectName(name());
|
||||||
@@ -165,7 +263,7 @@ void DeclarativeToolsClient::setCurrentObjects(const QList<int> &debugIds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DeclarativeToolsClient::setObjectIdList(
|
void DeclarativeToolsClient::setObjectIdList(
|
||||||
const QList<QmlDebug::QmlDebugObjectReference> &objectRoots)
|
const QList<QmlDebugObjectReference> &objectRoots)
|
||||||
{
|
{
|
||||||
QByteArray message;
|
QByteArray message;
|
||||||
QDataStream ds(&message, QIODevice::WriteOnly);
|
QDataStream ds(&message, QIODevice::WriteOnly);
|
||||||
@@ -173,7 +271,7 @@ void DeclarativeToolsClient::setObjectIdList(
|
|||||||
QList<int> debugIds;
|
QList<int> debugIds;
|
||||||
QList<QString> objectIds;
|
QList<QString> objectIds;
|
||||||
|
|
||||||
foreach (const QmlDebug::QmlDebugObjectReference &ref, objectRoots)
|
foreach (const QmlDebugObjectReference &ref, objectRoots)
|
||||||
recurseObjectIdList(ref, debugIds, objectIds);
|
recurseObjectIdList(ref, debugIds, objectIds);
|
||||||
|
|
||||||
InspectorProtocol::Message cmd = InspectorProtocol::ObjectIdList;
|
InspectorProtocol::Message cmd = InspectorProtocol::ObjectIdList;
|
||||||
@@ -423,7 +521,7 @@ void DeclarativeToolsClient::applyChangesFromQmlFile()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DeclarativeToolsClient::log(LogDirection direction,
|
void DeclarativeToolsClient::log(LogDirection direction,
|
||||||
InspectorProtocol::Message message,
|
int message,
|
||||||
const QString &extra)
|
const QString &extra)
|
||||||
{
|
{
|
||||||
QString msg;
|
QString msg;
|
||||||
@@ -432,11 +530,14 @@ void DeclarativeToolsClient::log(LogDirection direction,
|
|||||||
else
|
else
|
||||||
msg += QLatin1String(" receiving ");
|
msg += QLatin1String(" receiving ");
|
||||||
|
|
||||||
msg += InspectorProtocol::toString(message);
|
InspectorProtocol::Message msgType
|
||||||
|
= static_cast<InspectorProtocol::Message>(message);
|
||||||
|
msg += InspectorProtocol::toString(msgType);
|
||||||
msg += QLatin1Char(' ');
|
msg += QLatin1Char(' ');
|
||||||
msg += extra;
|
msg += extra;
|
||||||
emit logActivity(name(), msg);
|
emit logActivity(name(), msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace QmlDebug
|
||||||
} // namespace QmlJSInspector
|
|
||||||
|
#include "declarativetoolsclient.moc"
|
@@ -34,16 +34,13 @@
|
|||||||
|
|
||||||
#include "basetoolsclient.h"
|
#include "basetoolsclient.h"
|
||||||
|
|
||||||
#include <inspectorprotocol.h>
|
namespace QmlDebug {
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
class QMLDEBUG_EXPORT DeclarativeToolsClient : public BaseToolsClient
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class DeclarativeToolsClient : public BaseToolsClient
|
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
DeclarativeToolsClient(QmlDebug::QmlDebugConnection *client);
|
DeclarativeToolsClient(QmlDebugConnection *client);
|
||||||
|
|
||||||
void setCurrentObjects(const QList<int> &debugIds);
|
void setCurrentObjects(const QList<int> &debugIds);
|
||||||
void reloadViewer();
|
void reloadViewer();
|
||||||
@@ -67,7 +64,7 @@ public:
|
|||||||
QList<int> currentObjects() const;
|
QList<int> currentObjects() const;
|
||||||
|
|
||||||
// ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's
|
// ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's
|
||||||
void setObjectIdList(const QList<QmlDebug::QmlDebugObjectReference> &objectRoots);
|
void setObjectIdList(const QList<QmlDebugObjectReference> &objectRoots);
|
||||||
|
|
||||||
void clearComponentCache();
|
void clearComponentCache();
|
||||||
|
|
||||||
@@ -76,15 +73,14 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void log(LogDirection direction,
|
void log(LogDirection direction,
|
||||||
QmlJSDebugger::InspectorProtocol::Message message,
|
int message,
|
||||||
const QString &extra = QString());
|
const QString &extra = QString());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<int> m_currentDebugIds;
|
QList<int> m_currentDebugIds;
|
||||||
QmlDebug::QmlDebugConnection *m_connection;
|
QmlDebugConnection *m_connection;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace QmlDebug
|
||||||
} // namespace QmlJSInspector
|
|
||||||
|
|
||||||
#endif // DECLARATIVETOOLSCLIENT_H
|
#endif // DECLARATIVETOOLSCLIENT_H
|
@@ -19,7 +19,10 @@ HEADERS += \
|
|||||||
$$PWD/qv8profilerclient.h \
|
$$PWD/qv8profilerclient.h \
|
||||||
$$PWD/qmldebugconstants.h \
|
$$PWD/qmldebugconstants.h \
|
||||||
$$PWD/qdebugmessageclient.h \
|
$$PWD/qdebugmessageclient.h \
|
||||||
$$PWD/qmlenginedebugclient.h
|
$$PWD/qmlenginedebugclient.h \
|
||||||
|
$$PWD/basetoolsclient.h \
|
||||||
|
$$PWD/declarativetoolsclient.h \
|
||||||
|
$$PWD/qmltoolsclient.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/qmldebugclient.cpp \
|
$$PWD/qmldebugclient.cpp \
|
||||||
@@ -29,5 +32,8 @@ SOURCES += \
|
|||||||
$$PWD/qpacketprotocol.cpp \
|
$$PWD/qpacketprotocol.cpp \
|
||||||
$$PWD/qv8profilerclient.cpp \
|
$$PWD/qv8profilerclient.cpp \
|
||||||
$$PWD/qdebugmessageclient.cpp \
|
$$PWD/qdebugmessageclient.cpp \
|
||||||
$$PWD/qmlenginedebugclient.cpp
|
$$PWD/qmlenginedebugclient.cpp \
|
||||||
|
$$PWD/basetoolsclient.cpp \
|
||||||
|
$$PWD/declarativetoolsclient.cpp \
|
||||||
|
$$PWD/qmltoolsclient.cpp
|
||||||
|
|
||||||
|
@@ -20,6 +20,11 @@ QtcLibrary {
|
|||||||
files: [
|
files: [
|
||||||
"baseenginedebugclient.cpp",
|
"baseenginedebugclient.cpp",
|
||||||
"baseenginedebugclient.h",
|
"baseenginedebugclient.h",
|
||||||
|
"basetoolsclient.cpp",
|
||||||
|
"basetoolsclient.h",
|
||||||
|
"declarativeenginedebugclient.h",
|
||||||
|
"declarativetoolsclient.cpp",
|
||||||
|
"declarativetoolsclient.h",
|
||||||
"qdebugmessageclient.cpp",
|
"qdebugmessageclient.cpp",
|
||||||
"qdebugmessageclient.h",
|
"qdebugmessageclient.h",
|
||||||
"qmldebugclient.cpp",
|
"qmldebugclient.cpp",
|
||||||
@@ -34,7 +39,6 @@ QtcLibrary {
|
|||||||
"qmlprofilertraceclient.h",
|
"qmlprofilertraceclient.h",
|
||||||
"qpacketprotocol.cpp",
|
"qpacketprotocol.cpp",
|
||||||
"qpacketprotocol.h",
|
"qpacketprotocol.h",
|
||||||
"declarativeenginedebugclient.h",
|
|
||||||
"qmlenginedebugclient.cpp",
|
"qmlenginedebugclient.cpp",
|
||||||
"qmlenginedebugclient.h",
|
"qmlenginedebugclient.h",
|
||||||
"qv8profilerclient.cpp",
|
"qv8profilerclient.cpp",
|
||||||
|
@@ -30,8 +30,7 @@
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "qmltoolsclient.h"
|
#include "qmltoolsclient.h"
|
||||||
#include "qmljsclientproxy.h"
|
#include <QStringList>
|
||||||
#include "qmljsinspectorconstants.h"
|
|
||||||
|
|
||||||
//INSPECTOR SERVICE PROTOCOL
|
//INSPECTOR SERVICE PROTOCOL
|
||||||
// <HEADER><COMMAND><DATA>
|
// <HEADER><COMMAND><DATA>
|
||||||
@@ -61,11 +60,10 @@ const char DESTROY_OBJECT[] = "destroyObject";
|
|||||||
const char MOVE_OBJECT[] = "moveObject";
|
const char MOVE_OBJECT[] = "moveObject";
|
||||||
const char CLEAR_CACHE[] = "clearCache";
|
const char CLEAR_CACHE[] = "clearCache";
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
namespace QmlDebug {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
QmlToolsClient::QmlToolsClient(QmlDebugConnection *client)
|
QmlToolsClient::QmlToolsClient(QmlDebugConnection *client)
|
||||||
: BaseToolsClient(client, QLatin1String(Constants::QML_INSPECTOR)),
|
: BaseToolsClient(client, QLatin1String("QmlInspector")),
|
||||||
m_connection(client),
|
m_connection(client),
|
||||||
m_requestId(0),
|
m_requestId(0),
|
||||||
m_slowDownFactor(1)
|
m_slowDownFactor(1)
|
||||||
@@ -328,5 +326,4 @@ void QmlToolsClient::log(LogDirection direction,
|
|||||||
emit logActivity(name(), msg);
|
emit logActivity(name(), msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace QmlDebug
|
||||||
} // namespace QmlJSInspector
|
|
@@ -33,14 +33,14 @@
|
|||||||
#define QMLTOOLSCLIENT_H
|
#define QMLTOOLSCLIENT_H
|
||||||
|
|
||||||
#include "basetoolsclient.h"
|
#include "basetoolsclient.h"
|
||||||
namespace QmlJSInspector {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class QmlToolsClient : public BaseToolsClient
|
namespace QmlDebug {
|
||||||
|
|
||||||
|
class QMLDEBUG_EXPORT QmlToolsClient : public BaseToolsClient
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit QmlToolsClient(QmlDebug::QmlDebugConnection *client);
|
explicit QmlToolsClient(QmlDebugConnection *client);
|
||||||
|
|
||||||
void setCurrentObjects(const QList<int> &debugIds);
|
void setCurrentObjects(const QList<int> &debugIds);
|
||||||
void reloadViewer();
|
void reloadViewer();
|
||||||
@@ -64,7 +64,7 @@ public:
|
|||||||
QList<int> currentObjects() const;
|
QList<int> currentObjects() const;
|
||||||
|
|
||||||
// ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's
|
// ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's
|
||||||
void setObjectIdList(const QList<QmlDebug::QmlDebugObjectReference> &objectRoots);
|
void setObjectIdList(const QList<QmlDebugObjectReference> &objectRoots);
|
||||||
|
|
||||||
void clearComponentCache();
|
void clearComponentCache();
|
||||||
|
|
||||||
@@ -78,12 +78,11 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QList<int> m_currentDebugIds;
|
QList<int> m_currentDebugIds;
|
||||||
QmlDebug::QmlDebugConnection *m_connection;
|
QmlDebugConnection *m_connection;
|
||||||
int m_requestId;
|
int m_requestId;
|
||||||
qreal m_slowDownFactor;
|
qreal m_slowDownFactor;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace QmlDebug
|
||||||
} // namespace QmlJSInspector
|
|
||||||
|
|
||||||
#endif // QMLTOOLSCLIENT_H
|
#endif // QMLTOOLSCLIENT_H
|
@@ -18,6 +18,7 @@ Alternatively, this plugin may be used under the terms of the GNU Lesser General
|
|||||||
<dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
|
<dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
|
||||||
<dependency name=\"Find\" version=\"$$QTCREATOR_VERSION\"/>
|
<dependency name=\"Find\" version=\"$$QTCREATOR_VERSION\"/>
|
||||||
<dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/>
|
<dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/>
|
||||||
|
<dependency name=\"QmlJSTools\" version=\"$$QTCREATOR_VERSION\"/>
|
||||||
<!-- Debugger plugin adds items to the editor\'s context menu -->
|
<!-- Debugger plugin adds items to the editor\'s context menu -->
|
||||||
<dependency name=\"CppEditor\" version=\"$$QTCREATOR_VERSION\" type=\"optional\"/>
|
<dependency name=\"CppEditor\" version=\"$$QTCREATOR_VERSION\" type=\"optional\"/>
|
||||||
</dependencyList>
|
</dependencyList>
|
||||||
|
@@ -74,6 +74,8 @@ CommonOptionsPageWidget::CommonOptionsPageWidget
|
|||||||
m_ui.checkBoxSwitchModeOnExit);
|
m_ui.checkBoxSwitchModeOnExit);
|
||||||
m_group->insert(dc->action(RaiseOnInterrupt),
|
m_group->insert(dc->action(RaiseOnInterrupt),
|
||||||
m_ui.checkBoxBringToForegroundOnInterrrupt);
|
m_ui.checkBoxBringToForegroundOnInterrrupt);
|
||||||
|
m_group->insert(dc->action(ShowQmlObjectTree),
|
||||||
|
m_ui.checkBoxShowQmlObjectTree);
|
||||||
m_group->insert(dc->action(FontSizeFollowsEditor),
|
m_group->insert(dc->action(FontSizeFollowsEditor),
|
||||||
m_ui.checkBoxFontSizeFollowsEditor);
|
m_ui.checkBoxFontSizeFollowsEditor);
|
||||||
m_group->insert(dc->action(AutoDerefPointers), 0);
|
m_group->insert(dc->action(AutoDerefPointers), 0);
|
||||||
@@ -123,6 +125,7 @@ QString CommonOptionsPageWidget::searchKeyWords() const
|
|||||||
<< sep << m_ui.checkBoxSwitchModeOnExit->text()
|
<< sep << m_ui.checkBoxSwitchModeOnExit->text()
|
||||||
<< sep << m_ui.labelMaximalStackDepth->text()
|
<< sep << m_ui.labelMaximalStackDepth->text()
|
||||||
<< sep << m_ui.checkBoxBringToForegroundOnInterrrupt->text()
|
<< sep << m_ui.checkBoxBringToForegroundOnInterrrupt->text()
|
||||||
|
<< sep << m_ui.checkBoxShowQmlObjectTree->text()
|
||||||
;
|
;
|
||||||
rc.remove(QLatin1Char('&'));
|
rc.remove(QLatin1Char('&'));
|
||||||
return rc;
|
return rc;
|
||||||
|
@@ -120,7 +120,14 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="checkBoxBringToForegroundOnInterrrupt">
|
||||||
|
<property name="text">
|
||||||
|
<string>Bring Qt Creator to foreground when application interrupts</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
<widget class="QCheckBox" name="checkBoxRegisterForPostMortem">
|
<widget class="QCheckBox" name="checkBoxRegisterForPostMortem">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Register Qt Creator for debugging crashed applications.</string>
|
<string>Register Qt Creator for debugging crashed applications.</string>
|
||||||
@@ -130,10 +137,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="1">
|
||||||
<widget class="QCheckBox" name="checkBoxBringToForegroundOnInterrrupt">
|
<widget class="QCheckBox" name="checkBoxShowQmlObjectTree">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Show QML object tree in Locals & Expressions when connected and not stepping.</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Bring Qt Creator to foreground when application interrupts</string>
|
<string>Show QML object tree</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@@ -72,7 +72,8 @@ HEADERS += \
|
|||||||
qtmessagelogview.h \
|
qtmessagelogview.h \
|
||||||
qtmessagelogproxymodel.h \
|
qtmessagelogproxymodel.h \
|
||||||
qtmessagelogitemdelegate.h \
|
qtmessagelogitemdelegate.h \
|
||||||
qtmessageloghandler.h
|
qtmessageloghandler.h \
|
||||||
|
localsandwatcherswindow.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
basewindow.cpp \
|
basewindow.cpp \
|
||||||
@@ -123,7 +124,8 @@ SOURCES += \
|
|||||||
qtmessagelogview.cpp \
|
qtmessagelogview.cpp \
|
||||||
qtmessagelogitemdelegate.cpp \
|
qtmessagelogitemdelegate.cpp \
|
||||||
qtmessageloghandler.cpp \
|
qtmessageloghandler.cpp \
|
||||||
qtmessagelogeditor.cpp
|
qtmessagelogeditor.cpp \
|
||||||
|
localsandwatcherswindow.cpp
|
||||||
|
|
||||||
FORMS += attachexternaldialog.ui \
|
FORMS += attachexternaldialog.ui \
|
||||||
attachcoredialog.ui \
|
attachcoredialog.ui \
|
||||||
|
@@ -8,6 +8,7 @@ QtcPlugin {
|
|||||||
Depends { name: "qt"; submodules: ['widgets', 'network', 'script'] }
|
Depends { name: "qt"; submodules: ['widgets', 'network', 'script'] }
|
||||||
Depends { name: "Core" }
|
Depends { name: "Core" }
|
||||||
Depends { name: "CppTools" }
|
Depends { name: "CppTools" }
|
||||||
|
Depends { name: "QmlJSTools" }
|
||||||
Depends { name: "Find" }
|
Depends { name: "Find" }
|
||||||
Depends { name: "ProjectExplorer" }
|
Depends { name: "ProjectExplorer" }
|
||||||
Depends { name: "TextEditor" }
|
Depends { name: "TextEditor" }
|
||||||
@@ -75,6 +76,8 @@ QtcPlugin {
|
|||||||
"disassemblerlines.cpp",
|
"disassemblerlines.cpp",
|
||||||
"disassemblerlines.h",
|
"disassemblerlines.h",
|
||||||
"dumperoptionpage.ui",
|
"dumperoptionpage.ui",
|
||||||
|
"localsandwatcherswindow.cpp",
|
||||||
|
"localsandwatcherswindow.h",
|
||||||
"logwindow.cpp",
|
"logwindow.cpp",
|
||||||
"logwindow.h",
|
"logwindow.h",
|
||||||
"memoryagent.cpp",
|
"memoryagent.cpp",
|
||||||
@@ -243,6 +246,12 @@ QtcPlugin {
|
|||||||
"qml/qscriptdebuggerclient.cpp",
|
"qml/qscriptdebuggerclient.cpp",
|
||||||
"qml/qmlv8debuggerclient.cpp",
|
"qml/qmlv8debuggerclient.cpp",
|
||||||
"qml/interactiveinterpreter.cpp",
|
"qml/interactiveinterpreter.cpp",
|
||||||
|
"qml/qmlinspectoradapter.cpp",
|
||||||
|
"qml/qmlinspectoradapter.h",
|
||||||
|
"qml/qmlinspectoragent.cpp",
|
||||||
|
"qml/qmlinspectoragent.h",
|
||||||
|
"qml/qmllivetextpreview.cpp",
|
||||||
|
"qml/qmllivetextpreview.h",
|
||||||
"script/scriptengine.cpp",
|
"script/scriptengine.cpp",
|
||||||
"script/scriptengine.h",
|
"script/scriptengine.h",
|
||||||
"shared/backtrace.cpp",
|
"shared/backtrace.cpp",
|
||||||
|
@@ -36,5 +36,9 @@
|
|||||||
<file>images/log.png</file>
|
<file>images/log.png</file>
|
||||||
<file>images/prompt.png</file>
|
<file>images/prompt.png</file>
|
||||||
<file>images/warning.png</file>
|
<file>images/warning.png</file>
|
||||||
|
<file>images/qml/zoom.png</file>
|
||||||
|
<file>images/qml/select.png</file>
|
||||||
|
<file>images/qml/app-on-top.png</file>
|
||||||
|
<file>images/qml/apply-on-save.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@@ -3,6 +3,7 @@ include(../../plugins/cpptools/cpptools.pri)
|
|||||||
include(../../plugins/find/find.pri)
|
include(../../plugins/find/find.pri)
|
||||||
include(../../plugins/projectexplorer/projectexplorer.pri)
|
include(../../plugins/projectexplorer/projectexplorer.pri)
|
||||||
include(../../plugins/texteditor/texteditor.pri)
|
include(../../plugins/texteditor/texteditor.pri)
|
||||||
|
include(../../plugins/qmljstools/qmljstools.pri)
|
||||||
include(../../libs/cplusplus/cplusplus.pri)
|
include(../../libs/cplusplus/cplusplus.pri)
|
||||||
include(../../libs/utils/utils.pri)
|
include(../../libs/utils/utils.pri)
|
||||||
include(../../libs/symbianutils/symbianutils.pri)
|
include(../../libs/symbianutils/symbianutils.pri)
|
||||||
|
@@ -549,6 +549,30 @@ DebuggerSettings::DebuggerSettings(QSettings *settings)
|
|||||||
item->setSettingsKey(debugModeGroup, QLatin1String("WatchdogTimeout"));
|
item->setSettingsKey(debugModeGroup, QLatin1String("WatchdogTimeout"));
|
||||||
item->setDefaultValue(20);
|
item->setDefaultValue(20);
|
||||||
insertItem(GdbWatchdogTimeout, item);
|
insertItem(GdbWatchdogTimeout, item);
|
||||||
|
|
||||||
|
//
|
||||||
|
// QML Tools
|
||||||
|
//
|
||||||
|
item = new SavedAction(this);
|
||||||
|
item->setSettingsKey(debugModeGroup, QLatin1String("ShowQmlObjectTree"));
|
||||||
|
item->setDefaultValue(true);
|
||||||
|
insertItem(ShowQmlObjectTree, item);
|
||||||
|
|
||||||
|
item = new SavedAction(this);
|
||||||
|
item->setSettingsKey("QML.Inspector", QLatin1String("QmlInspector.ShowAppOnTop"));
|
||||||
|
item->setText(tr("Show Application On Top"));
|
||||||
|
item->setCheckable(true);
|
||||||
|
item->setDefaultValue(false);
|
||||||
|
item->setIcon(QIcon(QLatin1String(":/debugger/images/qml/app-on-top.png")));
|
||||||
|
insertItem(ShowAppOnTop, item);
|
||||||
|
|
||||||
|
item = new SavedAction(this);
|
||||||
|
item->setSettingsKey("QML.Inspector", QLatin1String("QmlInspector.FromQml"));
|
||||||
|
item->setText(tr("Apply Changes on Save"));
|
||||||
|
item->setCheckable(true);
|
||||||
|
item->setDefaultValue(false);
|
||||||
|
item->setIcon(QIcon(QLatin1String(":/debugger/images/qml/apply-on-save.png")));
|
||||||
|
insertItem(QmlUpdateOnSave, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
DebuggerSettings::~DebuggerSettings()
|
DebuggerSettings::~DebuggerSettings()
|
||||||
|
@@ -169,7 +169,12 @@ enum DebuggerActionCode
|
|||||||
AlwaysAdjustThreadsColumnWidths,
|
AlwaysAdjustThreadsColumnWidths,
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
AlwaysAdjustModulesColumnWidths
|
AlwaysAdjustModulesColumnWidths,
|
||||||
|
|
||||||
|
// QML Tools
|
||||||
|
ShowQmlObjectTree,
|
||||||
|
ShowAppOnTop,
|
||||||
|
QmlUpdateOnSave
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -52,7 +52,7 @@ const char G_MANUAL_REMOTE[] = "Debugger.Group.Manual.Remote";
|
|||||||
const char G_AUTOMATIC_REMOTE[] = "Debugger.Group.Automatic.Remote";
|
const char G_AUTOMATIC_REMOTE[] = "Debugger.Group.Automatic.Remote";
|
||||||
const char G_START_QML[] = "Debugger.Group.Start.Qml";
|
const char G_START_QML[] = "Debugger.Group.Start.Qml";
|
||||||
|
|
||||||
// Common actions (accessed by QML inspector)
|
// Common actions
|
||||||
const char INTERRUPT[] = "Debugger.Interrupt";
|
const char INTERRUPT[] = "Debugger.Interrupt";
|
||||||
const char CONTINUE[] = "Debugger.Continue";
|
const char CONTINUE[] = "Debugger.Continue";
|
||||||
const char STOP[] = "Debugger.Stop";
|
const char STOP[] = "Debugger.Stop";
|
||||||
@@ -63,6 +63,8 @@ const char STEPOUT[] = "Debugger.StepOut";
|
|||||||
const char NEXT[] = "Debugger.NextLine";
|
const char NEXT[] = "Debugger.NextLine";
|
||||||
const char REVERSE[] = "Debugger.ReverseDirection";
|
const char REVERSE[] = "Debugger.ReverseDirection";
|
||||||
const char OPERATE_BY_INSTRUCTION[] = "Debugger.OperateByInstruction";
|
const char OPERATE_BY_INSTRUCTION[] = "Debugger.OperateByInstruction";
|
||||||
|
const char QML_SELECTTOOL[] = "Debugger.QmlSelectTool";
|
||||||
|
const char QML_ZOOMTOOL[] = "Debugger.QmlZoomTool";
|
||||||
|
|
||||||
// DebuggerMainWindow dock widget names
|
// DebuggerMainWindow dock widget names
|
||||||
const char DOCKWIDGET_BREAK[] = "Debugger.Docks.Break";
|
const char DOCKWIDGET_BREAK[] = "Debugger.Docks.Break";
|
||||||
|
@@ -513,6 +513,14 @@ QAbstractItemModel *DebuggerEngine::returnModel() const
|
|||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QAbstractItemModel *DebuggerEngine::inspectorModel() const
|
||||||
|
{
|
||||||
|
QAbstractItemModel *model = watchHandler()->model(InspectWatch);
|
||||||
|
if (model->objectName().isEmpty()) // Make debugging easier.
|
||||||
|
model->setObjectName(objectName() + QLatin1String("InspectorModel"));
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
|
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
|
||||||
{
|
{
|
||||||
QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
|
QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
|
||||||
|
@@ -75,6 +75,7 @@ class SourceFilesHandler;
|
|||||||
class ThreadsHandler;
|
class ThreadsHandler;
|
||||||
class WatchHandler;
|
class WatchHandler;
|
||||||
class BreakpointParameters;
|
class BreakpointParameters;
|
||||||
|
class QmlAdapter;
|
||||||
class QmlCppEngine;
|
class QmlCppEngine;
|
||||||
class DebuggerToolTipContext;
|
class DebuggerToolTipContext;
|
||||||
class MemoryMarkup;
|
class MemoryMarkup;
|
||||||
@@ -231,6 +232,7 @@ public:
|
|||||||
virtual QAbstractItemModel *localsModel() const;
|
virtual QAbstractItemModel *localsModel() const;
|
||||||
virtual QAbstractItemModel *watchersModel() const;
|
virtual QAbstractItemModel *watchersModel() const;
|
||||||
virtual QAbstractItemModel *returnModel() const;
|
virtual QAbstractItemModel *returnModel() const;
|
||||||
|
virtual QAbstractItemModel *inspectorModel() const;
|
||||||
virtual QAbstractItemModel *toolTipsModel() const;
|
virtual QAbstractItemModel *toolTipsModel() const;
|
||||||
virtual QAbstractItemModel *sourceFilesModel() const;
|
virtual QAbstractItemModel *sourceFilesModel() const;
|
||||||
virtual QAbstractItemModel *qtMessageLogModel() const;
|
virtual QAbstractItemModel *qtMessageLogModel() const;
|
||||||
@@ -408,7 +410,7 @@ private:
|
|||||||
// Wrapper engine needs access to state of its subengines.
|
// Wrapper engine needs access to state of its subengines.
|
||||||
friend class Internal::QmlCppEngine;
|
friend class Internal::QmlCppEngine;
|
||||||
friend class Internal::DebuggerPluginPrivate;
|
friend class Internal::DebuggerPluginPrivate;
|
||||||
friend class QmlAdapter;
|
friend class Internal::QmlAdapter;
|
||||||
|
|
||||||
virtual void setState(DebuggerState state, bool forced = false);
|
virtual void setState(DebuggerState state, bool forced = false);
|
||||||
|
|
||||||
|
@@ -62,6 +62,7 @@
|
|||||||
#include "watchwindow.h"
|
#include "watchwindow.h"
|
||||||
#include "watchutils.h"
|
#include "watchutils.h"
|
||||||
#include "debuggertooltipmanager.h"
|
#include "debuggertooltipmanager.h"
|
||||||
|
#include "localsandwatcherswindow.h"
|
||||||
|
|
||||||
#include "snapshothandler.h"
|
#include "snapshothandler.h"
|
||||||
#include "threadshandler.h"
|
#include "threadshandler.h"
|
||||||
@@ -1119,6 +1120,10 @@ public slots:
|
|||||||
void attachedToProcess(const QString &channel, const QString &sysroot,
|
void attachedToProcess(const QString &channel, const QString &sysroot,
|
||||||
const QString &remoteCommandLine, const QString &remoteExecutable);
|
const QString &remoteCommandLine, const QString &remoteExecutable);
|
||||||
|
|
||||||
|
void updateQmlActions() {
|
||||||
|
action(QmlUpdateOnSave)->setEnabled(boolSetting(ShowQmlObjectTree));
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DebuggerMainWindow *m_mainWindow;
|
DebuggerMainWindow *m_mainWindow;
|
||||||
DebuggerRunControlFactory *m_debuggerRunControlFactory;
|
DebuggerRunControlFactory *m_debuggerRunControlFactory;
|
||||||
@@ -1177,6 +1182,7 @@ public:
|
|||||||
WatchWindow *m_returnWindow;
|
WatchWindow *m_returnWindow;
|
||||||
WatchWindow *m_localsWindow;
|
WatchWindow *m_localsWindow;
|
||||||
WatchWindow *m_watchersWindow;
|
WatchWindow *m_watchersWindow;
|
||||||
|
WatchWindow *m_inspectorWindow;
|
||||||
BaseWindow *m_registerWindow;
|
BaseWindow *m_registerWindow;
|
||||||
BaseWindow *m_modulesWindow;
|
BaseWindow *m_modulesWindow;
|
||||||
BaseWindow *m_snapshotWindow;
|
BaseWindow *m_snapshotWindow;
|
||||||
@@ -1184,6 +1190,7 @@ public:
|
|||||||
BaseWindow *m_stackWindow;
|
BaseWindow *m_stackWindow;
|
||||||
BaseWindow *m_threadsWindow;
|
BaseWindow *m_threadsWindow;
|
||||||
LogWindow *m_logWindow;
|
LogWindow *m_logWindow;
|
||||||
|
LocalsAndWatchersWindow *m_localsAndWatchersWindow;
|
||||||
|
|
||||||
bool m_busy;
|
bool m_busy;
|
||||||
QString m_lastPermanentStatusMessage;
|
QString m_lastPermanentStatusMessage;
|
||||||
@@ -1230,6 +1237,7 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) :
|
|||||||
m_returnWindow = 0;
|
m_returnWindow = 0;
|
||||||
m_localsWindow = 0;
|
m_localsWindow = 0;
|
||||||
m_watchersWindow = 0;
|
m_watchersWindow = 0;
|
||||||
|
m_inspectorWindow = 0;
|
||||||
m_registerWindow = 0;
|
m_registerWindow = 0;
|
||||||
m_modulesWindow = 0;
|
m_modulesWindow = 0;
|
||||||
m_snapshotWindow = 0;
|
m_snapshotWindow = 0;
|
||||||
@@ -1237,6 +1245,7 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) :
|
|||||||
m_stackWindow = 0;
|
m_stackWindow = 0;
|
||||||
m_threadsWindow = 0;
|
m_threadsWindow = 0;
|
||||||
m_logWindow = 0;
|
m_logWindow = 0;
|
||||||
|
m_localsAndWatchersWindow = 0;
|
||||||
m_qtMessageLogWindow = 0;
|
m_qtMessageLogWindow = 0;
|
||||||
|
|
||||||
m_mainWindow = 0;
|
m_mainWindow = 0;
|
||||||
@@ -2130,6 +2139,7 @@ void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine)
|
|||||||
//m_threadBox->setModel(engine->threadsModel());
|
//m_threadBox->setModel(engine->threadsModel());
|
||||||
//m_threadBox->setModelColumn(ThreadData::ComboNameColumn);
|
//m_threadBox->setModelColumn(ThreadData::ComboNameColumn);
|
||||||
m_watchersWindow->setModel(engine->watchersModel());
|
m_watchersWindow->setModel(engine->watchersModel());
|
||||||
|
m_inspectorWindow->setModel(engine->inspectorModel());
|
||||||
m_qtMessageLogWindow->setModel(engine->qtMessageLogModel());
|
m_qtMessageLogWindow->setModel(engine->qtMessageLogModel());
|
||||||
|
|
||||||
engine->watchHandler()->rebuildModel();
|
engine->watchHandler()->rebuildModel();
|
||||||
@@ -2162,6 +2172,7 @@ void DebuggerPluginPrivate::fontSettingsChanged
|
|||||||
changeFontSize(m_stackWindow, size);
|
changeFontSize(m_stackWindow, size);
|
||||||
changeFontSize(m_threadsWindow, size);
|
changeFontSize(m_threadsWindow, size);
|
||||||
changeFontSize(m_watchersWindow, size);
|
changeFontSize(m_watchersWindow, size);
|
||||||
|
changeFontSize(m_inspectorWindow, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebuggerPluginPrivate::cleanupViews()
|
void DebuggerPluginPrivate::cleanupViews()
|
||||||
@@ -2305,6 +2316,7 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
|
|||||||
m_debugWithoutDeployAction->setEnabled(false);
|
m_debugWithoutDeployAction->setEnabled(false);
|
||||||
m_visibleStartAction->setAction(m_continueAction);
|
m_visibleStartAction->setAction(m_continueAction);
|
||||||
m_hiddenStopAction->setAction(m_exitAction);
|
m_hiddenStopAction->setAction(m_exitAction);
|
||||||
|
m_localsAndWatchersWindow->setShowLocals(true);
|
||||||
} else if (state == InferiorRunOk) {
|
} else if (state == InferiorRunOk) {
|
||||||
// Shift-F5 interrupts. It is also "interruptible".
|
// Shift-F5 interrupts. It is also "interruptible".
|
||||||
m_interruptAction->setEnabled(true);
|
m_interruptAction->setEnabled(true);
|
||||||
@@ -2314,6 +2326,7 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
|
|||||||
m_debugWithoutDeployAction->setEnabled(false);
|
m_debugWithoutDeployAction->setEnabled(false);
|
||||||
m_visibleStartAction->setAction(m_interruptAction);
|
m_visibleStartAction->setAction(m_interruptAction);
|
||||||
m_hiddenStopAction->setAction(m_interruptAction);
|
m_hiddenStopAction->setAction(m_interruptAction);
|
||||||
|
m_localsAndWatchersWindow->setShowLocals(false);
|
||||||
} else if (state == DebuggerFinished) {
|
} else if (state == DebuggerFinished) {
|
||||||
// We don't want to do anything anymore.
|
// We don't want to do anything anymore.
|
||||||
m_interruptAction->setEnabled(false);
|
m_interruptAction->setEnabled(false);
|
||||||
@@ -2403,7 +2416,6 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
|
|||||||
|| state == DebuggerFinished
|
|| state == DebuggerFinished
|
||||||
|| state == InferiorUnrunnable;
|
|| state == InferiorUnrunnable;
|
||||||
setBusyCursor(!notbusy);
|
setBusyCursor(!notbusy);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebuggerPluginPrivate::updateDebugActions()
|
void DebuggerPluginPrivate::updateDebugActions()
|
||||||
@@ -2927,6 +2939,8 @@ void DebuggerPluginPrivate::extensionsInitialized()
|
|||||||
m_localsWindow->setObjectName(QLatin1String("CppDebugLocals"));
|
m_localsWindow->setObjectName(QLatin1String("CppDebugLocals"));
|
||||||
m_watchersWindow = new WatchWindow(WatchTreeView::WatchersType);
|
m_watchersWindow = new WatchWindow(WatchTreeView::WatchersType);
|
||||||
m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers"));
|
m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers"));
|
||||||
|
m_inspectorWindow = new WatchWindow(WatchTreeView::InspectType);
|
||||||
|
m_inspectorWindow->setObjectName(QLatin1String("Inspector"));
|
||||||
|
|
||||||
// Snapshot
|
// Snapshot
|
||||||
m_snapshotHandler = new SnapshotHandler;
|
m_snapshotHandler = new SnapshotHandler;
|
||||||
@@ -3018,6 +3032,22 @@ void DebuggerPluginPrivate::extensionsInitialized()
|
|||||||
connect(action(OperateByInstruction), SIGNAL(triggered(bool)),
|
connect(action(OperateByInstruction), SIGNAL(triggered(bool)),
|
||||||
SLOT(handleOperateByInstructionTriggered(bool)));
|
SLOT(handleOperateByInstructionTriggered(bool)));
|
||||||
|
|
||||||
|
QAction *qmlSelectDummyAction = new QAction(tr("Select"), this);
|
||||||
|
qmlSelectDummyAction->setCheckable(true);
|
||||||
|
qmlSelectDummyAction->setIcon(QIcon(_(":/debugger/images/qml/select.png")));
|
||||||
|
qmlSelectDummyAction->setEnabled(false);
|
||||||
|
Core::Command *qmlSelectCommand
|
||||||
|
= am->registerAction(qmlSelectDummyAction, QML_SELECTTOOL,
|
||||||
|
globalcontext);
|
||||||
|
|
||||||
|
QAction *qmlZoomDummyAction = new QAction(tr("Zoom"), this);
|
||||||
|
qmlZoomDummyAction->setCheckable(true);
|
||||||
|
qmlZoomDummyAction->setIcon(QIcon(_(":/debugger/images/qml/zoom.png")));
|
||||||
|
qmlZoomDummyAction->setEnabled(false);
|
||||||
|
Core::Command *qmlZoomCommand
|
||||||
|
= am->registerAction(qmlZoomDummyAction, QML_ZOOMTOOL,
|
||||||
|
globalcontext);
|
||||||
|
|
||||||
ActionContainer *debugMenu =
|
ActionContainer *debugMenu =
|
||||||
am->actionContainer(ProjectExplorer::Constants::M_DEBUG);
|
am->actionContainer(ProjectExplorer::Constants::M_DEBUG);
|
||||||
|
|
||||||
@@ -3044,17 +3074,13 @@ void DebuggerPluginPrivate::extensionsInitialized()
|
|||||||
m_mainWindow->createDockWidget(CppLanguage, m_stackWindow);
|
m_mainWindow->createDockWidget(CppLanguage, m_stackWindow);
|
||||||
m_mainWindow->createDockWidget(CppLanguage, m_threadsWindow);
|
m_mainWindow->createDockWidget(CppLanguage, m_threadsWindow);
|
||||||
|
|
||||||
QSplitter *localsAndWatchers = new MiniSplitter(Qt::Vertical);
|
m_localsAndWatchersWindow = new LocalsAndWatchersWindow(
|
||||||
localsAndWatchers->setObjectName(QLatin1String(DOCKWIDGET_WATCHERS));
|
m_localsWindow, m_inspectorWindow, m_returnWindow,
|
||||||
localsAndWatchers->setWindowTitle(m_localsWindow->windowTitle());
|
m_watchersWindow);
|
||||||
localsAndWatchers->addWidget(m_localsWindow);
|
m_localsAndWatchersWindow->setObjectName(QLatin1String(DOCKWIDGET_WATCHERS));
|
||||||
localsAndWatchers->addWidget(m_returnWindow);
|
m_localsAndWatchersWindow->setWindowTitle(m_localsWindow->windowTitle());
|
||||||
localsAndWatchers->addWidget(m_watchersWindow);
|
|
||||||
localsAndWatchers->setStretchFactor(0, 3);
|
|
||||||
localsAndWatchers->setStretchFactor(1, 1);
|
|
||||||
localsAndWatchers->setStretchFactor(2, 1);
|
|
||||||
|
|
||||||
dock = m_mainWindow->createDockWidget(CppLanguage, localsAndWatchers);
|
dock = m_mainWindow->createDockWidget(CppLanguage, m_localsAndWatchersWindow);
|
||||||
dock->setProperty(DOCKWIDGET_DEFAULT_AREA, Qt::RightDockWidgetArea);
|
dock->setProperty(DOCKWIDGET_DEFAULT_AREA, Qt::RightDockWidgetArea);
|
||||||
|
|
||||||
m_mainWindow->addStagedMenuEntries();
|
m_mainWindow->addStagedMenuEntries();
|
||||||
@@ -3443,6 +3469,11 @@ void DebuggerPluginPrivate::extensionsInitialized()
|
|||||||
connect(action(SettingsDialog), SIGNAL(triggered()),
|
connect(action(SettingsDialog), SIGNAL(triggered()),
|
||||||
SLOT(showSettingsDialog()));
|
SLOT(showSettingsDialog()));
|
||||||
|
|
||||||
|
// QML Actions
|
||||||
|
connect(action(ShowQmlObjectTree), SIGNAL(valueChanged(QVariant)),
|
||||||
|
SLOT(updateQmlActions()));
|
||||||
|
updateQmlActions();
|
||||||
|
|
||||||
// Toolbar
|
// Toolbar
|
||||||
QWidget *toolbarContainer = new QWidget;
|
QWidget *toolbarContainer = new QWidget;
|
||||||
|
|
||||||
@@ -3472,6 +3503,19 @@ void DebuggerPluginPrivate::extensionsInitialized()
|
|||||||
hbox->addSpacerItem(new QSpacerItem(4, 0));
|
hbox->addSpacerItem(new QSpacerItem(4, 0));
|
||||||
|
|
||||||
m_mainWindow->setToolBar(CppLanguage, toolbarContainer);
|
m_mainWindow->setToolBar(CppLanguage, toolbarContainer);
|
||||||
|
|
||||||
|
QWidget *qmlToolbar = new QWidget;
|
||||||
|
hbox = new QHBoxLayout(qmlToolbar);
|
||||||
|
hbox->setMargin(0);
|
||||||
|
hbox->setSpacing(0);
|
||||||
|
hbox->addWidget(toolButton(action(QmlUpdateOnSave)));
|
||||||
|
hbox->addWidget(toolButton(action(ShowAppOnTop)));
|
||||||
|
hbox->addWidget(new Utils::StyledSeparator);
|
||||||
|
hbox->addWidget(toolButton(qmlSelectCommand->action()));
|
||||||
|
hbox->addWidget(toolButton(qmlZoomCommand->action()));
|
||||||
|
hbox->addWidget(new Utils::StyledSeparator);
|
||||||
|
m_mainWindow->setToolBar(QmlLanguage, qmlToolbar);
|
||||||
|
|
||||||
m_mainWindow->setToolBar(AnyLanguage, m_statusLabel);
|
m_mainWindow->setToolBar(AnyLanguage, m_statusLabel);
|
||||||
|
|
||||||
connect(action(EnableReverseDebugging),
|
connect(action(EnableReverseDebugging),
|
||||||
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
41
src/plugins/debugger/localsandwatcherswindow.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "localsandwatcherswindow.h"
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QSplitter>
|
||||||
|
#include <QStackedWidget>
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
LocalsAndWatchersWindow::LocalsAndWatchersWindow(
|
||||||
|
QWidget *locals, QWidget *inspector, QWidget *returnWidget,
|
||||||
|
QWidget *watchers, QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||||
|
layout->setMargin(0);
|
||||||
|
layout->setSpacing(0);
|
||||||
|
|
||||||
|
m_splitter = new QSplitter(Qt::Vertical);
|
||||||
|
layout->addWidget(m_splitter);
|
||||||
|
|
||||||
|
m_localsAndInspector = new QStackedWidget();
|
||||||
|
m_localsAndInspector->addWidget(locals);
|
||||||
|
m_localsAndInspector->addWidget(inspector);
|
||||||
|
m_localsAndInspector->setCurrentWidget(inspector);
|
||||||
|
|
||||||
|
m_splitter->addWidget(m_localsAndInspector);
|
||||||
|
m_splitter->addWidget(returnWidget);
|
||||||
|
m_splitter->addWidget(watchers);
|
||||||
|
|
||||||
|
m_splitter->setStretchFactor(0, 3);
|
||||||
|
m_splitter->setStretchFactor(2, 1);
|
||||||
|
m_splitter->setStretchFactor(3, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalsAndWatchersWindow::setShowLocals(bool showLocals)
|
||||||
|
{
|
||||||
|
m_localsAndInspector->setCurrentIndex(showLocals ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Debugger
|
32
src/plugins/debugger/localsandwatcherswindow.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef LOCALSANDWATCHERSWIDGET_H
|
||||||
|
#define LOCALSANDWATCHERSWIDGET_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QSplitter;
|
||||||
|
class QStackedWidget;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class LocalsAndWatchersWindow : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit LocalsAndWatchersWindow(
|
||||||
|
QWidget *locals, QWidget *inspector,
|
||||||
|
QWidget *returnWidget, QWidget *watchers, QWidget *parent = 0);
|
||||||
|
|
||||||
|
void setShowLocals(bool showLocals);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSplitter *m_splitter;
|
||||||
|
QStackedWidget *m_localsAndInspector;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Debugger
|
||||||
|
|
||||||
|
#endif // LOCALSANDWATCHERSWIDGET_H
|
@@ -8,7 +8,10 @@ HEADERS += \
|
|||||||
$$PWD/qscriptdebuggerclient.h \
|
$$PWD/qscriptdebuggerclient.h \
|
||||||
$$PWD/qmlv8debuggerclient.h \
|
$$PWD/qmlv8debuggerclient.h \
|
||||||
$$PWD/interactiveinterpreter.h \
|
$$PWD/interactiveinterpreter.h \
|
||||||
$$PWD/qmlv8debuggerclientconstants.h
|
$$PWD/qmlv8debuggerclientconstants.h \
|
||||||
|
$$PWD/qmlinspectoragent.h \
|
||||||
|
$$PWD/qmllivetextpreview.h \
|
||||||
|
$$PWD/qmlinspectoradapter.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/qmlengine.cpp \
|
$$PWD/qmlengine.cpp \
|
||||||
@@ -17,4 +20,7 @@ SOURCES += \
|
|||||||
$$PWD/qmlcppengine.cpp \
|
$$PWD/qmlcppengine.cpp \
|
||||||
$$PWD/qscriptdebuggerclient.cpp \
|
$$PWD/qscriptdebuggerclient.cpp \
|
||||||
$$PWD/qmlv8debuggerclient.cpp \
|
$$PWD/qmlv8debuggerclient.cpp \
|
||||||
$$PWD/interactiveinterpreter.cpp
|
$$PWD/interactiveinterpreter.cpp \
|
||||||
|
$$PWD/qmlinspectoragent.cpp \
|
||||||
|
$$PWD/qmllivetextpreview.cpp \
|
||||||
|
$$PWD/qmlinspectoradapter.cpp
|
||||||
|
@@ -32,116 +32,80 @@
|
|||||||
|
|
||||||
#include "qmladapter.h"
|
#include "qmladapter.h"
|
||||||
|
|
||||||
#include "qscriptdebuggerclient.h"
|
|
||||||
#include "qmlv8debuggerclient.h"
|
|
||||||
|
|
||||||
#include "qmlengine.h"
|
#include "qmlengine.h"
|
||||||
|
#include "qmlv8debuggerclient.h"
|
||||||
|
#include "qscriptdebuggerclient.h"
|
||||||
|
|
||||||
#include <extensionsystem/pluginmanager.h>
|
#include <qmldebug/qdebugmessageclient.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <qmldebug/baseenginedebugclient.h>
|
|
||||||
#include <qmldebug/qdebugmessageclient.h>
|
|
||||||
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QWeakPointer>
|
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class QmlAdapterPrivate
|
QmlAdapter::QmlAdapter(DebuggerEngine *engine, QObject *parent)
|
||||||
{
|
: QObject(parent)
|
||||||
public:
|
, m_engine(engine)
|
||||||
explicit QmlAdapterPrivate(DebuggerEngine *engine)
|
|
||||||
: m_engine(engine)
|
|
||||||
, m_qmlClient(0)
|
, m_qmlClient(0)
|
||||||
, m_engineDebugClient(0)
|
|
||||||
, m_conn(0)
|
, m_conn(0)
|
||||||
, m_currentSelectedDebugId(-1)
|
|
||||||
, m_msgClient(0)
|
, m_msgClient(0)
|
||||||
{
|
{
|
||||||
m_connectionTimer.setInterval(4000);
|
m_connectionTimer.setInterval(4000);
|
||||||
m_connectionTimer.setSingleShot(true);
|
m_connectionTimer.setSingleShot(true);
|
||||||
}
|
connect(&m_connectionTimer, SIGNAL(timeout()), SLOT(checkConnectionState()));
|
||||||
|
|
||||||
QWeakPointer<DebuggerEngine> m_engine;
|
m_conn = new QmlDebugConnection(this);
|
||||||
BaseQmlDebuggerClient *m_qmlClient;
|
connect(m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
|
||||||
BaseEngineDebugClient *m_engineDebugClient;
|
|
||||||
QTimer m_connectionTimer;
|
|
||||||
QmlDebugConnection *m_conn;
|
|
||||||
QHash<QString, BaseQmlDebuggerClient*> debugClients;
|
|
||||||
int m_currentSelectedDebugId;
|
|
||||||
QString m_currentSelectedDebugName;
|
|
||||||
QDebugMessageClient *m_msgClient;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
|
|
||||||
QmlAdapter::QmlAdapter(DebuggerEngine *engine, QObject *parent)
|
|
||||||
: QObject(parent), d(new Internal::QmlAdapterPrivate(engine))
|
|
||||||
{
|
|
||||||
connect(&d->m_connectionTimer, SIGNAL(timeout()), SLOT(checkConnectionState()));
|
|
||||||
d->m_conn = new QmlDebugConnection(this);
|
|
||||||
connect(d->m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
|
|
||||||
SLOT(connectionStateChanged()));
|
SLOT(connectionStateChanged()));
|
||||||
connect(d->m_conn, SIGNAL(error(QAbstractSocket::SocketError)),
|
connect(m_conn, SIGNAL(error(QAbstractSocket::SocketError)),
|
||||||
SLOT(connectionErrorOccurred(QAbstractSocket::SocketError)));
|
SLOT(connectionErrorOccurred(QAbstractSocket::SocketError)));
|
||||||
|
|
||||||
ExtensionSystem::PluginManager *pluginManager =
|
|
||||||
ExtensionSystem::PluginManager::instance();
|
|
||||||
pluginManager->addObject(this);
|
|
||||||
|
|
||||||
createDebuggerClients();
|
createDebuggerClients();
|
||||||
d->m_msgClient = new QDebugMessageClient(d->m_conn);
|
m_msgClient = new QDebugMessageClient(m_conn);
|
||||||
connect(d->m_msgClient, SIGNAL(newStatus(QmlDebugClient::Status)),
|
connect(m_msgClient, SIGNAL(newStatus(QmlDebugClient::Status)),
|
||||||
this, SLOT(clientStatusChanged(QmlDebugClient::Status)));
|
this, SLOT(clientStatusChanged(QmlDebugClient::Status)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlAdapter::~QmlAdapter()
|
QmlAdapter::~QmlAdapter()
|
||||||
{
|
{
|
||||||
ExtensionSystem::PluginManager *pluginManager =
|
|
||||||
ExtensionSystem::PluginManager::instance();
|
|
||||||
|
|
||||||
if (pluginManager->allObjects().contains(this))
|
|
||||||
pluginManager->removeObject(this);
|
|
||||||
delete d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAdapter::beginConnectionTcp(const QString &address, quint16 port)
|
void QmlAdapter::beginConnectionTcp(const QString &address, quint16 port)
|
||||||
{
|
{
|
||||||
if (d->m_engine.isNull()
|
if (m_engine.isNull()
|
||||||
|| (d->m_conn && d->m_conn->state() != QAbstractSocket::UnconnectedState))
|
|| (m_conn && m_conn->state() != QAbstractSocket::UnconnectedState))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
showConnectionStatusMessage(tr("Connecting to debug server %1:%2").arg(address).arg(
|
showConnectionStatusMessage(tr("Connecting to debug server %1:%2").arg(address).arg(
|
||||||
QString::number(port)));
|
QString::number(port)));
|
||||||
d->m_conn->connectToHost(address, port);
|
m_conn->connectToHost(address, port);
|
||||||
|
|
||||||
//A timeout to check the connection state
|
//A timeout to check the connection state
|
||||||
d->m_connectionTimer.start();
|
m_connectionTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAdapter::beginConnectionOst(const QString &channel)
|
void QmlAdapter::beginConnectionOst(const QString &channel)
|
||||||
{
|
{
|
||||||
if (d->m_engine.isNull()
|
if (m_engine.isNull()
|
||||||
|| (d->m_conn && d->m_conn->state() != QAbstractSocket::UnconnectedState))
|
|| (m_conn && m_conn->state() != QAbstractSocket::UnconnectedState))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
showConnectionStatusMessage(tr("Connecting to debug server on %1").arg(channel));
|
showConnectionStatusMessage(tr("Connecting to debug server on %1").arg(channel));
|
||||||
d->m_conn->connectToOst(channel);
|
m_conn->connectToOst(channel);
|
||||||
|
|
||||||
//A timeout to check the connection state
|
//A timeout to check the connection state
|
||||||
d->m_connectionTimer.start();
|
m_connectionTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAdapter::closeConnection()
|
void QmlAdapter::closeConnection()
|
||||||
{
|
{
|
||||||
if (d->m_connectionTimer.isActive()) {
|
if (m_connectionTimer.isActive()) {
|
||||||
d->m_connectionTimer.stop();
|
m_connectionTimer.stop();
|
||||||
} else {
|
} else {
|
||||||
if (d->m_conn) {
|
if (m_conn) {
|
||||||
d->m_conn->close();
|
m_conn->close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,13 +113,13 @@ void QmlAdapter::closeConnection()
|
|||||||
void QmlAdapter::connectionErrorOccurred(QAbstractSocket::SocketError socketError)
|
void QmlAdapter::connectionErrorOccurred(QAbstractSocket::SocketError socketError)
|
||||||
{
|
{
|
||||||
showConnectionStatusMessage(tr("Error: (%1) %2", "%1=error code, %2=error message")
|
showConnectionStatusMessage(tr("Error: (%1) %2", "%1=error code, %2=error message")
|
||||||
.arg(socketError).arg(d->m_conn->errorString()));
|
.arg(socketError).arg(m_conn->errorString()));
|
||||||
|
|
||||||
// this is only an error if we are already connected and something goes wrong.
|
// this is only an error if we are already connected and something goes wrong.
|
||||||
if (isConnected()) {
|
if (isConnected()) {
|
||||||
emit connectionError(socketError);
|
emit connectionError(socketError);
|
||||||
} else {
|
} else {
|
||||||
d->m_connectionTimer.stop();
|
m_connectionTimer.stop();
|
||||||
emit connectionStartupFailed();
|
emit connectionStartupFailed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,13 +143,13 @@ void QmlAdapter::debugClientStatusChanged(QmlDebugClient::Status status)
|
|||||||
QmlDebugClient *client = qobject_cast<QmlDebugClient*>(sender());
|
QmlDebugClient *client = qobject_cast<QmlDebugClient*>(sender());
|
||||||
QTC_ASSERT(client, return);
|
QTC_ASSERT(client, return);
|
||||||
|
|
||||||
d->m_qmlClient = qobject_cast<Internal::BaseQmlDebuggerClient *>(client);
|
m_qmlClient = qobject_cast<Internal::BaseQmlDebuggerClient *>(client);
|
||||||
d->m_qmlClient->startSession();
|
m_qmlClient->startSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAdapter::connectionStateChanged()
|
void QmlAdapter::connectionStateChanged()
|
||||||
{
|
{
|
||||||
switch (d->m_conn->state()) {
|
switch (m_conn->state()) {
|
||||||
case QAbstractSocket::UnconnectedState:
|
case QAbstractSocket::UnconnectedState:
|
||||||
{
|
{
|
||||||
showConnectionStatusMessage(tr("disconnected.\n\n"));
|
showConnectionStatusMessage(tr("disconnected.\n\n"));
|
||||||
@@ -203,7 +167,7 @@ void QmlAdapter::connectionStateChanged()
|
|||||||
{
|
{
|
||||||
showConnectionStatusMessage(tr("connected.\n"));
|
showConnectionStatusMessage(tr("connected.\n"));
|
||||||
|
|
||||||
d->m_connectionTimer.stop();
|
m_connectionTimer.stop();
|
||||||
|
|
||||||
//reloadEngines();
|
//reloadEngines();
|
||||||
emit connected();
|
emit connected();
|
||||||
@@ -228,125 +192,83 @@ void QmlAdapter::checkConnectionState()
|
|||||||
|
|
||||||
void QmlAdapter::createDebuggerClients()
|
void QmlAdapter::createDebuggerClients()
|
||||||
{
|
{
|
||||||
|
Internal::QScriptDebuggerClient *debugClient1 = new Internal::QScriptDebuggerClient(m_conn);
|
||||||
Internal::QScriptDebuggerClient *client1 = new Internal::QScriptDebuggerClient(d->m_conn);
|
connect(debugClient1, SIGNAL(newStatus(QmlDebugClient::Status)),
|
||||||
connect(client1, SIGNAL(newStatus(QmlDebugClient::Status)),
|
|
||||||
this, SLOT(clientStatusChanged(QmlDebugClient::Status)));
|
this, SLOT(clientStatusChanged(QmlDebugClient::Status)));
|
||||||
connect(client1, SIGNAL(newStatus(QmlDebugClient::Status)),
|
connect(debugClient1, SIGNAL(newStatus(QmlDebugClient::Status)),
|
||||||
this, SLOT(debugClientStatusChanged(QmlDebugClient::Status)));
|
this, SLOT(debugClientStatusChanged(QmlDebugClient::Status)));
|
||||||
|
|
||||||
Internal::QmlV8DebuggerClient *client2 = new Internal::QmlV8DebuggerClient(d->m_conn);
|
Internal::QmlV8DebuggerClient *debugClient2 = new Internal::QmlV8DebuggerClient(m_conn);
|
||||||
connect(client2, SIGNAL(newStatus(QmlDebugClient::Status)),
|
connect(debugClient2, SIGNAL(newStatus(QmlDebugClient::Status)),
|
||||||
this, SLOT(clientStatusChanged(QmlDebugClient::Status)));
|
this, SLOT(clientStatusChanged(QmlDebugClient::Status)));
|
||||||
connect(client2, SIGNAL(newStatus(QmlDebugClient::Status)),
|
connect(debugClient2, SIGNAL(newStatus(QmlDebugClient::Status)),
|
||||||
this, SLOT(debugClientStatusChanged(QmlDebugClient::Status)));
|
this, SLOT(debugClientStatusChanged(QmlDebugClient::Status)));
|
||||||
|
|
||||||
d->debugClients.insert(client1->name(),client1);
|
m_debugClients.insert(debugClient1->name(),debugClient1);
|
||||||
d->debugClients.insert(client2->name(),client2);
|
m_debugClients.insert(debugClient2->name(),debugClient2);
|
||||||
|
|
||||||
|
debugClient1->setEngine((Internal::QmlEngine*)(m_engine.data()));
|
||||||
client1->setEngine((Internal::QmlEngine*)(d->m_engine.data()));
|
debugClient2->setEngine((Internal::QmlEngine*)(m_engine.data()));
|
||||||
client2->setEngine((Internal::QmlEngine*)(d->m_engine.data()));
|
|
||||||
|
|
||||||
//engine->startSuccessful(); // FIXME: AAA: port to new debugger states
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlAdapter::isConnected() const
|
bool QmlAdapter::isConnected() const
|
||||||
{
|
{
|
||||||
return d->m_conn && d->m_qmlClient && d->m_conn->state() == QAbstractSocket::ConnectedState;
|
return m_conn && m_qmlClient && m_conn->state() == QAbstractSocket::ConnectedState;
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlDebugConnection *QmlAdapter::connection() const
|
QmlDebugConnection *QmlAdapter::connection() const
|
||||||
{
|
{
|
||||||
return d->m_conn;
|
return m_conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
DebuggerEngine *QmlAdapter::debuggerEngine() const
|
DebuggerEngine *QmlAdapter::debuggerEngine() const
|
||||||
{
|
{
|
||||||
return d->m_engine.data();
|
return m_engine.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAdapter::showConnectionStatusMessage(const QString &message)
|
void QmlAdapter::showConnectionStatusMessage(const QString &message)
|
||||||
{
|
{
|
||||||
if (!d->m_engine.isNull())
|
if (!m_engine.isNull())
|
||||||
d->m_engine.data()->showMessage(QLatin1String("QML Debugger: ") + message, LogStatus);
|
m_engine.data()->showMessage(QLatin1String("QML Debugger: ") + message, LogStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAdapter::showConnectionErrorMessage(const QString &message)
|
void QmlAdapter::showConnectionErrorMessage(const QString &message)
|
||||||
{
|
{
|
||||||
if (!d->m_engine.isNull())
|
if (!m_engine.isNull())
|
||||||
d->m_engine.data()->showMessage(QLatin1String("QML Debugger: ") + message, LogError);
|
m_engine.data()->showMessage(QLatin1String("QML Debugger: ") + message, LogError);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlAdapter::disableJsDebugging(bool block)
|
bool QmlAdapter::disableJsDebugging(bool block)
|
||||||
{
|
{
|
||||||
if (d->m_engine.isNull())
|
if (m_engine.isNull())
|
||||||
return block;
|
return block;
|
||||||
|
|
||||||
bool isBlocked = d->m_engine.data()->state() == InferiorRunOk;
|
bool isBlocked = m_engine.data()->state() == InferiorRunOk;
|
||||||
|
|
||||||
if (isBlocked == block)
|
if (isBlocked == block)
|
||||||
return block;
|
return block;
|
||||||
|
|
||||||
if (block) {
|
if (block)
|
||||||
d->m_engine.data()->continueInferior();
|
m_engine.data()->continueInferior();
|
||||||
} else {
|
else
|
||||||
d->m_engine.data()->requestInterruptInferior();
|
m_engine.data()->requestInterruptInferior();
|
||||||
}
|
|
||||||
|
|
||||||
return isBlocked;
|
return isBlocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
Internal::BaseQmlDebuggerClient *QmlAdapter::activeDebuggerClient()
|
Internal::BaseQmlDebuggerClient *QmlAdapter::activeDebuggerClient()
|
||||||
{
|
{
|
||||||
return d->m_qmlClient;
|
return m_qmlClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<QString, Internal::BaseQmlDebuggerClient*> QmlAdapter::debuggerClients()
|
QHash<QString, Internal::BaseQmlDebuggerClient*> QmlAdapter::debuggerClients()
|
||||||
{
|
{
|
||||||
return d->debugClients;
|
return m_debugClients;
|
||||||
}
|
|
||||||
|
|
||||||
BaseEngineDebugClient *QmlAdapter::engineDebugClient() const
|
|
||||||
{
|
|
||||||
return d->m_engineDebugClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlAdapter::setEngineDebugClient(BaseEngineDebugClient *client)
|
|
||||||
{
|
|
||||||
Internal::QmlEngine *engine =
|
|
||||||
qobject_cast<Internal::QmlEngine *>(d->m_engine.data());
|
|
||||||
if (engine && d->m_engineDebugClient)
|
|
||||||
disconnect(d->m_engineDebugClient, SIGNAL(result(quint32,QVariant,QByteArray)),
|
|
||||||
engine,
|
|
||||||
SLOT(expressionEvaluated(quint32,QVariant)));
|
|
||||||
d->m_engineDebugClient = client;
|
|
||||||
if (engine && d->m_engineDebugClient)
|
|
||||||
connect(d->m_engineDebugClient, SIGNAL(result(quint32,QVariant,QByteArray)),
|
|
||||||
engine,
|
|
||||||
SLOT(expressionEvaluated(quint32,QVariant)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QDebugMessageClient *QmlAdapter::messageClient() const
|
QDebugMessageClient *QmlAdapter::messageClient() const
|
||||||
{
|
{
|
||||||
return d->m_msgClient;
|
return m_msgClient;
|
||||||
}
|
|
||||||
|
|
||||||
int QmlAdapter::currentSelectedDebugId() const
|
|
||||||
{
|
|
||||||
return d->m_currentSelectedDebugId;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QmlAdapter::currentSelectedDisplayName() const
|
|
||||||
{
|
|
||||||
return d->m_currentSelectedDebugName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlAdapter::setCurrentSelectedDebugInfo(int currentDebugId, const QString &displayName)
|
|
||||||
{
|
|
||||||
d->m_currentSelectedDebugId = currentDebugId;
|
|
||||||
d->m_currentSelectedDebugName = displayName;
|
|
||||||
emit selectionChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAdapter::logServiceStatusChange(const QString &service, float version,
|
void QmlAdapter::logServiceStatusChange(const QString &service, float version,
|
||||||
@@ -374,8 +296,9 @@ void QmlAdapter::logServiceStatusChange(const QString &service, float version,
|
|||||||
|
|
||||||
void QmlAdapter::logServiceActivity(const QString &service, const QString &logMessage)
|
void QmlAdapter::logServiceActivity(const QString &service, const QString &logMessage)
|
||||||
{
|
{
|
||||||
if (!d->m_engine.isNull())
|
if (!m_engine.isNull())
|
||||||
d->m_engine.data()->showMessage(service + QLatin1Char(' ') + logMessage, LogDebug);
|
m_engine.data()->showMessage(service + QLatin1Char(' ') + logMessage, LogDebug);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
} // namespace Debugger
|
} // namespace Debugger
|
||||||
|
@@ -35,18 +35,21 @@
|
|||||||
|
|
||||||
#include "debugger_global.h"
|
#include "debugger_global.h"
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QAbstractSocket>
|
|
||||||
#include <qmldebug/qmldebugclient.h>
|
#include <qmldebug/qmldebugclient.h>
|
||||||
|
|
||||||
|
#include <QAbstractSocket>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPointer>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
using namespace QmlDebug;
|
||||||
|
|
||||||
namespace QmlDebug {
|
namespace QmlDebug {
|
||||||
class BaseEngineDebugClient;
|
class BaseEngineDebugClient;
|
||||||
class QmlDebugConnection;
|
class QmlDebugConnection;
|
||||||
class QDebugMessageClient;
|
class QDebugMessageClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace QmlDebug;
|
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
|
|
||||||
class DebuggerEngine;
|
class DebuggerEngine;
|
||||||
@@ -54,9 +57,8 @@ class DebuggerEngine;
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
class BaseQmlDebuggerClient;
|
class BaseQmlDebuggerClient;
|
||||||
class QmlAdapterPrivate;
|
class QmlAdapterPrivate;
|
||||||
} // namespace Internal
|
|
||||||
|
|
||||||
class DEBUGGER_EXPORT QmlAdapter : public QObject
|
class QmlAdapter : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -79,14 +81,8 @@ public:
|
|||||||
QHash<QString, Internal::BaseQmlDebuggerClient*> debuggerClients();
|
QHash<QString, Internal::BaseQmlDebuggerClient*> debuggerClients();
|
||||||
|
|
||||||
BaseEngineDebugClient *engineDebugClient() const;
|
BaseEngineDebugClient *engineDebugClient() const;
|
||||||
void setEngineDebugClient(BaseEngineDebugClient *client);
|
|
||||||
|
|
||||||
QDebugMessageClient *messageClient() const;
|
QDebugMessageClient *messageClient() const;
|
||||||
|
|
||||||
int currentSelectedDebugId() const;
|
|
||||||
QString currentSelectedDisplayName() const;
|
|
||||||
void setCurrentSelectedDebugInfo(int debugId, const QString &displayName = QString());
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void logServiceStatusChange(const QString &service, float version,
|
void logServiceStatusChange(const QString &service, float version,
|
||||||
QmlDebugClient::Status newStatus);
|
QmlDebugClient::Status newStatus);
|
||||||
@@ -98,7 +94,6 @@ signals:
|
|||||||
void connectionStartupFailed();
|
void connectionStartupFailed();
|
||||||
void connectionError(QAbstractSocket::SocketError socketError);
|
void connectionError(QAbstractSocket::SocketError socketError);
|
||||||
void serviceConnectionError(const QString serviceName);
|
void serviceConnectionError(const QString serviceName);
|
||||||
void selectionChanged();
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void connectionErrorOccurred(QAbstractSocket::SocketError socketError);
|
void connectionErrorOccurred(QAbstractSocket::SocketError socketError);
|
||||||
@@ -113,9 +108,15 @@ private:
|
|||||||
void showConnectionErrorMessage(const QString &message);
|
void showConnectionErrorMessage(const QString &message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Internal::QmlAdapterPrivate *d;
|
QPointer<DebuggerEngine> m_engine;
|
||||||
|
BaseQmlDebuggerClient *m_qmlClient;
|
||||||
|
QTimer m_connectionTimer;
|
||||||
|
QmlDebugConnection *m_conn;
|
||||||
|
QHash<QString, BaseQmlDebuggerClient*> m_debugClients;
|
||||||
|
QDebugMessageClient *m_msgClient;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
} // namespace Debugger
|
} // namespace Debugger
|
||||||
|
|
||||||
#endif // QMLADAPTER_H
|
#endif // QMLADAPTER_H
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
#include "stackhandler.h"
|
#include "stackhandler.h"
|
||||||
#include "qmlengine.h"
|
#include "qmlengine.h"
|
||||||
#include "qtmessageloghandler.h"
|
#include "qtmessageloghandler.h"
|
||||||
|
#include "watchdata.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
@@ -149,6 +150,8 @@ bool QmlCppEngine::setToolTipExpression(const QPoint & mousePos,
|
|||||||
void QmlCppEngine::updateWatchData(const WatchData &data,
|
void QmlCppEngine::updateWatchData(const WatchData &data,
|
||||||
const WatchUpdateFlags &flags)
|
const WatchUpdateFlags &flags)
|
||||||
{
|
{
|
||||||
|
if (data.iname.startsWith("inspect."))
|
||||||
|
d->m_qmlEngine->updateWatchData(data, flags);
|
||||||
d->m_activeEngine->updateWatchData(data, flags);
|
d->m_activeEngine->updateWatchData(data, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -40,7 +40,7 @@ namespace Internal {
|
|||||||
|
|
||||||
class QmlCppEnginePrivate;
|
class QmlCppEnginePrivate;
|
||||||
|
|
||||||
class DEBUGGER_EXPORT QmlCppEngine : public DebuggerEngine
|
class QmlCppEngine : public DebuggerEngine
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@@ -32,8 +32,10 @@
|
|||||||
|
|
||||||
#include "qmlengine.h"
|
#include "qmlengine.h"
|
||||||
#include "qmladapter.h"
|
#include "qmladapter.h"
|
||||||
|
#include "qmlinspectoradapter.h"
|
||||||
#include "interactiveinterpreter.h"
|
#include "interactiveinterpreter.h"
|
||||||
#include "baseqmldebuggerclient.h"
|
#include "baseqmldebuggerclient.h"
|
||||||
|
#include "qmlinspectoragent.h"
|
||||||
|
|
||||||
#include "debuggerstartparameters.h"
|
#include "debuggerstartparameters.h"
|
||||||
#include "debuggeractions.h"
|
#include "debuggeractions.h"
|
||||||
@@ -113,13 +115,13 @@ public:
|
|||||||
private:
|
private:
|
||||||
friend class QmlEngine;
|
friend class QmlEngine;
|
||||||
QmlAdapter m_adapter;
|
QmlAdapter m_adapter;
|
||||||
|
QmlInspectorAdapter m_inspectorAdapter;
|
||||||
ApplicationLauncher m_applicationLauncher;
|
ApplicationLauncher m_applicationLauncher;
|
||||||
QTimer m_noDebugOutputTimer;
|
QTimer m_noDebugOutputTimer;
|
||||||
QmlOutputParser m_outputParser;
|
QmlOutputParser m_outputParser;
|
||||||
QHash<QString, QTextDocument*> m_sourceDocuments;
|
QHash<QString, QTextDocument*> m_sourceDocuments;
|
||||||
QHash<QString, QWeakPointer<TextEditor::ITextEditor> > m_sourceEditors;
|
QHash<QString, QWeakPointer<TextEditor::ITextEditor> > m_sourceEditors;
|
||||||
InteractiveInterpreter m_interpreter;
|
InteractiveInterpreter m_interpreter;
|
||||||
bool m_validContext;
|
|
||||||
QHash<QString,BreakpointModelId> pendingBreakpoints;
|
QHash<QString,BreakpointModelId> pendingBreakpoints;
|
||||||
QList<quint32> queryIds;
|
QList<quint32> queryIds;
|
||||||
bool m_retryOnConnectFail;
|
bool m_retryOnConnectFail;
|
||||||
@@ -128,10 +130,11 @@ private:
|
|||||||
|
|
||||||
QmlEnginePrivate::QmlEnginePrivate(QmlEngine *q)
|
QmlEnginePrivate::QmlEnginePrivate(QmlEngine *q)
|
||||||
: m_adapter(q),
|
: m_adapter(q),
|
||||||
m_validContext(false),
|
m_inspectorAdapter(&m_adapter, q),
|
||||||
m_retryOnConnectFail(false),
|
m_retryOnConnectFail(false),
|
||||||
m_automaticConnect(false)
|
m_automaticConnect(false)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
class ASTWalker: public Visitor
|
class ASTWalker: public Visitor
|
||||||
{
|
{
|
||||||
@@ -326,14 +329,18 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters,
|
|||||||
SLOT(updateCurrentContext()));
|
SLOT(updateCurrentContext()));
|
||||||
connect(this->stackHandler(), SIGNAL(currentIndexChanged()),
|
connect(this->stackHandler(), SIGNAL(currentIndexChanged()),
|
||||||
SLOT(updateCurrentContext()));
|
SLOT(updateCurrentContext()));
|
||||||
connect(&d->m_adapter, SIGNAL(selectionChanged()),
|
connect(&d->m_inspectorAdapter, SIGNAL(selectionChanged()),
|
||||||
SLOT(updateCurrentContext()));
|
SLOT(updateCurrentContext()));
|
||||||
|
connect(d->m_inspectorAdapter.agent(), SIGNAL(
|
||||||
|
expressionResult(quint32,QVariant)),
|
||||||
|
SLOT(expressionEvaluated(quint32,QVariant)));
|
||||||
connect(d->m_adapter.messageClient(),
|
connect(d->m_adapter.messageClient(),
|
||||||
SIGNAL(message(QtMsgType,QString,
|
SIGNAL(message(QtMsgType,QString,
|
||||||
QmlDebug::QDebugContextInfo)),
|
QmlDebug::QDebugContextInfo)),
|
||||||
SLOT(appendDebugOutput(QtMsgType,QString,
|
SLOT(appendDebugOutput(QtMsgType,QString,
|
||||||
QmlDebug::QDebugContextInfo)));
|
QmlDebug::QDebugContextInfo)));
|
||||||
|
|
||||||
|
|
||||||
connect(&d->m_applicationLauncher,
|
connect(&d->m_applicationLauncher,
|
||||||
SIGNAL(processExited(int)),
|
SIGNAL(processExited(int)),
|
||||||
SLOT(disconnected()));
|
SLOT(disconnected()));
|
||||||
@@ -1027,8 +1034,11 @@ void QmlEngine::updateWatchData(const WatchData &data,
|
|||||||
{
|
{
|
||||||
// qDebug() << "UPDATE WATCH DATA" << data.toString();
|
// qDebug() << "UPDATE WATCH DATA" << data.toString();
|
||||||
//watchHandler()->rebuildModel();
|
//watchHandler()->rebuildModel();
|
||||||
showStatusMessage(tr("Stopped."), 5000);
|
//showStatusMessage(tr("Stopped."), 5000);
|
||||||
|
|
||||||
|
if (data.iname.startsWith("inspect.")) {
|
||||||
|
d->m_inspectorAdapter.agent()->updateWatchData(data);
|
||||||
|
} else {
|
||||||
if (!data.name.isEmpty() && d->m_adapter.activeDebuggerClient()) {
|
if (!data.name.isEmpty() && d->m_adapter.activeDebuggerClient()) {
|
||||||
if (data.isValueNeeded()) {
|
if (data.isValueNeeded()) {
|
||||||
d->m_adapter.activeDebuggerClient()->updateWatchData(data);
|
d->m_adapter.activeDebuggerClient()->updateWatchData(data);
|
||||||
@@ -1038,8 +1048,9 @@ void QmlEngine::updateWatchData(const WatchData &data,
|
|||||||
d->m_adapter.activeDebuggerClient()->expandObject(data.iname, data.id);
|
d->m_adapter.activeDebuggerClient()->expandObject(data.iname, data.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronizeWatchers();
|
synchronizeWatchers();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!data.isSomethingNeeded())
|
if (!data.isSomethingNeeded())
|
||||||
watchHandler()->insertData(data);
|
watchHandler()->insertData(data);
|
||||||
@@ -1111,8 +1122,7 @@ void QmlEngine::updateCurrentContext()
|
|||||||
{
|
{
|
||||||
const QString context = state() == InferiorStopOk ?
|
const QString context = state() == InferiorStopOk ?
|
||||||
stackHandler()->currentFrame().function :
|
stackHandler()->currentFrame().function :
|
||||||
d->m_adapter.currentSelectedDisplayName();
|
d->m_inspectorAdapter.currentSelectedDisplayName();
|
||||||
d->m_validContext = !context.isEmpty();
|
|
||||||
showMessage(tr("Context: ").append(context), QtMessageLogStatus);
|
showMessage(tr("Context: ").append(context), QtMessageLogStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1154,8 +1164,6 @@ bool QmlEngine::evaluateScriptExpression(const QString& expression)
|
|||||||
bool didEvaluate = true;
|
bool didEvaluate = true;
|
||||||
//Check if string is only white spaces
|
//Check if string is only white spaces
|
||||||
if (!expression.trimmed().isEmpty()) {
|
if (!expression.trimmed().isEmpty()) {
|
||||||
//Check for a valid context
|
|
||||||
if (d->m_validContext) {
|
|
||||||
//check if it can be evaluated
|
//check if it can be evaluated
|
||||||
if (canEvaluateScript(expression)) {
|
if (canEvaluateScript(expression)) {
|
||||||
//Evaluate expression based on engine state
|
//Evaluate expression based on engine state
|
||||||
@@ -1163,14 +1171,11 @@ bool QmlEngine::evaluateScriptExpression(const QString& expression)
|
|||||||
//is sent to V8DebugService. In all other cases, the
|
//is sent to V8DebugService. In all other cases, the
|
||||||
//expression is evaluated by QDeclarativeEngine.
|
//expression is evaluated by QDeclarativeEngine.
|
||||||
if (state() != InferiorStopOk) {
|
if (state() != InferiorStopOk) {
|
||||||
BaseEngineDebugClient *engineDebug =
|
QmlInspectorAgent *agent = d->m_inspectorAdapter.agent();
|
||||||
d->m_adapter.engineDebugClient();
|
quint32 queryId
|
||||||
|
= agent->queryExpressionResult(
|
||||||
int id = d->m_adapter.currentSelectedDebugId();
|
d->m_inspectorAdapter.currentSelectedDebugId(),
|
||||||
if (engineDebug && id != -1) {
|
expression);
|
||||||
quint32 queryId =
|
|
||||||
engineDebug->queryExpressionResult(
|
|
||||||
id, expression);
|
|
||||||
if (queryId) {
|
if (queryId) {
|
||||||
d->queryIds << queryId;
|
d->queryIds << queryId;
|
||||||
} else {
|
} else {
|
||||||
@@ -1182,23 +1187,12 @@ bool QmlEngine::evaluateScriptExpression(const QString& expression)
|
|||||||
QtMessageLogHandler::ErrorType,
|
QtMessageLogHandler::ErrorType,
|
||||||
_("Error evaluating expression.")));
|
_("Error evaluating expression.")));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
executeDebuggerCommand(expression, QmlLanguage);
|
executeDebuggerCommand(expression, QmlLanguage);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
didEvaluate = false;
|
didEvaluate = false;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//Incase of invalid context, show Error message
|
|
||||||
qtMessageLogHandler()->
|
|
||||||
appendItem(new QtMessageLogItem(
|
|
||||||
qtMessageLogHandler()->root(),
|
|
||||||
QtMessageLogHandler::ErrorType,
|
|
||||||
_("Cannot evaluate without "
|
|
||||||
"a valid QML/JS Context.")),
|
|
||||||
qtMessageLogHandler()->rowCount());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return didEvaluate;
|
return didEvaluate;
|
||||||
}
|
}
|
||||||
|
@@ -49,15 +49,13 @@ class IEditor;
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
|
|
||||||
class QmlAdapter;
|
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class QtMessageLogItem;
|
class QtMessageLogItem;
|
||||||
|
class QmlAdapter;
|
||||||
class QmlEnginePrivate;
|
class QmlEnginePrivate;
|
||||||
|
|
||||||
class DEBUGGER_EXPORT QmlEngine : public DebuggerEngine
|
class QmlEngine : public DebuggerEngine
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
611
src/plugins/debugger/qml/qmlinspectoradapter.cpp
Normal file
@@ -0,0 +1,611 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "qmlinspectoradapter.h"
|
||||||
|
|
||||||
|
#include "debuggeractions.h"
|
||||||
|
#include "debuggercore.h"
|
||||||
|
#include "debuggerstringutils.h"
|
||||||
|
#include "qmladapter.h"
|
||||||
|
#include "qmlengine.h"
|
||||||
|
#include "qmlinspectoragent.h"
|
||||||
|
#include "qmllivetextpreview.h"
|
||||||
|
|
||||||
|
#include <coreplugin/actionmanager/actionmanager.h>
|
||||||
|
#include <coreplugin/editormanager/ieditor.h>
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <qmldebug/declarativeenginedebugclient.h>
|
||||||
|
#include <qmldebug/declarativetoolsclient.h>
|
||||||
|
#include <qmldebug/qmlenginedebugclient.h>
|
||||||
|
#include <qmldebug/qmltoolsclient.h>
|
||||||
|
#include <qmljseditor/qmljseditorconstants.h>
|
||||||
|
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||||
|
#include <qmljstools/qmljssemanticinfo.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/savedaction.h>
|
||||||
|
|
||||||
|
using namespace QmlDebug;
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
// Get semantic info from QmlJSTextEditorWidget
|
||||||
|
// (we use the meta object system here to avoid having to link
|
||||||
|
// against qmljseditor)
|
||||||
|
static QmlJSTools::SemanticInfo getSemanticInfo(QPlainTextEdit *qmlJSTextEdit)
|
||||||
|
{
|
||||||
|
QmlJSTools::SemanticInfo info;
|
||||||
|
QTC_ASSERT(QLatin1String(qmlJSTextEdit->metaObject()->className())
|
||||||
|
== QLatin1String("QmlJSEditor::QmlJSTextEditorWidget"),
|
||||||
|
return info);
|
||||||
|
QTC_ASSERT(qmlJSTextEdit->metaObject()->indexOfProperty("semanticInfo")
|
||||||
|
!= -1, return info);
|
||||||
|
|
||||||
|
info = qmlJSTextEdit->property("semanticInfo")
|
||||||
|
.value<QmlJSTools::SemanticInfo>();
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* QmlInspectorAdapter manages the clients for the inspector, and the
|
||||||
|
* integration with the text editor.
|
||||||
|
*/
|
||||||
|
QmlInspectorAdapter::QmlInspectorAdapter(QmlAdapter *debugAdapter,
|
||||||
|
QmlEngine *engine,
|
||||||
|
QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_debugAdapter(debugAdapter)
|
||||||
|
, m_engine(engine)
|
||||||
|
, m_engineClient(0)
|
||||||
|
, m_toolsClient(0)
|
||||||
|
, m_agent(new QmlInspectorAgent(engine, this))
|
||||||
|
, m_targetToSync(NoTarget)
|
||||||
|
, m_debugIdToSelect(-1)
|
||||||
|
, m_currentSelectedDebugId(-1)
|
||||||
|
, m_listeningToEditorManager(false)
|
||||||
|
, m_selectionCallbackExpected(false)
|
||||||
|
, m_cursorPositionChangedExternally(false)
|
||||||
|
, m_toolsClientConnected(false)
|
||||||
|
, m_inspectorToolsContext("Debugger.QmlInspector")
|
||||||
|
, m_selectAction(new QAction(this))
|
||||||
|
, m_zoomAction(new QAction(this))
|
||||||
|
{
|
||||||
|
connect(m_agent, SIGNAL(objectFetched(QmlDebugObjectReference)),
|
||||||
|
SLOT(onObjectFetched(QmlDebugObjectReference)));
|
||||||
|
connect(m_agent, SIGNAL(objectTreeUpdated()),
|
||||||
|
SLOT(onObjectTreeUpdated()));
|
||||||
|
|
||||||
|
QmlDebugConnection *connection = m_debugAdapter->connection();
|
||||||
|
DeclarativeEngineDebugClient *engineClient1
|
||||||
|
= new DeclarativeEngineDebugClient(connection);
|
||||||
|
connect(engineClient1, SIGNAL(newStatus(QmlDebugClient::Status)),
|
||||||
|
this, SLOT(clientStatusChanged(QmlDebugClient::Status)));
|
||||||
|
connect(engineClient1, SIGNAL(newStatus(QmlDebugClient::Status)),
|
||||||
|
this, SLOT(engineClientStatusChanged(QmlDebugClient::Status)));
|
||||||
|
|
||||||
|
QmlEngineDebugClient *engineClient2 = new QmlEngineDebugClient(connection);
|
||||||
|
connect(engineClient2, SIGNAL(newStatus(QmlDebugClient::Status)),
|
||||||
|
this, SLOT(clientStatusChanged(QmlDebugClient::Status)));
|
||||||
|
connect(engineClient2, SIGNAL(newStatus(QmlDebugClient::Status)),
|
||||||
|
this, SLOT(engineClientStatusChanged(QmlDebugClient::Status)));
|
||||||
|
|
||||||
|
m_engineClients.insert(engineClient1->name(), engineClient1);
|
||||||
|
m_engineClients.insert(engineClient2->name(), engineClient2);
|
||||||
|
|
||||||
|
if (engineClient1->status() == QmlDebugClient::Enabled)
|
||||||
|
setActiveEngineClient(engineClient1);
|
||||||
|
if (engineClient2->status() == QmlDebugClient::Enabled)
|
||||||
|
setActiveEngineClient(engineClient2);
|
||||||
|
|
||||||
|
DeclarativeToolsClient *toolsClient1 = new DeclarativeToolsClient(connection);
|
||||||
|
connect(toolsClient1, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)),
|
||||||
|
this, SLOT(clientStatusChanged(QmlDebugClient::Status)));
|
||||||
|
connect(toolsClient1, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)),
|
||||||
|
this, SLOT(toolsClientStatusChanged(QmlDebugClient::Status)));
|
||||||
|
|
||||||
|
QmlToolsClient *toolsClient2 = new QmlToolsClient(connection);
|
||||||
|
connect(toolsClient2, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)),
|
||||||
|
this, SLOT(clientStatusChanged(QmlDebugClient::Status)));
|
||||||
|
connect(toolsClient2, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)),
|
||||||
|
this, SLOT(toolsClientStatusChanged(QmlDebugClient::Status)));
|
||||||
|
|
||||||
|
// toolbar
|
||||||
|
m_selectAction->setObjectName("QML Select Action");
|
||||||
|
m_zoomAction->setObjectName("QML Zoom Action");
|
||||||
|
m_selectAction->setCheckable(true);
|
||||||
|
m_zoomAction->setCheckable(true);
|
||||||
|
|
||||||
|
connect(m_selectAction, SIGNAL(triggered(bool)),
|
||||||
|
SLOT(onSelectActionTriggered(bool)));
|
||||||
|
connect(m_zoomAction, SIGNAL(triggered(bool)),
|
||||||
|
SLOT(onZoomActionTriggered(bool)));
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlInspectorAdapter::~QmlInspectorAdapter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseEngineDebugClient *QmlInspectorAdapter::engineClient() const
|
||||||
|
{
|
||||||
|
return m_engineClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseToolsClient *QmlInspectorAdapter::toolsClient() const
|
||||||
|
{
|
||||||
|
return m_toolsClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlInspectorAgent *QmlInspectorAdapter::agent() const
|
||||||
|
{
|
||||||
|
return m_agent;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QmlInspectorAdapter::currentSelectedDebugId() const
|
||||||
|
{
|
||||||
|
return m_currentSelectedDebugId;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QmlInspectorAdapter::currentSelectedDisplayName() const
|
||||||
|
{
|
||||||
|
return m_currentSelectedDebugName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::clientStatusChanged(QmlDebugClient::Status status)
|
||||||
|
{
|
||||||
|
QString serviceName;
|
||||||
|
float version = 0;
|
||||||
|
if (QmlDebugClient *client = qobject_cast<QmlDebugClient*>(sender())) {
|
||||||
|
serviceName = client->name();
|
||||||
|
version = client->serviceVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_debugAdapter->logServiceStatusChange(serviceName, version, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::toolsClientStatusChanged(QmlDebugClient::Status status)
|
||||||
|
{
|
||||||
|
Core::ICore *core = Core::ICore::instance();
|
||||||
|
Core::ActionManager *am = Core::ICore::actionManager();
|
||||||
|
BaseToolsClient *client = qobject_cast<BaseToolsClient*>(sender());
|
||||||
|
if (status == QmlDebugClient::Enabled) {
|
||||||
|
m_toolsClient = client;
|
||||||
|
|
||||||
|
connect(client, SIGNAL(currentObjectsChanged(QList<int>)),
|
||||||
|
SLOT(selectObjectsFromToolsClient(QList<int>)));
|
||||||
|
connect(client, SIGNAL(logActivity(QString,QString)),
|
||||||
|
m_debugAdapter, SLOT(logServiceActivity(QString,QString)));
|
||||||
|
|
||||||
|
// only enable zoom action for Qt 4.x/old client
|
||||||
|
// (zooming is integrated into selection tool in Qt 5).
|
||||||
|
m_zoomAction->setEnabled(
|
||||||
|
qobject_cast<DeclarativeToolsClient*>(client) != 0);
|
||||||
|
|
||||||
|
// register actions here
|
||||||
|
// because there can be multiple QmlEngines
|
||||||
|
// at the same time (but hopefully one one is connected)
|
||||||
|
am->registerAction(m_selectAction,
|
||||||
|
Core::Id(Constants::QML_SELECTTOOL),
|
||||||
|
m_inspectorToolsContext);
|
||||||
|
am->registerAction(m_zoomAction, Core::Id(Constants::QML_ZOOMTOOL),
|
||||||
|
m_inspectorToolsContext);
|
||||||
|
|
||||||
|
core->updateAdditionalContexts(Core::Context(),
|
||||||
|
m_inspectorToolsContext);
|
||||||
|
|
||||||
|
Utils::SavedAction *action = debuggerCore()->action(QmlUpdateOnSave);
|
||||||
|
connect(action, SIGNAL(valueChanged(QVariant)),
|
||||||
|
SLOT(onUpdateOnSaveChanged(QVariant)));
|
||||||
|
|
||||||
|
action = debuggerCore()->action(ShowAppOnTop);
|
||||||
|
connect(action, SIGNAL(valueChanged(QVariant)),
|
||||||
|
SLOT(onShowAppOnTopChanged(QVariant)));
|
||||||
|
if (action->isChecked())
|
||||||
|
m_toolsClient->showAppOnTop(true);
|
||||||
|
|
||||||
|
m_toolsClientConnected = true;
|
||||||
|
} else if (m_toolsClientConnected
|
||||||
|
&& client == m_toolsClient) {
|
||||||
|
disconnect(client, SIGNAL(currentObjectsChanged(QList<int>)),
|
||||||
|
this, SLOT(selectObjectsFromToolsClient(QList<int>)));
|
||||||
|
disconnect(client, SIGNAL(logActivity(QString,QString)),
|
||||||
|
m_debugAdapter, SLOT(logServiceActivity(QString,QString)));
|
||||||
|
|
||||||
|
am->unregisterAction(m_selectAction,
|
||||||
|
Core::Id(Constants::QML_SELECTTOOL));
|
||||||
|
am->unregisterAction(m_zoomAction,
|
||||||
|
Core::Id(Constants::QML_ZOOMTOOL));
|
||||||
|
|
||||||
|
m_selectAction->setChecked(false);
|
||||||
|
m_zoomAction->setChecked(false);
|
||||||
|
core->updateAdditionalContexts(m_inspectorToolsContext,
|
||||||
|
Core::Context());
|
||||||
|
|
||||||
|
Utils::SavedAction *action = debuggerCore()->action(QmlUpdateOnSave);
|
||||||
|
disconnect(action, 0, this, 0);
|
||||||
|
action = debuggerCore()->action(ShowAppOnTop);
|
||||||
|
disconnect(action, 0, this, 0);
|
||||||
|
|
||||||
|
m_toolsClientConnected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::engineClientStatusChanged(QmlDebugClient::Status status)
|
||||||
|
{
|
||||||
|
if (status != QmlDebugClient::Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BaseEngineDebugClient *client
|
||||||
|
= qobject_cast<BaseEngineDebugClient*>(sender());
|
||||||
|
QTC_ASSERT(client, return);
|
||||||
|
setActiveEngineClient(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::selectObjectsFromEditor(const QList<int> &debugIds)
|
||||||
|
{
|
||||||
|
int debugId = debugIds.first();
|
||||||
|
|
||||||
|
if (m_selectionCallbackExpected) {
|
||||||
|
m_selectionCallbackExpected = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_cursorPositionChangedExternally = true;
|
||||||
|
|
||||||
|
QmlDebugObjectReference clientRef
|
||||||
|
= agent()->objectForId(debugId);
|
||||||
|
|
||||||
|
// if children haven't been loaded yet do so first, the editor
|
||||||
|
// might actually be interested in the children!
|
||||||
|
if (clientRef.debugId() != debugId
|
||||||
|
|| clientRef.needsMoreData()) {
|
||||||
|
m_targetToSync = ToolTarget;
|
||||||
|
m_debugIdToSelect = debugId;
|
||||||
|
agent()->fetchObject(debugId);
|
||||||
|
} else {
|
||||||
|
selectObject(clientRef, ToolTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::selectObjectsFromToolsClient(const QList<int> &debugIds)
|
||||||
|
{
|
||||||
|
if (debugIds.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int debugId = debugIds.first();
|
||||||
|
|
||||||
|
QmlDebugObjectReference clientRef
|
||||||
|
= agent()->objectForId(debugId);
|
||||||
|
|
||||||
|
if (clientRef.debugId() != debugId) {
|
||||||
|
m_targetToSync = EditorTarget;
|
||||||
|
m_debugIdToSelect = debugId;
|
||||||
|
agent()->fetchObject(debugId);
|
||||||
|
} else {
|
||||||
|
selectObject(clientRef, EditorTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::onObjectFetched(const QmlDebugObjectReference &ref)
|
||||||
|
{
|
||||||
|
if (ref.debugId() == m_debugIdToSelect) {
|
||||||
|
m_debugIdToSelect = -1;
|
||||||
|
selectObject(ref, m_targetToSync);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::onObjectTreeUpdated()
|
||||||
|
{
|
||||||
|
if (m_currentSelectedDebugId == -1) {
|
||||||
|
// select root element on startup
|
||||||
|
if (!m_agent->rootObjects().isEmpty())
|
||||||
|
selectObject(m_agent->rootObjects().first(), NoTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::createPreviewForEditor(Core::IEditor *newEditor)
|
||||||
|
{
|
||||||
|
if (newEditor && newEditor->id()
|
||||||
|
!= QmlJSEditor::Constants::C_QMLJSEDITOR_ID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString filename = newEditor->document()->fileName();
|
||||||
|
QmlJS::ModelManagerInterface *modelManager =
|
||||||
|
QmlJS::ModelManagerInterface::instance();
|
||||||
|
QmlJS::Document::Ptr doc = modelManager->snapshot().document(filename);
|
||||||
|
if (!doc) {
|
||||||
|
if (filename.endsWith(".qml")) {
|
||||||
|
// add to list of docs that we have to update when
|
||||||
|
// snapshot figures out that there's a new document
|
||||||
|
m_pendingPreviewDocumentNames.append(filename);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!doc->qmlProgram())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QmlJS::Document::Ptr initdoc = m_loadedSnapshot.document(filename);
|
||||||
|
if (!initdoc)
|
||||||
|
initdoc = doc;
|
||||||
|
|
||||||
|
if (m_textPreviews.contains(filename)) {
|
||||||
|
QmlLiveTextPreview *preview = m_textPreviews.value(filename);
|
||||||
|
preview->associateEditor(newEditor);
|
||||||
|
} else {
|
||||||
|
QmlLiveTextPreview *preview
|
||||||
|
= new QmlLiveTextPreview(doc, initdoc, this, this);
|
||||||
|
connect(preview,
|
||||||
|
SIGNAL(selectedItemsChanged(QList<int>)),
|
||||||
|
SLOT(selectObjectsFromEditor(QList<int>)));
|
||||||
|
preview->setApplyChangesToQmlInspector(
|
||||||
|
debuggerCore()->action(QmlUpdateOnSave)->isChecked());
|
||||||
|
|
||||||
|
m_textPreviews.insert(newEditor->document()->fileName(), preview);
|
||||||
|
preview->associateEditor(newEditor);
|
||||||
|
preview->updateDebugIds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::removePreviewForEditor(Core::IEditor *editor)
|
||||||
|
{
|
||||||
|
if (QmlLiveTextPreview *preview
|
||||||
|
= m_textPreviews.value(editor->document()->fileName())) {
|
||||||
|
preview->unassociateEditor(editor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::updatePendingPreviewDocuments(QmlJS::Document::Ptr doc)
|
||||||
|
{
|
||||||
|
int idx = -1;
|
||||||
|
idx = m_pendingPreviewDocumentNames.indexOf(doc->fileName());
|
||||||
|
|
||||||
|
if (idx == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Core::EditorManager *em = Core::EditorManager::instance();
|
||||||
|
QList<Core::IEditor *> editors
|
||||||
|
= em->editorsForFileName(doc->fileName());
|
||||||
|
|
||||||
|
if (editors.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_pendingPreviewDocumentNames.removeAt(idx);
|
||||||
|
|
||||||
|
Core::IEditor *editor = editors.takeFirst();
|
||||||
|
createPreviewForEditor(editor);
|
||||||
|
QmlLiveTextPreview *preview
|
||||||
|
= m_textPreviews.value(editor->document()->fileName());
|
||||||
|
foreach (Core::IEditor *editor, editors)
|
||||||
|
preview->associateEditor(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::onSelectActionTriggered(bool checked)
|
||||||
|
{
|
||||||
|
if (checked) {
|
||||||
|
toolsClient()->setDesignModeBehavior(true);
|
||||||
|
toolsClient()->changeToSelectTool();
|
||||||
|
m_zoomAction->setChecked(false);
|
||||||
|
} else {
|
||||||
|
toolsClient()->setDesignModeBehavior(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::onZoomActionTriggered(bool checked)
|
||||||
|
{
|
||||||
|
if (checked) {
|
||||||
|
toolsClient()->setDesignModeBehavior(true);
|
||||||
|
toolsClient()->changeToZoomTool();
|
||||||
|
m_selectAction->setChecked(false);
|
||||||
|
} else {
|
||||||
|
toolsClient()->setDesignModeBehavior(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::onShowAppOnTopChanged(const QVariant &value)
|
||||||
|
{
|
||||||
|
bool showAppOnTop = value.toBool();
|
||||||
|
if (m_toolsClient->status() == QmlDebugClient::Enabled)
|
||||||
|
m_toolsClient->showAppOnTop(showAppOnTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::onUpdateOnSaveChanged(const QVariant &value)
|
||||||
|
{
|
||||||
|
bool updateOnSave = value.toBool();
|
||||||
|
for (QHash<QString, QmlLiveTextPreview *>::const_iterator it
|
||||||
|
= m_textPreviews.constBegin();
|
||||||
|
it != m_textPreviews.constEnd(); ++it) {
|
||||||
|
it.value()->setApplyChangesToQmlInspector(updateOnSave);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::setActiveEngineClient(BaseEngineDebugClient *client)
|
||||||
|
{
|
||||||
|
if (m_engineClient == client)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_engineClient = client;
|
||||||
|
m_agent->setEngineClient(m_engineClient);
|
||||||
|
|
||||||
|
|
||||||
|
if (m_engineClient &&
|
||||||
|
m_engineClient->status() == QmlDebugClient::Enabled) {
|
||||||
|
QmlJS::ModelManagerInterface *modelManager
|
||||||
|
= QmlJS::ModelManagerInterface::instance();
|
||||||
|
QmlJS::Snapshot snapshot = modelManager->snapshot();
|
||||||
|
for (QHash<QString, QmlLiveTextPreview *>::const_iterator it
|
||||||
|
= m_textPreviews.constBegin();
|
||||||
|
it != m_textPreviews.constEnd(); ++it) {
|
||||||
|
QmlJS::Document::Ptr doc = snapshot.document(it.key());
|
||||||
|
it.value()->resetInitialDoc(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
initializePreviews();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::initializePreviews()
|
||||||
|
{
|
||||||
|
Core::EditorManager *em = Core::EditorManager::instance();
|
||||||
|
QmlJS::ModelManagerInterface *modelManager
|
||||||
|
= QmlJS::ModelManagerInterface::instance();
|
||||||
|
m_loadedSnapshot = modelManager->snapshot();
|
||||||
|
|
||||||
|
if (!m_listeningToEditorManager) {
|
||||||
|
m_listeningToEditorManager = true;
|
||||||
|
connect(em, SIGNAL(editorAboutToClose(Core::IEditor*)),
|
||||||
|
this, SLOT(removePreviewForEditor(Core::IEditor*)));
|
||||||
|
connect(em, SIGNAL(editorOpened(Core::IEditor*)),
|
||||||
|
this, SLOT(createPreviewForEditor(Core::IEditor*)));
|
||||||
|
connect(modelManager,
|
||||||
|
SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)),
|
||||||
|
this, SLOT(updatePendingPreviewDocuments(QmlJS::Document::Ptr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// initial update
|
||||||
|
foreach (Core::IEditor *editor, em->openedEditors())
|
||||||
|
createPreviewForEditor(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::showConnectionStatusMessage(const QString &message)
|
||||||
|
{
|
||||||
|
m_engine->showMessage(_("QML Inspector: ") + message, LogStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::gotoObjectReferenceDefinition(
|
||||||
|
const QmlDebugObjectReference &obj)
|
||||||
|
{
|
||||||
|
if (m_cursorPositionChangedExternally) {
|
||||||
|
m_cursorPositionChangedExternally = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlDebugFileReference source = obj.source();
|
||||||
|
|
||||||
|
const QString fileName = m_engine->toFileInProject(source.url());
|
||||||
|
|
||||||
|
Core::EditorManager *editorManager = Core::EditorManager::instance();
|
||||||
|
Core::IEditor *currentEditor = editorManager->currentEditor();
|
||||||
|
Core::IEditor *editor = editorManager->openEditor(fileName);
|
||||||
|
TextEditor::ITextEditor *textEditor
|
||||||
|
= qobject_cast<TextEditor::ITextEditor*>(editor);
|
||||||
|
|
||||||
|
if (currentEditor != editor)
|
||||||
|
m_selectionCallbackExpected = true;
|
||||||
|
|
||||||
|
if (textEditor) {
|
||||||
|
QmlDebugObjectReference ref = objectReferenceForLocation(fileName);
|
||||||
|
if (ref.debugId() != obj.debugId()) {
|
||||||
|
m_selectionCallbackExpected = true;
|
||||||
|
editorManager->addCurrentPositionToNavigationHistory();
|
||||||
|
textEditor->gotoLine(source.lineNumber());
|
||||||
|
textEditor->widget()->setFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlDebugObjectReference QmlInspectorAdapter::objectReferenceForLocation(
|
||||||
|
const QString &fileName, int cursorPosition) const
|
||||||
|
{
|
||||||
|
Core::EditorManager *editorManager = Core::EditorManager::instance();
|
||||||
|
Core::IEditor *editor = editorManager->openEditor(fileName);
|
||||||
|
TextEditor::ITextEditor *textEditor
|
||||||
|
= qobject_cast<TextEditor::ITextEditor*>(editor);
|
||||||
|
|
||||||
|
if (textEditor
|
||||||
|
&& textEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
|
||||||
|
if (cursorPosition == -1)
|
||||||
|
cursorPosition = textEditor->position();
|
||||||
|
TextEditor::BaseTextEditor *baseTextEditor =
|
||||||
|
static_cast<TextEditor::BaseTextEditor*>(editor);
|
||||||
|
QPlainTextEdit *editWidget
|
||||||
|
= qobject_cast<QPlainTextEdit*>(baseTextEditor->widget());
|
||||||
|
|
||||||
|
QmlJSTools::SemanticInfo semanticInfo = getSemanticInfo(editWidget);
|
||||||
|
|
||||||
|
if (QmlJS::AST::Node *node
|
||||||
|
= semanticInfo.declaringMemberNoProperties(cursorPosition)) {
|
||||||
|
if (QmlJS::AST::UiObjectMember *objMember
|
||||||
|
= node->uiObjectMemberCast()) {
|
||||||
|
return agent()->objectForLocation(
|
||||||
|
objMember->firstSourceLocation().startLine,
|
||||||
|
objMember->firstSourceLocation().startColumn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QmlDebugObjectReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QString displayName(const QmlDebugObjectReference &obj)
|
||||||
|
{
|
||||||
|
// special! state names
|
||||||
|
if (obj.className() == "State") {
|
||||||
|
foreach (const QmlDebugPropertyReference &prop, obj.properties()) {
|
||||||
|
if (prop.name() == "name")
|
||||||
|
return prop.value().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// has id?
|
||||||
|
if (!obj.idString().isEmpty())
|
||||||
|
return obj.idString();
|
||||||
|
|
||||||
|
// return the simplified class name then
|
||||||
|
QString objTypeName = obj.className();
|
||||||
|
QStringList declarativeStrings;
|
||||||
|
declarativeStrings << QLatin1String("QDeclarative")
|
||||||
|
<< QLatin1String("QQml");
|
||||||
|
foreach (const QString &str, declarativeStrings) {
|
||||||
|
if (objTypeName.startsWith(str)) {
|
||||||
|
objTypeName = objTypeName.mid(str.length()).section('_', 0, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QString("<%1>").arg(objTypeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAdapter::selectObject(const QmlDebugObjectReference &obj,
|
||||||
|
SelectionTarget target)
|
||||||
|
{
|
||||||
|
if (target == ToolTarget)
|
||||||
|
m_toolsClient->setObjectIdList(
|
||||||
|
QList<QmlDebugObjectReference>() << obj);
|
||||||
|
|
||||||
|
if (target == EditorTarget)
|
||||||
|
gotoObjectReferenceDefinition(obj);
|
||||||
|
|
||||||
|
agent()->selectObjectInTree(obj.debugId());
|
||||||
|
|
||||||
|
m_currentSelectedDebugId = obj.debugId();
|
||||||
|
m_currentSelectedDebugName = displayName(obj);
|
||||||
|
emit selectionChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Debugger
|
150
src/plugins/debugger/qml/qmlinspectoradapter.h
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QMLINSPECTORADAPTER_H
|
||||||
|
#define QMLINSPECTORADAPTER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include <coreplugin/icontext.h>
|
||||||
|
#include <qmldebug/qmldebugclient.h>
|
||||||
|
#include <qmljs/qmljsdocument.h>
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class IEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace QmlDebug {
|
||||||
|
class BaseEngineDebugClient;
|
||||||
|
class BaseToolsClient;
|
||||||
|
class QmlDebugObjectReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace QmlDebug;
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class WatchTreeView;
|
||||||
|
class QmlAdapter;
|
||||||
|
class QmlEngine;
|
||||||
|
class QmlInspectorAgent;
|
||||||
|
class QmlLiveTextPreview;
|
||||||
|
|
||||||
|
class QmlInspectorAdapter : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QmlInspectorAdapter(QmlAdapter *debugAdapter, QmlEngine *engine,
|
||||||
|
QObject *parent = 0);
|
||||||
|
~QmlInspectorAdapter();
|
||||||
|
|
||||||
|
BaseEngineDebugClient *engineClient() const;
|
||||||
|
BaseToolsClient *toolsClient() const;
|
||||||
|
QmlInspectorAgent *agent() const;
|
||||||
|
|
||||||
|
int currentSelectedDebugId() const;
|
||||||
|
QString currentSelectedDisplayName() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void expressionResult();
|
||||||
|
void selectionChanged();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void clientStatusChanged(QmlDebugClient::Status status);
|
||||||
|
void toolsClientStatusChanged(QmlDebugClient::Status status);
|
||||||
|
void engineClientStatusChanged(QmlDebugClient::Status status);
|
||||||
|
|
||||||
|
void selectObjectsFromEditor(const QList<int> &debugIds);
|
||||||
|
void selectObjectsFromToolsClient(const QList<int> &debugIds);
|
||||||
|
void onObjectFetched(const QmlDebugObjectReference &ref);
|
||||||
|
void onObjectTreeUpdated();
|
||||||
|
|
||||||
|
void createPreviewForEditor(Core::IEditor *newEditor);
|
||||||
|
void removePreviewForEditor(Core::IEditor *editor);
|
||||||
|
void updatePendingPreviewDocuments(QmlJS::Document::Ptr doc);
|
||||||
|
|
||||||
|
void onSelectActionTriggered(bool checked);
|
||||||
|
void onZoomActionTriggered(bool checked);
|
||||||
|
void onShowAppOnTopChanged(const QVariant &value);
|
||||||
|
void onUpdateOnSaveChanged(const QVariant &value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setActiveEngineClient(BaseEngineDebugClient *client);
|
||||||
|
|
||||||
|
void initializePreviews();
|
||||||
|
void showConnectionStatusMessage(const QString &message);
|
||||||
|
|
||||||
|
void gotoObjectReferenceDefinition(const QmlDebugObjectReference &obj);
|
||||||
|
QmlDebugObjectReference objectReferenceForLocation(
|
||||||
|
const QString &fileName, int cursorPosition = -1) const;
|
||||||
|
|
||||||
|
enum SelectionTarget { NoTarget, ToolTarget, EditorTarget };
|
||||||
|
void selectObject(
|
||||||
|
const QmlDebugObjectReference &objectReference,
|
||||||
|
SelectionTarget target);
|
||||||
|
|
||||||
|
|
||||||
|
QmlAdapter *m_debugAdapter;
|
||||||
|
QmlEngine *m_engine;
|
||||||
|
BaseEngineDebugClient *m_engineClient;
|
||||||
|
QHash<QString, BaseEngineDebugClient*> m_engineClients;
|
||||||
|
BaseToolsClient *m_toolsClient;
|
||||||
|
QmlInspectorAgent *m_agent;
|
||||||
|
|
||||||
|
SelectionTarget m_targetToSync;
|
||||||
|
int m_debugIdToSelect;
|
||||||
|
|
||||||
|
int m_currentSelectedDebugId;
|
||||||
|
QString m_currentSelectedDebugName;
|
||||||
|
|
||||||
|
// Qml/JS editor integration
|
||||||
|
bool m_listeningToEditorManager;
|
||||||
|
QHash<QString, QmlLiveTextPreview *> m_textPreviews;
|
||||||
|
QmlJS::Snapshot m_loadedSnapshot; //the snapshot loaded by the viewer
|
||||||
|
QStringList m_pendingPreviewDocumentNames;
|
||||||
|
bool m_selectionCallbackExpected;
|
||||||
|
bool m_cursorPositionChangedExternally;
|
||||||
|
|
||||||
|
// toolbar
|
||||||
|
bool m_toolsClientConnected;
|
||||||
|
Core::Context m_inspectorToolsContext;
|
||||||
|
QAction *m_selectAction;
|
||||||
|
QAction *m_zoomAction;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Debugger
|
||||||
|
|
||||||
|
#endif // QMLINSPECTORADAPTER_H
|
786
src/plugins/debugger/qml/qmlinspectoragent.cpp
Normal file
@@ -0,0 +1,786 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "qmlinspectoragent.h"
|
||||||
|
|
||||||
|
#include "debuggeractions.h"
|
||||||
|
#include "debuggercore.h"
|
||||||
|
#include "debuggerengine.h"
|
||||||
|
#include "debuggerstringutils.h"
|
||||||
|
#include "watchhandler.h"
|
||||||
|
|
||||||
|
#include <qmldebug/qmldebugconstants.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/savedaction.h>
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
enum {
|
||||||
|
debug = false
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* DebuggerAgent updates the watchhandler with the object tree data.
|
||||||
|
*/
|
||||||
|
QmlInspectorAgent::QmlInspectorAgent(DebuggerEngine *engine, QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_engine(engine)
|
||||||
|
, m_engineClient(0)
|
||||||
|
, m_engineQueryId(0)
|
||||||
|
, m_rootContextQueryId(0)
|
||||||
|
, m_objectToSelect(-1)
|
||||||
|
{
|
||||||
|
connect(debuggerCore()->action(ShowQmlObjectTree),
|
||||||
|
SIGNAL(valueChanged(QVariant)), SLOT(updateStatus()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::refreshObjectTree()
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "()";
|
||||||
|
|
||||||
|
if (!m_rootContextQueryId) {
|
||||||
|
m_objectTreeQueryIds.clear();
|
||||||
|
queryEngineContext(m_engines.value(0).debugId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::fetchObject(int debugId)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << debugId << ")";
|
||||||
|
|
||||||
|
m_fetchCurrentObjectsQueryIds
|
||||||
|
<< fetchContextObject(QmlDebugObjectReference(debugId));
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 QmlInspectorAgent::queryExpressionResult(int debugId,
|
||||||
|
const QString &expression)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << debugId << expression
|
||||||
|
<< m_engines.value(0).debugId() << ")";
|
||||||
|
|
||||||
|
return m_engineClient->queryExpressionResult(debugId, expression,
|
||||||
|
m_engines.value(0).debugId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::updateWatchData(const WatchData &data)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << data.id << ")";
|
||||||
|
|
||||||
|
if (data.id) {
|
||||||
|
// objects
|
||||||
|
QmlDebugObjectReference ref(data.id);
|
||||||
|
m_fetchCurrentObjectsQueryIds << fetchContextObject(ref);
|
||||||
|
WatchData d = data;
|
||||||
|
d.setAllUnneeded();
|
||||||
|
m_engine->watchHandler()->beginCycle(InspectWatch, false);
|
||||||
|
m_engine->watchHandler()->insertData(d);
|
||||||
|
m_engine->watchHandler()->endCycle(InspectWatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::selectObjectInTree(int debugId)
|
||||||
|
{
|
||||||
|
if (debug) {
|
||||||
|
qDebug() << __FUNCTION__ << "(" << debugId << ")";
|
||||||
|
qDebug() << " " << debugId << "already fetched? "
|
||||||
|
<< m_debugIdToIname.contains(debugId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_debugIdToIname.contains(debugId)) {
|
||||||
|
QByteArray iname = m_debugIdToIname.value(debugId);
|
||||||
|
QTC_ASSERT(iname.startsWith("inspect."), qDebug() << iname);
|
||||||
|
QModelIndex itemIndex = m_engine->watchHandler()->itemIndex(iname);
|
||||||
|
QTC_ASSERT(itemIndex.isValid(),
|
||||||
|
qDebug() << "No for " << debugId << ", iname " << iname; return;);
|
||||||
|
if (debug)
|
||||||
|
qDebug() << " selecting" << iname << "in tree";
|
||||||
|
m_engine->watchHandler()->setCurrentModelIndex(InspectWatch, itemIndex);
|
||||||
|
m_objectToSelect = 0;
|
||||||
|
} else {
|
||||||
|
// we've to fetch it
|
||||||
|
m_objectToSelect = debugId;
|
||||||
|
m_fetchCurrentObjectsQueryIds
|
||||||
|
<< fetchContextObject(QmlDebugObjectReference(debugId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 QmlInspectorAgent::setBindingForObject(int objectDebugId,
|
||||||
|
const QString &propertyName,
|
||||||
|
const QVariant &value,
|
||||||
|
bool isLiteralValue,
|
||||||
|
QString source,
|
||||||
|
int line)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << objectDebugId << propertyName
|
||||||
|
<< value.toString() << isLiteralValue << source << line << ")";
|
||||||
|
|
||||||
|
if (objectDebugId == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (propertyName == QLatin1String("id"))
|
||||||
|
return 0; // Crashes the QMLViewer.
|
||||||
|
|
||||||
|
if (!isConnected()
|
||||||
|
|| !debuggerCore()->boolSetting(ShowQmlObjectTree))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
log(LogSend, QString("SET_BINDING %1 %2 %3 %4").arg(
|
||||||
|
QString::number(objectDebugId), propertyName, value.toString(),
|
||||||
|
QString(isLiteralValue ? "true" : "false")));
|
||||||
|
|
||||||
|
quint32 queryId = m_engineClient->setBindingForObject(
|
||||||
|
objectDebugId, propertyName, value.toString(), isLiteralValue,
|
||||||
|
source, line);
|
||||||
|
|
||||||
|
if (!queryId)
|
||||||
|
log(LogSend, QString("SET_BINDING failed!"));
|
||||||
|
|
||||||
|
return queryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 QmlInspectorAgent::setMethodBodyForObject(int objectDebugId,
|
||||||
|
const QString &methodName,
|
||||||
|
const QString &methodBody)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << objectDebugId
|
||||||
|
<< methodName << methodBody << ")";
|
||||||
|
|
||||||
|
if (objectDebugId == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!isConnected()
|
||||||
|
|| !debuggerCore()->boolSetting(ShowQmlObjectTree))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
log(LogSend, QString("SET_METHOD_BODY %1 %2 %3").arg(
|
||||||
|
QString::number(objectDebugId), methodName, methodBody));
|
||||||
|
|
||||||
|
quint32 queryId = m_engineClient->setMethodBody(
|
||||||
|
objectDebugId, methodName, methodBody);
|
||||||
|
|
||||||
|
if (!queryId)
|
||||||
|
log(LogSend, QString("failed!"));
|
||||||
|
|
||||||
|
return queryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 QmlInspectorAgent::resetBindingForObject(int objectDebugId,
|
||||||
|
const QString &propertyName)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << objectDebugId
|
||||||
|
<< propertyName << ")";
|
||||||
|
|
||||||
|
if (objectDebugId == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!isConnected()
|
||||||
|
|| !debuggerCore()->boolSetting(ShowQmlObjectTree))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
log(LogSend, QString("RESET_BINDING %1 %2").arg(
|
||||||
|
QString::number(objectDebugId), propertyName));
|
||||||
|
|
||||||
|
quint32 queryId = m_engineClient->resetBindingForObject(
|
||||||
|
objectDebugId, propertyName);
|
||||||
|
|
||||||
|
if (!queryId)
|
||||||
|
log(LogSend, QString("failed!"));
|
||||||
|
|
||||||
|
return queryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QList<QmlDebugObjectReference> QmlInspectorAgent::objects() const
|
||||||
|
{
|
||||||
|
QList<QmlDebugObjectReference> result;
|
||||||
|
foreach (const QmlDebugObjectReference &it, m_rootObjects)
|
||||||
|
result.append(objects(it));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlDebugObjectReference QmlInspectorAgent::objectForId(int debugId) const
|
||||||
|
{
|
||||||
|
foreach (const QmlDebugObjectReference &it, m_rootObjects) {
|
||||||
|
QmlDebugObjectReference result = objectForId(debugId, it);
|
||||||
|
if (result.debugId() == debugId)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return QmlDebugObjectReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlDebugObjectReference QmlInspectorAgent::objectForId(
|
||||||
|
const QString &objectId) const
|
||||||
|
{
|
||||||
|
if (!objectId.isEmpty() && objectId[0].isLower()) {
|
||||||
|
const QList<QmlDebugObjectReference> refs = objects();
|
||||||
|
foreach (const QmlDebugObjectReference &ref, refs) {
|
||||||
|
if (ref.idString() == objectId)
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QmlDebugObjectReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlDebugObjectReference QmlInspectorAgent::objectForLocation(
|
||||||
|
int line, int column) const
|
||||||
|
{
|
||||||
|
const QList<QmlDebugObjectReference> refs = objects();
|
||||||
|
foreach (const QmlDebugObjectReference &ref, refs) {
|
||||||
|
if (ref.source().lineNumber() == line
|
||||||
|
&& ref.source().columnNumber() == column)
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QmlDebugObjectReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlInspectorAgent::addObjectWatch(int objectDebugId)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << objectDebugId << ")";
|
||||||
|
|
||||||
|
if (objectDebugId == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!isConnected()
|
||||||
|
|| !debuggerCore()->boolSetting(ShowQmlObjectTree))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// already set
|
||||||
|
if (m_objectWatches.contains(objectDebugId))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
QmlDebugObjectReference ref = objectForId(objectDebugId);
|
||||||
|
if (ref.debugId() != objectDebugId)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// is flooding the debugging output log!
|
||||||
|
// log(LogSend, QString("WATCH_PROPERTY %1").arg(objectDebugId));
|
||||||
|
|
||||||
|
if (m_engineClient->addWatch(ref))
|
||||||
|
m_objectWatches.append(objectDebugId);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlInspectorAgent::isObjectBeingWatched(int objectDebugId)
|
||||||
|
{
|
||||||
|
return m_objectWatches.contains(objectDebugId);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlInspectorAgent::removeObjectWatch(int objectDebugId)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << objectDebugId << ")";
|
||||||
|
|
||||||
|
if (objectDebugId == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!m_objectWatches.contains(objectDebugId))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!isConnected())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_objectWatches.removeOne(objectDebugId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::removeAllObjectWatches()
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "()";
|
||||||
|
|
||||||
|
foreach (int watchedObject, m_objectWatches)
|
||||||
|
removeObjectWatch(watchedObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::setEngineClient(BaseEngineDebugClient *client)
|
||||||
|
{
|
||||||
|
if (m_engineClient == client)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_engineClient) {
|
||||||
|
disconnect(m_engineClient, SIGNAL(newStatus(QmlDebugClient::Status)),
|
||||||
|
this, SLOT(updateStatus()));
|
||||||
|
disconnect(m_engineClient, SIGNAL(result(quint32,QVariant,QByteArray)),
|
||||||
|
this, SLOT(onResult(quint32,QVariant,QByteArray)));
|
||||||
|
disconnect(m_engineClient, SIGNAL(newObjects()),
|
||||||
|
this, SLOT(newObjects()));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_engineClient = client;
|
||||||
|
|
||||||
|
if (m_engineClient) {
|
||||||
|
connect(m_engineClient, SIGNAL(newStatus(QmlDebugClient::Status)),
|
||||||
|
this, SLOT(updateStatus()));
|
||||||
|
connect(m_engineClient, SIGNAL(result(quint32,QVariant,QByteArray)),
|
||||||
|
this, SLOT(onResult(quint32,QVariant,QByteArray)));
|
||||||
|
connect(m_engineClient, SIGNAL(newObjects()),
|
||||||
|
this, SLOT(newObjects()));
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::updateStatus()
|
||||||
|
{
|
||||||
|
if (m_engineClient
|
||||||
|
&& (m_engineClient->status() == QmlDebugClient::Enabled)
|
||||||
|
&& debuggerCore()->boolSetting(ShowQmlObjectTree)) {
|
||||||
|
reloadEngines();
|
||||||
|
} else {
|
||||||
|
// clear view
|
||||||
|
m_engine->watchHandler()->beginCycle(InspectWatch, true);
|
||||||
|
m_engine->watchHandler()->endCycle(InspectWatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::onResult(quint32 queryId, const QVariant &value,
|
||||||
|
const QByteArray &type)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "() ...";
|
||||||
|
|
||||||
|
if (type == _("FETCH_OBJECT_R")) {
|
||||||
|
log(LogReceive, _("FETCH_OBJECT_R %1").arg(
|
||||||
|
qvariant_cast<QmlDebugObjectReference>(value).idString()));
|
||||||
|
} else {
|
||||||
|
log(LogReceive, QLatin1String(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_objectTreeQueryIds.contains(queryId)) {
|
||||||
|
m_objectTreeQueryIds.removeOne(queryId);
|
||||||
|
objectTreeFetched(qvariant_cast<QmlDebugObjectReference>(value));
|
||||||
|
} else if (queryId == m_engineQueryId) {
|
||||||
|
m_engineQueryId = 0;
|
||||||
|
updateEngineList(qvariant_cast<QmlDebugEngineReferenceList>(value));
|
||||||
|
} else if (queryId == m_rootContextQueryId) {
|
||||||
|
m_rootContextQueryId = 0;
|
||||||
|
rootContextChanged(qvariant_cast<QmlDebugContextReference>(value));
|
||||||
|
} else if (m_fetchCurrentObjectsQueryIds.contains(queryId)) {
|
||||||
|
m_fetchCurrentObjectsQueryIds.removeOne(queryId);
|
||||||
|
QmlDebugObjectReference obj
|
||||||
|
= qvariant_cast<QmlDebugObjectReference>(value);
|
||||||
|
m_fetchCurrentObjects.push_front(obj);
|
||||||
|
onCurrentObjectsFetched(obj);
|
||||||
|
} else {
|
||||||
|
emit expressionResult(queryId, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "done";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::newObjects()
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "()";
|
||||||
|
|
||||||
|
log(LogReceive, QString("OBJECT_CREATED"));
|
||||||
|
refreshObjectTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::reloadEngines()
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "()";
|
||||||
|
|
||||||
|
if (!isConnected())
|
||||||
|
return;
|
||||||
|
|
||||||
|
log(LogSend, _("LIST_ENGINES"));
|
||||||
|
|
||||||
|
m_engineQueryId = m_engineClient->queryAvailableEngines();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::queryEngineContext(int id)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << id << ")";
|
||||||
|
|
||||||
|
if (id < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!isConnected()
|
||||||
|
|| !debuggerCore()->boolSetting(ShowQmlObjectTree))
|
||||||
|
return;
|
||||||
|
|
||||||
|
log(LogSend, QString("LIST_OBJECTS %1").arg(QString::number(id)));
|
||||||
|
|
||||||
|
m_rootContextQueryId
|
||||||
|
= m_engineClient->queryRootContexts(QmlDebugEngineReference(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 QmlInspectorAgent::fetchContextObject(const QmlDebugObjectReference &obj)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << obj << ")";
|
||||||
|
|
||||||
|
if (!isConnected()
|
||||||
|
|| !debuggerCore()->boolSetting(ShowQmlObjectTree))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
log(LogSend, QString("FETCH_OBJECT %1").arg(obj.idString()));
|
||||||
|
quint32 queryId = m_engineClient->queryObject(obj);
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << obj.debugId() << ")"
|
||||||
|
<< " - query id" << queryId;
|
||||||
|
return queryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch the root objects from the context + any child contexts
|
||||||
|
void QmlInspectorAgent::fetchRootObjects(const QmlDebugContextReference &context,
|
||||||
|
bool clear)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << context << clear << ")";
|
||||||
|
|
||||||
|
if (!isConnected()
|
||||||
|
|| !debuggerCore()->boolSetting(ShowQmlObjectTree))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (clear) {
|
||||||
|
m_rootObjects.clear();
|
||||||
|
m_objectTreeQueryIds.clear();
|
||||||
|
}
|
||||||
|
foreach (const QmlDebugObjectReference & obj, context.objects()) {
|
||||||
|
quint32 queryId = 0;
|
||||||
|
using namespace QmlDebug::Constants;
|
||||||
|
if (m_engineClient->objectName() == QML_DEBUGGER &&
|
||||||
|
m_engineClient->serviceVersion() >= CURRENT_SUPPORTED_VERSION) {
|
||||||
|
//Fetch only root objects
|
||||||
|
if (obj.parentId() == -1)
|
||||||
|
queryId = fetchContextObject(obj);
|
||||||
|
} else {
|
||||||
|
queryId = m_engineClient->queryObjectRecursive(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryId)
|
||||||
|
m_objectTreeQueryIds << queryId;
|
||||||
|
}
|
||||||
|
foreach (const QmlDebugContextReference &child, context.contexts())
|
||||||
|
fetchRootObjects(child, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::updateEngineList(const QmlDebugEngineReferenceList &engines)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << engines << ")";
|
||||||
|
|
||||||
|
m_engines = engines;
|
||||||
|
|
||||||
|
// only care about first engine atm
|
||||||
|
queryEngineContext(engines.first().debugId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::rootContextChanged(const QmlDebugContextReference &context)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << context << ")";
|
||||||
|
|
||||||
|
fetchRootObjects(context, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::objectTreeFetched(const QmlDebugObjectReference &object)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << object << ")";
|
||||||
|
|
||||||
|
m_rootObjects.append(object);
|
||||||
|
|
||||||
|
if (m_objectTreeQueryIds.isEmpty()) {
|
||||||
|
int old_count = m_debugIdHash.count();
|
||||||
|
m_debugIdHash.clear();
|
||||||
|
m_debugIdHash.reserve(old_count + 1);
|
||||||
|
m_debugIdToIname.clear();
|
||||||
|
foreach (const QmlDebugObjectReference &it, m_rootObjects)
|
||||||
|
buildDebugIdHashRecursive(it);
|
||||||
|
|
||||||
|
emit objectTreeUpdated();
|
||||||
|
|
||||||
|
// sync tree with watchhandler
|
||||||
|
QList<WatchData> watchData;
|
||||||
|
foreach (const QmlDebugObjectReference &obj, m_rootObjects)
|
||||||
|
watchData.append(buildWatchData(obj, WatchData()));
|
||||||
|
|
||||||
|
WatchHandler *watchHandler = m_engine->watchHandler();
|
||||||
|
watchHandler->beginCycle(InspectWatch, true);
|
||||||
|
watchHandler->insertBulkData(watchData);
|
||||||
|
watchHandler->endCycle(InspectWatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::onCurrentObjectsFetched(const QmlDebugObjectReference &obj)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "( " << obj << ")";
|
||||||
|
|
||||||
|
// get parents if not known yet
|
||||||
|
if (!getObjectHierarchy(obj))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
qDebug() << " adding" << m_fetchCurrentObjects << "to tree";
|
||||||
|
|
||||||
|
foreach (const QmlDebugObjectReference &o, m_fetchCurrentObjects)
|
||||||
|
addObjectToTree(o, false);
|
||||||
|
|
||||||
|
QmlDebugObjectReference last = m_fetchCurrentObjects.last();
|
||||||
|
m_fetchCurrentObjects.clear();
|
||||||
|
|
||||||
|
if (m_objectToSelect == last.debugId()) {
|
||||||
|
// select item in view
|
||||||
|
QByteArray iname = m_debugIdToIname.value(last.debugId());
|
||||||
|
QModelIndex itemIndex = m_engine->watchHandler()->itemIndex(iname);
|
||||||
|
QTC_ASSERT(itemIndex.isValid(), return);
|
||||||
|
if (debug)
|
||||||
|
qDebug() << " selecting" << iname << "in tree";
|
||||||
|
m_engine->watchHandler()->setCurrentModelIndex(InspectWatch, itemIndex);
|
||||||
|
m_objectToSelect = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit objectFetched(last);
|
||||||
|
emit objectTreeUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetches all anchestors of object. Returns if all has been fetched already.
|
||||||
|
bool QmlInspectorAgent::getObjectHierarchy(const QmlDebugObjectReference &obj)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << obj << ")";
|
||||||
|
|
||||||
|
QmlDebugObjectReference parent = objectForId(obj.parentId());
|
||||||
|
//for root object
|
||||||
|
if (obj.parentId() == -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
//for other objects
|
||||||
|
if (parent.debugId() == -1 || parent.needsMoreData()) {
|
||||||
|
m_fetchCurrentObjectsQueryIds
|
||||||
|
<< fetchContextObject(QmlDebugObjectReference(obj.parentId()));
|
||||||
|
} else {
|
||||||
|
return getObjectHierarchy(parent);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::buildDebugIdHashRecursive(const QmlDebugObjectReference &ref)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << ref << ")";
|
||||||
|
|
||||||
|
QUrl fileUrl = ref.source().url();
|
||||||
|
int lineNum = ref.source().lineNumber();
|
||||||
|
int colNum = ref.source().columnNumber();
|
||||||
|
int rev = 0;
|
||||||
|
|
||||||
|
// handle the case where the url contains the revision number encoded.
|
||||||
|
//(for object created by the debugger)
|
||||||
|
static QRegExp rx("(.*)_(\\d+):(\\d+)$");
|
||||||
|
if (rx.exactMatch(fileUrl.path())) {
|
||||||
|
fileUrl.setPath(rx.cap(1));
|
||||||
|
rev = rx.cap(2).toInt();
|
||||||
|
lineNum += rx.cap(3).toInt() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString filePath
|
||||||
|
= m_engine->toFileInProject(fileUrl);
|
||||||
|
|
||||||
|
// append the debug ids in the hash
|
||||||
|
QPair<QString, int> file = qMakePair<QString, int>(filePath, rev);
|
||||||
|
QPair<int, int> location = qMakePair<int, int>(lineNum, colNum);
|
||||||
|
if (!m_debugIdHash[file][location].contains(ref.debugId()))
|
||||||
|
m_debugIdHash[file][location].append(ref.debugId());
|
||||||
|
|
||||||
|
foreach (const QmlDebugObjectReference &it, ref.children())
|
||||||
|
buildDebugIdHashRecursive(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QByteArray buildIName(const WatchData &parent, int debugId)
|
||||||
|
{
|
||||||
|
if (!parent.isValid())
|
||||||
|
return "inspect." + QByteArray::number(debugId);
|
||||||
|
return parent.iname + "." + QByteArray::number(debugId);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QByteArray buildIName(const WatchData &parent, const QString &name)
|
||||||
|
{
|
||||||
|
return parent.iname + "." + name.toLatin1();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<WatchData> QmlInspectorAgent::buildWatchData(const QmlDebugObjectReference &obj,
|
||||||
|
const WatchData &parent)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << __FUNCTION__ << "(" << obj << parent.iname << ")";
|
||||||
|
|
||||||
|
QList<WatchData> list;
|
||||||
|
|
||||||
|
WatchData objWatch;
|
||||||
|
QString name = obj.idString();
|
||||||
|
if (name.isEmpty())
|
||||||
|
name = obj.className();
|
||||||
|
|
||||||
|
// object
|
||||||
|
objWatch.id = obj.debugId();
|
||||||
|
objWatch.exp = name.toLatin1();
|
||||||
|
objWatch.name = name;
|
||||||
|
objWatch.iname = buildIName(parent, obj.debugId());
|
||||||
|
objWatch.type = obj.className().toLatin1();
|
||||||
|
objWatch.value = _("object");
|
||||||
|
objWatch.setHasChildren(true);
|
||||||
|
objWatch.setAllUnneeded();
|
||||||
|
|
||||||
|
list.append(objWatch);
|
||||||
|
m_debugIdToIname.insert(objWatch.id, objWatch.iname);
|
||||||
|
|
||||||
|
// properties
|
||||||
|
WatchData propertiesWatch;
|
||||||
|
propertiesWatch.id = objWatch.id;
|
||||||
|
propertiesWatch.exp = "";
|
||||||
|
propertiesWatch.name = tr("properties");
|
||||||
|
propertiesWatch.iname = objWatch.iname + ".[properties]";
|
||||||
|
propertiesWatch.type = "";
|
||||||
|
propertiesWatch.value = _("list");
|
||||||
|
propertiesWatch.setHasChildren(true);
|
||||||
|
propertiesWatch.setAllUnneeded();
|
||||||
|
|
||||||
|
list.append(propertiesWatch);
|
||||||
|
|
||||||
|
foreach (const QmlDebugPropertyReference &property, obj.properties()) {
|
||||||
|
WatchData propertyWatch;
|
||||||
|
propertyWatch.exp = property.name().toLatin1();
|
||||||
|
propertyWatch.name = property.name();
|
||||||
|
propertyWatch.iname = buildIName(propertiesWatch, property.name());
|
||||||
|
propertyWatch.type = property.valueTypeName().toLatin1();
|
||||||
|
propertyWatch.value = property.value().toString();
|
||||||
|
propertyWatch.setAllUnneeded();
|
||||||
|
propertyWatch.setHasChildren(false);
|
||||||
|
list.append(propertyWatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// recurse
|
||||||
|
foreach (const QmlDebugObjectReference &child, obj.children())
|
||||||
|
list.append(buildWatchData(child, objWatch));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::addObjectToTree(const QmlDebugObjectReference &obj,
|
||||||
|
bool notify)
|
||||||
|
{
|
||||||
|
int count = m_rootObjects.count();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
int parentId = obj.parentId();
|
||||||
|
if (m_engineClient->serviceVersion() < 2) {
|
||||||
|
// we don't get parentId in qt 4.x
|
||||||
|
parentId = m_rootObjects[i].insertObjectInTree(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parentId >= 0) {
|
||||||
|
buildDebugIdHashRecursive(obj);
|
||||||
|
if (notify)
|
||||||
|
emit objectTreeUpdated();
|
||||||
|
|
||||||
|
// find parent
|
||||||
|
QTC_ASSERT(m_debugIdToIname.contains(parentId), break);
|
||||||
|
QByteArray iname = m_debugIdToIname.value(parentId);
|
||||||
|
const WatchData *parent = m_engine->watchHandler()->findItem(iname);
|
||||||
|
if (parent) {
|
||||||
|
QList<WatchData> watches = buildWatchData(obj, *parent);
|
||||||
|
m_engine->watchHandler()->beginCycle(false);
|
||||||
|
m_engine->watchHandler()->insertBulkData(watches);
|
||||||
|
m_engine->watchHandler()->endCycle();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlDebugObjectReference QmlInspectorAgent::objectForId(int debugId,
|
||||||
|
const QmlDebugObjectReference &objectRef) const
|
||||||
|
{
|
||||||
|
if (objectRef.debugId() == debugId)
|
||||||
|
return objectRef;
|
||||||
|
|
||||||
|
foreach (const QmlDebugObjectReference &child, objectRef.children()) {
|
||||||
|
QmlDebugObjectReference result = objectForId(debugId, child);
|
||||||
|
if (result.debugId() == debugId)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QmlDebugObjectReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QmlDebugObjectReference> QmlInspectorAgent::objects(
|
||||||
|
const QmlDebugObjectReference &objectRef) const
|
||||||
|
{
|
||||||
|
QList<QmlDebugObjectReference> result;
|
||||||
|
result.append(objectRef);
|
||||||
|
|
||||||
|
foreach (const QmlDebugObjectReference &child, objectRef.children())
|
||||||
|
result.append(objects(child));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlInspectorAgent::log(QmlInspectorAgent::LogDirection direction,
|
||||||
|
const QString &message)
|
||||||
|
{
|
||||||
|
QString msg = _("Inspector");
|
||||||
|
if (direction == LogSend)
|
||||||
|
msg += _(" sending ");
|
||||||
|
else
|
||||||
|
msg += _(" receiving ");
|
||||||
|
msg += message;
|
||||||
|
|
||||||
|
if (m_engine)
|
||||||
|
m_engine->showMessage(msg, LogDebug);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlInspectorAgent::isConnected()
|
||||||
|
{
|
||||||
|
return m_engineClient
|
||||||
|
&& (m_engineClient->status() == QmlDebugClient::Enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Internal
|
||||||
|
} // Debugger
|
160
src/plugins/debugger/qml/qmlinspectoragent.h
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QMLINSPECTORAGENT_H
|
||||||
|
#define QMLINSPECTORAGENT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include <qmldebug/baseenginedebugclient.h>
|
||||||
|
#include <watchdata.h>
|
||||||
|
|
||||||
|
using namespace QmlDebug;
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
|
||||||
|
class DebuggerEngine;
|
||||||
|
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class WatchData;
|
||||||
|
|
||||||
|
//map <filename, editorRevision> -> <lineNumber, columnNumber> -> debugId
|
||||||
|
typedef
|
||||||
|
QHash<QPair<QString, int>, QHash<QPair<int, int>, QList<int> > > DebugIdHash;
|
||||||
|
|
||||||
|
class QmlInspectorAgent : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit QmlInspectorAgent(DebuggerEngine *engine, QObject *parent = 0);
|
||||||
|
|
||||||
|
|
||||||
|
void refreshObjectTree();
|
||||||
|
void fetchObject(int debugId);
|
||||||
|
quint32 queryExpressionResult(int debugId, const QString &expression);
|
||||||
|
|
||||||
|
void updateWatchData(const WatchData &data);
|
||||||
|
void selectObjectInTree(int debugId);
|
||||||
|
|
||||||
|
quint32 setBindingForObject(int objectDebugId,
|
||||||
|
const QString &propertyName,
|
||||||
|
const QVariant &value,
|
||||||
|
bool isLiteralValue,
|
||||||
|
QString source,
|
||||||
|
int line);
|
||||||
|
quint32 setMethodBodyForObject(int objectDebugId, const QString &methodName,
|
||||||
|
const QString &methodBody);
|
||||||
|
quint32 resetBindingForObject(int objectDebugId,
|
||||||
|
const QString &propertyName);
|
||||||
|
|
||||||
|
QList<QmlDebugObjectReference> objects() const;
|
||||||
|
QmlDebugObjectReference objectForId(int debugId) const;
|
||||||
|
QmlDebugObjectReference objectForId(const QString &objectId) const;
|
||||||
|
QmlDebugObjectReference objectForLocation(int line, int column) const;
|
||||||
|
QList<QmlDebugObjectReference> rootObjects() const { return m_rootObjects; }
|
||||||
|
DebugIdHash debugIdHash() const { return m_debugIdHash; }
|
||||||
|
|
||||||
|
bool addObjectWatch(int objectDebugId);
|
||||||
|
bool isObjectBeingWatched(int objectDebugId);
|
||||||
|
bool removeObjectWatch(int objectDebugId);
|
||||||
|
void removeAllObjectWatches();
|
||||||
|
|
||||||
|
void setEngineClient(BaseEngineDebugClient *client);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void objectTreeUpdated();
|
||||||
|
void objectFetched(const QmlDebugObjectReference &ref);
|
||||||
|
void expressionResult(quint32 queryId, const QVariant &value);
|
||||||
|
void propertyChanged(int debugId, const QByteArray &propertyName,
|
||||||
|
const QVariant &propertyValue);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updateStatus();
|
||||||
|
void onResult(quint32 queryId, const QVariant &value, const QByteArray &type);
|
||||||
|
void newObjects();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void reloadEngines();
|
||||||
|
void queryEngineContext(int id);
|
||||||
|
quint32 fetchContextObject(const QmlDebugObjectReference &obj);
|
||||||
|
void fetchRootObjects(const QmlDebugContextReference &context, bool clear);
|
||||||
|
|
||||||
|
void updateEngineList(const QmlDebugEngineReferenceList &engines);
|
||||||
|
void rootContextChanged(const QmlDebugContextReference &context);
|
||||||
|
void objectTreeFetched(const QmlDebugObjectReference &result);
|
||||||
|
void onCurrentObjectsFetched(const QmlDebugObjectReference &result);
|
||||||
|
bool getObjectHierarchy(const QmlDebugObjectReference &object);
|
||||||
|
|
||||||
|
|
||||||
|
void buildDebugIdHashRecursive(const QmlDebugObjectReference &ref);
|
||||||
|
QList<WatchData> buildWatchData(const QmlDebugObjectReference &obj,
|
||||||
|
const WatchData &parent);
|
||||||
|
void addObjectToTree(const QmlDebugObjectReference &obj, bool notify);
|
||||||
|
|
||||||
|
QmlDebugObjectReference objectForId(
|
||||||
|
int debugId,
|
||||||
|
const QmlDebugObjectReference &ref) const;
|
||||||
|
QList<QmlDebugObjectReference> objects(
|
||||||
|
const QmlDebugObjectReference &objectRef) const;
|
||||||
|
|
||||||
|
|
||||||
|
enum LogDirection {
|
||||||
|
LogSend,
|
||||||
|
LogReceive
|
||||||
|
};
|
||||||
|
void log(LogDirection direction, const QString &message);
|
||||||
|
|
||||||
|
bool isConnected();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DebuggerEngine *m_engine;
|
||||||
|
QmlDebug::BaseEngineDebugClient *m_engineClient;
|
||||||
|
|
||||||
|
quint32 m_engineQueryId;
|
||||||
|
quint32 m_rootContextQueryId;
|
||||||
|
int m_objectToSelect;
|
||||||
|
QList<quint32> m_objectTreeQueryIds;
|
||||||
|
QList<QmlDebugObjectReference> m_rootObjects;
|
||||||
|
QList<quint32> m_fetchCurrentObjectsQueryIds;
|
||||||
|
QList<QmlDebugObjectReference> m_fetchCurrentObjects;
|
||||||
|
QmlDebugEngineReferenceList m_engines;
|
||||||
|
QHash<int, QByteArray> m_debugIdToIname;
|
||||||
|
DebugIdHash m_debugIdHash;
|
||||||
|
|
||||||
|
QList<int> m_objectWatches;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Internal
|
||||||
|
} // Debugger
|
||||||
|
|
||||||
|
#endif // QMLINSPECTORAGENT_H
|
@@ -30,36 +30,23 @@
|
|||||||
**
|
**
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <typeinfo>
|
#include "qmllivetextpreview.h"
|
||||||
|
|
||||||
#include "qmljsinspector.h"
|
#include "qmlinspectoradapter.h"
|
||||||
#include "qmljsclientproxy.h"
|
#include "qmlinspectoragent.h"
|
||||||
#include "qmljslivetextpreview.h"
|
|
||||||
|
|
||||||
#include "qmljsinspectorconstants.h"
|
|
||||||
#include <qmljseditor/qmljseditorconstants.h>
|
|
||||||
#include <qmljs/qmljsdelta.h>
|
|
||||||
#include <qmljs/parser/qmljsast_p.h>
|
|
||||||
#include <extensionsystem/pluginmanager.h>
|
|
||||||
#include <projectexplorer/projectexplorer.h>
|
|
||||||
#include <projectexplorer/project.h>
|
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
|
||||||
#include <coreplugin/infobar.h>
|
#include <coreplugin/infobar.h>
|
||||||
#include <coreplugin/editormanager/ieditor.h>
|
#include <qmldebug/basetoolsclient.h>
|
||||||
#include <coreplugin/id.h>
|
#include <qmljseditor/qmljseditorconstants.h>
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <qmljs/parser/qmljsast_p.h>
|
||||||
|
#include <qmljs/qmljsdelta.h>
|
||||||
#include <debugger/debuggerconstants.h>
|
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
using namespace QmlJS;
|
using namespace QmlJS;
|
||||||
using namespace QmlJS::AST;
|
using namespace QmlJS::AST;
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -87,298 +74,6 @@ private:
|
|||||||
int activated;
|
int activated;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool MapObjectWithDebugReference::visit(UiObjectDefinition *ast)
|
|
||||||
{
|
|
||||||
if (lookupObjects.contains(ast))
|
|
||||||
activated++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MapObjectWithDebugReference::visit(UiObjectBinding *ast)
|
|
||||||
{
|
|
||||||
if (lookupObjects.contains(ast))
|
|
||||||
activated++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapObjectWithDebugReference::endVisit(UiObjectDefinition *ast)
|
|
||||||
{
|
|
||||||
process(ast);
|
|
||||||
if (lookupObjects.contains(ast))
|
|
||||||
activated--;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapObjectWithDebugReference::endVisit(UiObjectBinding *ast)
|
|
||||||
{
|
|
||||||
process(ast);
|
|
||||||
if (lookupObjects.contains(ast))
|
|
||||||
activated--;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapObjectWithDebugReference::process(UiObjectMember *ast)
|
|
||||||
{
|
|
||||||
if (lookupObjects.isEmpty() || activated) {
|
|
||||||
SourceLocation loc = ast->firstSourceLocation();
|
|
||||||
QHash<QPair<int, int>, DebugIdList>::const_iterator it
|
|
||||||
= ids.constFind(qMakePair<int, int>(loc.startLine, loc.startColumn));
|
|
||||||
if (it != ids.constEnd())
|
|
||||||
result[ast].append(*it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapObjectWithDebugReference::process(UiObjectBinding *ast)
|
|
||||||
{
|
|
||||||
if (lookupObjects.isEmpty() || activated) {
|
|
||||||
SourceLocation loc = ast->qualifiedTypeNameId->identifierToken;
|
|
||||||
QHash<QPair<int, int>, DebugIdList>::const_iterator it
|
|
||||||
= ids.constFind(qMakePair<int, int>(loc.startLine, loc.startColumn));
|
|
||||||
if (it != ids.constEnd())
|
|
||||||
result[ast].append(*it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSLiveTextPreview::associateEditor(Core::IEditor *editor)
|
|
||||||
{
|
|
||||||
using namespace TextEditor;
|
|
||||||
if (editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
|
|
||||||
QTC_ASSERT(QLatin1String(editor->widget()->metaObject()->className()) ==
|
|
||||||
QLatin1String("QmlJSEditor::QmlJSTextEditorWidget"),
|
|
||||||
return);
|
|
||||||
|
|
||||||
BaseTextEditorWidget *editWidget
|
|
||||||
= qobject_cast<BaseTextEditorWidget*>(editor->widget());
|
|
||||||
QTC_ASSERT(editWidget, return);
|
|
||||||
|
|
||||||
if (!m_editors.contains(editWidget)) {
|
|
||||||
m_editors << editWidget;
|
|
||||||
if (m_clientProxy.data())
|
|
||||||
connect(editWidget,
|
|
||||||
SIGNAL(selectedElementsChanged(QList<int>,QString)),
|
|
||||||
SLOT(changeSelectedElements(QList<int>,QString)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSLiveTextPreview::unassociateEditor(Core::IEditor *oldEditor)
|
|
||||||
{
|
|
||||||
using namespace TextEditor;
|
|
||||||
if (oldEditor && oldEditor->id()
|
|
||||||
== QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
|
|
||||||
BaseTextEditorWidget *editWidget
|
|
||||||
= qobject_cast<BaseTextEditorWidget*>(oldEditor->widget());
|
|
||||||
QTC_ASSERT(editWidget, return);
|
|
||||||
|
|
||||||
if (m_editors.contains(editWidget)) {
|
|
||||||
m_editors.removeOne(editWidget);
|
|
||||||
disconnect(editWidget, 0, this, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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_applyChangesToQmlInspector(true)
|
|
||||||
, m_clientProxy(clientProxy)
|
|
||||||
, m_nodeForOffset(0)
|
|
||||||
, m_updateNodeForOffset(false)
|
|
||||||
{
|
|
||||||
Q_ASSERT(doc->fileName() == initDoc->fileName());
|
|
||||||
m_filename = doc->fileName();
|
|
||||||
|
|
||||||
connect(QmlJS::ModelManagerInterface::instance(), SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)),
|
|
||||||
SLOT(documentChanged(QmlJS::Document::Ptr)));
|
|
||||||
|
|
||||||
if (m_clientProxy.data()) {
|
|
||||||
connect(m_clientProxy.data(), SIGNAL(objectTreeUpdated()),
|
|
||||||
SLOT(updateDebugIds()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSLiveTextPreview::resetInitialDoc(const QmlJS::Document::Ptr &doc)
|
|
||||||
{
|
|
||||||
m_initialDoc = doc;
|
|
||||||
m_previousDoc = doc;
|
|
||||||
m_createdObjects.clear();
|
|
||||||
m_debugIds.clear();
|
|
||||||
m_docWithUnappliedChanges.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QList<int> QmlJSLiveTextPreview::objectReferencesForOffset(quint32 offset)
|
|
||||||
{
|
|
||||||
QList<int> result;
|
|
||||||
QHashIterator<QmlJS::AST::UiObjectMember*, QList<int> > iter(m_debugIds);
|
|
||||||
QmlJS::AST::UiObjectMember *possibleNode = 0;
|
|
||||||
while(iter.hasNext()) {
|
|
||||||
iter.next();
|
|
||||||
QmlJS::AST::UiObjectMember *member = iter.key();
|
|
||||||
quint32 startOffset = member->firstSourceLocation().offset;
|
|
||||||
quint32 endOffset = member->lastSourceLocation().offset;
|
|
||||||
if (startOffset <= offset && offset <= endOffset) {
|
|
||||||
if (!possibleNode)
|
|
||||||
possibleNode = member;
|
|
||||||
if (possibleNode->firstSourceLocation().offset <= startOffset &&
|
|
||||||
endOffset <= possibleNode->lastSourceLocation().offset)
|
|
||||||
possibleNode = member;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (possibleNode) {
|
|
||||||
if (possibleNode != m_nodeForOffset) {
|
|
||||||
//We have found a better match, set flag so that we can
|
|
||||||
//query again to check if this is the best match for the offset
|
|
||||||
m_updateNodeForOffset = true;
|
|
||||||
m_nodeForOffset = possibleNode;
|
|
||||||
}
|
|
||||||
result = m_debugIds.value(possibleNode);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSLiveTextPreview::changeSelectedElements(QList<int> offsets,
|
|
||||||
const QString &wordAtCursor)
|
|
||||||
{
|
|
||||||
if (m_editors.isEmpty() || !m_previousDoc || !m_clientProxy)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_updateNodeForOffset = false;
|
|
||||||
m_lastOffsets = offsets;
|
|
||||||
QmlDebugObjectReference objectRefUnderCursor;
|
|
||||||
objectRefUnderCursor
|
|
||||||
= m_clientProxy.data()->objectReferenceForId(wordAtCursor);
|
|
||||||
|
|
||||||
QList<int> selectedReferences;
|
|
||||||
bool containsReferenceUnderCursor = false;
|
|
||||||
|
|
||||||
foreach(int offset, offsets) {
|
|
||||||
if (offset >= 0) {
|
|
||||||
QList<int> list = objectReferencesForOffset(offset);
|
|
||||||
|
|
||||||
if (!containsReferenceUnderCursor
|
|
||||||
&& objectRefUnderCursor.debugId() != -1) {
|
|
||||||
foreach(int id, list) {
|
|
||||||
if (id == objectRefUnderCursor.debugId()) {
|
|
||||||
containsReferenceUnderCursor = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedReferences << list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fallback: use ref under cursor if nothing else is found
|
|
||||||
if (selectedReferences.isEmpty()
|
|
||||||
&& !containsReferenceUnderCursor
|
|
||||||
&& objectRefUnderCursor.debugId() != -1)
|
|
||||||
{
|
|
||||||
selectedReferences << objectRefUnderCursor.debugId();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!selectedReferences.isEmpty()) {
|
|
||||||
QList<QmlDebugObjectReference> refs;
|
|
||||||
foreach(int i, selectedReferences)
|
|
||||||
refs << QmlDebugObjectReference(i);
|
|
||||||
emit selectedItemsChanged(refs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static QList<int> findRootObjectRecursive(const QmlDebugObjectReference &object,
|
|
||||||
const Document::Ptr &doc)
|
|
||||||
{
|
|
||||||
QList<int> result;
|
|
||||||
if (object.className() == doc->componentName())
|
|
||||||
result += object.debugId();
|
|
||||||
|
|
||||||
foreach (const QmlDebugObjectReference &it, object.children()) {
|
|
||||||
result += findRootObjectRecursive(it, doc);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSLiveTextPreview::updateDebugIds()
|
|
||||||
{
|
|
||||||
if (!m_initialDoc->qmlProgram())
|
|
||||||
return;
|
|
||||||
|
|
||||||
ClientProxy *clientProxy = m_clientProxy.data();
|
|
||||||
if (!clientProxy)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DebugIdHash::const_iterator it
|
|
||||||
= clientProxy->debugIdHash().constFind(
|
|
||||||
qMakePair<QString, int>(m_initialDoc->fileName(), 0));
|
|
||||||
if (it != clientProxy->debugIdHash().constEnd()) {
|
|
||||||
// Map all the object that comes from the document as it has been loaded
|
|
||||||
// by the server.
|
|
||||||
const QmlJS::Document::Ptr &doc = m_initialDoc;
|
|
||||||
|
|
||||||
MapObjectWithDebugReference visitor;
|
|
||||||
visitor.ids = (*it);
|
|
||||||
visitor.filename = doc->fileName();
|
|
||||||
doc->qmlProgram()->accept(&visitor);
|
|
||||||
|
|
||||||
m_debugIds = visitor.result;
|
|
||||||
if (doc != m_previousDoc) {
|
|
||||||
Delta delta;
|
|
||||||
m_debugIds = delta(doc, m_previousDoc, m_debugIds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const QmlJS::Document::Ptr &doc = m_previousDoc;
|
|
||||||
if (!doc->qmlProgram())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Map the root nodes of the document.
|
|
||||||
if(doc->qmlProgram()->members && doc->qmlProgram()->members->member) {
|
|
||||||
UiObjectMember *root = doc->qmlProgram()->members->member;
|
|
||||||
QList<int> r;
|
|
||||||
foreach (const QmlDebugObjectReference& it,
|
|
||||||
clientProxy->rootObjectReference()) {
|
|
||||||
r += findRootObjectRecursive(it, doc);
|
|
||||||
}
|
|
||||||
if (!r.isEmpty())
|
|
||||||
m_debugIds[root] += r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map the node of the later created objects.
|
|
||||||
for (QHash<Document::Ptr,QSet<UiObjectMember*> >::const_iterator it
|
|
||||||
= m_createdObjects.constBegin();
|
|
||||||
it != m_createdObjects.constEnd(); ++it) {
|
|
||||||
|
|
||||||
const QmlJS::Document::Ptr &doc = it.key();
|
|
||||||
|
|
||||||
DebugIdHash::const_iterator id_it = clientProxy->debugIdHash().constFind(
|
|
||||||
qMakePair<QString, int>(doc->fileName(), doc->editorRevision()));
|
|
||||||
if (id_it == clientProxy->debugIdHash().constEnd())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
MapObjectWithDebugReference visitor;
|
|
||||||
visitor.ids = *id_it;
|
|
||||||
visitor.filename = doc->fileName();
|
|
||||||
visitor.lookupObjects = it.value();
|
|
||||||
doc->qmlProgram()->accept(&visitor);
|
|
||||||
|
|
||||||
Delta::DebugIdMap debugIds = visitor.result;
|
|
||||||
if (doc != m_previousDoc) {
|
|
||||||
Delta delta;
|
|
||||||
debugIds = delta(doc, m_previousDoc, debugIds);
|
|
||||||
}
|
|
||||||
for(Delta::DebugIdMap::const_iterator it2 = debugIds.constBegin();
|
|
||||||
it2 != debugIds.constEnd(); ++it2) {
|
|
||||||
m_debugIds[it2.key()] += it2.value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (m_updateNodeForOffset)
|
|
||||||
changeSelectedElements(m_lastOffsets, QString());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class UpdateInspector : public Delta {
|
class UpdateInspector : public Delta {
|
||||||
private:
|
private:
|
||||||
static inline QString stripQuotes(const QString &str)
|
static inline QString stripQuotes(const QString &str)
|
||||||
@@ -491,7 +186,8 @@ protected:
|
|||||||
Q_UNUSED(scriptBinding);
|
Q_UNUSED(scriptBinding);
|
||||||
Q_UNUSED(parentDefinition);
|
Q_UNUSED(parentDefinition);
|
||||||
appliedChangesToViewer = true;
|
appliedChangesToViewer = true;
|
||||||
m_clientProxy->setMethodBodyForObject(debugId, methodName, methodBody);
|
m_inspectorAdapter->engineClient()->setMethodBody(debugId,
|
||||||
|
methodName, methodBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updateScriptBinding(DebugId debugId,
|
virtual void updateScriptBinding(DebugId debugId,
|
||||||
@@ -501,11 +197,11 @@ protected:
|
|||||||
const QString &scriptCode)
|
const QString &scriptCode)
|
||||||
{
|
{
|
||||||
if (unsyncronizableChanges
|
if (unsyncronizableChanges
|
||||||
== QmlJSLiveTextPreview::NoUnsyncronizableChanges) {
|
== QmlLiveTextPreview::NoUnsyncronizableChanges) {
|
||||||
if (propertyName == QLatin1String("id")) {
|
if (propertyName == QLatin1String("id")) {
|
||||||
unsyncronizableElementName = propertyName;
|
unsyncronizableElementName = propertyName;
|
||||||
unsyncronizableChanges
|
unsyncronizableChanges
|
||||||
= QmlJSLiveTextPreview::AttributeChangeWarning;
|
= QmlLiveTextPreview::AttributeChangeWarning;
|
||||||
unsyncronizableChangeLine
|
unsyncronizableChangeLine
|
||||||
= parentDefinition->firstSourceLocation().startLine;
|
= parentDefinition->firstSourceLocation().startLine;
|
||||||
unsyncronizableChangeColumn
|
unsyncronizableChangeColumn
|
||||||
@@ -518,7 +214,7 @@ protected:
|
|||||||
if (isLiteral)
|
if (isLiteral)
|
||||||
expr = castToLiteral(scriptCode, scriptBinding);
|
expr = castToLiteral(scriptCode, scriptBinding);
|
||||||
appliedChangesToViewer = true;
|
appliedChangesToViewer = true;
|
||||||
m_clientProxy->setBindingForObject(
|
m_inspectorAdapter->engineClient()->setBindingForObject(
|
||||||
debugId, propertyName, expr,
|
debugId, propertyName, expr,
|
||||||
isLiteral, document()->fileName(),
|
isLiteral, document()->fileName(),
|
||||||
scriptBinding->firstSourceLocation().startLine);
|
scriptBinding->firstSourceLocation().startLine);
|
||||||
@@ -527,13 +223,13 @@ protected:
|
|||||||
virtual void resetBindingForObject(int debugId, const QString &propertyName)
|
virtual void resetBindingForObject(int debugId, const QString &propertyName)
|
||||||
{
|
{
|
||||||
appliedChangesToViewer = true;
|
appliedChangesToViewer = true;
|
||||||
m_clientProxy->resetBindingForObject(debugId, propertyName);
|
m_inspectorAdapter->engineClient()->resetBindingForObject(debugId, propertyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void removeObject(int debugId)
|
virtual void removeObject(int debugId)
|
||||||
{
|
{
|
||||||
appliedChangesToViewer = true;
|
appliedChangesToViewer = true;
|
||||||
m_clientProxy->destroyQmlObject(debugId);
|
m_inspectorAdapter->toolsClient()->destroyQmlObject(debugId);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void createObject(const QString &qmlText, DebugId ref,
|
virtual void createObject(const QString &qmlText, DebugId ref,
|
||||||
@@ -543,18 +239,18 @@ protected:
|
|||||||
{
|
{
|
||||||
appliedChangesToViewer = true;
|
appliedChangesToViewer = true;
|
||||||
referenceRefreshRequired = true;
|
referenceRefreshRequired = true;
|
||||||
m_clientProxy->createQmlObject(qmlText, ref, importList, filename, order);
|
m_inspectorAdapter->toolsClient()->createQmlObject(qmlText, ref, importList, filename, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void reparentObject(int debugId, int newParent)
|
virtual void reparentObject(int debugId, int newParent)
|
||||||
{
|
{
|
||||||
appliedChangesToViewer = true;
|
appliedChangesToViewer = true;
|
||||||
m_clientProxy->reparentQmlObject(debugId, newParent);
|
m_inspectorAdapter->toolsClient()->reparentQmlObject(debugId, newParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void notifyUnsyncronizableElementChange(UiObjectMember *parent)
|
void notifyUnsyncronizableElementChange(UiObjectMember *parent)
|
||||||
{
|
{
|
||||||
if (unsyncronizableChanges == QmlJSLiveTextPreview::NoUnsyncronizableChanges) {
|
if (unsyncronizableChanges == QmlLiveTextPreview::NoUnsyncronizableChanges) {
|
||||||
UiObjectDefinition *parentDefinition = cast<UiObjectDefinition *>(parent);
|
UiObjectDefinition *parentDefinition = cast<UiObjectDefinition *>(parent);
|
||||||
if (parentDefinition && parentDefinition->qualifiedTypeNameId
|
if (parentDefinition && parentDefinition->qualifiedTypeNameId
|
||||||
&& !parentDefinition->qualifiedTypeNameId->name.isEmpty())
|
&& !parentDefinition->qualifiedTypeNameId->name.isEmpty())
|
||||||
@@ -562,7 +258,7 @@ protected:
|
|||||||
unsyncronizableElementName
|
unsyncronizableElementName
|
||||||
= parentDefinition->qualifiedTypeNameId->name.toString();
|
= parentDefinition->qualifiedTypeNameId->name.toString();
|
||||||
unsyncronizableChanges
|
unsyncronizableChanges
|
||||||
= QmlJSLiveTextPreview::ElementChangeWarning;
|
= QmlLiveTextPreview::ElementChangeWarning;
|
||||||
unsyncronizableChangeLine
|
unsyncronizableChangeLine
|
||||||
= parentDefinition->firstSourceLocation().startLine;
|
= parentDefinition->firstSourceLocation().startLine;
|
||||||
unsyncronizableChangeColumn
|
unsyncronizableChangeColumn
|
||||||
@@ -572,30 +268,294 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UpdateInspector(ClientProxy *clientProxy)
|
UpdateInspector(QmlInspectorAdapter *inspectorAdapter)
|
||||||
: appliedChangesToViewer(false)
|
: appliedChangesToViewer(false)
|
||||||
, referenceRefreshRequired(false)
|
, referenceRefreshRequired(false)
|
||||||
, unsyncronizableChanges(QmlJSLiveTextPreview::NoUnsyncronizableChanges)
|
, unsyncronizableChanges(QmlLiveTextPreview::NoUnsyncronizableChanges)
|
||||||
, m_clientProxy(clientProxy)
|
, m_inspectorAdapter(inspectorAdapter)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool appliedChangesToViewer;
|
bool appliedChangesToViewer;
|
||||||
bool referenceRefreshRequired;
|
bool referenceRefreshRequired;
|
||||||
QString unsyncronizableElementName;
|
QString unsyncronizableElementName;
|
||||||
QmlJSLiveTextPreview::UnsyncronizableChangeType unsyncronizableChanges;
|
QmlLiveTextPreview::UnsyncronizableChangeType unsyncronizableChanges;
|
||||||
unsigned unsyncronizableChangeLine;
|
unsigned unsyncronizableChangeLine;
|
||||||
unsigned unsyncronizableChangeColumn;
|
unsigned unsyncronizableChangeColumn;
|
||||||
ClientProxy *m_clientProxy;
|
QmlInspectorAdapter *m_inspectorAdapter;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc)
|
bool MapObjectWithDebugReference::visit(UiObjectDefinition *ast)
|
||||||
{
|
{
|
||||||
if (doc->fileName() != m_previousDoc->fileName() || m_clientProxy.isNull())
|
if (lookupObjects.contains(ast))
|
||||||
|
activated++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MapObjectWithDebugReference::visit(UiObjectBinding *ast)
|
||||||
|
{
|
||||||
|
if (lookupObjects.contains(ast))
|
||||||
|
activated++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapObjectWithDebugReference::endVisit(UiObjectDefinition *ast)
|
||||||
|
{
|
||||||
|
process(ast);
|
||||||
|
if (lookupObjects.contains(ast))
|
||||||
|
activated--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapObjectWithDebugReference::endVisit(UiObjectBinding *ast)
|
||||||
|
{
|
||||||
|
process(ast);
|
||||||
|
if (lookupObjects.contains(ast))
|
||||||
|
activated--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapObjectWithDebugReference::process(UiObjectMember *ast)
|
||||||
|
{
|
||||||
|
if (lookupObjects.isEmpty() || activated) {
|
||||||
|
SourceLocation loc = ast->firstSourceLocation();
|
||||||
|
QHash<QPair<int, int>, DebugIdList>::const_iterator it
|
||||||
|
= ids.constFind(qMakePair<int, int>(loc.startLine, loc.startColumn));
|
||||||
|
if (it != ids.constEnd())
|
||||||
|
result[ast].append(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapObjectWithDebugReference::process(UiObjectBinding *ast)
|
||||||
|
{
|
||||||
|
if (lookupObjects.isEmpty() || activated) {
|
||||||
|
SourceLocation loc = ast->qualifiedTypeNameId->identifierToken;
|
||||||
|
QHash<QPair<int, int>, DebugIdList>::const_iterator it
|
||||||
|
= ids.constFind(qMakePair<int, int>(loc.startLine, loc.startColumn));
|
||||||
|
if (it != ids.constEnd())
|
||||||
|
result[ast].append(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Manages a Qml/JS document for the inspector
|
||||||
|
*/
|
||||||
|
QmlLiveTextPreview::QmlLiveTextPreview(const QmlJS::Document::Ptr &doc,
|
||||||
|
const QmlJS::Document::Ptr &initDoc,
|
||||||
|
QmlInspectorAdapter *inspectorAdapter,
|
||||||
|
QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_previousDoc(doc)
|
||||||
|
, m_initialDoc(initDoc)
|
||||||
|
, m_applyChangesToQmlInspector(true)
|
||||||
|
, m_inspectorAdapter(inspectorAdapter)
|
||||||
|
, m_nodeForOffset(0)
|
||||||
|
, m_updateNodeForOffset(false)
|
||||||
|
{
|
||||||
|
QTC_CHECK(doc->fileName() == initDoc->fileName());
|
||||||
|
|
||||||
|
QmlJS::ModelManagerInterface *modelManager
|
||||||
|
= QmlJS::ModelManagerInterface::instance();
|
||||||
|
|
||||||
|
connect(modelManager, SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)),
|
||||||
|
SLOT(documentChanged(QmlJS::Document::Ptr)));
|
||||||
|
|
||||||
|
connect(m_inspectorAdapter->agent(), SIGNAL(objectTreeUpdated()),
|
||||||
|
SLOT(updateDebugIds()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlLiveTextPreview::associateEditor(Core::IEditor *editor)
|
||||||
|
{
|
||||||
|
using namespace TextEditor;
|
||||||
|
if (editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
|
||||||
|
QTC_ASSERT(QLatin1String(editor->widget()->metaObject()->className()) ==
|
||||||
|
QLatin1String("QmlJSEditor::QmlJSTextEditorWidget"),
|
||||||
|
return);
|
||||||
|
|
||||||
|
BaseTextEditorWidget *editWidget
|
||||||
|
= qobject_cast<BaseTextEditorWidget*>(editor->widget());
|
||||||
|
QTC_ASSERT(editWidget, return);
|
||||||
|
|
||||||
|
if (!m_editors.contains(editWidget)) {
|
||||||
|
m_editors << editWidget;
|
||||||
|
if (m_inspectorAdapter)
|
||||||
|
connect(editWidget,
|
||||||
|
SIGNAL(selectedElementsChanged(QList<int>,QString)),
|
||||||
|
SLOT(changeSelectedElements(QList<int>,QString)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlLiveTextPreview::unassociateEditor(Core::IEditor *oldEditor)
|
||||||
|
{
|
||||||
|
using namespace TextEditor;
|
||||||
|
if (oldEditor && oldEditor->id()
|
||||||
|
== QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
|
||||||
|
BaseTextEditorWidget *editWidget
|
||||||
|
= qobject_cast<BaseTextEditorWidget*>(oldEditor->widget());
|
||||||
|
QTC_ASSERT(editWidget, return);
|
||||||
|
|
||||||
|
if (m_editors.contains(editWidget)) {
|
||||||
|
m_editors.removeOne(editWidget);
|
||||||
|
disconnect(editWidget, 0, this, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlLiveTextPreview::resetInitialDoc(const QmlJS::Document::Ptr &doc)
|
||||||
|
{
|
||||||
|
m_initialDoc = doc;
|
||||||
|
m_previousDoc = doc;
|
||||||
|
m_createdObjects.clear();
|
||||||
|
m_debugIds.clear();
|
||||||
|
m_docWithUnappliedChanges.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlLiveTextPreview::setApplyChangesToQmlInspector(bool applyChanges)
|
||||||
|
{
|
||||||
|
if (applyChanges && !m_applyChangesToQmlInspector) {
|
||||||
|
if (m_docWithUnappliedChanges) {
|
||||||
|
m_applyChangesToQmlInspector = true;
|
||||||
|
documentChanged(m_docWithUnappliedChanges);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_applyChangesToQmlInspector = applyChanges;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QList<int> findRootObjectRecursive(const QmlDebugObjectReference &object,
|
||||||
|
const Document::Ptr &doc)
|
||||||
|
{
|
||||||
|
QList<int> result;
|
||||||
|
if (object.className() == doc->componentName())
|
||||||
|
result += object.debugId();
|
||||||
|
|
||||||
|
foreach (const QmlDebugObjectReference &it, object.children()) {
|
||||||
|
result += findRootObjectRecursive(it, doc);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlLiveTextPreview::updateDebugIds()
|
||||||
|
{
|
||||||
|
if (!m_initialDoc->qmlProgram())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool experimentalWarningShown = false;
|
DebugIdHash::const_iterator it
|
||||||
|
= m_inspectorAdapter->agent()->debugIdHash().constFind(
|
||||||
|
qMakePair<QString, int>(m_initialDoc->fileName(), 0));
|
||||||
|
if (it != m_inspectorAdapter->agent()->debugIdHash().constEnd()) {
|
||||||
|
// Map all the object that comes from the document as it has been loaded
|
||||||
|
// by the server.
|
||||||
|
const QmlJS::Document::Ptr &doc = m_initialDoc;
|
||||||
|
|
||||||
|
MapObjectWithDebugReference visitor;
|
||||||
|
visitor.ids = (*it);
|
||||||
|
visitor.filename = doc->fileName();
|
||||||
|
doc->qmlProgram()->accept(&visitor);
|
||||||
|
|
||||||
|
m_debugIds = visitor.result;
|
||||||
|
if (doc != m_previousDoc) {
|
||||||
|
Delta delta;
|
||||||
|
m_debugIds = delta(doc, m_previousDoc, m_debugIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QmlJS::Document::Ptr &doc = m_previousDoc;
|
||||||
|
if (!doc->qmlProgram())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Map the root nodes of the document.
|
||||||
|
if (doc->qmlProgram()->members && doc->qmlProgram()->members->member) {
|
||||||
|
UiObjectMember *root = doc->qmlProgram()->members->member;
|
||||||
|
QList<int> r;
|
||||||
|
foreach (const QmlDebugObjectReference& it,
|
||||||
|
m_inspectorAdapter->agent()->rootObjects()) {
|
||||||
|
r += findRootObjectRecursive(it, doc);
|
||||||
|
}
|
||||||
|
if (!r.isEmpty())
|
||||||
|
m_debugIds[root] += r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map the node of the later created objects.
|
||||||
|
for (QHash<Document::Ptr,QSet<UiObjectMember*> >::const_iterator it
|
||||||
|
= m_createdObjects.constBegin();
|
||||||
|
it != m_createdObjects.constEnd(); ++it) {
|
||||||
|
|
||||||
|
const QmlJS::Document::Ptr &doc = it.key();
|
||||||
|
|
||||||
|
DebugIdHash::const_iterator id_it = m_inspectorAdapter->agent()->debugIdHash().constFind(
|
||||||
|
qMakePair<QString, int>(doc->fileName(), doc->editorRevision()));
|
||||||
|
if (id_it == m_inspectorAdapter->agent()->debugIdHash().constEnd())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MapObjectWithDebugReference visitor;
|
||||||
|
visitor.ids = *id_it;
|
||||||
|
visitor.filename = doc->fileName();
|
||||||
|
visitor.lookupObjects = it.value();
|
||||||
|
doc->qmlProgram()->accept(&visitor);
|
||||||
|
|
||||||
|
Delta::DebugIdMap debugIds = visitor.result;
|
||||||
|
if (doc != m_previousDoc) {
|
||||||
|
Delta delta;
|
||||||
|
debugIds = delta(doc, m_previousDoc, debugIds);
|
||||||
|
}
|
||||||
|
for (Delta::DebugIdMap::const_iterator it2 = debugIds.constBegin();
|
||||||
|
it2 != debugIds.constEnd(); ++it2) {
|
||||||
|
m_debugIds[it2.key()] += it2.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_updateNodeForOffset)
|
||||||
|
changeSelectedElements(m_lastOffsets, QString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlLiveTextPreview::changeSelectedElements(QList<int> offsets,
|
||||||
|
const QString &wordAtCursor)
|
||||||
|
{
|
||||||
|
if (m_editors.isEmpty() || !m_previousDoc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_updateNodeForOffset = false;
|
||||||
|
m_lastOffsets = offsets;
|
||||||
|
QmlDebugObjectReference objectRefUnderCursor;
|
||||||
|
objectRefUnderCursor
|
||||||
|
= m_inspectorAdapter->agent()->objectForId(wordAtCursor);
|
||||||
|
|
||||||
|
QList<int> selectedReferences;
|
||||||
|
bool containsReferenceUnderCursor = false;
|
||||||
|
|
||||||
|
foreach (int offset, offsets) {
|
||||||
|
if (offset >= 0) {
|
||||||
|
QList<int> list = objectReferencesForOffset(offset);
|
||||||
|
|
||||||
|
if (!containsReferenceUnderCursor
|
||||||
|
&& objectRefUnderCursor.debugId() != -1) {
|
||||||
|
foreach (int id, list) {
|
||||||
|
if (id == objectRefUnderCursor.debugId()) {
|
||||||
|
containsReferenceUnderCursor = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedReferences << list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback: use ref under cursor if nothing else is found
|
||||||
|
if (selectedReferences.isEmpty()
|
||||||
|
&& !containsReferenceUnderCursor
|
||||||
|
&& objectRefUnderCursor.debugId() != -1) {
|
||||||
|
selectedReferences << objectRefUnderCursor.debugId();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!selectedReferences.isEmpty())
|
||||||
|
emit selectedItemsChanged(selectedReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc)
|
||||||
|
{
|
||||||
|
if (doc->fileName() != m_previousDoc->fileName())
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_applyChangesToQmlInspector) {
|
if (m_applyChangesToQmlInspector) {
|
||||||
m_docWithUnappliedChanges.clear();
|
m_docWithUnappliedChanges.clear();
|
||||||
@@ -603,21 +563,14 @@ void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc)
|
|||||||
if (doc && m_previousDoc && doc->fileName() == m_previousDoc->fileName()
|
if (doc && m_previousDoc && doc->fileName() == m_previousDoc->fileName()
|
||||||
&& doc->qmlProgram() && m_previousDoc->qmlProgram())
|
&& doc->qmlProgram() && m_previousDoc->qmlProgram())
|
||||||
{
|
{
|
||||||
UpdateInspector delta(m_clientProxy.data());
|
UpdateInspector delta(m_inspectorAdapter);
|
||||||
m_debugIds = delta(m_previousDoc, doc, m_debugIds);
|
m_debugIds = delta(m_previousDoc, doc, m_debugIds);
|
||||||
|
|
||||||
if (delta.referenceRefreshRequired)
|
if (delta.referenceRefreshRequired)
|
||||||
m_clientProxy.data()->refreshObjectTree();
|
m_inspectorAdapter->agent()->refreshObjectTree();
|
||||||
|
|
||||||
if (InspectorUi::instance()->showExperimentalWarning()
|
|
||||||
&& delta.appliedChangesToViewer) {
|
|
||||||
showExperimentalWarning();
|
|
||||||
experimentalWarningShown = true;
|
|
||||||
InspectorUi::instance()->setShowExperimentalWarning(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delta.unsyncronizableChanges != NoUnsyncronizableChanges
|
if (delta.unsyncronizableChanges != NoUnsyncronizableChanges)
|
||||||
&& !experimentalWarningShown)
|
|
||||||
showSyncWarning(delta.unsyncronizableChanges,
|
showSyncWarning(delta.unsyncronizableChanges,
|
||||||
delta.unsyncronizableElementName,
|
delta.unsyncronizableElementName,
|
||||||
delta.unsyncronizableChangeLine,
|
delta.unsyncronizableChangeLine,
|
||||||
@@ -627,30 +580,44 @@ void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc)
|
|||||||
if (!delta.newObjects.isEmpty())
|
if (!delta.newObjects.isEmpty())
|
||||||
m_createdObjects[doc] += delta.newObjects;
|
m_createdObjects[doc] += delta.newObjects;
|
||||||
|
|
||||||
m_clientProxy.data()->clearComponentCache();
|
m_inspectorAdapter->toolsClient()->clearComponentCache();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_docWithUnappliedChanges = doc;
|
m_docWithUnappliedChanges = doc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlJSLiveTextPreview::showExperimentalWarning()
|
QList<int> QmlLiveTextPreview::objectReferencesForOffset(quint32 offset)
|
||||||
{
|
{
|
||||||
foreach (QWeakPointer<TextEditor::BaseTextEditorWidget> editor, m_editors)
|
QList<int> result;
|
||||||
if (editor) {
|
QHashIterator<QmlJS::AST::UiObjectMember*, QList<int> > iter(m_debugIds);
|
||||||
Core::InfoBarEntry info(
|
QmlJS::AST::UiObjectMember *possibleNode = 0;
|
||||||
Constants::INFO_EXPERIMENTAL,
|
while (iter.hasNext()) {
|
||||||
tr("You changed a QML file in Live Preview mode, which "
|
iter.next();
|
||||||
"modifies the running QML application. In case of "
|
QmlJS::AST::UiObjectMember *member = iter.key();
|
||||||
"unexpected behavior, please reload the QML "
|
quint32 startOffset = member->firstSourceLocation().offset;
|
||||||
"application."));
|
quint32 endOffset = member->lastSourceLocation().offset;
|
||||||
info.setCustomButtonInfo(tr("Disable Live Preview"), this,
|
if (startOffset <= offset && offset <= endOffset) {
|
||||||
SLOT(disableLivePreview()));
|
if (!possibleNode)
|
||||||
editor.data()->editorDocument()->infoBar()->addInfo(info);
|
possibleNode = member;
|
||||||
|
if (possibleNode->firstSourceLocation().offset <= startOffset &&
|
||||||
|
endOffset <= possibleNode->lastSourceLocation().offset)
|
||||||
|
possibleNode = member;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (possibleNode) {
|
||||||
|
if (possibleNode != m_nodeForOffset) {
|
||||||
|
//We have found a better match, set flag so that we can
|
||||||
|
//query again to check if this is the best match for the offset
|
||||||
|
m_updateNodeForOffset = true;
|
||||||
|
m_nodeForOffset = possibleNode;
|
||||||
|
}
|
||||||
|
result = m_debugIds.value(possibleNode);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void QmlJSLiveTextPreview::showSyncWarning(
|
void QmlLiveTextPreview::showSyncWarning(
|
||||||
UnsyncronizableChangeType unsyncronizableChangeType,
|
UnsyncronizableChangeType unsyncronizableChangeType,
|
||||||
const QString &elementName, unsigned line, unsigned column)
|
const QString &elementName, unsigned line, unsigned column)
|
||||||
{
|
{
|
||||||
@@ -666,87 +633,22 @@ void QmlJSLiveTextPreview::showSyncWarning(
|
|||||||
"changed without reloading the QML application. ")
|
"changed without reloading the QML application. ")
|
||||||
.arg(elementName, QString::number(line), QString::number(column));
|
.arg(elementName, QString::number(line), QString::number(column));
|
||||||
break;
|
break;
|
||||||
case QmlJSLiveTextPreview::NoUnsyncronizableChanges:
|
case QmlLiveTextPreview::NoUnsyncronizableChanges:
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
errorMessage.append(tr("You can continue debugging, but behavior can be unexpected."));
|
errorMessage.append(tr("You can continue debugging, but behavior can be unexpected."));
|
||||||
|
|
||||||
foreach (QWeakPointer<TextEditor::BaseTextEditorWidget> editor, m_editors) {
|
foreach (TextEditor::BaseTextEditorWidget *editor, m_editors) {
|
||||||
if (editor) {
|
if (editor) {
|
||||||
Core::InfoBar *infoBar = editor.data()->editorDocument()->infoBar();
|
Core::InfoBar *infoBar = editor->editorDocument()->infoBar();
|
||||||
infoBar->addInfo(Core::InfoBarEntry(
|
infoBar->addInfo(Core::InfoBarEntry(
|
||||||
QLatin1String(Constants::INFO_OUT_OF_SYNC),
|
QLatin1String("Debugger.Inspector.OutOfSyncWarning"),
|
||||||
errorMessage));
|
errorMessage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlJSLiveTextPreview::reloadQmlViewer()
|
|
||||||
{
|
|
||||||
foreach (QWeakPointer<TextEditor::BaseTextEditorWidget> editor, m_editors) {
|
|
||||||
if (editor) {
|
|
||||||
Core::InfoBar *infoBar = editor.data()->editorDocument()->infoBar();
|
|
||||||
infoBar->removeInfo(Constants::INFO_OUT_OF_SYNC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
emit reloadQmlViewerRequested();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSLiveTextPreview::disableLivePreview()
|
|
||||||
{
|
|
||||||
foreach (QWeakPointer<TextEditor::BaseTextEditorWidget> editor, m_editors) {
|
|
||||||
if (editor) {
|
|
||||||
Core::InfoBar *infoBar = editor.data()->editorDocument()->infoBar();
|
|
||||||
infoBar->removeInfo(Constants::INFO_OUT_OF_SYNC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
emit disableLivePreviewRequested();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSLiveTextPreview::setApplyChangesToQmlInspector(bool applyChanges)
|
|
||||||
{
|
|
||||||
if (applyChanges && !m_applyChangesToQmlInspector) {
|
|
||||||
if (m_docWithUnappliedChanges) {
|
|
||||||
m_applyChangesToQmlInspector = true;
|
|
||||||
documentChanged(m_docWithUnappliedChanges);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_applyChangesToQmlInspector = applyChanges;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSLiveTextPreview::setClientProxy(ClientProxy *clientProxy)
|
|
||||||
{
|
|
||||||
if (m_clientProxy.data()) {
|
|
||||||
disconnect(m_clientProxy.data(), SIGNAL(objectTreeUpdated()),
|
|
||||||
this, SLOT(updateDebugIds()));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_clientProxy = clientProxy;
|
|
||||||
|
|
||||||
if (m_clientProxy.data()) {
|
|
||||||
connect(m_clientProxy.data(), SIGNAL(objectTreeUpdated()),
|
|
||||||
SLOT(updateDebugIds()));
|
|
||||||
|
|
||||||
foreach (QWeakPointer<TextEditor::BaseTextEditorWidget> editWidget,
|
|
||||||
m_editors)
|
|
||||||
if (editWidget)
|
|
||||||
connect(editWidget.data(),
|
|
||||||
SIGNAL(selectedElementsChanged(QList<int>,QString)),
|
|
||||||
this,
|
|
||||||
SLOT(changeSelectedElements(QList<int>,QString)));
|
|
||||||
} else {
|
|
||||||
foreach (QWeakPointer<TextEditor::BaseTextEditorWidget> editWidget,
|
|
||||||
m_editors)
|
|
||||||
if (editWidget)
|
|
||||||
disconnect(editWidget.data(),
|
|
||||||
SIGNAL(selectedElementsChanged(QList<int>,QString)),
|
|
||||||
this,
|
|
||||||
SLOT(changeSelectedElements(QList<int>,QString)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace QmlJSInspector
|
} // namespace Debugger
|
@@ -30,21 +30,14 @@
|
|||||||
**
|
**
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#ifndef SCRIPTBINDINGREWRITER_H
|
#ifndef QMLLIVETEXTPREVIEW_H
|
||||||
#define SCRIPTBINDINGREWRITER_H
|
#define QMLLIVETEXTPREVIEW_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QWeakPointer>
|
|
||||||
#include <texteditor/basetexteditor.h>
|
#include <texteditor/basetexteditor.h>
|
||||||
|
|
||||||
#include <qmldebug/baseenginedebugclient.h>
|
|
||||||
#include <qmljs/parser/qmljsastfwd_p.h>
|
|
||||||
#include <qmljs/qmljsdocument.h>
|
#include <qmljs/qmljsdocument.h>
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QTextDocument)
|
|
||||||
|
|
||||||
using namespace QmlDebug;
|
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class IEditor;
|
class IEditor;
|
||||||
}
|
}
|
||||||
@@ -53,41 +46,28 @@ namespace QmlJS {
|
|||||||
class ModelManagerInterface;
|
class ModelManagerInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class ClientProxy;
|
class UpdateInspector;
|
||||||
|
class QmlInspectorAdapter;
|
||||||
|
|
||||||
|
class QmlLiveTextPreview : public QObject
|
||||||
class QmlJSLiveTextPreview : public QObject
|
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QmlJSLiveTextPreview(const QmlJS::Document::Ptr &doc,
|
QmlLiveTextPreview(const QmlJS::Document::Ptr &doc,
|
||||||
const QmlJS::Document::Ptr &initDoc,
|
const QmlJS::Document::Ptr &initDoc,
|
||||||
ClientProxy *clientProxy,
|
QmlInspectorAdapter *inspectorAdapter,
|
||||||
QObject *parent = 0);
|
QObject *parent = 0);
|
||||||
//void updateDocuments();
|
|
||||||
|
|
||||||
void associateEditor(Core::IEditor *editor);
|
void associateEditor(Core::IEditor *editor);
|
||||||
void unassociateEditor(Core::IEditor *editor);
|
void unassociateEditor(Core::IEditor *editor);
|
||||||
void setActiveObject(const QmlDebugObjectReference &object);
|
|
||||||
void mapObjectToQml(const QmlDebugObjectReference &object);
|
|
||||||
void resetInitialDoc(const QmlJS::Document::Ptr &doc);
|
void resetInitialDoc(const QmlJS::Document::Ptr &doc);
|
||||||
|
|
||||||
void setClientProxy(ClientProxy *clientProxy);
|
|
||||||
|
|
||||||
enum UnsyncronizableChangeType {
|
|
||||||
NoUnsyncronizableChanges,
|
|
||||||
AttributeChangeWarning,
|
|
||||||
ElementChangeWarning
|
|
||||||
};
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void selectedItemsChanged(const QList<QmlDebugObjectReference> &objects);
|
void selectedItemsChanged(const QList<int> &debugIds);
|
||||||
void reloadQmlViewerRequested();
|
|
||||||
void disableLivePreviewRequested();
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setApplyChangesToQmlInspector(bool applyChanges);
|
void setApplyChangesToQmlInspector(bool applyChanges);
|
||||||
@@ -96,17 +76,18 @@ public slots:
|
|||||||
private slots:
|
private slots:
|
||||||
void changeSelectedElements(QList<int> offsets, const QString &wordAtCursor);
|
void changeSelectedElements(QList<int> offsets, const QString &wordAtCursor);
|
||||||
void documentChanged(QmlJS::Document::Ptr doc);
|
void documentChanged(QmlJS::Document::Ptr doc);
|
||||||
void disableLivePreview();
|
|
||||||
void reloadQmlViewer();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum UnsyncronizableChangeType {
|
||||||
|
NoUnsyncronizableChanges,
|
||||||
|
AttributeChangeWarning,
|
||||||
|
ElementChangeWarning
|
||||||
|
};
|
||||||
|
|
||||||
QList<int> objectReferencesForOffset(quint32 offset);
|
QList<int> objectReferencesForOffset(quint32 offset);
|
||||||
QVariant castToLiteral(const QString &expression,
|
|
||||||
QmlJS::AST::UiScriptBinding *scriptBinding);
|
|
||||||
void showSyncWarning(UnsyncronizableChangeType unsyncronizableChangeType,
|
void showSyncWarning(UnsyncronizableChangeType unsyncronizableChangeType,
|
||||||
const QString &elementName,
|
const QString &elementName,
|
||||||
unsigned line, unsigned column);
|
unsigned line, unsigned column);
|
||||||
void showExperimentalWarning();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QHash<QmlJS::AST::UiObjectMember*, QList<int> > m_debugIds;
|
QHash<QmlJS::AST::UiObjectMember*, QList<int> > m_debugIds;
|
||||||
@@ -114,20 +95,20 @@ private:
|
|||||||
|
|
||||||
QmlJS::Document::Ptr m_previousDoc;
|
QmlJS::Document::Ptr m_previousDoc;
|
||||||
QmlJS::Document::Ptr m_initialDoc; //the document that was loaded by the server
|
QmlJS::Document::Ptr m_initialDoc; //the document that was loaded by the server
|
||||||
QString m_filename;
|
|
||||||
|
|
||||||
QList<QWeakPointer<TextEditor::BaseTextEditorWidget> > m_editors;
|
QList<QPointer<TextEditor::BaseTextEditorWidget> > m_editors;
|
||||||
|
|
||||||
bool m_applyChangesToQmlInspector;
|
bool m_applyChangesToQmlInspector;
|
||||||
QmlJS::Document::Ptr m_docWithUnappliedChanges;
|
QmlJS::Document::Ptr m_docWithUnappliedChanges;
|
||||||
QWeakPointer<ClientProxy> m_clientProxy;
|
QmlInspectorAdapter *m_inspectorAdapter;
|
||||||
QList<int> m_lastOffsets;
|
QList<int> m_lastOffsets;
|
||||||
QmlJS::AST::UiObjectMember *m_nodeForOffset;
|
QmlJS::AST::UiObjectMember *m_nodeForOffset;
|
||||||
bool m_updateNodeForOffset;
|
bool m_updateNodeForOffset;
|
||||||
|
|
||||||
|
friend class UpdateInspector;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace QmlJSInspector
|
} // namespace Debugger
|
||||||
|
|
||||||
#endif // SCRIPTBINDINGREWRITER_H
|
#endif // QMLLIVETEXTPREVIEW_H
|
@@ -172,6 +172,10 @@ WatchModel::WatchModel(WatchHandler *handler, WatchType type)
|
|||||||
m_root->iname = "tooltip";
|
m_root->iname = "tooltip";
|
||||||
m_root->name = WatchHandler::tr("Tooltip");
|
m_root->name = WatchHandler::tr("Tooltip");
|
||||||
break;
|
break;
|
||||||
|
case InspectWatch:
|
||||||
|
m_root->iname = "inspect";
|
||||||
|
m_root->name = WatchHandler::tr("Inspector");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,7 +580,7 @@ bool WatchModel::canFetchMore(const QModelIndex &index) const
|
|||||||
{
|
{
|
||||||
WatchItem *item = watchItem(index);
|
WatchItem *item = watchItem(index);
|
||||||
QTC_ASSERT(item, return false);
|
QTC_ASSERT(item, return false);
|
||||||
return index.isValid() && m_handler->m_contentsValid && !m_fetchTriggered.contains(item->iname);
|
return index.isValid() && contentIsValid() && !m_fetchTriggered.contains(item->iname);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WatchModel::fetchMore(const QModelIndex &index)
|
void WatchModel::fetchMore(const QModelIndex &index)
|
||||||
@@ -713,6 +717,14 @@ int WatchModel::itemFormat(const WatchData &data) const
|
|||||||
return theTypeFormats.value(stripForFormat(data.type), -1);
|
return theTypeFormats.value(stripForFormat(data.type), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WatchModel::contentIsValid() const
|
||||||
|
{
|
||||||
|
// inspector doesn't follow normal beginCycle()/endCycle()
|
||||||
|
if (m_type == InspectWatch)
|
||||||
|
return true;
|
||||||
|
return m_handler->m_contentsValid;
|
||||||
|
}
|
||||||
|
|
||||||
static inline QString expression(const WatchItem *item)
|
static inline QString expression(const WatchItem *item)
|
||||||
{
|
{
|
||||||
if (!item->exp.isEmpty())
|
if (!item->exp.isEmpty())
|
||||||
@@ -812,7 +824,7 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
|
|||||||
static const QVariant red(QColor(200, 0, 0));
|
static const QVariant red(QColor(200, 0, 0));
|
||||||
static const QVariant gray(QColor(140, 140, 140));
|
static const QVariant gray(QColor(140, 140, 140));
|
||||||
switch (idx.column()) {
|
switch (idx.column()) {
|
||||||
case 1: return (!data.valueEnabled || !m_handler->m_contentsValid) ? gray
|
case 1: return (!data.valueEnabled || !contentIsValid()) ? gray
|
||||||
: data.changed ? red : QVariant();
|
: data.changed ? red : QVariant();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -927,7 +939,7 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro
|
|||||||
|
|
||||||
Qt::ItemFlags WatchModel::flags(const QModelIndex &idx) const
|
Qt::ItemFlags WatchModel::flags(const QModelIndex &idx) const
|
||||||
{
|
{
|
||||||
if (!m_handler->m_contentsValid)
|
if (!contentIsValid())
|
||||||
return Qt::ItemFlags();
|
return Qt::ItemFlags();
|
||||||
|
|
||||||
if (!idx.isValid())
|
if (!idx.isValid())
|
||||||
@@ -1276,6 +1288,7 @@ WatchHandler::WatchHandler(DebuggerEngine *engine)
|
|||||||
m_locals = new WatchModel(this, LocalsWatch);
|
m_locals = new WatchModel(this, LocalsWatch);
|
||||||
m_watchers = new WatchModel(this, WatchersWatch);
|
m_watchers = new WatchModel(this, WatchersWatch);
|
||||||
m_tooltips = new WatchModel(this, TooltipsWatch);
|
m_tooltips = new WatchModel(this, TooltipsWatch);
|
||||||
|
m_inspect = new WatchModel(this, InspectWatch);
|
||||||
|
|
||||||
m_contentsValid = false;
|
m_contentsValid = false;
|
||||||
m_resetLocationScheduled = false;
|
m_resetLocationScheduled = false;
|
||||||
@@ -1294,6 +1307,7 @@ void WatchHandler::beginCycle(bool fullCycle)
|
|||||||
m_locals->beginCycle(fullCycle);
|
m_locals->beginCycle(fullCycle);
|
||||||
m_watchers->beginCycle(fullCycle);
|
m_watchers->beginCycle(fullCycle);
|
||||||
m_tooltips->beginCycle(fullCycle);
|
m_tooltips->beginCycle(fullCycle);
|
||||||
|
// don't sync m_inspect here: It's updated on it's own
|
||||||
}
|
}
|
||||||
|
|
||||||
void WatchHandler::endCycle()
|
void WatchHandler::endCycle()
|
||||||
@@ -1309,6 +1323,16 @@ void WatchHandler::endCycle()
|
|||||||
updateWatchersWindow();
|
updateWatchersWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WatchHandler::beginCycle(WatchType type, bool fullCycle)
|
||||||
|
{
|
||||||
|
model(type)->beginCycle(fullCycle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WatchHandler::endCycle(WatchType type)
|
||||||
|
{
|
||||||
|
model(type)->endCycle();
|
||||||
|
}
|
||||||
|
|
||||||
void WatchHandler::cleanup()
|
void WatchHandler::cleanup()
|
||||||
{
|
{
|
||||||
m_expandedINames.clear();
|
m_expandedINames.clear();
|
||||||
@@ -1316,10 +1340,12 @@ void WatchHandler::cleanup()
|
|||||||
m_return->reinitialize();
|
m_return->reinitialize();
|
||||||
m_locals->reinitialize();
|
m_locals->reinitialize();
|
||||||
m_tooltips->reinitialize();
|
m_tooltips->reinitialize();
|
||||||
|
m_inspect->reinitialize();
|
||||||
m_return->m_fetchTriggered.clear();
|
m_return->m_fetchTriggered.clear();
|
||||||
m_locals->m_fetchTriggered.clear();
|
m_locals->m_fetchTriggered.clear();
|
||||||
m_watchers->m_fetchTriggered.clear();
|
m_watchers->m_fetchTriggered.clear();
|
||||||
m_tooltips->m_fetchTriggered.clear();
|
m_tooltips->m_fetchTriggered.clear();
|
||||||
|
m_inspect->m_fetchTriggered.clear();
|
||||||
#if 1
|
#if 1
|
||||||
for (EditHandlers::ConstIterator it = m_editHandlers.begin();
|
for (EditHandlers::ConstIterator it = m_editHandlers.begin();
|
||||||
it != m_editHandlers.end(); ++it) {
|
it != m_editHandlers.end(); ++it) {
|
||||||
@@ -1336,6 +1362,7 @@ void WatchHandler::emitAllChanged()
|
|||||||
m_locals->emitAllChanged();
|
m_locals->emitAllChanged();
|
||||||
m_watchers->emitAllChanged();
|
m_watchers->emitAllChanged();
|
||||||
m_tooltips->emitAllChanged();
|
m_tooltips->emitAllChanged();
|
||||||
|
m_inspect->emitAllChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WatchHandler::insertData(const WatchData &data)
|
void WatchHandler::insertData(const WatchData &data)
|
||||||
@@ -1347,9 +1374,10 @@ void WatchHandler::insertData(const WatchData &data)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.isSomethingNeeded() && data.iname.contains('.')) {
|
if (data.isSomethingNeeded() && data.iname.contains(".")) {
|
||||||
MODEL_DEBUG("SOMETHING NEEDED: " << data.toString());
|
MODEL_DEBUG("SOMETHING NEEDED: " << data.toString());
|
||||||
if (!m_engine->isSynchronous()) {
|
if (!m_engine->isSynchronous()
|
||||||
|
|| data.iname.startsWith("inspect.")) {
|
||||||
WatchModel *model = modelForIName(data.iname);
|
WatchModel *model = modelForIName(data.iname);
|
||||||
QTC_ASSERT(model, return);
|
QTC_ASSERT(model, return);
|
||||||
model->insertData(data);
|
model->insertData(data);
|
||||||
@@ -1381,6 +1409,7 @@ void WatchHandler::reinsertAllData()
|
|||||||
m_watchers->reinsertAllData();
|
m_watchers->reinsertAllData();
|
||||||
m_tooltips->reinsertAllData();
|
m_tooltips->reinsertAllData();
|
||||||
m_return->reinsertAllData();
|
m_return->reinsertAllData();
|
||||||
|
m_inspect->reinsertAllData();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bulk-insertion
|
// Bulk-insertion
|
||||||
@@ -1685,6 +1714,7 @@ WatchModel *WatchHandler::model(WatchType type) const
|
|||||||
case LocalsWatch: return m_locals;
|
case LocalsWatch: return m_locals;
|
||||||
case WatchersWatch: return m_watchers;
|
case WatchersWatch: return m_watchers;
|
||||||
case TooltipsWatch: return m_tooltips;
|
case TooltipsWatch: return m_tooltips;
|
||||||
|
case InspectWatch: return m_inspect;
|
||||||
}
|
}
|
||||||
QTC_CHECK(false);
|
QTC_CHECK(false);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1700,6 +1730,8 @@ WatchModel *WatchHandler::modelForIName(const QByteArray &iname) const
|
|||||||
return m_tooltips;
|
return m_tooltips;
|
||||||
if (iname.startsWith("watch"))
|
if (iname.startsWith("watch"))
|
||||||
return m_watchers;
|
return m_watchers;
|
||||||
|
if (iname.startsWith("inspect"))
|
||||||
|
return m_inspect;
|
||||||
QTC_ASSERT(false, qDebug() << "INAME: " << iname);
|
QTC_ASSERT(false, qDebug() << "INAME: " << iname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1746,6 +1778,7 @@ void WatchHandler::setFormat(const QByteArray &type0, int format)
|
|||||||
m_locals->emitDataChanged(1);
|
m_locals->emitDataChanged(1);
|
||||||
m_watchers->emitDataChanged(1);
|
m_watchers->emitDataChanged(1);
|
||||||
m_tooltips->emitDataChanged(1);
|
m_tooltips->emitDataChanged(1);
|
||||||
|
m_inspect->emitDataChanged(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int WatchHandler::format(const QByteArray &iname) const
|
int WatchHandler::format(const QByteArray &iname) const
|
||||||
@@ -1905,6 +1938,7 @@ void WatchHandler::resetLocation()
|
|||||||
m_locals->invalidateAll();
|
m_locals->invalidateAll();
|
||||||
m_watchers->invalidateAll();
|
m_watchers->invalidateAll();
|
||||||
m_tooltips->invalidateAll();
|
m_tooltips->invalidateAll();
|
||||||
|
m_inspect->invalidateAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1914,6 +1948,14 @@ bool WatchHandler::isValidToolTip(const QByteArray &iname) const
|
|||||||
return item && !item->type.trimmed().isEmpty();
|
return item && !item->type.trimmed().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WatchHandler::setCurrentModelIndex(WatchType modelType,
|
||||||
|
const QModelIndex &index)
|
||||||
|
{
|
||||||
|
if (WatchModel *m = model(modelType)) {
|
||||||
|
emit m->setCurrentIndex(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QHash<QByteArray, int> WatchHandler::watcherNames()
|
QHash<QByteArray, int> WatchHandler::watcherNames()
|
||||||
{
|
{
|
||||||
return theWatcherNames;
|
return theWatcherNames;
|
||||||
|
@@ -55,7 +55,8 @@ enum WatchType
|
|||||||
ReturnWatch,
|
ReturnWatch,
|
||||||
LocalsWatch,
|
LocalsWatch,
|
||||||
WatchersWatch,
|
WatchersWatch,
|
||||||
TooltipsWatch
|
TooltipsWatch,
|
||||||
|
InspectWatch
|
||||||
};
|
};
|
||||||
|
|
||||||
enum IntegerFormat
|
enum IntegerFormat
|
||||||
@@ -78,6 +79,9 @@ public:
|
|||||||
virtual int rowCount(const QModelIndex &idx = QModelIndex()) const;
|
virtual int rowCount(const QModelIndex &idx = QModelIndex()) const;
|
||||||
virtual int columnCount(const QModelIndex &idx) const;
|
virtual int columnCount(const QModelIndex &idx) const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void setCurrentIndex(const QModelIndex &index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVariant data(const QModelIndex &index, int role) const;
|
QVariant data(const QModelIndex &index, int role) const;
|
||||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||||
@@ -131,6 +135,7 @@ private:
|
|||||||
DebuggerEngine *engine() const;
|
DebuggerEngine *engine() const;
|
||||||
QString display(const WatchItem *item, int col) const;
|
QString display(const WatchItem *item, int col) const;
|
||||||
int itemFormat(const WatchData &data) const;
|
int itemFormat(const WatchData &data) const;
|
||||||
|
bool contentIsValid() const;
|
||||||
int m_generationCounter;
|
int m_generationCounter;
|
||||||
|
|
||||||
WatchHandler *m_handler;
|
WatchHandler *m_handler;
|
||||||
@@ -157,6 +162,10 @@ public:
|
|||||||
void beginCycle(bool fullCycle = true); // Called at begin of updateLocals() cycle
|
void beginCycle(bool fullCycle = true); // Called at begin of updateLocals() cycle
|
||||||
void updateWatchers(); // Called after locals are fetched
|
void updateWatchers(); // Called after locals are fetched
|
||||||
void endCycle(); // Called after all results have been received
|
void endCycle(); // Called after all results have been received
|
||||||
|
|
||||||
|
void beginCycle(WatchType type, bool fullCycle = true);
|
||||||
|
void endCycle(WatchType type);
|
||||||
|
|
||||||
void showEditValue(const WatchData &data);
|
void showEditValue(const WatchData &data);
|
||||||
|
|
||||||
void insertData(const WatchData &data);
|
void insertData(const WatchData &data);
|
||||||
@@ -204,6 +213,8 @@ public:
|
|||||||
void resetLocation();
|
void resetLocation();
|
||||||
bool isValidToolTip(const QByteArray &iname) const;
|
bool isValidToolTip(const QByteArray &iname) const;
|
||||||
|
|
||||||
|
void setCurrentModelIndex(WatchType modelType, const QModelIndex &index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class WatchModel;
|
friend class WatchModel;
|
||||||
|
|
||||||
@@ -230,6 +241,7 @@ private:
|
|||||||
WatchModel *m_locals;
|
WatchModel *m_locals;
|
||||||
WatchModel *m_watchers;
|
WatchModel *m_watchers;
|
||||||
WatchModel *m_tooltips;
|
WatchModel *m_tooltips;
|
||||||
|
WatchModel *m_inspect;
|
||||||
DebuggerEngine *m_engine;
|
DebuggerEngine *m_engine;
|
||||||
|
|
||||||
int m_watcherCounter;
|
int m_watcherCounter;
|
||||||
|
@@ -994,11 +994,15 @@ void WatchTreeView::setModel(QAbstractItemModel *model)
|
|||||||
setRootIsDecorated(true);
|
setRootIsDecorated(true);
|
||||||
if (header()) {
|
if (header()) {
|
||||||
header()->setDefaultAlignment(Qt::AlignLeft);
|
header()->setDefaultAlignment(Qt::AlignLeft);
|
||||||
if (m_type != LocalsType)
|
if (m_type != LocalsType && m_type != InspectType)
|
||||||
header()->hide();
|
header()->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(model, SIGNAL(layoutChanged()), SLOT(resetHelper()));
|
connect(model, SIGNAL(layoutChanged()), SLOT(resetHelper()));
|
||||||
|
|
||||||
|
QTC_ASSERT(qobject_cast<WatchModel*>(model), return);
|
||||||
|
connect(model, SIGNAL(setCurrentIndex(QModelIndex)),
|
||||||
|
SLOT(setCurrentIndex(QModelIndex)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WatchTreeView::resetHelper()
|
void WatchTreeView::resetHelper()
|
||||||
|
@@ -49,7 +49,7 @@ class WatchTreeView : public BaseTreeView
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Type { ReturnType, LocalsType, TooltipType, WatchersType };
|
enum Type { ReturnType, LocalsType, TooltipType, WatchersType, InspectType };
|
||||||
|
|
||||||
explicit WatchTreeView(Type type, QWidget *parent = 0);
|
explicit WatchTreeView(Type type, QWidget *parent = 0);
|
||||||
Type type() const { return m_type; }
|
Type type() const { return m_type; }
|
||||||
|
@@ -61,8 +61,7 @@ include(../../qtcreator.pri)
|
|||||||
|
|
||||||
contains(QT_CONFIG, declarative)|contains(QT_CONFIG, quick1) {
|
contains(QT_CONFIG, declarative)|contains(QT_CONFIG, quick1) {
|
||||||
SUBDIRS += \
|
SUBDIRS += \
|
||||||
plugin_qmlprojectmanager \
|
plugin_qmlprojectmanager
|
||||||
plugin_qmljsinspector
|
|
||||||
|
|
||||||
include(../private_headers.pri)
|
include(../private_headers.pri)
|
||||||
exists($${QT_PRIVATE_HEADERS}/QtDeclarative/private/qdeclarativecontext_p.h) {
|
exists($${QT_PRIVATE_HEADERS}/QtDeclarative/private/qdeclarativecontext_p.h) {
|
||||||
@@ -193,6 +192,7 @@ plugin_debugger.subdir = debugger
|
|||||||
plugin_debugger.depends = plugin_projectexplorer
|
plugin_debugger.depends = plugin_projectexplorer
|
||||||
plugin_debugger.depends += plugin_coreplugin
|
plugin_debugger.depends += plugin_coreplugin
|
||||||
plugin_debugger.depends += plugin_cpptools
|
plugin_debugger.depends += plugin_cpptools
|
||||||
|
plugin_debugger.depends += plugin_qmljstools
|
||||||
|
|
||||||
plugin_fakevim.subdir = fakevim
|
plugin_fakevim.subdir = fakevim
|
||||||
plugin_fakevim.depends = plugin_coreplugin
|
plugin_fakevim.depends = plugin_coreplugin
|
||||||
@@ -264,10 +264,6 @@ plugin_qmldesigner.depends += plugin_qt4projectmanager
|
|||||||
plugin_qmldesigner.depends += plugin_qmlprojectmanager
|
plugin_qmldesigner.depends += plugin_qmlprojectmanager
|
||||||
plugin_qmldesigner.depends += plugin_cpptools
|
plugin_qmldesigner.depends += plugin_cpptools
|
||||||
|
|
||||||
plugin_qmljsinspector.subdir = qmljsinspector
|
|
||||||
plugin_qmljsinspector.depends += plugin_debugger
|
|
||||||
plugin_qmljsinspector.depends += plugin_qmljstools
|
|
||||||
|
|
||||||
plugin_mercurial.subdir = mercurial
|
plugin_mercurial.subdir = mercurial
|
||||||
plugin_mercurial.depends = plugin_vcsbase
|
plugin_mercurial.depends = plugin_vcsbase
|
||||||
plugin_mercurial.depends += plugin_projectexplorer
|
plugin_mercurial.depends += plugin_projectexplorer
|
||||||
|
@@ -1,26 +0,0 @@
|
|||||||
<plugin name=\"QmlJSInspector\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
|
|
||||||
<vendor>Nokia Corporation</vendor>
|
|
||||||
<copyright>(C) 2011 Nokia Corporation</copyright>
|
|
||||||
<license>
|
|
||||||
Commercial Usage
|
|
||||||
|
|
||||||
Licensees holding valid Qt Commercial licenses may use this plugin in
|
|
||||||
accordance with the Qt Commercial License Agreement provided with the
|
|
||||||
Software or, alternatively, in accordance with the terms contained in
|
|
||||||
a written agreement between you and Nokia.
|
|
||||||
|
|
||||||
GNU Lesser General Public License Usage
|
|
||||||
|
|
||||||
Alternatively, this plugin may be used under the terms of the GNU Lesser
|
|
||||||
General Public License version 2.1 as published by the Free Software
|
|
||||||
Foundation. Please review the following information to
|
|
||||||
ensure the GNU Lesser General Public License version 2.1 requirements
|
|
||||||
will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.</license>
|
|
||||||
<category>Qt Quick</category>
|
|
||||||
<description>Debugger for QML files</description>
|
|
||||||
<url>http://qt.nokia.com</url>
|
|
||||||
<dependencyList>
|
|
||||||
<dependency name=\"Debugger\" version=\"$$QTCREATOR_VERSION\"/>
|
|
||||||
<dependency name=\"QmlJSTools\" version=\"$$QTCREATOR_VERSION\"/>
|
|
||||||
</dependencyList>
|
|
||||||
</plugin>
|
|
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 735 B |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.2 KiB |
@@ -1,810 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#include "qmljsclientproxy.h"
|
|
||||||
#include "qmltoolsclient.h"
|
|
||||||
#include "declarativetoolsclient.h"
|
|
||||||
#include "qmljsinspector.h"
|
|
||||||
|
|
||||||
#include <qmldebug/qmldebugconstants.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>
|
|
||||||
#include <projectexplorer/project.h>
|
|
||||||
#include <qmldebug/declarativeenginedebugclient.h>
|
|
||||||
#include <qmldebug/qmlenginedebugclient.h>
|
|
||||||
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QAbstractSocket>
|
|
||||||
|
|
||||||
using namespace QmlJSInspector::Internal;
|
|
||||||
|
|
||||||
ClientProxy::ClientProxy(Debugger::QmlAdapter *adapter, QObject *parent)
|
|
||||||
: QObject(parent)
|
|
||||||
, m_adapter(adapter)
|
|
||||||
, m_engineClient(0)
|
|
||||||
, m_inspectorHelperClient(0)
|
|
||||||
, m_engineQueryId(0)
|
|
||||||
, m_contextQueryId(0)
|
|
||||||
, m_isConnected(false)
|
|
||||||
{
|
|
||||||
connectToServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientProxy::~ClientProxy()
|
|
||||||
{
|
|
||||||
m_adapter.data()->setEngineDebugClient(0);
|
|
||||||
m_adapter.data()->setCurrentSelectedDebugInfo(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::connectToServer()
|
|
||||||
{
|
|
||||||
DeclarativeEngineDebugClient *client1 = new DeclarativeEngineDebugClient(
|
|
||||||
m_adapter.data()->connection());
|
|
||||||
QmlEngineDebugClient *client2 = new QmlEngineDebugClient(
|
|
||||||
m_adapter.data()->connection());
|
|
||||||
|
|
||||||
connect(client1, SIGNAL(newStatus(QmlDebugClient::Status)),
|
|
||||||
SLOT(clientStatusChanged(QmlDebugClient::Status)));
|
|
||||||
connect(client1, SIGNAL(newStatus(QmlDebugClient::Status)),
|
|
||||||
SLOT(engineClientStatusChanged(QmlDebugClient::Status)));
|
|
||||||
|
|
||||||
connect(client2, SIGNAL(newStatus(QmlDebugClient::Status)),
|
|
||||||
SLOT(clientStatusChanged(QmlDebugClient::Status)));
|
|
||||||
connect(client2, SIGNAL(newStatus(QmlDebugClient::Status)),
|
|
||||||
SLOT(engineClientStatusChanged(QmlDebugClient::Status)));
|
|
||||||
|
|
||||||
DeclarativeToolsClient *toolsClient1 = new DeclarativeToolsClient(
|
|
||||||
m_adapter.data()->connection());
|
|
||||||
QmlToolsClient *toolsClient2 = new QmlToolsClient(
|
|
||||||
m_adapter.data()->connection());
|
|
||||||
|
|
||||||
connect(toolsClient1, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)),
|
|
||||||
SLOT(clientStatusChanged(QmlDebugClient::Status)));
|
|
||||||
connect(toolsClient1, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)),
|
|
||||||
SLOT(toolsClientStatusChanged(QmlDebugClient::Status)));
|
|
||||||
|
|
||||||
connect(toolsClient2, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)),
|
|
||||||
SLOT(clientStatusChanged(QmlDebugClient::Status)));
|
|
||||||
connect(toolsClient2, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)),
|
|
||||||
SLOT(toolsClientStatusChanged(QmlDebugClient::Status)));
|
|
||||||
|
|
||||||
updateConnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::clientStatusChanged(QmlDebugClient::Status status)
|
|
||||||
{
|
|
||||||
QString serviceName;
|
|
||||||
float version = 0;
|
|
||||||
if (QmlDebugClient *client
|
|
||||||
= qobject_cast<QmlDebugClient*>(sender())) {
|
|
||||||
serviceName = client->name();
|
|
||||||
version = client->serviceVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_adapter)
|
|
||||||
m_adapter.data()->logServiceStatusChange(serviceName, version, status);
|
|
||||||
|
|
||||||
updateConnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlDebugClient *ClientProxy::engineDebugClient() const
|
|
||||||
{
|
|
||||||
return m_engineClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlDebugClient *ClientProxy::toolsClient() const
|
|
||||||
{
|
|
||||||
return m_inspectorHelperClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::engineClientStatusChanged(
|
|
||||||
QmlDebugClient::Status status)
|
|
||||||
{
|
|
||||||
if (status == QmlDebugClient::Enabled) {
|
|
||||||
m_engineClient = qobject_cast<BaseEngineDebugClient*>(sender());
|
|
||||||
connect(m_engineClient, SIGNAL(newObjects()), this, SLOT(newObjects()));
|
|
||||||
connect(m_engineClient, SIGNAL(result(quint32,QVariant,QByteArray)),
|
|
||||||
SLOT(onResult(quint32,QVariant,QByteArray)));
|
|
||||||
connect(m_engineClient, SIGNAL(valueChanged(int,QByteArray,QVariant)),
|
|
||||||
SLOT(objectWatchTriggered(int,QByteArray,QVariant)));
|
|
||||||
m_adapter.data()->setEngineDebugClient(m_engineClient);
|
|
||||||
updateConnected();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::toolsClientStatusChanged(
|
|
||||||
QmlDebugClient::Status status)
|
|
||||||
{
|
|
||||||
if (status == QmlDebugClient::Enabled) {
|
|
||||||
m_inspectorHelperClient = qobject_cast<BaseToolsClient*>(sender());
|
|
||||||
connect(m_inspectorHelperClient, SIGNAL(currentObjectsChanged(QList<int>)),
|
|
||||||
SLOT(onCurrentObjectsChanged(QList<int>)));
|
|
||||||
connect(m_inspectorHelperClient, SIGNAL(zoomToolActivated()),
|
|
||||||
SIGNAL(zoomToolActivated()));
|
|
||||||
connect(m_inspectorHelperClient, SIGNAL(selectToolActivated()),
|
|
||||||
SIGNAL(selectToolActivated()));
|
|
||||||
connect(m_inspectorHelperClient, SIGNAL(selectMarqueeToolActivated()),
|
|
||||||
SIGNAL(selectMarqueeToolActivated()));
|
|
||||||
connect(m_inspectorHelperClient, SIGNAL(animationSpeedChanged(qreal)),
|
|
||||||
SIGNAL(animationSpeedChanged(qreal)));
|
|
||||||
connect(m_inspectorHelperClient, SIGNAL(animationPausedChanged(bool)),
|
|
||||||
SIGNAL(animationPausedChanged(bool)));
|
|
||||||
connect(m_inspectorHelperClient, SIGNAL(designModeBehaviorChanged(bool)),
|
|
||||||
SIGNAL(designModeBehaviorChanged(bool)));
|
|
||||||
connect(m_inspectorHelperClient, SIGNAL(showAppOnTopChanged(bool)),
|
|
||||||
SIGNAL(showAppOnTopChanged(bool)));
|
|
||||||
connect(m_inspectorHelperClient, SIGNAL(reloaded()), this,
|
|
||||||
SIGNAL(serverReloaded()));
|
|
||||||
connect(m_inspectorHelperClient, SIGNAL(logActivity(QString,QString)),
|
|
||||||
m_adapter.data(), SLOT(logServiceActivity(QString,QString)));
|
|
||||||
updateConnected();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::refreshObjectTree()
|
|
||||||
{
|
|
||||||
if (!m_contextQueryId) {
|
|
||||||
m_objectTreeQueryIds.clear();
|
|
||||||
queryEngineContext(m_engines.value(0).debugId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::onCurrentObjectsChanged(const QList<int> &debugIds,
|
|
||||||
bool requestIfNeeded)
|
|
||||||
{
|
|
||||||
QList<QmlDebugObjectReference> selectedItems;
|
|
||||||
m_fetchCurrentObjects.clear();
|
|
||||||
m_fetchCurrentObjectsQueryIds.clear();
|
|
||||||
foreach (int debugId, debugIds) {
|
|
||||||
QmlDebugObjectReference ref = objectReferenceForId(debugId);
|
|
||||||
if (ref.debugId() != -1 && !ref.needsMoreData()) {
|
|
||||||
selectedItems << ref;
|
|
||||||
} else if (requestIfNeeded) {
|
|
||||||
m_fetchCurrentObjectsQueryIds
|
|
||||||
<< fetchContextObject(QmlDebugObjectReference(debugId));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit selectedItemsChanged(selectedItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::onCurrentObjectsFetched(quint32 queryId,
|
|
||||||
const QVariant &result)
|
|
||||||
{
|
|
||||||
m_fetchCurrentObjectsQueryIds.removeOne(queryId);
|
|
||||||
QmlDebugObjectReference obj
|
|
||||||
= qvariant_cast<QmlDebugObjectReference>(result);
|
|
||||||
m_fetchCurrentObjects.push_front(obj);
|
|
||||||
|
|
||||||
if (!getObjectHierarchy(obj))
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (const QmlDebugObjectReference &o, m_fetchCurrentObjects)
|
|
||||||
addObjectToTree(o, false);
|
|
||||||
emit selectedItemsChanged(QList<QmlDebugObjectReference>() <<
|
|
||||||
m_fetchCurrentObjects.last());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClientProxy::getObjectHierarchy(const QmlDebugObjectReference &obj)
|
|
||||||
{
|
|
||||||
QmlDebugObjectReference parent = objectReferenceForId(obj.parentId());
|
|
||||||
//for root object
|
|
||||||
if (obj.parentId() == -1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
//for other objects
|
|
||||||
if (parent.debugId() == -1 || parent.needsMoreData()) {
|
|
||||||
m_fetchCurrentObjectsQueryIds
|
|
||||||
<< fetchContextObject(QmlDebugObjectReference(obj.parentId()));
|
|
||||||
} else {
|
|
||||||
return getObjectHierarchy(parent);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::setSelectedItemsByDebugId(const QList<int> &debugIds)
|
|
||||||
{
|
|
||||||
if (!isConnected())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_inspectorHelperClient->setCurrentObjects(debugIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::setSelectedItemsByObjectId(
|
|
||||||
const QList<QmlDebugObjectReference> &objectRefs)
|
|
||||||
{
|
|
||||||
if (isConnected()) {
|
|
||||||
QList<int> debugIds;
|
|
||||||
|
|
||||||
foreach (const QmlDebugObjectReference &ref, objectRefs) {
|
|
||||||
debugIds << ref.debugId();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_inspectorHelperClient->setCurrentObjects(debugIds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::addObjectToTree(const QmlDebugObjectReference &obj,
|
|
||||||
bool notify)
|
|
||||||
{
|
|
||||||
int count = m_rootObjects.count();
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
if (m_rootObjects[i].insertObjectInTree(obj)) {
|
|
||||||
buildDebugIdHashRecursive(obj);
|
|
||||||
if (notify)
|
|
||||||
emit objectTreeUpdated();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlDebugObjectReference ClientProxy::objectReferenceForId(int debugId) const
|
|
||||||
{
|
|
||||||
foreach (const QmlDebugObjectReference &it, m_rootObjects) {
|
|
||||||
QmlDebugObjectReference result = objectReferenceForId(debugId, it);
|
|
||||||
if (result.debugId() == debugId)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return QmlDebugObjectReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::log(LogDirection direction, const QString &message)
|
|
||||||
{
|
|
||||||
QString msg;
|
|
||||||
if (direction == LogSend) {
|
|
||||||
msg += " sending ";
|
|
||||||
} else {
|
|
||||||
msg += " receiving ";
|
|
||||||
}
|
|
||||||
msg += message;
|
|
||||||
|
|
||||||
if (m_adapter)
|
|
||||||
m_adapter.data()->logServiceActivity("QmlDebug", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QmlDebugObjectReference>
|
|
||||||
QmlJSInspector::Internal::ClientProxy::rootObjectReference() const
|
|
||||||
{
|
|
||||||
return m_rootObjects;
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlDebugObjectReference
|
|
||||||
ClientProxy::objectReferenceForId(
|
|
||||||
int debugId,
|
|
||||||
const QmlDebugObjectReference &objectRef) const
|
|
||||||
{
|
|
||||||
if (objectRef.debugId() == debugId)
|
|
||||||
return objectRef;
|
|
||||||
|
|
||||||
foreach (const QmlDebugObjectReference &child, objectRef.children()) {
|
|
||||||
QmlDebugObjectReference result = objectReferenceForId(debugId, child);
|
|
||||||
if (result.debugId() == debugId)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return QmlDebugObjectReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlDebugObjectReference ClientProxy::objectReferenceForId(
|
|
||||||
const QString &objectId) const
|
|
||||||
{
|
|
||||||
if (!objectId.isEmpty() && objectId[0].isLower()) {
|
|
||||||
const QList<QmlDebugObjectReference> refs = objectReferences();
|
|
||||||
foreach (const QmlDebugObjectReference &ref, refs) {
|
|
||||||
if (ref.idString() == objectId)
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QmlDebugObjectReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlDebugObjectReference ClientProxy::objectReferenceForLocation(
|
|
||||||
int line, int column) const
|
|
||||||
{
|
|
||||||
const QList<QmlDebugObjectReference> refs = objectReferences();
|
|
||||||
foreach (const QmlDebugObjectReference &ref, refs) {
|
|
||||||
if (ref.source().lineNumber() == line
|
|
||||||
&& ref.source().columnNumber() == column)
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
return QmlDebugObjectReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QmlDebugObjectReference> ClientProxy::objectReferences() const
|
|
||||||
{
|
|
||||||
QList<QmlDebugObjectReference> result;
|
|
||||||
foreach (const QmlDebugObjectReference &it, m_rootObjects) {
|
|
||||||
result.append(objectReferences(it));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QmlDebugObjectReference>
|
|
||||||
ClientProxy::objectReferences(const QmlDebugObjectReference &objectRef) const
|
|
||||||
{
|
|
||||||
QList<QmlDebugObjectReference> result;
|
|
||||||
result.append(objectRef);
|
|
||||||
|
|
||||||
foreach (const QmlDebugObjectReference &child, objectRef.children()) {
|
|
||||||
result.append(objectReferences(child));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint32 ClientProxy::setBindingForObject(int objectDebugId,
|
|
||||||
const QString &propertyName,
|
|
||||||
const QVariant &value,
|
|
||||||
bool isLiteralValue,
|
|
||||||
QString source,
|
|
||||||
int line)
|
|
||||||
{
|
|
||||||
if (objectDebugId == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (propertyName == QLatin1String("id"))
|
|
||||||
return false; // Crashes the QMLViewer.
|
|
||||||
|
|
||||||
if (!isConnected())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
log(LogSend, QString("SET_BINDING %1 %2 %3 %4").arg(
|
|
||||||
QString::number(objectDebugId), propertyName, value.toString(),
|
|
||||||
QString(isLiteralValue ? "true" : "false")));
|
|
||||||
|
|
||||||
quint32 queryId = m_engineClient->setBindingForObject(
|
|
||||||
objectDebugId, propertyName, value.toString(), isLiteralValue,
|
|
||||||
source, line);
|
|
||||||
|
|
||||||
if (!queryId)
|
|
||||||
log(LogSend, QString("failed!"));
|
|
||||||
|
|
||||||
return queryId;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint32 ClientProxy::setMethodBodyForObject(int objectDebugId,
|
|
||||||
const QString &methodName,
|
|
||||||
const QString &methodBody)
|
|
||||||
{
|
|
||||||
if (objectDebugId == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!isConnected())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
log(LogSend, QString("SET_METHOD_BODY %1 %2 %3").arg(
|
|
||||||
QString::number(objectDebugId), methodName, methodBody));
|
|
||||||
|
|
||||||
quint32 queryId = m_engineClient->setMethodBody(
|
|
||||||
objectDebugId, methodName, methodBody);
|
|
||||||
|
|
||||||
if (!queryId)
|
|
||||||
log(LogSend, QString("failed!"));
|
|
||||||
|
|
||||||
return queryId;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint32 ClientProxy::resetBindingForObject(int objectDebugId,
|
|
||||||
const QString &propertyName)
|
|
||||||
{
|
|
||||||
if (objectDebugId == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!isConnected())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
log(LogSend, QString("RESET_BINDING %1 %2").arg(
|
|
||||||
QString::number(objectDebugId), propertyName));
|
|
||||||
|
|
||||||
quint32 queryId = m_engineClient->resetBindingForObject(
|
|
||||||
objectDebugId, propertyName);
|
|
||||||
|
|
||||||
if (!queryId)
|
|
||||||
log(LogSend, QString("failed!"));
|
|
||||||
|
|
||||||
return queryId;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint32 ClientProxy::queryExpressionResult(int objectDebugId,
|
|
||||||
const QString &expr)
|
|
||||||
{
|
|
||||||
if (objectDebugId == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!isConnected())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
bool block = false;
|
|
||||||
if (m_adapter)
|
|
||||||
block = m_adapter.data()->disableJsDebugging(true);
|
|
||||||
|
|
||||||
log(LogSend, QString("EVAL_EXPRESSION %1 %2").arg(
|
|
||||||
QString::number(objectDebugId), expr));
|
|
||||||
quint32 queryId
|
|
||||||
= m_engineClient->queryExpressionResult(objectDebugId, expr);
|
|
||||||
|
|
||||||
if (m_adapter)
|
|
||||||
m_adapter.data()->disableJsDebugging(block);
|
|
||||||
return queryId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::clearComponentCache()
|
|
||||||
{
|
|
||||||
if (isConnected())
|
|
||||||
m_inspectorHelperClient->clearComponentCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClientProxy::addObjectWatch(int objectDebugId)
|
|
||||||
{
|
|
||||||
if (objectDebugId == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!isConnected())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// already set
|
|
||||||
if (m_objectWatches.contains(objectDebugId))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
QmlDebugObjectReference ref = objectReferenceForId(objectDebugId);
|
|
||||||
if (ref.debugId() != objectDebugId)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// is flooding the debugging output log!
|
|
||||||
// log(LogSend, QString("WATCH_PROPERTY %1").arg(objectDebugId));
|
|
||||||
|
|
||||||
if (m_engineClient->addWatch(ref))
|
|
||||||
m_objectWatches.append(objectDebugId);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClientProxy::isObjectBeingWatched(int objectDebugId)
|
|
||||||
{
|
|
||||||
return m_objectWatches.contains(objectDebugId);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ClientProxy::objectWatchTriggered(int objectDebugId,
|
|
||||||
const QByteArray &propertyName,
|
|
||||||
const QVariant &propertyValue)
|
|
||||||
{
|
|
||||||
if (m_objectWatches.contains(objectDebugId))
|
|
||||||
emit propertyChanged(objectDebugId, propertyName, propertyValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClientProxy::removeObjectWatch(int objectDebugId)
|
|
||||||
{
|
|
||||||
if (objectDebugId == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!m_objectWatches.contains(objectDebugId))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!isConnected())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_objectWatches.removeOne(objectDebugId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::removeAllObjectWatches()
|
|
||||||
{
|
|
||||||
foreach (int watchedObject, m_objectWatches)
|
|
||||||
removeObjectWatch(watchedObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::queryEngineContext(int id)
|
|
||||||
{
|
|
||||||
if (id < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!isConnected())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (m_contextQueryId)
|
|
||||||
m_contextQueryId = 0;
|
|
||||||
|
|
||||||
log(LogSend, QString("LIST_OBJECTS %1").arg(QString::number(id)));
|
|
||||||
|
|
||||||
m_contextQueryId
|
|
||||||
= m_engineClient->queryRootContexts(QmlDebugEngineReference(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::contextChanged(const QVariant &value)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (m_contextQueryId) {
|
|
||||||
m_contextQueryId = 0;
|
|
||||||
emit rootContext(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
quint32 ClientProxy::fetchContextObject(const QmlDebugObjectReference &obj)
|
|
||||||
{
|
|
||||||
if (!isConnected())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
log(LogSend, QString("FETCH_OBJECT %1").arg(obj.idString()));
|
|
||||||
return m_engineClient->queryObject(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::fetchRootObjects(
|
|
||||||
const QmlDebugContextReference &context, bool clear)
|
|
||||||
{
|
|
||||||
if (!isConnected())
|
|
||||||
return;
|
|
||||||
if (clear) {
|
|
||||||
m_rootObjects.clear();
|
|
||||||
m_objectTreeQueryIds.clear();
|
|
||||||
}
|
|
||||||
foreach (const QmlDebugObjectReference & obj, context.objects()) {
|
|
||||||
quint32 queryId = 0;
|
|
||||||
using namespace QmlDebug::Constants;
|
|
||||||
if (m_engineClient->objectName() == QML_DEBUGGER &&
|
|
||||||
m_engineClient->serviceVersion() >= CURRENT_SUPPORTED_VERSION) {
|
|
||||||
//Fetch only root objects
|
|
||||||
if (obj.parentId() == -1)
|
|
||||||
queryId = fetchContextObject(obj);
|
|
||||||
} else {
|
|
||||||
queryId = m_engineClient->queryObjectRecursive(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (queryId)
|
|
||||||
m_objectTreeQueryIds << queryId;
|
|
||||||
}
|
|
||||||
foreach (const QmlDebugContextReference &child, context.contexts()) {
|
|
||||||
fetchRootObjects(child, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::insertObjectInTreeIfNeeded(
|
|
||||||
const QmlDebugObjectReference &object)
|
|
||||||
{
|
|
||||||
if (!m_rootObjects.contains(object))
|
|
||||||
return;
|
|
||||||
int count = m_rootObjects.count();
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
if (m_rootObjects[i].parentId() < 0
|
|
||||||
&& m_rootObjects[i].insertObjectInTree(object)) {
|
|
||||||
m_rootObjects.removeOne(object);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::onResult(quint32 queryId, const QVariant &value,
|
|
||||||
const QByteArray &type)
|
|
||||||
{
|
|
||||||
if (type == "FETCH_OBJECT_R") {
|
|
||||||
log(LogReceive, QString("FETCH_OBJECT_R %1").arg(
|
|
||||||
qvariant_cast<QmlDebugObjectReference>(value).idString()));
|
|
||||||
} else {
|
|
||||||
log(LogReceive, QLatin1String(type));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_objectTreeQueryIds.contains(queryId))
|
|
||||||
objectTreeFetched(queryId, value);
|
|
||||||
else if (queryId == m_engineQueryId)
|
|
||||||
updateEngineList(value);
|
|
||||||
else if (queryId == m_contextQueryId)
|
|
||||||
contextChanged(value);
|
|
||||||
else if (m_fetchCurrentObjectsQueryIds.contains(queryId))
|
|
||||||
onCurrentObjectsFetched(queryId, value);
|
|
||||||
else
|
|
||||||
emit result(queryId, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::objectTreeFetched(quint32 queryId, const QVariant &result)
|
|
||||||
{
|
|
||||||
QmlDebugObjectReference obj
|
|
||||||
= qvariant_cast<QmlDebugObjectReference>(result);
|
|
||||||
m_rootObjects.append(obj);
|
|
||||||
|
|
||||||
m_objectTreeQueryIds.removeOne(queryId);
|
|
||||||
if (m_objectTreeQueryIds.isEmpty()) {
|
|
||||||
int old_count = m_debugIdHash.count();
|
|
||||||
m_debugIdHash.clear();
|
|
||||||
m_debugIdHash.reserve(old_count + 1);
|
|
||||||
foreach (const QmlDebugObjectReference &it, m_rootObjects)
|
|
||||||
buildDebugIdHashRecursive(it);
|
|
||||||
emit objectTreeUpdated();
|
|
||||||
|
|
||||||
if (isConnected()) {
|
|
||||||
if (!m_inspectorHelperClient->currentObjects().isEmpty())
|
|
||||||
onCurrentObjectsChanged(m_inspectorHelperClient->currentObjects(),
|
|
||||||
false);
|
|
||||||
|
|
||||||
m_inspectorHelperClient->setObjectIdList(m_rootObjects);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::buildDebugIdHashRecursive(const QmlDebugObjectReference &ref)
|
|
||||||
{
|
|
||||||
QUrl fileUrl = ref.source().url();
|
|
||||||
int lineNum = ref.source().lineNumber();
|
|
||||||
int colNum = ref.source().columnNumber();
|
|
||||||
int rev = 0;
|
|
||||||
|
|
||||||
// handle the case where the url contains the revision number encoded.
|
|
||||||
//(for object created by the debugger)
|
|
||||||
static QRegExp rx("(.*)_(\\d+):(\\d+)$");
|
|
||||||
if (rx.exactMatch(fileUrl.path())) {
|
|
||||||
fileUrl.setPath(rx.cap(1));
|
|
||||||
rev = rx.cap(2).toInt();
|
|
||||||
lineNum += rx.cap(3).toInt() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString filePath
|
|
||||||
= InspectorUi::instance()->findFileInProject(fileUrl);
|
|
||||||
|
|
||||||
// append the debug ids in the hash
|
|
||||||
m_debugIdHash[qMakePair<QString, int>(filePath, rev)][qMakePair<int, int>(
|
|
||||||
lineNum, colNum)].append(ref.debugId());
|
|
||||||
|
|
||||||
foreach (const QmlDebugObjectReference &it, ref.children())
|
|
||||||
buildDebugIdHashRecursive(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ClientProxy::reloadQmlViewer()
|
|
||||||
{
|
|
||||||
if (isConnected())
|
|
||||||
m_inspectorHelperClient->reloadViewer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::setDesignModeBehavior(bool inDesignMode)
|
|
||||||
{
|
|
||||||
if (isConnected())
|
|
||||||
m_inspectorHelperClient->setDesignModeBehavior(inDesignMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::setAnimationSpeed(qreal slowDownFactor)
|
|
||||||
{
|
|
||||||
if (isConnected())
|
|
||||||
m_inspectorHelperClient->setAnimationSpeed(slowDownFactor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::setAnimationPaused(bool paused)
|
|
||||||
{
|
|
||||||
if (isConnected())
|
|
||||||
m_inspectorHelperClient->setAnimationPaused(paused);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::changeToZoomTool()
|
|
||||||
{
|
|
||||||
if (isConnected())
|
|
||||||
m_inspectorHelperClient->changeToZoomTool();
|
|
||||||
}
|
|
||||||
void ClientProxy::changeToSelectTool()
|
|
||||||
{
|
|
||||||
if (isConnected())
|
|
||||||
m_inspectorHelperClient->changeToSelectTool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::changeToSelectMarqueeTool()
|
|
||||||
{
|
|
||||||
if (isConnected())
|
|
||||||
m_inspectorHelperClient->changeToSelectMarqueeTool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::showAppOnTop(bool showOnTop)
|
|
||||||
{
|
|
||||||
if (isConnected())
|
|
||||||
m_inspectorHelperClient->showAppOnTop(showOnTop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::createQmlObject(const QString &qmlText, int parentDebugId,
|
|
||||||
const QStringList &imports,
|
|
||||||
const QString &filename, int order)
|
|
||||||
{
|
|
||||||
if (isConnected())
|
|
||||||
m_inspectorHelperClient->createQmlObject(qmlText, parentDebugId, imports,
|
|
||||||
filename, order);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::destroyQmlObject(int debugId)
|
|
||||||
{
|
|
||||||
if (isConnected())
|
|
||||||
m_inspectorHelperClient->destroyQmlObject(debugId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::reparentQmlObject(int debugId, int newParent)
|
|
||||||
{
|
|
||||||
if (isConnected())
|
|
||||||
m_inspectorHelperClient->reparentQmlObject(debugId, newParent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::updateConnected()
|
|
||||||
{
|
|
||||||
bool isConnected = m_inspectorHelperClient &&
|
|
||||||
m_inspectorHelperClient->status() == QmlDebugClient::Enabled &&
|
|
||||||
m_engineClient &&
|
|
||||||
m_engineClient->status() == QmlDebugClient::Enabled;
|
|
||||||
|
|
||||||
if (isConnected != m_isConnected) {
|
|
||||||
m_isConnected = isConnected;
|
|
||||||
if (isConnected) {
|
|
||||||
emit connected();
|
|
||||||
reloadEngines();
|
|
||||||
} else {
|
|
||||||
emit disconnected();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::reloadEngines()
|
|
||||||
{
|
|
||||||
if (!isConnected())
|
|
||||||
return;
|
|
||||||
|
|
||||||
emit aboutToReloadEngines();
|
|
||||||
|
|
||||||
log(LogSend, QString("LIST_ENGINES"));
|
|
||||||
|
|
||||||
m_engineQueryId = m_engineClient->queryAvailableEngines();
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QmlDebugEngineReference> ClientProxy::engines() const
|
|
||||||
{
|
|
||||||
return m_engines;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::updateEngineList(const QVariant &value)
|
|
||||||
{
|
|
||||||
m_engines = qvariant_cast<QmlDebugEngineReferenceList>(value);
|
|
||||||
m_engineQueryId = 0;
|
|
||||||
emit enginesChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
Debugger::QmlAdapter *ClientProxy::qmlAdapter() const
|
|
||||||
{
|
|
||||||
return m_adapter.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClientProxy::isConnected() const
|
|
||||||
{
|
|
||||||
return m_isConnected;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientProxy::newObjects()
|
|
||||||
{
|
|
||||||
log(LogReceive, QString("OBJECT_CREATED"));
|
|
||||||
refreshObjectTree();
|
|
||||||
}
|
|
@@ -1,219 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
#ifndef QMLJSCLIENTPROXY_H
|
|
||||||
#define QMLJSCLIENTPROXY_H
|
|
||||||
|
|
||||||
#include "qmljsinspectorplugin.h"
|
|
||||||
#include <qmldebug/baseenginedebugclient.h>
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QUrl)
|
|
||||||
|
|
||||||
using namespace QmlDebug;
|
|
||||||
|
|
||||||
namespace Debugger {
|
|
||||||
class QmlAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
|
|
||||||
//map <filename, editorRevision> -> <lineNumber, columnNumber> -> debugIds
|
|
||||||
typedef
|
|
||||||
QHash<QPair<QString, int>, QHash<QPair<int, int>, QList<int> > > DebugIdHash;
|
|
||||||
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class InspectorPlugin;
|
|
||||||
class BaseToolsClient;
|
|
||||||
|
|
||||||
|
|
||||||
class ClientProxy : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ClientProxy(Debugger::QmlAdapter *adapter, QObject *parent = 0);
|
|
||||||
~ClientProxy();
|
|
||||||
|
|
||||||
quint32 setBindingForObject(int objectDebugId,
|
|
||||||
const QString &propertyName,
|
|
||||||
const QVariant &value,
|
|
||||||
bool isLiteralValue,
|
|
||||||
QString source,
|
|
||||||
int line);
|
|
||||||
|
|
||||||
quint32 setMethodBodyForObject(int objectDebugId, const QString &methodName,
|
|
||||||
const QString &methodBody);
|
|
||||||
quint32 resetBindingForObject(int objectDebugId,
|
|
||||||
const QString &propertyName);
|
|
||||||
quint32 queryExpressionResult(int objectDebugId, const QString &expr);
|
|
||||||
void clearComponentCache();
|
|
||||||
|
|
||||||
bool addObjectWatch(int objectDebugId);
|
|
||||||
bool isObjectBeingWatched(int objectDebugId);
|
|
||||||
bool removeObjectWatch(int objectDebugId);
|
|
||||||
void removeAllObjectWatches();
|
|
||||||
|
|
||||||
// returns the object references
|
|
||||||
QList<QmlDebugObjectReference> objectReferences() const;
|
|
||||||
QmlDebugObjectReference objectReferenceForId(int debugId) const;
|
|
||||||
QmlDebugObjectReference objectReferenceForId(const QString &objectId) const;
|
|
||||||
QmlDebugObjectReference objectReferenceForLocation(int line,
|
|
||||||
int column) const;
|
|
||||||
QList<QmlDebugObjectReference> rootObjectReference() const;
|
|
||||||
DebugIdHash debugIdHash() const { return m_debugIdHash; }
|
|
||||||
|
|
||||||
bool isConnected() const;
|
|
||||||
|
|
||||||
void setSelectedItemsByDebugId(const QList<int> &debugIds);
|
|
||||||
void setSelectedItemsByObjectId(
|
|
||||||
const QList<QmlDebugObjectReference> &objectRefs);
|
|
||||||
|
|
||||||
QList<QmlDebugEngineReference> engines() const;
|
|
||||||
|
|
||||||
Debugger::QmlAdapter *qmlAdapter() const;
|
|
||||||
|
|
||||||
quint32 fetchContextObject(const QmlDebugObjectReference& obj);
|
|
||||||
void addObjectToTree(const QmlDebugObjectReference &obj, bool notify = true);
|
|
||||||
void fetchRootObjects(const QmlDebugContextReference &context, bool clear);
|
|
||||||
void insertObjectInTreeIfNeeded(const QmlDebugObjectReference &object);
|
|
||||||
|
|
||||||
QmlDebugClient *engineDebugClient() const;
|
|
||||||
QmlDebugClient *toolsClient() const;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void objectTreeUpdated();
|
|
||||||
void connectionStatusMessage(const QString &text);
|
|
||||||
|
|
||||||
void aboutToReloadEngines();
|
|
||||||
void enginesChanged();
|
|
||||||
|
|
||||||
void selectedItemsChanged(
|
|
||||||
const QList<QmlDebugObjectReference> &selectedItems);
|
|
||||||
|
|
||||||
void connected();
|
|
||||||
void disconnected();
|
|
||||||
|
|
||||||
void selectToolActivated();
|
|
||||||
void selectMarqueeToolActivated();
|
|
||||||
void zoomToolActivated();
|
|
||||||
void animationSpeedChanged(qreal slowDownFactor);
|
|
||||||
void animationPausedChanged(bool paused);
|
|
||||||
void designModeBehaviorChanged(bool inDesignMode);
|
|
||||||
void showAppOnTopChanged(bool showAppOnTop);
|
|
||||||
void serverReloaded();
|
|
||||||
void propertyChanged(int debugId, const QByteArray &propertyName,
|
|
||||||
const QVariant &propertyValue);
|
|
||||||
|
|
||||||
void result(quint32 queryId, const QVariant &result);
|
|
||||||
void rootContext(const QVariant &context);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void refreshObjectTree();
|
|
||||||
void queryEngineContext(int id);
|
|
||||||
void reloadQmlViewer();
|
|
||||||
|
|
||||||
void setDesignModeBehavior(bool inDesignMode);
|
|
||||||
void setAnimationSpeed(qreal slowDownFactor);
|
|
||||||
void setAnimationPaused(bool paused);
|
|
||||||
void changeToZoomTool();
|
|
||||||
void changeToSelectTool();
|
|
||||||
void changeToSelectMarqueeTool();
|
|
||||||
void showAppOnTop(bool showOnTop);
|
|
||||||
void createQmlObject(const QString &qmlText, int parentDebugId,
|
|
||||||
const QStringList &imports,
|
|
||||||
const QString &filename = QString(), int order = 0);
|
|
||||||
void destroyQmlObject(int debugId);
|
|
||||||
void reparentQmlObject(int debugId, int newParent);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void connectToServer();
|
|
||||||
void clientStatusChanged(QmlDebugClient::Status status);
|
|
||||||
void engineClientStatusChanged(QmlDebugClient::Status status);
|
|
||||||
void toolsClientStatusChanged(QmlDebugClient::Status status);
|
|
||||||
|
|
||||||
void onCurrentObjectsChanged(const QList<int> &debugIds,
|
|
||||||
bool requestIfNeeded = true);
|
|
||||||
void newObjects();
|
|
||||||
void objectWatchTriggered(int debugId, const QByteArray &propertyName,
|
|
||||||
const QVariant &propertyValue);
|
|
||||||
void onResult(quint32 queryId, const QVariant &value,
|
|
||||||
const QByteArray &type);
|
|
||||||
void onCurrentObjectsFetched(quint32 queryId, const QVariant &result);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void contextChanged(const QVariant &value);
|
|
||||||
void updateEngineList(const QVariant &value);
|
|
||||||
void objectTreeFetched(quint32 queryId, const QVariant &result);
|
|
||||||
void updateConnected();
|
|
||||||
void reloadEngines();
|
|
||||||
bool getObjectHierarchy(const QmlDebugObjectReference &obj);
|
|
||||||
|
|
||||||
QList<QmlDebugObjectReference> objectReferences(
|
|
||||||
const QmlDebugObjectReference &objectRef) const;
|
|
||||||
QmlDebugObjectReference objectReferenceForId(
|
|
||||||
int debugId,
|
|
||||||
const QmlDebugObjectReference &ref) const;
|
|
||||||
|
|
||||||
enum LogDirection {
|
|
||||||
LogSend,
|
|
||||||
LogReceive
|
|
||||||
};
|
|
||||||
void log(LogDirection direction, const QString &message);
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
void buildDebugIdHashRecursive(const QmlDebugObjectReference &ref);
|
|
||||||
|
|
||||||
QWeakPointer<Debugger::QmlAdapter> m_adapter;
|
|
||||||
BaseEngineDebugClient *m_engineClient;
|
|
||||||
BaseToolsClient *m_inspectorHelperClient;
|
|
||||||
|
|
||||||
quint32 m_engineQueryId;
|
|
||||||
quint32 m_contextQueryId;
|
|
||||||
QList<quint32> m_objectTreeQueryIds;
|
|
||||||
QList<quint32> m_fetchCurrentObjectsQueryIds;
|
|
||||||
|
|
||||||
QList<QmlDebugObjectReference> m_rootObjects;
|
|
||||||
QList<QmlDebugObjectReference> m_fetchCurrentObjects;
|
|
||||||
QmlDebugEngineReferenceList m_engines;
|
|
||||||
DebugIdHash m_debugIdHash;
|
|
||||||
|
|
||||||
QList<int> m_objectWatches;
|
|
||||||
|
|
||||||
bool m_isConnected;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace QmlJSInspector
|
|
||||||
|
|
||||||
#endif // QMLJSCLIENTPROXY_H
|
|
@@ -1,91 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
#include "qmljscontextcrumblepath.h"
|
|
||||||
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
ContextCrumblePath::ContextCrumblePath(QWidget *parent)
|
|
||||||
: CrumblePath(parent)
|
|
||||||
, m_isEmpty(true)
|
|
||||||
{
|
|
||||||
updateContextPath(QStringList(), QList<int>());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ContextCrumblePath::updateContextPath(const QStringList &path,
|
|
||||||
const QList<int> &debugIds)
|
|
||||||
{
|
|
||||||
Q_ASSERT(path.count() == debugIds.count());
|
|
||||||
|
|
||||||
CrumblePath::clear();
|
|
||||||
|
|
||||||
m_isEmpty = path.isEmpty();
|
|
||||||
if (m_isEmpty) {
|
|
||||||
pushElement(tr("[no context]"), -2);
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < path.count(); i++)
|
|
||||||
pushElement(path[i], debugIds[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ContextCrumblePath::addChildren(const QStringList &childrenNames,
|
|
||||||
const QList<int> &childrenDebugIds)
|
|
||||||
{
|
|
||||||
Q_ASSERT(childrenNames.count() == childrenDebugIds.count());
|
|
||||||
for (int i = 0; i < childrenNames.count(); i++)
|
|
||||||
addChild(childrenNames[i], childrenDebugIds[i]);
|
|
||||||
|
|
||||||
//Sort them alphabetically
|
|
||||||
if (childrenDebugIds.count())
|
|
||||||
sortChildren();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ContextCrumblePath::clear()
|
|
||||||
{
|
|
||||||
updateContextPath(QStringList(), QList<int>());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ContextCrumblePath::isEmpty() const
|
|
||||||
{
|
|
||||||
return m_isEmpty;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ContextCrumblePath::debugIdForIndex(int index) const
|
|
||||||
{
|
|
||||||
return CrumblePath::dataForIndex(index).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace QmlJSInspector
|
|
@@ -1,64 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
#ifndef QMLJSCONTEXTCRUMBLEPATH_H
|
|
||||||
#define QMLJSCONTEXTCRUMBLEPATH_H
|
|
||||||
|
|
||||||
#include <utils/crumblepath.h>
|
|
||||||
#include <QStringList>
|
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class ContextCrumblePath : public Utils::CrumblePath
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
ContextCrumblePath(QWidget *parent = 0);
|
|
||||||
|
|
||||||
bool isEmpty() const;
|
|
||||||
int debugIdForIndex(int index) const;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void updateContextPath(const QStringList &path, const QList<int> &debugIds);
|
|
||||||
void addChildren(const QStringList &childrenNames,
|
|
||||||
const QList<int> &childrenDebugIds);
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_isEmpty;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace QmlJSInspector
|
|
||||||
|
|
||||||
#endif // QMLJSCONTEXTCRUMBLEPATH_H
|
|
@@ -1,192 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QMLJSINSPECTOR_H
|
|
||||||
#define QMLJSINSPECTOR_H
|
|
||||||
|
|
||||||
#include <coreplugin/editormanager/ieditor.h>
|
|
||||||
#include <utils/fileinprojectfinder.h>
|
|
||||||
|
|
||||||
#include <qmldebug/baseenginedebugclient.h>
|
|
||||||
|
|
||||||
#include <qmljs/qmljsdocument.h>
|
|
||||||
#include <qmljs/parser/qmljsastfwd_p.h>
|
|
||||||
|
|
||||||
#include <debugger/debuggerconstants.h>
|
|
||||||
|
|
||||||
#include <QAction>
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
using namespace QmlDebug;
|
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
|
||||||
class Project;
|
|
||||||
class Environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace TextEditor {
|
|
||||||
class ITextEditor;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class IContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace QmlJS {
|
|
||||||
class ModelManagerInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class QmlJsInspectorToolBar;
|
|
||||||
class QmlJSPropertyInspector;
|
|
||||||
class ClientProxy;
|
|
||||||
class InspectorSettings;
|
|
||||||
class ContextCrumblePath;
|
|
||||||
class QmlJSLiveTextPreview;
|
|
||||||
|
|
||||||
class InspectorUi : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum DebugMode {
|
|
||||||
StandaloneMode,
|
|
||||||
CppProjectWithQmlEngines,
|
|
||||||
QmlProjectWithCppPlugins
|
|
||||||
};
|
|
||||||
|
|
||||||
InspectorUi(QObject *parent = 0);
|
|
||||||
virtual ~InspectorUi();
|
|
||||||
|
|
||||||
void saveSettings() const;
|
|
||||||
void restoreSettings();
|
|
||||||
|
|
||||||
bool showExperimentalWarning();
|
|
||||||
void setShowExperimentalWarning(bool value);
|
|
||||||
|
|
||||||
static InspectorUi *instance();
|
|
||||||
|
|
||||||
QString findFileInProject(const QUrl &fileUrl) const;
|
|
||||||
|
|
||||||
void setupUi();
|
|
||||||
bool isConnected() const;
|
|
||||||
void connected(ClientProxy *clientProxy);
|
|
||||||
void disconnected();
|
|
||||||
void setDebuggerEngine(QObject *qmlEngine);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void statusMessage(const QString &text);
|
|
||||||
void livePreviewActivated(bool isActivated);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void reloadQmlViewer();
|
|
||||||
void serverReloaded();
|
|
||||||
void setApplyChangesToQmlInspector(bool applyChanges);
|
|
||||||
void onResult(quint32 queryId, const QVariant &result);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void enable();
|
|
||||||
void disable();
|
|
||||||
void gotoObjectReferenceDefinition(const QmlDebugObjectReference &obj);
|
|
||||||
void selectItems(const QList<QmlDebugObjectReference> &objectReferences);
|
|
||||||
void selectItems(const QList<int> &objectIds);
|
|
||||||
void changeSelectedItems(const QList<QmlDebugObjectReference> &objects);
|
|
||||||
void changePropertyValue(int debugId,const QString &propertyName,
|
|
||||||
const QString &valueExpression, bool isLiteral);
|
|
||||||
void objectTreeReady();
|
|
||||||
void onRootContext(const QVariant &value);
|
|
||||||
|
|
||||||
void updateEngineList();
|
|
||||||
|
|
||||||
void removePreviewForEditor(Core::IEditor *newEditor);
|
|
||||||
QmlJSLiveTextPreview *createPreviewForEditor(Core::IEditor *newEditor);
|
|
||||||
|
|
||||||
void disableLivePreview();
|
|
||||||
void crumblePathElementClicked(const QVariant &data);
|
|
||||||
|
|
||||||
void updatePendingPreviewDocuments(QmlJS::Document::Ptr doc);
|
|
||||||
void showDebuggerTooltip(const QPoint &mousePos,
|
|
||||||
TextEditor::ITextEditor *editor, int cursorPos);
|
|
||||||
void onEngineStateChanged(Debugger::DebuggerState state);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void showRoot();
|
|
||||||
void resetViews();
|
|
||||||
|
|
||||||
void initializeDocuments();
|
|
||||||
void applyChangesToQmlInspectorHelper(bool applyChanges);
|
|
||||||
void setupDockWidgets();
|
|
||||||
QString filenameForShadowBuildFile(const QString &filename) const;
|
|
||||||
void populateCrumblePath(const QmlDebugObjectReference &objRef);
|
|
||||||
bool isRoot(const QmlDebugObjectReference &obj) const;
|
|
||||||
QmlDebugObjectReference objectReferenceForLocation(
|
|
||||||
const QString &fileName, int cursorPosition = -1) const;
|
|
||||||
|
|
||||||
void connectSignals();
|
|
||||||
void disconnectSignals();
|
|
||||||
|
|
||||||
void showObject(const QmlDebugObjectReference &obj);
|
|
||||||
|
|
||||||
QmlDebugObjectReference findParentRecursive(
|
|
||||||
int goalDebugId,
|
|
||||||
const QList<QmlDebugObjectReference > &objectsToSearch);
|
|
||||||
private:
|
|
||||||
bool m_listeningToEditorManager;
|
|
||||||
QmlJsInspectorToolBar *m_toolBar;
|
|
||||||
ContextCrumblePath *m_crumblePath;
|
|
||||||
QmlJSPropertyInspector *m_propertyInspector;
|
|
||||||
|
|
||||||
InspectorSettings *m_settings;
|
|
||||||
ClientProxy *m_clientProxy;
|
|
||||||
quint32 m_debugQuery;
|
|
||||||
quint32 m_showObjectQueryId;
|
|
||||||
QList<quint32> m_updateObjectQueryIds;
|
|
||||||
|
|
||||||
// Qml/JS integration
|
|
||||||
QHash<QString, QmlJSLiveTextPreview *> m_textPreviews;
|
|
||||||
QmlJS::Snapshot m_loadedSnapshot; //the snapshot loaded by the viewer
|
|
||||||
|
|
||||||
QStringList m_pendingPreviewDocumentNames;
|
|
||||||
Utils::FileInProjectFinder m_projectFinder;
|
|
||||||
|
|
||||||
static InspectorUi *m_instance;
|
|
||||||
bool m_selectionCallbackExpected;
|
|
||||||
bool m_cursorPositionChangedExternally;
|
|
||||||
bool m_onCrumblePathClicked;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // Internal
|
|
||||||
} // QmlJSInspector
|
|
||||||
|
|
||||||
#endif // QMLJSINSPECTOR_H
|
|
@@ -1,51 +0,0 @@
|
|||||||
TEMPLATE = lib
|
|
||||||
TARGET = QmlJSInspector
|
|
||||||
INCLUDEPATH += .
|
|
||||||
DEPENDPATH += .
|
|
||||||
QT += network
|
|
||||||
greaterThan(QT_MAJOR_VERSION, 4) {
|
|
||||||
QT += quick1
|
|
||||||
} else {
|
|
||||||
QT += declarative
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINES += QMLJSINSPECTOR_LIBRARY
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
qmljsinspector_global.h \
|
|
||||||
qmljsinspectorconstants.h \
|
|
||||||
qmljsinspectorplugin.h \
|
|
||||||
qmljsclientproxy.h \
|
|
||||||
qmljsinspector.h \
|
|
||||||
qmljsinspectortoolbar.h \
|
|
||||||
qmljslivetextpreview.h \
|
|
||||||
basetoolsclient.h \
|
|
||||||
qmljscontextcrumblepath.h \
|
|
||||||
qmljsinspectorsettings.h \
|
|
||||||
qmljspropertyinspector.h \
|
|
||||||
declarativetoolsclient.h \
|
|
||||||
qmltoolsclient.h
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
qmljsinspectorplugin.cpp \
|
|
||||||
qmljsclientproxy.cpp \
|
|
||||||
qmljsinspector.cpp \
|
|
||||||
qmljsinspectortoolbar.cpp \
|
|
||||||
qmljslivetextpreview.cpp \
|
|
||||||
basetoolsclient.cpp \
|
|
||||||
qmljscontextcrumblepath.cpp \
|
|
||||||
qmljsinspectorsettings.cpp \
|
|
||||||
qmljspropertyinspector.cpp \
|
|
||||||
declarativetoolsclient.cpp \
|
|
||||||
qmltoolsclient.cpp
|
|
||||||
|
|
||||||
include(../../../share/qtcreator/qml/qmljsdebugger/protocol/protocol.pri)
|
|
||||||
|
|
||||||
RESOURCES += qmljsinspector.qrc
|
|
||||||
|
|
||||||
include(../../qtcreatorplugin.pri)
|
|
||||||
include(../../libs/qmldebug/qmldebug.pri)
|
|
||||||
include(../../libs/qmleditorwidgets/qmleditorwidgets.pri)
|
|
||||||
|
|
||||||
include(../../plugins/debugger/debugger.pri)
|
|
||||||
include(../../plugins/qmljstools/qmljstools.pri)
|
|
@@ -1,59 +0,0 @@
|
|||||||
import qbs.base 1.0
|
|
||||||
|
|
||||||
import "../QtcPlugin.qbs" as QtcPlugin
|
|
||||||
|
|
||||||
QtcPlugin {
|
|
||||||
name: "QmlJSInspector"
|
|
||||||
|
|
||||||
Depends { name: "qt"; submodules: ['widgets', 'quick1'] }
|
|
||||||
Depends { name: "Core" }
|
|
||||||
Depends { name: "Debugger" }
|
|
||||||
Depends { name: "LanguageUtils" }
|
|
||||||
Depends { name: "TextEditor" }
|
|
||||||
Depends { name: "QmlJS" }
|
|
||||||
Depends { name: "QmlJSTools" }
|
|
||||||
Depends { name: "QmlEditorWidgets" }
|
|
||||||
Depends { name: "QmlDebug" }
|
|
||||||
|
|
||||||
|
|
||||||
Depends { name: "cpp" }
|
|
||||||
cpp.includePaths: [
|
|
||||||
".",
|
|
||||||
"../../libs/qmleditorwidgets",
|
|
||||||
"../../../share/qtcreator/qml/qmljsdebugger/protocol",
|
|
||||||
"../../shared/symbianutils",
|
|
||||||
"..",
|
|
||||||
"../../libs",
|
|
||||||
buildDirectory
|
|
||||||
]
|
|
||||||
|
|
||||||
files: [
|
|
||||||
"basetoolsclient.h",
|
|
||||||
"declarativetoolsclient.h",
|
|
||||||
"qmljsinspector_global.h",
|
|
||||||
"qmljsinspectorconstants.h",
|
|
||||||
"qmljsinspectorplugin.h",
|
|
||||||
"qmljsclientproxy.h",
|
|
||||||
"qmljsinspector.h",
|
|
||||||
"qmljsinspectortoolbar.h",
|
|
||||||
"qmljslivetextpreview.h",
|
|
||||||
"qmltoolsclient.h",
|
|
||||||
"qmljscontextcrumblepath.h",
|
|
||||||
"qmljsinspectorsettings.h",
|
|
||||||
"qmljspropertyinspector.h",
|
|
||||||
"../../../share/qtcreator/qml/qmljsdebugger/protocol/inspectorprotocol.h",
|
|
||||||
"basetoolsclient.cpp",
|
|
||||||
"declarativetoolsclient.cpp",
|
|
||||||
"qmljsinspectorplugin.cpp",
|
|
||||||
"qmljsclientproxy.cpp",
|
|
||||||
"qmljsinspector.cpp",
|
|
||||||
"qmljsinspectortoolbar.cpp",
|
|
||||||
"qmljslivetextpreview.cpp",
|
|
||||||
"qmltoolsclient.cpp",
|
|
||||||
"qmljscontextcrumblepath.cpp",
|
|
||||||
"qmljsinspectorsettings.cpp",
|
|
||||||
"qmljspropertyinspector.cpp",
|
|
||||||
"qmljsinspector.qrc",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@@ -1,20 +0,0 @@
|
|||||||
<RCC>
|
|
||||||
<qresource prefix="/qml">
|
|
||||||
<file>images/from-qml.png</file>
|
|
||||||
<file>images/pause.png</file>
|
|
||||||
<file>images/reload.png</file>
|
|
||||||
<file>images/play.png</file>
|
|
||||||
<file>images/select.png</file>
|
|
||||||
<file>images/to-qml.png</file>
|
|
||||||
<file>images/select-marquee.png</file>
|
|
||||||
<file>images/zoom.png</file>
|
|
||||||
<file>images/select-small.png</file>
|
|
||||||
<file>images/play-small.png</file>
|
|
||||||
<file>images/to-qml-small.png</file>
|
|
||||||
<file>images/pause-small.png</file>
|
|
||||||
<file>images/from-qml-small.png</file>
|
|
||||||
<file>images/zoom-small.png</file>
|
|
||||||
<file>images/select-marquee-small.png</file>
|
|
||||||
<file>images/app-on-top.png</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
@@ -1,43 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
#ifndef QMLINSPECTOR_GLOBAL_H
|
|
||||||
#define QMLINSPECTOR_GLOBAL_H
|
|
||||||
|
|
||||||
#include <QtGlobal>
|
|
||||||
|
|
||||||
#if defined(QMLJSINSPECTOR_LIBRARY)
|
|
||||||
# define QMLINSPECTOR_EXPORT Q_DECL_EXPORT
|
|
||||||
#else
|
|
||||||
# define QMLINSPECTOR_EXPORT Q_DECL_IMPORT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // QMLINSPECTOR_GLOBAL_H
|
|
@@ -1,69 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QMLJSINSPECTORCONSTANTS_H
|
|
||||||
#define QMLJSINSPECTORCONSTANTS_H
|
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
namespace Constants {
|
|
||||||
|
|
||||||
const char INFO_EXPERIMENTAL[] = "QmlInspector.Experimental";
|
|
||||||
const char INFO_OUT_OF_SYNC[] = "QmlInspector.OutOfSyncWarning";
|
|
||||||
|
|
||||||
const char PLAY_ACTION[] = "QmlInspector.Play";
|
|
||||||
const char SELECT_ACTION[] = "QmlInspector.Select";
|
|
||||||
const char ZOOM_ACTION[] = "QmlInspector.Zoom";
|
|
||||||
const char FROM_QML_ACTION[] = "QmlInspector.FromQml";
|
|
||||||
const char SHOW_APP_ON_TOP_ACTION[] = "QmlInspector.ShowAppOnTop";
|
|
||||||
|
|
||||||
// Settings
|
|
||||||
const char S_QML_INSPECTOR [] = "QML.Inspector";
|
|
||||||
const char S_LIVE_PREVIEW_WARNING_KEY[] = "ShowLivePreview";
|
|
||||||
|
|
||||||
const char ALWAYS_ADJUST_COLUMNS_WIDTHS[] = "AlwaysAdjustColumnWidths";
|
|
||||||
|
|
||||||
const char QML_INSPECTOR[] = "QmlInspector";
|
|
||||||
const char QDECLARATIVE_OBSERVER_MODE[] = "QDeclarativeObserverMode";
|
|
||||||
|
|
||||||
enum DesignTool {
|
|
||||||
NoTool = 0,
|
|
||||||
SelectionToolMode = 1,
|
|
||||||
MarqueeSelectionToolMode = 2,
|
|
||||||
MoveToolMode = 3,
|
|
||||||
ResizeToolMode = 4,
|
|
||||||
ZoomMode = 6
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Constants
|
|
||||||
} // namespace QmlJSInspector
|
|
||||||
|
|
||||||
#endif // QMLJSINSPECTORCONSTANTS_H
|
|
@@ -1,153 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#include "qmljsinspectorplugin.h"
|
|
||||||
|
|
||||||
#include "qmljsclientproxy.h"
|
|
||||||
#include "qmljsinspector.h"
|
|
||||||
#include "qmljsinspectorconstants.h"
|
|
||||||
#include "qmljsinspectortoolbar.h"
|
|
||||||
|
|
||||||
#include <coreplugin/coreconstants.h>
|
|
||||||
#include <coreplugin/icontext.h>
|
|
||||||
#include <coreplugin/icore.h>
|
|
||||||
#include <coreplugin/imode.h>
|
|
||||||
#include <coreplugin/modemanager.h>
|
|
||||||
#include <debugger/debuggerconstants.h>
|
|
||||||
#include <debugger/qml/qmladapter.h>
|
|
||||||
#include <extensionsystem/pluginmanager.h>
|
|
||||||
#include <utils/qtcassert.h>
|
|
||||||
|
|
||||||
#include <QStringList>
|
|
||||||
#include <QtPlugin>
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QToolButton>
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
using namespace QmlJSInspector::Internal;
|
|
||||||
using namespace QmlJSInspector::Constants;
|
|
||||||
|
|
||||||
InspectorPlugin::InspectorPlugin()
|
|
||||||
: IPlugin()
|
|
||||||
, m_clientProxy(0)
|
|
||||||
{
|
|
||||||
m_inspectorUi = new InspectorUi(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
InspectorPlugin::~InspectorPlugin()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
InspectorUi *InspectorPlugin::inspector() const
|
|
||||||
{
|
|
||||||
return m_inspectorUi;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExtensionSystem::IPlugin::ShutdownFlag InspectorPlugin::aboutToShutdown()
|
|
||||||
{
|
|
||||||
m_inspectorUi->saveSettings();
|
|
||||||
return SynchronousShutdown;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InspectorPlugin::initialize(const QStringList &arguments,
|
|
||||||
QString *errorString)
|
|
||||||
{
|
|
||||||
Q_UNUSED(arguments);
|
|
||||||
Q_UNUSED(errorString);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InspectorPlugin::extensionsInitialized()
|
|
||||||
{
|
|
||||||
ExtensionSystem::PluginManager *pluginManager
|
|
||||||
= ExtensionSystem::PluginManager::instance();
|
|
||||||
|
|
||||||
connect(pluginManager, SIGNAL(objectAdded(QObject*)),
|
|
||||||
SLOT(objectAdded(QObject*)));
|
|
||||||
connect(Core::ModeManager::instance(),
|
|
||||||
SIGNAL(currentModeAboutToChange(Core::IMode*)),
|
|
||||||
this, SLOT(modeAboutToChange(Core::IMode*)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void InspectorPlugin::objectAdded(QObject *object)
|
|
||||||
{
|
|
||||||
Debugger::QmlAdapter *adapter = qobject_cast<Debugger::QmlAdapter *>(object);
|
|
||||||
if (adapter) {
|
|
||||||
//Disconnect inspector plugin when qml adapter emits disconnected
|
|
||||||
connect(adapter, SIGNAL(disconnected()), this, SLOT(disconnect()));
|
|
||||||
m_clientProxy = new ClientProxy(adapter);
|
|
||||||
if (m_clientProxy->isConnected()) {
|
|
||||||
clientProxyConnected();
|
|
||||||
} else {
|
|
||||||
connect(m_clientProxy, SIGNAL(connected()),
|
|
||||||
this, SLOT(clientProxyConnected()));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (object->objectName() == QLatin1String("QmlEngine"))
|
|
||||||
m_inspectorUi->setDebuggerEngine(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InspectorPlugin::disconnect()
|
|
||||||
{
|
|
||||||
if (m_inspectorUi->isConnected()) {
|
|
||||||
m_inspectorUi->disconnected();
|
|
||||||
delete m_clientProxy;
|
|
||||||
m_clientProxy = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InspectorPlugin::clientProxyConnected()
|
|
||||||
{
|
|
||||||
m_inspectorUi->connected(m_clientProxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InspectorPlugin::modeAboutToChange(Core::IMode *newMode)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(newMode, return);
|
|
||||||
|
|
||||||
if (newMode->id() == Debugger::Constants::MODE_DEBUG) {
|
|
||||||
m_inspectorUi->setupUi();
|
|
||||||
|
|
||||||
// Make sure we're not called again.
|
|
||||||
QObject::disconnect(Core::ModeManager::instance(),
|
|
||||||
SIGNAL(currentModeAboutToChange(Core::IMode*)),
|
|
||||||
this, SLOT(modeAboutToChange(Core::IMode*)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_EXPORT_PLUGIN(InspectorPlugin)
|
|
@@ -1,88 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
#ifndef QMLJSINSPECTORPLUGIN_H
|
|
||||||
#define QMLJSINSPECTORPLUGIN_H
|
|
||||||
|
|
||||||
#include <extensionsystem/iplugin.h>
|
|
||||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QPointer>
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class IMode;
|
|
||||||
} // namespace Core
|
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class ClientProxy;
|
|
||||||
class InspectorUi;
|
|
||||||
|
|
||||||
class InspectorPlugin : public ExtensionSystem::IPlugin
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin"
|
|
||||||
FILE "QmlJSInspector.json")
|
|
||||||
|
|
||||||
public:
|
|
||||||
InspectorPlugin();
|
|
||||||
virtual ~InspectorPlugin();
|
|
||||||
|
|
||||||
//static InspectorPlugin *instance();
|
|
||||||
|
|
||||||
InspectorUi *inspector() const;
|
|
||||||
|
|
||||||
// ExtensionSystem::IPlugin interface
|
|
||||||
virtual bool initialize(const QStringList &arguments, QString *errorString);
|
|
||||||
virtual void extensionsInitialized();
|
|
||||||
virtual ExtensionSystem::IPlugin::ShutdownFlag aboutToShutdown();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void objectAdded(QObject *object);
|
|
||||||
void disconnect();
|
|
||||||
void clientProxyConnected();
|
|
||||||
void modeAboutToChange(Core::IMode *mode);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void createActions();
|
|
||||||
|
|
||||||
private:
|
|
||||||
ClientProxy *m_clientProxy;
|
|
||||||
InspectorUi *m_inspectorUi;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace QmlJSInspector
|
|
||||||
|
|
||||||
#endif // QMLINSPECTORPLUGIN_H
|
|
@@ -1,76 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#include "qmljsinspectorsettings.h"
|
|
||||||
#include "qmljsinspectorconstants.h"
|
|
||||||
#include <QSettings>
|
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
using namespace QmlJSInspector::Constants;
|
|
||||||
|
|
||||||
InspectorSettings::InspectorSettings(QObject *parent)
|
|
||||||
: QObject(parent),
|
|
||||||
m_showLivePreviewWarning(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void InspectorSettings::restoreSettings(QSettings *settings)
|
|
||||||
{
|
|
||||||
settings->beginGroup(QLatin1String(S_QML_INSPECTOR));
|
|
||||||
m_showLivePreviewWarning
|
|
||||||
= settings->value(QLatin1String(S_LIVE_PREVIEW_WARNING_KEY),
|
|
||||||
true).toBool();
|
|
||||||
settings->endGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InspectorSettings::saveSettings(QSettings *settings) const
|
|
||||||
{
|
|
||||||
settings->beginGroup(QLatin1String(S_QML_INSPECTOR));
|
|
||||||
settings->setValue(QLatin1String(S_LIVE_PREVIEW_WARNING_KEY),
|
|
||||||
m_showLivePreviewWarning);
|
|
||||||
settings->endGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InspectorSettings::showLivePreviewWarning() const
|
|
||||||
{
|
|
||||||
return m_showLivePreviewWarning;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InspectorSettings::setShowLivePreviewWarning(bool value)
|
|
||||||
{
|
|
||||||
m_showLivePreviewWarning = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace QmlJSInspector
|
|
@@ -1,63 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#ifndef INSPECTORSETTINGS_H
|
|
||||||
#define INSPECTORSETTINGS_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QSettings)
|
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class InspectorSettings : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
InspectorSettings(QObject *parent = 0);
|
|
||||||
|
|
||||||
void restoreSettings(QSettings *settings);
|
|
||||||
void saveSettings(QSettings *settings) const;
|
|
||||||
|
|
||||||
bool showLivePreviewWarning() const;
|
|
||||||
void setShowLivePreviewWarning(bool value);
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_showLivePreviewWarning;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace QmlJSInspector
|
|
||||||
|
|
||||||
#endif // INSPECTORSETTINGS_H
|
|
@@ -1,373 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#include "qmljsinspectortoolbar.h"
|
|
||||||
|
|
||||||
#include "qmljsinspectorconstants.h"
|
|
||||||
|
|
||||||
#include <coreplugin/actionmanager/actionmanager.h>
|
|
||||||
#include <coreplugin/actionmanager/command.h>
|
|
||||||
#include <coreplugin/id.h>
|
|
||||||
#include <coreplugin/icore.h>
|
|
||||||
#include <debugger/debuggerconstants.h>
|
|
||||||
#include <debugger/debuggermainwindow.h>
|
|
||||||
#include <debugger/debuggerplugin.h>
|
|
||||||
#include <extensionsystem/pluginmanager.h>
|
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
|
||||||
|
|
||||||
#include <utils/styledbar.h>
|
|
||||||
#include <utils/savedaction.h>
|
|
||||||
|
|
||||||
#include <QAction>
|
|
||||||
#include <QActionGroup>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QToolButton>
|
|
||||||
#include <QLineEdit>
|
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
static QToolButton *toolButton(QAction *action)
|
|
||||||
{
|
|
||||||
QToolButton *button = new QToolButton;
|
|
||||||
button->setDefaultAction(action);
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlJsInspectorToolBar::QmlJsInspectorToolBar(QObject *parent) :
|
|
||||||
QObject(parent),
|
|
||||||
m_fromQmlAction(0),
|
|
||||||
m_playAction(0),
|
|
||||||
m_selectAction(0),
|
|
||||||
m_zoomAction(0),
|
|
||||||
m_showAppOnTopAction(0),
|
|
||||||
m_playSpeedMenuActions(0),
|
|
||||||
m_playIcon(QIcon(QLatin1String(":/qml/images/play-small.png"))),
|
|
||||||
m_pauseIcon(QIcon(QLatin1String(":/qml/images/pause-small.png"))),
|
|
||||||
m_emitSignals(true),
|
|
||||||
m_paused(false),
|
|
||||||
m_animationSpeed(1.0f),
|
|
||||||
m_designModeActive(false),
|
|
||||||
m_activeTool(NoTool),
|
|
||||||
m_barWidget(0),
|
|
||||||
m_zoomActionEnable(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::setEnabled(bool value)
|
|
||||||
{
|
|
||||||
m_fromQmlAction->setEnabled(value);
|
|
||||||
m_showAppOnTopAction->setEnabled(value);
|
|
||||||
m_playAction->setEnabled(value);
|
|
||||||
m_selectAction->setEnabled(value);
|
|
||||||
m_zoomAction->setEnabled(value && m_zoomActionEnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::enable()
|
|
||||||
{
|
|
||||||
setEnabled(true);
|
|
||||||
m_emitSignals = false;
|
|
||||||
setAnimationSpeed(1.0f);
|
|
||||||
m_designModeActive = false;
|
|
||||||
updateDesignModeActions(NoTool);
|
|
||||||
m_emitSignals = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::disable()
|
|
||||||
{
|
|
||||||
setAnimationSpeed(1.0f);
|
|
||||||
m_designModeActive = false;
|
|
||||||
updateDesignModeActions(NoTool);
|
|
||||||
setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::activateSelectTool()
|
|
||||||
{
|
|
||||||
updateDesignModeActions(SelectionToolMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::activateZoomTool()
|
|
||||||
{
|
|
||||||
updateDesignModeActions(ZoomMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::setAnimationSpeed(qreal slowDownFactor)
|
|
||||||
{
|
|
||||||
if (m_animationSpeed == slowDownFactor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_emitSignals = false;
|
|
||||||
m_animationSpeed = slowDownFactor;
|
|
||||||
|
|
||||||
foreach (QAction *action, m_playSpeedMenuActions->actions()) {
|
|
||||||
if (action->data().toReal() == slowDownFactor) {
|
|
||||||
action->setChecked(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_emitSignals = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::setAnimationPaused(bool paused)
|
|
||||||
{
|
|
||||||
if (m_paused == paused)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_paused = paused;
|
|
||||||
updatePlayAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::setDesignModeBehavior(bool inDesignMode)
|
|
||||||
{
|
|
||||||
m_emitSignals = false;
|
|
||||||
m_designModeActive = inDesignMode;
|
|
||||||
updateDesignModeActions(m_activeTool);
|
|
||||||
m_emitSignals = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::setShowAppOnTop(bool showAppOnTop)
|
|
||||||
{
|
|
||||||
m_emitSignals = false;
|
|
||||||
m_showAppOnTopAction->setChecked(showAppOnTop);
|
|
||||||
m_emitSignals = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::setZoomToolEnabled(bool enable)
|
|
||||||
{
|
|
||||||
m_zoomActionEnable = enable;
|
|
||||||
m_zoomAction->setEnabled(m_zoomActionEnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::createActions()
|
|
||||||
{
|
|
||||||
using namespace Constants;
|
|
||||||
|
|
||||||
Core::Context context(Debugger::Constants::C_QMLDEBUGGER);
|
|
||||||
Core::ActionManager *am = Core::ICore::actionManager();
|
|
||||||
|
|
||||||
m_fromQmlAction = new Utils::SavedAction(this);
|
|
||||||
m_fromQmlAction->setDefaultValue(false);
|
|
||||||
m_fromQmlAction->setSettingsKey(QLatin1String(S_QML_INSPECTOR),
|
|
||||||
QLatin1String(FROM_QML_ACTION));
|
|
||||||
m_fromQmlAction->setText(tr("Apply Changes on Save"));
|
|
||||||
m_fromQmlAction->setCheckable(true);
|
|
||||||
m_fromQmlAction->setIcon(QIcon(QLatin1String(":/qml/images/from-qml-small.png")));
|
|
||||||
|
|
||||||
m_showAppOnTopAction = new Utils::SavedAction(this);
|
|
||||||
m_showAppOnTopAction->setDefaultValue(false);
|
|
||||||
m_showAppOnTopAction->setSettingsKey(QLatin1String(S_QML_INSPECTOR),
|
|
||||||
QLatin1String(SHOW_APP_ON_TOP_ACTION));
|
|
||||||
m_showAppOnTopAction->setText(tr("Show application on top"));
|
|
||||||
m_showAppOnTopAction->setCheckable(true);
|
|
||||||
m_showAppOnTopAction->setIcon(QIcon(QLatin1String(":/qml/images/app-on-top.png")));
|
|
||||||
|
|
||||||
m_playAction =
|
|
||||||
new QAction(m_pauseIcon, tr("Play/Pause Animations"), this);
|
|
||||||
m_selectAction =
|
|
||||||
new QAction(QIcon(QLatin1String(":/qml/images/select-small.png")),
|
|
||||||
tr("Select"), this);
|
|
||||||
m_zoomAction =
|
|
||||||
new QAction(QIcon(QLatin1String(":/qml/images/zoom-small.png")),
|
|
||||||
tr("Zoom"), this);
|
|
||||||
|
|
||||||
m_selectAction->setCheckable(true);
|
|
||||||
m_zoomAction->setCheckable(true);
|
|
||||||
|
|
||||||
Core::Command *command
|
|
||||||
= am->registerAction(m_playAction, PLAY_ACTION, context);
|
|
||||||
command->setAttribute(Core::Command::CA_UpdateIcon);
|
|
||||||
am->registerAction(m_selectAction, SELECT_ACTION, context);
|
|
||||||
am->registerAction(m_zoomAction, ZOOM_ACTION, context);
|
|
||||||
am->registerAction(m_fromQmlAction, FROM_QML_ACTION, context);
|
|
||||||
am->registerAction(m_showAppOnTopAction, SHOW_APP_ON_TOP_ACTION, context);
|
|
||||||
|
|
||||||
m_barWidget = new QWidget;
|
|
||||||
|
|
||||||
QMenu *playSpeedMenu = new QMenu(m_barWidget);
|
|
||||||
m_playSpeedMenuActions = new QActionGroup(this);
|
|
||||||
m_playSpeedMenuActions->setExclusive(true);
|
|
||||||
QAction *speedAction = playSpeedMenu->addAction(tr("1x"),
|
|
||||||
this, SLOT(changeAnimationSpeed()));
|
|
||||||
speedAction->setCheckable(true);
|
|
||||||
speedAction->setChecked(true);
|
|
||||||
speedAction->setData(1.0f);
|
|
||||||
m_playSpeedMenuActions->addAction(speedAction);
|
|
||||||
|
|
||||||
speedAction = playSpeedMenu->addAction(tr("0.5x"),
|
|
||||||
this, SLOT(changeAnimationSpeed()));
|
|
||||||
speedAction->setCheckable(true);
|
|
||||||
speedAction->setData(2.0f);
|
|
||||||
m_playSpeedMenuActions->addAction(speedAction);
|
|
||||||
|
|
||||||
speedAction = playSpeedMenu->addAction(tr("0.25x"),
|
|
||||||
this, SLOT(changeAnimationSpeed()));
|
|
||||||
speedAction->setCheckable(true);
|
|
||||||
speedAction->setData(4.0f);
|
|
||||||
m_playSpeedMenuActions->addAction(speedAction);
|
|
||||||
|
|
||||||
speedAction = playSpeedMenu->addAction(tr("0.125x"),
|
|
||||||
this, SLOT(changeAnimationSpeed()));
|
|
||||||
speedAction->setCheckable(true);
|
|
||||||
speedAction->setData(8.0f);
|
|
||||||
m_playSpeedMenuActions->addAction(speedAction);
|
|
||||||
|
|
||||||
speedAction = playSpeedMenu->addAction(tr("0.1x"),
|
|
||||||
this, SLOT(changeAnimationSpeed()));
|
|
||||||
speedAction->setCheckable(true);
|
|
||||||
speedAction->setData(10.0f);
|
|
||||||
m_playSpeedMenuActions->addAction(speedAction);
|
|
||||||
|
|
||||||
QHBoxLayout *toolBarLayout = new QHBoxLayout(m_barWidget);
|
|
||||||
toolBarLayout->setMargin(0);
|
|
||||||
toolBarLayout->setSpacing(0);
|
|
||||||
|
|
||||||
// QML Helpers
|
|
||||||
toolBarLayout->addWidget(toolButton(am->command(FROM_QML_ACTION)->action()));
|
|
||||||
toolBarLayout->addWidget(
|
|
||||||
toolButton(am->command(SHOW_APP_ON_TOP_ACTION)->action()));
|
|
||||||
m_playButton = toolButton(am->command(PLAY_ACTION)->action());
|
|
||||||
m_playButton->setMenu(playSpeedMenu);
|
|
||||||
toolBarLayout->addWidget(m_playButton);
|
|
||||||
|
|
||||||
// Inspector
|
|
||||||
toolBarLayout->addWidget(new Utils::StyledSeparator);
|
|
||||||
toolBarLayout->addWidget(toolButton(am->command(SELECT_ACTION)->action()));
|
|
||||||
toolBarLayout->addWidget(toolButton(am->command(ZOOM_ACTION)->action()));
|
|
||||||
toolBarLayout->addWidget(new Utils::StyledSeparator);
|
|
||||||
|
|
||||||
connect(m_fromQmlAction, SIGNAL(triggered()),
|
|
||||||
SLOT(activateFromQml()));
|
|
||||||
connect(m_showAppOnTopAction, SIGNAL(triggered()),
|
|
||||||
SLOT(showAppOnTopClick()));
|
|
||||||
connect(m_playAction, SIGNAL(triggered()),
|
|
||||||
SLOT(activatePlayOnClick()));
|
|
||||||
connect(m_selectAction, SIGNAL(triggered(bool)),
|
|
||||||
SLOT(selectToolTriggered(bool)));
|
|
||||||
connect(m_zoomAction, SIGNAL(triggered(bool)),
|
|
||||||
SLOT(zoomToolTriggered(bool)));
|
|
||||||
|
|
||||||
readSettings();
|
|
||||||
connect(Core::ICore::instance(),
|
|
||||||
SIGNAL(saveSettingsRequested()), SLOT(writeSettings()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::readSettings()
|
|
||||||
{
|
|
||||||
QSettings *settings = Core::ICore::settings();
|
|
||||||
m_fromQmlAction->readSettings(settings);
|
|
||||||
m_showAppOnTopAction->readSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::writeSettings() const
|
|
||||||
{
|
|
||||||
QSettings *settings = Core::ICore::settings();
|
|
||||||
m_fromQmlAction->writeSettings(settings);
|
|
||||||
m_showAppOnTopAction->writeSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *QmlJsInspectorToolBar::widget() const
|
|
||||||
{
|
|
||||||
return m_barWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::changeAnimationSpeed()
|
|
||||||
{
|
|
||||||
QAction *action = static_cast<QAction*>(sender());
|
|
||||||
|
|
||||||
m_animationSpeed = action->data().toReal();
|
|
||||||
emit animationSpeedChanged(m_animationSpeed);
|
|
||||||
|
|
||||||
updatePlayAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::activatePlayOnClick()
|
|
||||||
{
|
|
||||||
m_paused = !m_paused;
|
|
||||||
emit animationPausedChanged(m_paused);
|
|
||||||
updatePlayAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::updatePlayAction()
|
|
||||||
{
|
|
||||||
m_playAction->setIcon(m_paused ? m_playIcon : m_pauseIcon);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::selectToolTriggered(bool checked)
|
|
||||||
{
|
|
||||||
if (m_designModeActive != checked) {
|
|
||||||
m_designModeActive = checked;
|
|
||||||
emit designModeSelected(checked);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checked)
|
|
||||||
emit selectToolSelected();
|
|
||||||
updateDesignModeActions(SelectionToolMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::zoomToolTriggered(bool checked)
|
|
||||||
{
|
|
||||||
if (m_designModeActive != checked) {
|
|
||||||
m_designModeActive = checked;
|
|
||||||
emit designModeSelected(checked);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checked)
|
|
||||||
emit zoomToolSelected();
|
|
||||||
|
|
||||||
updateDesignModeActions(ZoomMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::showAppOnTopClick()
|
|
||||||
{
|
|
||||||
if (m_emitSignals)
|
|
||||||
emit showAppOnTopSelected(m_showAppOnTopAction->isChecked());
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::activateFromQml()
|
|
||||||
{
|
|
||||||
if (m_emitSignals)
|
|
||||||
emit applyChangesFromQmlFileTriggered(m_fromQmlAction->isChecked());
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJsInspectorToolBar::updateDesignModeActions(DesignTool activeTool)
|
|
||||||
{
|
|
||||||
m_activeTool = activeTool;
|
|
||||||
m_selectAction->setChecked(m_designModeActive
|
|
||||||
&& (m_activeTool == SelectionToolMode));
|
|
||||||
m_zoomAction->setChecked(m_designModeActive
|
|
||||||
&& (m_activeTool == ZoomMode));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace QmlJSInspector
|
|
@@ -1,147 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QMLJSINSPECTORTOOLBAR_H
|
|
||||||
#define QMLJSINSPECTORTOOLBAR_H
|
|
||||||
|
|
||||||
#include <debugger/debuggerconstants.h>
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QIcon>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QAction;
|
|
||||||
class QActionGroup;
|
|
||||||
class QToolButton;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace Utils {
|
|
||||||
class StyledBar;
|
|
||||||
class SavedAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class QmlJsInspectorToolBar : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum DesignTool {
|
|
||||||
NoTool = 0,
|
|
||||||
SelectionToolMode = 1,
|
|
||||||
MarqueeSelectionToolMode = 2,
|
|
||||||
MoveToolMode = 3,
|
|
||||||
ResizeToolMode = 4,
|
|
||||||
ZoomMode = 6
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit QmlJsInspectorToolBar(QObject *parent = 0);
|
|
||||||
void createActions();
|
|
||||||
QWidget *widget() const;
|
|
||||||
void readSettings();
|
|
||||||
void setZoomToolEnabled(bool enable);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void writeSettings() const;
|
|
||||||
void setEnabled(bool value);
|
|
||||||
void enable();
|
|
||||||
void disable();
|
|
||||||
|
|
||||||
void activateSelectTool();
|
|
||||||
void activateZoomTool();
|
|
||||||
|
|
||||||
void setAnimationSpeed(qreal slowDownFactor);
|
|
||||||
void setAnimationPaused(bool paused);
|
|
||||||
|
|
||||||
void setDesignModeBehavior(bool inDesignMode);
|
|
||||||
void setShowAppOnTop(bool showAppOnTop);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void applyChangesFromQmlFileTriggered(bool isChecked);
|
|
||||||
|
|
||||||
void designModeSelected(bool);
|
|
||||||
void reloadSelected();
|
|
||||||
void selectToolSelected();
|
|
||||||
void zoomToolSelected();
|
|
||||||
|
|
||||||
void showAppOnTopSelected(bool isChecked);
|
|
||||||
|
|
||||||
void animationSpeedChanged(qreal slowdownFactor);
|
|
||||||
void animationPausedChanged(bool paused);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void activatePlayOnClick();
|
|
||||||
void selectToolTriggered(bool checked);
|
|
||||||
void zoomToolTriggered(bool checked);
|
|
||||||
|
|
||||||
void showAppOnTopClick();
|
|
||||||
|
|
||||||
void changeAnimationSpeed();
|
|
||||||
|
|
||||||
void activateFromQml();
|
|
||||||
|
|
||||||
void updatePlayAction();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void updateDesignModeActions(DesignTool activeTool);
|
|
||||||
|
|
||||||
Utils::SavedAction *m_fromQmlAction;
|
|
||||||
QAction *m_playAction;
|
|
||||||
QAction *m_selectAction;
|
|
||||||
QAction *m_zoomAction;
|
|
||||||
|
|
||||||
Utils::SavedAction *m_showAppOnTopAction;
|
|
||||||
|
|
||||||
QActionGroup *m_playSpeedMenuActions;
|
|
||||||
|
|
||||||
QToolButton *m_playButton;
|
|
||||||
QIcon m_playIcon;
|
|
||||||
QIcon m_pauseIcon;
|
|
||||||
|
|
||||||
bool m_emitSignals;
|
|
||||||
bool m_paused;
|
|
||||||
qreal m_animationSpeed;
|
|
||||||
|
|
||||||
bool m_designModeActive;
|
|
||||||
DesignTool m_activeTool;
|
|
||||||
|
|
||||||
QWidget *m_barWidget;
|
|
||||||
bool m_zoomActionEnable;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace QmlJSInspector
|
|
||||||
|
|
||||||
#endif // QMLJSINSPECTORTOOLBAR_H
|
|
@@ -1,627 +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)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
#include "qmljspropertyinspector.h"
|
|
||||||
#include "qmljsinspectorconstants.h"
|
|
||||||
|
|
||||||
#include <debugger/debuggerconstants.h>
|
|
||||||
#include <extensionsystem/pluginmanager.h>
|
|
||||||
#include <coreplugin/icore.h>
|
|
||||||
|
|
||||||
#include <QHeaderView>
|
|
||||||
#include <QItemDelegate>
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QDoubleValidator>
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
// expression editor
|
|
||||||
#include <QContextMenuEvent>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
// context menu
|
|
||||||
#include <QAction>
|
|
||||||
#include <QMenu>
|
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
|
||||||
#include <utils/savedaction.h>
|
|
||||||
|
|
||||||
const int PROPERTY_NAME_COLUMN = 0;
|
|
||||||
const int PROPERTY_TYPE_COLUMN = 1;
|
|
||||||
const int PROPERTY_VALUE_COLUMN = 2;
|
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
// *************************************************************************
|
|
||||||
// PropertyEdit
|
|
||||||
// *************************************************************************
|
|
||||||
|
|
||||||
class PropertyEditDelegate : public QItemDelegate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit PropertyEditDelegate(QObject *parent=0) : QItemDelegate(parent),
|
|
||||||
m_treeWidget(dynamic_cast<QmlJSPropertyInspector *>(parent)) {}
|
|
||||||
|
|
||||||
QWidget *createEditor(QWidget *parent,
|
|
||||||
const QStyleOptionViewItem &option,
|
|
||||||
const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
Q_UNUSED(option);
|
|
||||||
if (index.column() != PROPERTY_VALUE_COLUMN)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
switch (m_treeWidget->getTypeFor(index.row())) {
|
|
||||||
|
|
||||||
case QmlJSPropertyInspector::BooleanType: {
|
|
||||||
// invert the bool, skip editor
|
|
||||||
int objectId = m_treeWidget->getData(index.row(),
|
|
||||||
PROPERTY_NAME_COLUMN,
|
|
||||||
Qt::UserRole).toInt();
|
|
||||||
QString propertyName
|
|
||||||
= m_treeWidget->getData(index.row(),
|
|
||||||
PROPERTY_NAME_COLUMN,
|
|
||||||
Qt::DisplayRole).toString();
|
|
||||||
bool propertyValue
|
|
||||||
= m_treeWidget->getData(index.row(), PROPERTY_VALUE_COLUMN,
|
|
||||||
Qt::DisplayRole).toBool();
|
|
||||||
m_treeWidget->propertyValueEdited(objectId, propertyName,
|
|
||||||
!propertyValue?"true":"false",
|
|
||||||
true);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
case QmlJSPropertyInspector::NumberType: {
|
|
||||||
QLineEdit *editor = new QLineEdit(parent);
|
|
||||||
editor->setValidator(new QDoubleValidator(editor));
|
|
||||||
return editor;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
return new QLineEdit(parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setEditorData(QWidget *editor, const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
QVariant data = m_treeWidget->getData(index.row(), PROPERTY_VALUE_COLUMN,
|
|
||||||
Qt::DisplayRole);
|
|
||||||
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
|
|
||||||
lineEdit->setText(data.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
void setModelData(QWidget *editor, QAbstractItemModel *model,
|
|
||||||
const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
Q_UNUSED(model);
|
|
||||||
|
|
||||||
int objectId = m_treeWidget->getData(index.row(), PROPERTY_NAME_COLUMN,
|
|
||||||
Qt::UserRole).toInt();
|
|
||||||
if (objectId == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QString propertyName = m_treeWidget->getData(index.row(),
|
|
||||||
PROPERTY_NAME_COLUMN,
|
|
||||||
Qt::DisplayRole).toString();
|
|
||||||
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
|
|
||||||
QString propertyValue = lineEdit->text();
|
|
||||||
m_treeWidget->propertyValueEdited(objectId, propertyName, propertyValue,
|
|
||||||
true);
|
|
||||||
lineEdit->clearFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateEditorGeometry(QWidget *editor,
|
|
||||||
const QStyleOptionViewItem &option,
|
|
||||||
const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
Q_UNUSED(index);
|
|
||||||
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
|
|
||||||
lineEdit->setGeometry(option.rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QmlJSPropertyInspector *m_treeWidget;
|
|
||||||
|
|
||||||
};
|
|
||||||
// *************************************************************************
|
|
||||||
// expressionEdit
|
|
||||||
// *************************************************************************
|
|
||||||
|
|
||||||
ExpressionEdit::ExpressionEdit(const QString &title, QDialog *parent)
|
|
||||||
: QDialog(parent)
|
|
||||||
, m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok
|
|
||||||
| QDialogButtonBox::Cancel))
|
|
||||||
, m_exprInput(new QLineEdit(this))
|
|
||||||
{
|
|
||||||
setWindowTitle(title);
|
|
||||||
|
|
||||||
QVBoxLayout *vertLayout = new QVBoxLayout;
|
|
||||||
m_exprInput->setMinimumWidth(550);
|
|
||||||
connect(m_exprInput,SIGNAL(returnPressed()),this,SLOT(accept()));
|
|
||||||
vertLayout->addWidget(m_exprInput);
|
|
||||||
vertLayout->addWidget(m_buttonBox);
|
|
||||||
setLayout(vertLayout);
|
|
||||||
|
|
||||||
connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
|
||||||
connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ExpressionEdit::expression() const
|
|
||||||
{
|
|
||||||
return m_exprInput->text();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExpressionEdit::setItemData(int objectId, const QString &propertyName)
|
|
||||||
{
|
|
||||||
m_debugId = objectId;
|
|
||||||
m_paramName = propertyName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExpressionEdit::accept()
|
|
||||||
{
|
|
||||||
QDialog::accept();
|
|
||||||
emit dataChanged(m_debugId, m_paramName, expression());
|
|
||||||
}
|
|
||||||
|
|
||||||
// *************************************************************************
|
|
||||||
// color chooser
|
|
||||||
// *************************************************************************
|
|
||||||
|
|
||||||
inline QString extendedNameFromColor(QColor color)
|
|
||||||
{
|
|
||||||
int alphaValue = color.alpha();
|
|
||||||
if (alphaValue < 255)
|
|
||||||
return QLatin1String("#")
|
|
||||||
+ QString("%1").arg(alphaValue, 2, 16, QChar('0'))
|
|
||||||
+ color.name().right(6) ;
|
|
||||||
else
|
|
||||||
return color.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QString extendedNameFromColor(QVariant color) {
|
|
||||||
return extendedNameFromColor(QColor(color.value<QColor>()));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QColor colorFromExtendedName(QString name) {
|
|
||||||
QRegExp validator("#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})");
|
|
||||||
if (validator.exactMatch(name)) {
|
|
||||||
return QColor(validator.cap(2).toInt(0,16),
|
|
||||||
validator.cap(3).toInt(0,16),
|
|
||||||
validator.cap(4).toInt(0,16),
|
|
||||||
validator.cap(1).toInt(0,16));
|
|
||||||
}
|
|
||||||
return QColor(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorChooserDialog::ColorChooserDialog(const QString &title, QDialog *parent)
|
|
||||||
: QDialog(parent)
|
|
||||||
{
|
|
||||||
setWindowTitle(title);
|
|
||||||
|
|
||||||
QVBoxLayout *vertLayout = new QVBoxLayout;
|
|
||||||
m_mainFrame = new QmlEditorWidgets::CustomColorDialog(this);
|
|
||||||
setLayout(vertLayout);
|
|
||||||
|
|
||||||
setFixedSize(m_mainFrame->size());
|
|
||||||
|
|
||||||
connect(m_mainFrame,SIGNAL(accepted(QColor)),this,SLOT(acceptColor(QColor)));
|
|
||||||
connect(m_mainFrame,SIGNAL(rejected()),this,SLOT(reject()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ColorChooserDialog::setItemData(int objectId, const QString &propertyName,
|
|
||||||
const QString &colorName)
|
|
||||||
{
|
|
||||||
m_debugId = objectId;
|
|
||||||
m_paramName = propertyName;
|
|
||||||
m_mainFrame->setColor(QColor(colorName));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ColorChooserDialog::acceptColor(const QColor &color)
|
|
||||||
{
|
|
||||||
QDialog::accept();
|
|
||||||
emit dataChanged(m_debugId, m_paramName,
|
|
||||||
QChar('\"') + color.name() + QChar('\"'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// *************************************************************************
|
|
||||||
// QmlJSObjectTree
|
|
||||||
// *************************************************************************
|
|
||||||
inline QString cleanPropertyValue(QString propertyValue)
|
|
||||||
{
|
|
||||||
if (propertyValue == QString("<unknown value>"))
|
|
||||||
return QString();
|
|
||||||
if (propertyValue == QString("<unnamed object>"))
|
|
||||||
return QString();
|
|
||||||
return propertyValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// *************************************************************************
|
|
||||||
// QmlJSPropertyInspectorModel
|
|
||||||
// *************************************************************************
|
|
||||||
QmlJSPropertyInspectorModel::QmlJSPropertyInspectorModel()
|
|
||||||
: QStandardItemModel()
|
|
||||||
, m_contentsValid(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::ItemFlags QmlJSPropertyInspectorModel::flags(const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
return m_contentsValid ? QStandardItemModel::flags(index) : Qt::ItemFlags();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant QmlJSPropertyInspectorModel::headerData(
|
|
||||||
int section, Qt::Orientation orient, int role) const
|
|
||||||
{
|
|
||||||
if (orient == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
||||||
switch (section) {
|
|
||||||
case PROPERTY_NAME_COLUMN: return tr("Name");
|
|
||||||
case PROPERTY_VALUE_COLUMN: return tr("Value");
|
|
||||||
case PROPERTY_TYPE_COLUMN: return tr("Type");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return QStandardItemModel::headerData(section, orient, role);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspectorModel::setContentsValid(bool contentsValid)
|
|
||||||
{
|
|
||||||
m_contentsValid = contentsValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QmlJSPropertyInspectorModel::contentsValid() const
|
|
||||||
{
|
|
||||||
return m_contentsValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlJSPropertyInspector::QmlJSPropertyInspector(QWidget *parent)
|
|
||||||
: Utils::BaseTreeView(parent)
|
|
||||||
{
|
|
||||||
setItemDelegateForColumn(PROPERTY_VALUE_COLUMN,
|
|
||||||
new PropertyEditDelegate(this));
|
|
||||||
|
|
||||||
setModel(&m_model);
|
|
||||||
//Add an empty Row to make the headers visible!
|
|
||||||
addRow(QString(), QString(), QString(), -1, false);
|
|
||||||
|
|
||||||
m_adjustColumnsAction = new Utils::SavedAction(this);
|
|
||||||
m_adjustColumnsAction->setText(tr("Always Adjust Column Widths to Contents"));
|
|
||||||
m_adjustColumnsAction->setCheckable(true);
|
|
||||||
m_adjustColumnsAction->setValue(false);
|
|
||||||
m_adjustColumnsAction->setDefaultValue(false);
|
|
||||||
m_adjustColumnsAction->setSettingsKey(QLatin1String(Constants::S_QML_INSPECTOR),
|
|
||||||
QLatin1String(Constants::ALWAYS_ADJUST_COLUMNS_WIDTHS));
|
|
||||||
readSettings();
|
|
||||||
connect(Core::ICore::instance(),
|
|
||||||
SIGNAL(saveSettingsRequested()), SLOT(writeSettings()));
|
|
||||||
|
|
||||||
setAlwaysAdjustColumnsAction(m_adjustColumnsAction);
|
|
||||||
|
|
||||||
QAction *act = qobject_cast<QAction *>(
|
|
||||||
ExtensionSystem::PluginManager::instance()->getObjectByName(
|
|
||||||
QLatin1String(Debugger::Constants::USE_ALTERNATING_ROW_COLORS)));
|
|
||||||
if (act) {
|
|
||||||
setAlternatingRowColors(act->isChecked());
|
|
||||||
connect(act, SIGNAL(toggled(bool)),
|
|
||||||
SLOT(setAlternatingRowColorsHelper(bool)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspector::readSettings()
|
|
||||||
{
|
|
||||||
QSettings *settings = Core::ICore::settings();
|
|
||||||
m_adjustColumnsAction->readSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspector::writeSettings() const
|
|
||||||
{
|
|
||||||
QSettings *settings = Core::ICore::settings();
|
|
||||||
m_adjustColumnsAction->writeSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspector::addBaseContextActions(QMenu *menu)
|
|
||||||
{
|
|
||||||
QAction *act = qobject_cast<QAction *>(
|
|
||||||
ExtensionSystem::PluginManager::instance()->getObjectByName(
|
|
||||||
QLatin1String(Debugger::Constants::SORT_STRUCT_MEMBERS)));
|
|
||||||
if (act)
|
|
||||||
menu->addAction(act);
|
|
||||||
Utils::BaseTreeView::addBaseContextActions(menu);
|
|
||||||
|
|
||||||
act = qobject_cast<QAction *>(
|
|
||||||
ExtensionSystem::PluginManager::instance()->getObjectByName(
|
|
||||||
QLatin1String(Debugger::Constants::SETTINGS_DIALOG)));
|
|
||||||
if (act)
|
|
||||||
menu->addAction(act);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspector::clear()
|
|
||||||
{
|
|
||||||
m_model.removeRows(0, m_model.rowCount());
|
|
||||||
m_currentObjects.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspector::setContentsValid(bool contentsValid)
|
|
||||||
{
|
|
||||||
m_model.setContentsValid(contentsValid);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QmlJSPropertyInspector::contentsValid() const
|
|
||||||
{
|
|
||||||
return m_model.contentsValid();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspector::setCurrentObjects(
|
|
||||||
const QList<QmlDebugObjectReference> &objectList)
|
|
||||||
{
|
|
||||||
if (objectList.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
clear();
|
|
||||||
|
|
||||||
foreach (const QmlDebugObjectReference &obj, objectList) {
|
|
||||||
m_currentObjects << obj.debugId();
|
|
||||||
buildPropertyTree(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant QmlJSPropertyInspector::getData(int row, int column, int role) const
|
|
||||||
{
|
|
||||||
return m_model.data(m_model.index(row, column), role);
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlJSPropertyInspector::PropertyType
|
|
||||||
QmlJSPropertyInspector::getTypeFor(int row) const
|
|
||||||
{
|
|
||||||
return static_cast<QmlJSPropertyInspector::PropertyType>(
|
|
||||||
m_model.data(m_model.index(row, PROPERTY_TYPE_COLUMN),
|
|
||||||
Qt::UserRole).toInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspector::propertyValueChanged(int debugId,
|
|
||||||
const QByteArray &propertyName,
|
|
||||||
const QVariant &propertyValue)
|
|
||||||
{
|
|
||||||
if (m_model.rowCount() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QString propertyNameS = QString(propertyName);
|
|
||||||
for (int i = 0; i < m_model.rowCount(); i++) {
|
|
||||||
if (m_model.data(m_model.index(i, PROPERTY_NAME_COLUMN),
|
|
||||||
Qt::DisplayRole).toString() == propertyNameS &&
|
|
||||||
m_model.data(m_model.index(i, PROPERTY_NAME_COLUMN),
|
|
||||||
Qt::UserRole).toInt() == debugId) {
|
|
||||||
QString oldData = m_model.data(m_model.index(i, PROPERTY_VALUE_COLUMN),
|
|
||||||
Qt::DisplayRole).toString();
|
|
||||||
QString newData = propertyValue.toString();
|
|
||||||
if (QString(propertyValue.typeName()) == "QColor")
|
|
||||||
newData = extendedNameFromColor(propertyValue);
|
|
||||||
if (oldData != newData) {
|
|
||||||
m_model.setData(m_model.index(i, PROPERTY_VALUE_COLUMN), newData,
|
|
||||||
Qt::DisplayRole);
|
|
||||||
m_model.item(i, PROPERTY_VALUE_COLUMN)->setToolTip(newData);
|
|
||||||
m_model.item(i, PROPERTY_NAME_COLUMN)->setForeground(QBrush(Qt::red));
|
|
||||||
m_model.item(i, PROPERTY_VALUE_COLUMN)->setForeground(QBrush(Qt::red));
|
|
||||||
m_model.item(i, PROPERTY_TYPE_COLUMN)->setForeground(QBrush(Qt::red));
|
|
||||||
if (getTypeFor(i) == QmlJSPropertyInspector::ColorType)
|
|
||||||
setColorIcon(i);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspector::propertyValueEdited(const int objectId,
|
|
||||||
const QString &propertyName,
|
|
||||||
const QString &propertyValue,
|
|
||||||
bool isLiteral)
|
|
||||||
{
|
|
||||||
emit changePropertyValue(objectId, propertyName, propertyValue, isLiteral);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspector::buildPropertyTree(const QmlDebugObjectReference &obj)
|
|
||||||
{
|
|
||||||
// Strip off the misleading metadata
|
|
||||||
QString objTypeName = obj.className();
|
|
||||||
QString declarativeString("QDeclarative");
|
|
||||||
if (objTypeName.startsWith(declarativeString)) {
|
|
||||||
objTypeName = objTypeName.mid(declarativeString.length()).section('_',
|
|
||||||
0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// class
|
|
||||||
addRow(QString("class"),
|
|
||||||
objTypeName,
|
|
||||||
QString("qmlType"),
|
|
||||||
obj.debugId(),
|
|
||||||
false);
|
|
||||||
|
|
||||||
// id
|
|
||||||
if (!obj.idString().isEmpty()) {
|
|
||||||
addRow(QString("id"),
|
|
||||||
obj.idString(),
|
|
||||||
QString("idString"),
|
|
||||||
obj.debugId(),
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (const QmlDebugPropertyReference &prop, obj.properties()) {
|
|
||||||
QString propertyName = prop.name();
|
|
||||||
QString propertyValue = prop.value().toString();
|
|
||||||
|
|
||||||
if (cleanPropertyValue(propertyValue).isEmpty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (prop.valueTypeName() == "QColor") {
|
|
||||||
propertyValue = extendedNameFromColor(prop.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
addRow(propertyName, propertyValue, prop.valueTypeName(), obj.debugId(),
|
|
||||||
prop.hasNotifySignal());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_model.setHeaderData(PROPERTY_NAME_COLUMN, Qt::Horizontal,QVariant("name"));
|
|
||||||
m_model.setHeaderData(PROPERTY_VALUE_COLUMN, Qt::Horizontal,QVariant("value"));
|
|
||||||
m_model.setHeaderData(PROPERTY_TYPE_COLUMN, Qt::Horizontal,QVariant("type"));
|
|
||||||
|
|
||||||
QAction *act = qobject_cast<QAction *>(
|
|
||||||
ExtensionSystem::PluginManager::instance()->getObjectByName(
|
|
||||||
QLatin1String(Debugger::Constants::SORT_STRUCT_MEMBERS)));
|
|
||||||
if (act && act->isChecked())
|
|
||||||
m_model.sort(PROPERTY_NAME_COLUMN);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspector::addRow(const QString &name,const QString &value,
|
|
||||||
const QString &type, const int debugId,
|
|
||||||
bool editable)
|
|
||||||
{
|
|
||||||
QStandardItem *nameColumn = new QStandardItem(name);
|
|
||||||
nameColumn->setToolTip(name);
|
|
||||||
nameColumn->setData(QVariant(debugId),Qt::UserRole);
|
|
||||||
nameColumn->setEditable(false);
|
|
||||||
|
|
||||||
QStandardItem *valueColumn = new QStandardItem(value);
|
|
||||||
valueColumn->setToolTip(value);
|
|
||||||
valueColumn->setEditable(editable);
|
|
||||||
valueColumn->setData(QVariant(editable),Qt::UserRole+1);
|
|
||||||
|
|
||||||
QStandardItem *typeColumn = new QStandardItem(type);
|
|
||||||
typeColumn->setToolTip(type);
|
|
||||||
typeColumn->setEditable(false);
|
|
||||||
|
|
||||||
// encode type for easy lookup
|
|
||||||
QmlJSPropertyInspector::PropertyType typeCode
|
|
||||||
= QmlJSPropertyInspector::OtherType;
|
|
||||||
if (type == "bool")
|
|
||||||
typeCode = QmlJSPropertyInspector::BooleanType;
|
|
||||||
else if (type == "qreal")
|
|
||||||
typeCode = QmlJSPropertyInspector::NumberType;
|
|
||||||
else if (type == "QString")
|
|
||||||
typeCode = QmlJSPropertyInspector::StringType;
|
|
||||||
else if (type == "QColor")
|
|
||||||
typeCode = QmlJSPropertyInspector::ColorType;
|
|
||||||
|
|
||||||
typeColumn->setData(typeCode, Qt::UserRole);
|
|
||||||
|
|
||||||
QList<QStandardItem *> newRow;
|
|
||||||
newRow << nameColumn << typeColumn << valueColumn;
|
|
||||||
m_model.appendRow(newRow);
|
|
||||||
|
|
||||||
if (typeCode == QmlJSPropertyInspector::ColorType)
|
|
||||||
setColorIcon(m_model.indexFromItem(valueColumn).row());
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspector::setColorIcon(int row)
|
|
||||||
{
|
|
||||||
QStandardItem *item = m_model.item(row, PROPERTY_VALUE_COLUMN);
|
|
||||||
QColor color = colorFromExtendedName(item->data(Qt::DisplayRole).toString());
|
|
||||||
|
|
||||||
int recomendedLength = viewOptions().decorationSize.height() - 2;
|
|
||||||
|
|
||||||
QPixmap colorpix(recomendedLength, recomendedLength);
|
|
||||||
QPainter p(&colorpix);
|
|
||||||
if (color.alpha() != 255)
|
|
||||||
p.fillRect(1,1, recomendedLength -2, recomendedLength - 2, Qt::white);
|
|
||||||
p.fillRect(1, 1, recomendedLength - 2, recomendedLength - 2, color);
|
|
||||||
p.setPen(Qt::black);
|
|
||||||
p.drawRect(0, 0, recomendedLength - 1, recomendedLength - 1);
|
|
||||||
item->setIcon(colorpix);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspector::contextMenuEvent(QContextMenuEvent *ev)
|
|
||||||
{
|
|
||||||
QMenu menu;
|
|
||||||
QModelIndex itemIndex = indexAt(ev->pos());
|
|
||||||
bool isEditable = false;
|
|
||||||
bool isColor = false;
|
|
||||||
if (itemIndex.isValid()) {
|
|
||||||
isEditable = m_model.item(itemIndex.row(), PROPERTY_VALUE_COLUMN)->isEditable();
|
|
||||||
isColor = (getTypeFor(itemIndex.row()) == QmlJSPropertyInspector::ColorType);
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction exprAction(tr("Enter expression"), this);
|
|
||||||
if (isEditable)
|
|
||||||
menu.addAction(&exprAction);
|
|
||||||
|
|
||||||
QAction colorAction(tr("Choose color"), this);
|
|
||||||
if (isColor)
|
|
||||||
menu.addAction(&colorAction);
|
|
||||||
addBaseContextActions(&menu);
|
|
||||||
|
|
||||||
QAction *action = menu.exec(ev->globalPos());
|
|
||||||
if (action == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (action == &exprAction)
|
|
||||||
openExpressionEditor(itemIndex);
|
|
||||||
if (action == &colorAction)
|
|
||||||
openColorSelector(itemIndex);
|
|
||||||
handleBaseContextAction(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspector::openExpressionEditor(const QModelIndex &itemIndex)
|
|
||||||
{
|
|
||||||
const QString propertyName = getData(itemIndex.row(), PROPERTY_NAME_COLUMN,
|
|
||||||
Qt::DisplayRole).toString();
|
|
||||||
const QString dialogText = tr("JavaScript expression for %1").arg(propertyName);
|
|
||||||
const int objectId = getData(itemIndex.row(), PROPERTY_NAME_COLUMN,
|
|
||||||
Qt::UserRole).toInt();
|
|
||||||
|
|
||||||
ExpressionEdit *expressionDialog = new ExpressionEdit(dialogText);
|
|
||||||
expressionDialog->setItemData(objectId, propertyName);
|
|
||||||
|
|
||||||
connect(expressionDialog, SIGNAL(dataChanged(int,QString,QString)),
|
|
||||||
this, SLOT(propertyValueEdited(int,QString,QString)));
|
|
||||||
|
|
||||||
expressionDialog->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSPropertyInspector::openColorSelector(const QModelIndex &itemIndex)
|
|
||||||
{
|
|
||||||
const QString propertyName = getData(itemIndex.row(), PROPERTY_NAME_COLUMN,
|
|
||||||
Qt::DisplayRole).toString();
|
|
||||||
const QString dialogText = tr("Color selection for %1").arg(propertyName);
|
|
||||||
const int objectId = getData(itemIndex.row(), PROPERTY_NAME_COLUMN,
|
|
||||||
Qt::UserRole).toInt();
|
|
||||||
const QString propertyValue = getData(itemIndex.row(), PROPERTY_VALUE_COLUMN,
|
|
||||||
Qt::DisplayRole).toString();
|
|
||||||
|
|
||||||
ColorChooserDialog *colorDialog = new ColorChooserDialog(dialogText);
|
|
||||||
colorDialog->setItemData(objectId, propertyName, propertyValue);
|
|
||||||
|
|
||||||
connect(colorDialog, SIGNAL(dataChanged(int,QString,QString)),
|
|
||||||
this, SLOT(propertyValueEdited(int,QString,QString)));
|
|
||||||
|
|
||||||
colorDialog->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // Internal
|
|
||||||
} // QmlJSInspector
|
|
@@ -1,172 +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)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
#ifndef PROPERTYINSPECTOR_H
|
|
||||||
#define PROPERTYINSPECTOR_H
|
|
||||||
|
|
||||||
#include <qmldebug/baseenginedebugclient.h>
|
|
||||||
#include <utils/basetreeview.h>
|
|
||||||
#include <QStandardItemModel>
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
#include <QDialogButtonBox>
|
|
||||||
|
|
||||||
#include "customcolordialog.h"
|
|
||||||
|
|
||||||
using namespace QmlDebug;
|
|
||||||
|
|
||||||
namespace Utils {
|
|
||||||
class SavedAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class PropertyEditDelegate;
|
|
||||||
|
|
||||||
class ExpressionEdit : public QDialog
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit ExpressionEdit(const QString &title, QDialog *parent = 0);
|
|
||||||
|
|
||||||
QString expression() const;
|
|
||||||
void setItemData(int objectId, const QString &propertyName);
|
|
||||||
|
|
||||||
virtual void accept();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void dataChanged(int debugId, const QString ¶mName,
|
|
||||||
const QString &newExpression);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QDialogButtonBox *m_buttonBox;
|
|
||||||
QLineEdit *m_exprInput;
|
|
||||||
int m_debugId;
|
|
||||||
QString m_paramName;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ColorChooserDialog : public QDialog
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit ColorChooserDialog(const QString &title, QDialog *parent = 0);
|
|
||||||
|
|
||||||
void setItemData(int objectId,const QString &propertyName,
|
|
||||||
const QString &colorName);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void acceptColor(const QColor &color);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void dataChanged(int debugId, const QString ¶mName,
|
|
||||||
const QString &newExpression);
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_debugId;
|
|
||||||
QString m_paramName;
|
|
||||||
QmlEditorWidgets::CustomColorDialog *m_mainFrame;
|
|
||||||
};
|
|
||||||
|
|
||||||
class QmlJSPropertyInspectorModel : public QStandardItemModel
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
QmlJSPropertyInspectorModel();
|
|
||||||
void setContentsValid(bool contentsValid);
|
|
||||||
bool contentsValid() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_contentsValid;
|
|
||||||
};
|
|
||||||
|
|
||||||
class QmlJSPropertyInspector : public Utils::BaseTreeView
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
enum PropertyType
|
|
||||||
{
|
|
||||||
BooleanType,
|
|
||||||
NumberType,
|
|
||||||
StringType,
|
|
||||||
ColorType,
|
|
||||||
OtherType
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit QmlJSPropertyInspector(QWidget *parent = 0);
|
|
||||||
void readSettings();
|
|
||||||
void addBaseContextActions(QMenu *menu);
|
|
||||||
void clear();
|
|
||||||
void setContentsValid(bool contentsValid);
|
|
||||||
bool contentsValid() const;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void changePropertyValue(int debugId, QString propertyName,
|
|
||||||
QString valueExpression, bool isLiteral);
|
|
||||||
void customContextMenuRequested(const QPoint &pos);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void writeSettings() const;
|
|
||||||
void setCurrentObjects(const QList<QmlDebugObjectReference> &);
|
|
||||||
void propertyValueEdited(const int objectId,const QString &propertyName,
|
|
||||||
const QString &propertyValue, bool isLiteral = false);
|
|
||||||
void propertyValueChanged(int debugId, const QByteArray &propertyName,
|
|
||||||
const QVariant &propertyValue);
|
|
||||||
|
|
||||||
void openExpressionEditor(const QModelIndex &itemIndex);
|
|
||||||
void openColorSelector(const QModelIndex &itemIndex);
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class PropertyEditDelegate;
|
|
||||||
void buildPropertyTree(const QmlDebugObjectReference &);
|
|
||||||
void addRow(const QString &name, const QString &value, const QString &type,
|
|
||||||
const int debugId = -1, bool editable = true);
|
|
||||||
void setColorIcon(int row);
|
|
||||||
|
|
||||||
QVariant getData(int row, int column, int role) const;
|
|
||||||
QmlJSPropertyInspector::PropertyType getTypeFor(int row) const;
|
|
||||||
|
|
||||||
void contextMenuEvent(QContextMenuEvent *ev);
|
|
||||||
|
|
||||||
QmlJSPropertyInspectorModel m_model;
|
|
||||||
QList<int> m_currentObjects;
|
|
||||||
Utils::SavedAction *m_adjustColumnsAction;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // Internal
|
|
||||||
} // QmlJSInspector
|
|
||||||
|
|
||||||
#endif
|
|