forked from qt-creator/qt-creator
changing QmlJsLivePreview to work with multiple documents
This commit is contained in:
@@ -113,6 +113,21 @@ bool ClientProxy::connectToViewer(const QString &host, quint16 port)
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientProxy::refreshObjectTree()
|
||||
{
|
||||
if (!m_objectTreeQuery) {
|
||||
m_objectTreeQuery = m_client->queryObjectRecursive(m_rootObject, this);
|
||||
|
||||
if (!m_objectTreeQuery->isWaiting()) {
|
||||
objectTreeFetched();
|
||||
} else {
|
||||
connect(m_objectTreeQuery,
|
||||
SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
|
||||
SLOT(objectTreeFetched(QDeclarativeDebugQuery::State)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientProxy::onCurrentObjectsChanged(const QList<int> &debugIds)
|
||||
{
|
||||
QList<QDeclarativeDebugObjectReference> selectedItems;
|
||||
@@ -126,11 +141,9 @@ void ClientProxy::onCurrentObjectsChanged(const QList<int> &debugIds)
|
||||
// a) get some item and know its parent (although that's possible by adding it to a separate plugin)
|
||||
// b) add children to part of an existing tree.
|
||||
// So the only choice that remains is to update the complete tree when we have an unknown debug id.
|
||||
if (!m_objectTreeQuery) {
|
||||
if (!m_objectTreeQuery)
|
||||
m_objectTreeQuery = m_client->queryObjectRecursive(m_rootObject, this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (m_objectTreeQuery) {
|
||||
|
||||
@@ -62,6 +62,7 @@ public:
|
||||
// returns the object references for the given url.
|
||||
QList<QDeclarativeDebugObjectReference> objectReferences(const QUrl &url = QUrl()) const;
|
||||
QDeclarativeDebugObjectReference objectReferenceForId(int debugId) const;
|
||||
void refreshObjectTree();
|
||||
|
||||
bool isConnected() const;
|
||||
bool isUnconnected() const;
|
||||
|
||||
@@ -300,6 +300,7 @@ void Delta::insert(UiObjectMember *member, UiObjectMember *parentMember, const Q
|
||||
|
||||
foreach(const QDeclarativeDebugObjectReference &ref, debugReferences) {
|
||||
if (ref.debugId() != -1) {
|
||||
_referenceRefreshRequired = true;
|
||||
ClientProxy::instance()->createQmlObject(qmlText, ref, importList, doc->fileName());
|
||||
}
|
||||
}
|
||||
@@ -395,6 +396,7 @@ Delta::DebugIdMap Delta::operator()(const Document::Ptr &doc1, const Document::P
|
||||
QHash< UiObjectMember*, QList<QDeclarativeDebugObjectReference > > newDebuggIds;
|
||||
|
||||
Map M = Mapping(doc1, doc2);
|
||||
_referenceRefreshRequired = false;
|
||||
|
||||
BuildParentHash parents2;
|
||||
doc2->qmlProgram()->accept(&parents2);
|
||||
@@ -635,3 +637,8 @@ QList<Delta::Change> Delta::changes() const
|
||||
{
|
||||
return _changes;
|
||||
}
|
||||
|
||||
bool Delta::referenceRefreshRequired() const
|
||||
{
|
||||
return _referenceRefreshRequired;
|
||||
}
|
||||
|
||||
@@ -64,6 +64,14 @@ public:
|
||||
QmlJS::Document::Ptr previousDocument() const;
|
||||
|
||||
public:
|
||||
bool referenceRefreshRequired() const;
|
||||
static bool compare(UiSourceElement *source, UiSourceElement *other);
|
||||
static bool compare(QmlJS::AST::UiQualifiedId *id, QmlJS::AST::UiQualifiedId *other);
|
||||
static QmlJS::AST::UiObjectMemberList *objectMembers(QmlJS::AST::UiObjectMember *object);
|
||||
|
||||
private:
|
||||
void insert(UiObjectMember *member, UiObjectMember *parentMember,
|
||||
const QList<QDeclarativeDebugObjectReference> &debugReferences, const Document::Ptr &doc);
|
||||
void updateScriptBinding(const QDeclarativeDebugObjectReference &objectReference,
|
||||
QmlJS::AST::UiScriptBinding *scriptBinding,
|
||||
const QString &propertyName,
|
||||
@@ -73,14 +81,6 @@ public:
|
||||
const QString &methodName,
|
||||
const QString &methodBody);
|
||||
|
||||
static bool compare(UiSourceElement *source, UiSourceElement *other);
|
||||
static bool compare(QmlJS::AST::UiQualifiedId *id, QmlJS::AST::UiQualifiedId *other);
|
||||
static QmlJS::AST::UiObjectMemberList *objectMembers(QmlJS::AST::UiObjectMember *object);
|
||||
|
||||
private:
|
||||
void insert(UiObjectMember *member, UiObjectMember *parentMember,
|
||||
const QList<QDeclarativeDebugObjectReference> &debugReferences, const Document::Ptr &doc);
|
||||
|
||||
void update(UiObjectDefinition* oldObject, const QmlJS::Document::Ptr& oldDoc,
|
||||
UiObjectDefinition* newObject, const QmlJS::Document::Ptr& newDoc,
|
||||
const QList<QDeclarativeDebugObjectReference >& debugReferences);
|
||||
@@ -90,6 +90,7 @@ private:
|
||||
QmlJS::Document::Ptr _previousDoc;
|
||||
QList<Change> _changes;
|
||||
QUrl _url;
|
||||
bool _referenceRefreshRequired;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#include "qmljslivetextpreview.h"
|
||||
#include "qmljsprivateapi.h"
|
||||
|
||||
#include <qmljseditor/qmljseditorconstants.h>
|
||||
|
||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||
#include <qmljs/qmljsdocument.h>
|
||||
|
||||
@@ -128,12 +130,6 @@ Inspector::Inspector(QObject *parent)
|
||||
QWidget *contextWidget = 0;
|
||||
m_context = new InspectorContext(contextWidget);
|
||||
|
||||
m_textPreview = new QmlJSLiveTextPreview(this);
|
||||
|
||||
connect(m_textPreview,
|
||||
SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)),
|
||||
SLOT(changeSelectedItems(QList<QDeclarativeDebugObjectReference>)));
|
||||
|
||||
connect(m_clientProxy, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)),
|
||||
SLOT(setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference>)));
|
||||
|
||||
@@ -161,6 +157,9 @@ void Inspector::disconnectWidgets()
|
||||
|
||||
void Inspector::disconnected()
|
||||
{
|
||||
Core::EditorManager *em = Core::EditorManager::instance();
|
||||
disconnect(em, SIGNAL(editorAboutToClose(Core::IEditor*)), this, SLOT(removePreviewForEditor(Core::IEditor*)));
|
||||
disconnect(em, SIGNAL(editorOpened(Core::IEditor*)), this, SLOT(createPreviewForEditor(Core::IEditor*)));
|
||||
resetViews();
|
||||
updateMenuActions();
|
||||
}
|
||||
@@ -201,7 +200,7 @@ void Inspector::pollInspector()
|
||||
const quint16 port = quint16(m_runConfigurationDebugData.serverPort);
|
||||
|
||||
if (m_clientProxy->connectToViewer(host, port)) {
|
||||
m_textPreview->updateDocuments();
|
||||
initializeDocuments();
|
||||
m_connectionTimer->stop();
|
||||
m_connectionAttempts = 0;
|
||||
} else if (m_connectionAttempts == MaxConnectionAttempts) {
|
||||
@@ -215,6 +214,57 @@ void Inspector::pollInspector()
|
||||
updateMenuActions();
|
||||
}
|
||||
|
||||
QmlJS::ModelManagerInterface *Inspector::modelManager()
|
||||
{
|
||||
return ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>();
|
||||
}
|
||||
|
||||
void Inspector::initializeDocuments()
|
||||
{
|
||||
if (!modelManager())
|
||||
return;
|
||||
|
||||
QmlJS::Snapshot snapshot = modelManager()->snapshot();
|
||||
Core::EditorManager *em = Core::EditorManager::instance();
|
||||
connect(em, SIGNAL(editorAboutToClose(Core::IEditor*)), SLOT(removePreviewForEditor(Core::IEditor*)));
|
||||
connect(em, SIGNAL(editorOpened(Core::IEditor*)), SLOT(createPreviewForEditor(Core::IEditor*)));
|
||||
|
||||
// initial update
|
||||
foreach (QmlJS::Document::Ptr doc, snapshot) {
|
||||
QmlJSLiveTextPreview *preview = new QmlJSLiveTextPreview(doc, this);
|
||||
connect(preview,
|
||||
SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)),
|
||||
SLOT(changeSelectedItems(QList<QDeclarativeDebugObjectReference>)));
|
||||
m_textPreviews.insert(doc->fileName(), preview);
|
||||
}
|
||||
}
|
||||
|
||||
void Inspector::removePreviewForEditor(Core::IEditor *oldEditor)
|
||||
{
|
||||
if (QmlJSLiveTextPreview *preview = m_textPreviews.value(oldEditor->file()->fileName())) {
|
||||
preview->unassociateEditor(oldEditor);
|
||||
}
|
||||
}
|
||||
|
||||
void Inspector::createPreviewForEditor(Core::IEditor *newEditor)
|
||||
{
|
||||
if (newEditor && newEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
|
||||
QString filename = newEditor->file()->fileName();
|
||||
QmlJS::Document::Ptr doc = modelManager()->snapshot().document(filename);
|
||||
|
||||
if (m_textPreviews.contains(filename)) {
|
||||
m_textPreviews.value(filename)->associateEditor(newEditor);
|
||||
} else {
|
||||
|
||||
QmlJSLiveTextPreview *preview = new QmlJSLiveTextPreview(doc, this);
|
||||
connect(preview,
|
||||
SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)),
|
||||
SLOT(changeSelectedItems(QList<QDeclarativeDebugObjectReference>)));
|
||||
m_textPreviews.insert(newEditor->file()->fileName(), preview);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Inspector::setDebugConfigurationDataFromProject(ProjectExplorer::Project *projectToDebug)
|
||||
{
|
||||
if (!projectToDebug) {
|
||||
|
||||
@@ -54,6 +54,10 @@ namespace Debugger {
|
||||
class DebuggerRunControl;
|
||||
}
|
||||
|
||||
namespace QmlJS {
|
||||
class ModelManagerInterface;
|
||||
}
|
||||
|
||||
namespace QmlJSInspector {
|
||||
namespace Internal {
|
||||
|
||||
@@ -117,6 +121,9 @@ private slots:
|
||||
void disconnectWidgets();
|
||||
void disconnected();
|
||||
|
||||
void removePreviewForEditor(Core::IEditor *newEditor);
|
||||
void createPreviewForEditor(Core::IEditor *newEditor);
|
||||
|
||||
private:
|
||||
Debugger::DebuggerRunControl *createDebuggerRunControl(ProjectExplorer::RunConfiguration *runConfig,
|
||||
const QString &executableFile = QString(),
|
||||
@@ -131,6 +138,9 @@ private:
|
||||
bool addQuotesForData(const QVariant &value) const;
|
||||
void resetViews();
|
||||
|
||||
QmlJS::ModelManagerInterface *modelManager();
|
||||
void initializeDocuments();
|
||||
|
||||
private:
|
||||
QWeakPointer<QDeclarativeEngineDebug> m_client;
|
||||
QmlProjectManager::QmlProjectRunConfigurationDebugData m_runConfigurationDebugData;
|
||||
@@ -144,7 +154,7 @@ private:
|
||||
ClientProxy *m_clientProxy;
|
||||
|
||||
// Qml/JS integration
|
||||
QmlJSLiveTextPreview *m_textPreview;
|
||||
QHash<QString, QmlJSLiveTextPreview *> m_textPreviews;
|
||||
};
|
||||
|
||||
} // Internal
|
||||
|
||||
@@ -65,38 +65,56 @@ void MapObjectWithDebugReference::processRecursive(const QDeclarativeDebugObject
|
||||
}
|
||||
}
|
||||
|
||||
QmlJSLiveTextPreview::QmlJSLiveTextPreview(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
Core::EditorManager *editorManager = Core::EditorManager::instance();
|
||||
ClientProxy *clientProxy = ClientProxy::instance();
|
||||
connect(editorManager->instance(),
|
||||
SIGNAL(currentEditorChanged(Core::IEditor*)),
|
||||
SLOT(setEditor(Core::IEditor*)));
|
||||
connect(clientProxy,
|
||||
SIGNAL(objectTreeUpdated(QDeclarativeDebugObjectReference)),
|
||||
SLOT(updateDebugIds(QDeclarativeDebugObjectReference)));
|
||||
}
|
||||
|
||||
QmlJS::ModelManagerInterface *QmlJSLiveTextPreview::modelManager()
|
||||
{
|
||||
return ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>();
|
||||
}
|
||||
|
||||
void QmlJSLiveTextPreview::updateDocuments()
|
||||
void QmlJSLiveTextPreview::associateEditor(Core::IEditor *editor)
|
||||
{
|
||||
if (!modelManager())
|
||||
return;
|
||||
|
||||
m_snapshot = modelManager()->snapshot();
|
||||
setEditor(Core::EditorManager::instance()->currentEditor());
|
||||
|
||||
// initial update
|
||||
foreach (QmlJS::Document::Ptr doc, m_snapshot) {
|
||||
documentChanged(doc);
|
||||
if (editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
|
||||
QmlJSEditor::Internal::QmlJSTextEditor* qmljsEditor = qobject_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(editor->widget());
|
||||
if (qmljsEditor && !m_editors.contains(qmljsEditor)) {
|
||||
m_editors << qmljsEditor;
|
||||
connect(qmljsEditor,
|
||||
SIGNAL(selectedElementsChanged(QList<int>,QString)),
|
||||
SLOT(changeSelectedElements(QList<int>,QString)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QmlJSLiveTextPreview::unassociateEditor(Core::IEditor *oldEditor)
|
||||
{
|
||||
if (oldEditor && oldEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
|
||||
QmlJSEditor::Internal::QmlJSTextEditor* qmljsEditor = qobject_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(oldEditor->widget());
|
||||
if (qmljsEditor && m_editors.contains(qmljsEditor)) {
|
||||
m_editors.removeOne(qmljsEditor);
|
||||
disconnect(qmljsEditor,
|
||||
SIGNAL(selectedElementsChanged(QList<int>,QString)),
|
||||
this,
|
||||
SLOT(changeSelectedElements(QList<int>,QString)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QmlJSLiveTextPreview::QmlJSLiveTextPreview(QmlJS::Document::Ptr doc, QObject *parent) :
|
||||
QObject(parent), m_previousDoc(doc)
|
||||
{
|
||||
ClientProxy *clientProxy = ClientProxy::instance();
|
||||
m_filename = doc->fileName();
|
||||
|
||||
connect(modelManager(), SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)),
|
||||
SLOT(documentChanged(QmlJS::Document::Ptr)));
|
||||
|
||||
connect(clientProxy,
|
||||
SIGNAL(objectTreeUpdated(QDeclarativeDebugObjectReference)),
|
||||
SLOT(updateDebugIds(QDeclarativeDebugObjectReference)));
|
||||
|
||||
Core::EditorManager *em = Core::EditorManager::instance();
|
||||
QList<Core::IEditor *> editors = em->editorsForFileName(m_filename);
|
||||
|
||||
foreach(Core::IEditor *editor, editors)
|
||||
associateEditor(editor);
|
||||
}
|
||||
|
||||
QList<QDeclarativeDebugObjectReference > QmlJSLiveTextPreview::objectReferencesForOffset(quint32 offset) const
|
||||
@@ -116,12 +134,9 @@ QList<QDeclarativeDebugObjectReference > QmlJSLiveTextPreview::objectReferencesF
|
||||
|
||||
void QmlJSLiveTextPreview::changeSelectedElements(QList<int> offsets, const QString &wordAtCursor)
|
||||
{
|
||||
if (!m_currentEditor || !m_previousDoc)
|
||||
if (m_editors.isEmpty() || !m_previousDoc)
|
||||
return;
|
||||
|
||||
if (m_debugIds.isEmpty())
|
||||
m_debugIds = m_initialTable.value(m_previousDoc->fileName());
|
||||
|
||||
ClientProxy *clientProxy = ClientProxy::instance();
|
||||
|
||||
QDeclarativeDebugObjectReference objectRefUnderCursor;
|
||||
@@ -160,47 +175,26 @@ void QmlJSLiveTextPreview::changeSelectedElements(QList<int> offsets, const QStr
|
||||
emit selectedItemsChanged(selectedReferences);
|
||||
}
|
||||
|
||||
void QmlJSLiveTextPreview::setEditor(Core::IEditor *editor)
|
||||
{
|
||||
if (!m_currentEditor.isNull()) {
|
||||
disconnect(m_currentEditor.data(), SIGNAL(selectedElementsChanged(QList<int>, QString)), this, SLOT(changeSelectedElements(QList<int>, QString)));
|
||||
m_currentEditor.clear();
|
||||
m_previousDoc.clear();
|
||||
m_debugIds.clear();
|
||||
}
|
||||
|
||||
if (editor) {
|
||||
m_currentEditor = qobject_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(editor->widget());
|
||||
if (m_currentEditor) {
|
||||
connect(m_currentEditor.data(), SIGNAL(selectedElementsChanged(QList<int>, QString)), SLOT(changeSelectedElements(QList<int>, QString)));
|
||||
m_previousDoc = m_snapshot.document(editor->file()->fileName());
|
||||
m_debugIds = m_initialTable.value(editor->file()->fileName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QmlJSLiveTextPreview::updateDebugIds(const QDeclarativeDebugObjectReference &rootReference)
|
||||
{
|
||||
QmlJS::ModelManagerInterface *m = QmlJS::ModelManagerInterface::instance();
|
||||
Snapshot snapshot = m->snapshot();
|
||||
QHash<QString, QHash<UiObjectMember *, QList< QDeclarativeDebugObjectReference> > > allDebugIds;
|
||||
foreach(const Document::Ptr &doc, snapshot) {
|
||||
QmlJS::Document::Ptr doc = m_previousDoc;
|
||||
|
||||
if (!doc->qmlProgram())
|
||||
continue;
|
||||
return;
|
||||
|
||||
MapObjectWithDebugReference visitor;
|
||||
visitor.root = rootReference;
|
||||
QString filename = doc->fileName();
|
||||
visitor.filename = filename;
|
||||
visitor.filename = doc->fileName();
|
||||
doc->qmlProgram()->accept(&visitor);
|
||||
allDebugIds[filename] = visitor.result;
|
||||
}
|
||||
|
||||
m_initialTable = allDebugIds;
|
||||
m_debugIds.clear();
|
||||
m_debugIds = visitor.result;
|
||||
}
|
||||
|
||||
void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc)
|
||||
{
|
||||
if (doc->fileName() != m_previousDoc->fileName())
|
||||
return;
|
||||
|
||||
Core::ICore *core = Core::ICore::instance();
|
||||
const int dbgcontext = core->uniqueIDManager()->uniqueIdentifier(Debugger::Constants::C_DEBUGMODE);
|
||||
|
||||
@@ -210,12 +204,11 @@ void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc)
|
||||
if (doc && m_previousDoc && doc->fileName() == m_previousDoc->fileName()
|
||||
&& doc->qmlProgram() && m_previousDoc->qmlProgram())
|
||||
{
|
||||
if (m_debugIds.isEmpty())
|
||||
m_debugIds = m_initialTable.value(doc->fileName());
|
||||
|
||||
Delta delta;
|
||||
m_debugIds = delta(m_previousDoc, doc, m_debugIds);
|
||||
m_initialTable[doc->fileName()] = m_debugIds;
|
||||
|
||||
if (delta.referenceRefreshRequired())
|
||||
ClientProxy::instance()->refreshObjectTree();
|
||||
|
||||
m_previousDoc = doc;
|
||||
}
|
||||
|
||||
@@ -33,16 +33,15 @@ class QmlJSLiveTextPreview : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QmlJSLiveTextPreview(QObject *parent = 0);
|
||||
explicit QmlJSLiveTextPreview(QmlJS::Document::Ptr doc, QObject *parent = 0);
|
||||
static QmlJS::ModelManagerInterface *modelManager();
|
||||
void updateDocuments();
|
||||
//void updateDocuments();
|
||||
|
||||
void associateEditor(Core::IEditor *editor);
|
||||
void unassociateEditor(Core::IEditor *editor);
|
||||
void setActiveObject(const QDeclarativeDebugObjectReference &object);
|
||||
void mapObjectToQml(const QDeclarativeDebugObjectReference &object);
|
||||
|
||||
QHash<QString, QHash<QmlJS::AST::UiObjectMember *, QList< QDeclarativeDebugObjectReference> > > m_initialTable;
|
||||
QHash< QmlJS::AST::UiObjectMember*, QList<QDeclarativeDebugObjectReference > > m_debugIds;
|
||||
|
||||
signals:
|
||||
void selectedItemsChanged(const QList<QDeclarativeDebugObjectReference> &objects);
|
||||
|
||||
@@ -57,10 +56,13 @@ private:
|
||||
QVariant castToLiteral(const QString &expression, QmlJS::AST::UiScriptBinding *scriptBinding);
|
||||
|
||||
private:
|
||||
QmlJS::Document::Ptr m_previousDoc;
|
||||
QHash<QmlJS::AST::UiObjectMember*, QList<QDeclarativeDebugObjectReference> > m_initialTable;
|
||||
QHash<QmlJS::AST::UiObjectMember*, QList<QDeclarativeDebugObjectReference> > m_debugIds;
|
||||
|
||||
QmlJS::Snapshot m_snapshot;
|
||||
QWeakPointer<QmlJSEditor::Internal::QmlJSTextEditor> m_currentEditor;
|
||||
QmlJS::Document::Ptr m_previousDoc;
|
||||
QString m_filename;
|
||||
|
||||
QList<QWeakPointer<QmlJSEditor::Internal::QmlJSTextEditor> > m_editors;
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user