From cdb5dadfc2cdc44b7bef9ffbe9aa96d584c46939 Mon Sep 17 00:00:00 2001
From: Lasse Holmstedt <lasse.holmstedt@nokia.com>
Date: Tue, 27 Jul 2010 11:57:06 +0200
Subject: [PATCH] QmlJS Live Preview: Fixed highlighting from text editor-> qml
 observer

Now, the items about to be selected must inherit from QGraphicsObject.
Also, coding style was cleaned up a bit.
---
 src/plugins/qmljseditor/qmljseditor.cpp       | 73 +++++++++++--------
 src/plugins/qmljseditor/qmljseditor.h         |  2 +-
 src/plugins/qmljsinspector/qmljsinspector.cpp |  1 +
 .../qmljsinspector/qmljslivetextpreview.cpp   | 27 ++++---
 4 files changed, 63 insertions(+), 40 deletions(-)

diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp
index 40fb59dbf77..5fa3c18bf36 100644
--- a/src/plugins/qmljseditor/qmljseditor.cpp
+++ b/src/plugins/qmljseditor/qmljseditor.cpp
@@ -960,31 +960,37 @@ void QmlJSTextEditor::updateUsesNow()
 
     setExtraSelections(CodeSemanticsSelection, selections);
 
-    setSelectedElement();
+    setSelectedElements();
 }
 
 class SelectedElement: protected Visitor
 {
-    unsigned cursorPositionStart;
-    unsigned cursorPositionEnd;
-    QList<UiObjectMember *> selectedMembers;
+    unsigned m_cursorPositionStart;
+    unsigned m_cursorPositionEnd;
+    QList<UiObjectMember *> m_selectedMembers;
+    Document::Ptr m_document;
+    Snapshot m_snapshot;
+    LookupContext::Ptr m_lookupContext;
 
 public:
     SelectedElement()
-        : cursorPositionStart(0), cursorPositionEnd(0) {}
+        : m_cursorPositionStart(0), m_cursorPositionEnd(0) {}
 
-    QList<UiObjectMember *> operator()(Node *root, unsigned startPosition, unsigned endPosition)
+    QList<UiObjectMember *> operator()(Document::Ptr doc, Snapshot snapshot, unsigned startPosition, unsigned endPosition)
     {
-        cursorPositionStart = startPosition;
-        cursorPositionEnd = endPosition;
-        selectedMembers.clear();
-        Node::accept(root, this);
-        return selectedMembers;
+        m_document = doc;
+        m_snapshot = snapshot;
+        m_lookupContext = LookupContext::create(m_document, m_snapshot, QList<Node*>());
+        m_cursorPositionStart = startPosition;
+        m_cursorPositionEnd = endPosition;
+        m_selectedMembers.clear();
+        Node::accept(doc->qmlProgram(), this);
+        return m_selectedMembers;
     }
 
 protected:
 
-    bool isAcceptableParent(UiObjectMember *member) const
+    bool isSelectable(UiObjectMember *member) const
     {
         UiQualifiedId *id = 0;
         if (UiObjectDefinition *def = cast<UiObjectDefinition *>(member))
@@ -1011,6 +1017,20 @@ protected:
         return 0;
     }
 
+    bool hasVisualPresentation(Node *ast)
+    {
+        Bind *bind = m_document->bind();
+        const Interpreter::ObjectValue *objValue = bind->findQmlObject(ast);
+        QStringList prototypes;
+
+        while (objValue) {
+            prototypes.append(objValue->className());
+            objValue = objValue->prototype(m_lookupContext->context());
+        }
+
+        return prototypes.contains(QString("QGraphicsObject"));
+    }
+
     bool isIdBinding(UiObjectMember *member) const
     {
         if (UiScriptBinding *script = cast<UiScriptBinding *>(member)) {
@@ -1032,22 +1052,22 @@ protected:
 
     bool containsCursor(unsigned begin, unsigned end)
     {
-        return cursorPositionStart >= begin && cursorPositionEnd <= end;
+        return m_cursorPositionStart >= begin && m_cursorPositionEnd <= end;
     }
 
     bool intersectsCursor(unsigned begin, unsigned end)
     {
-        return (cursorPositionEnd >= begin && cursorPositionStart <= end);
+        return (m_cursorPositionEnd >= begin && m_cursorPositionStart <= end);
     }
 
     bool isRangeSelected() const
     {
-        return (cursorPositionStart != cursorPositionEnd);
+        return (m_cursorPositionStart != m_cursorPositionEnd);
     }
 
     virtual void postVisit(Node *ast)
     {
-        if ((cursorPositionStart == cursorPositionEnd && !selectedMembers.isEmpty()))
+        if (!isRangeSelected() && !m_selectedMembers.isEmpty())
             return; // nothing to do, we already have the results.
 
         if (UiObjectMember *member = ast->uiObjectMemberCast()) {
@@ -1057,23 +1077,17 @@ protected:
             if ((isRangeSelected() && intersectsCursor(begin, end))
             || (!isRangeSelected() && containsCursor(begin, end)))
             {
-                if (UiObjectInitializer *init = initializer(member)) {
-                    for (UiObjectMemberList *it = init->members; it; it = it->next) {
-                        if ((isRangeSelected() && isAcceptableParent(member))
-                         || (!isRangeSelected() && isIdBinding(it->member))) {
-                            selectedMembers << member;
-                            // move start towards end; this facilitates multiselection so that root is usually ignored.
-                            cursorPositionStart = qMin(end, cursorPositionEnd);
-                            break;
-                        }
-                    }
+                if (initializer(member) && isSelectable(member) && hasVisualPresentation(member)) {
+                    m_selectedMembers << member;
+                    // move start towards end; this facilitates multiselection so that root is usually ignored.
+                    m_cursorPositionStart = qMin(end, m_cursorPositionEnd);
                 }
             }
         }
     }
 };
 
-void QmlJSTextEditor::setSelectedElement()
+void QmlJSTextEditor::setSelectedElements()
 {
     QTextCursor tc = textCursor();
     QString wordAtCursor;
@@ -1093,10 +1107,11 @@ void QmlJSTextEditor::setSelectedElement()
         endPos = textCursor().position();
     }
 
-    if (Document::Ptr doc = m_semanticInfo.document) {
+    if (m_semanticInfo.document) {
         SelectedElement selectedMembers;
 
-        QList<UiObjectMember *> members = selectedMembers(doc->qmlProgram(), startPos, endPos);
+        QList<UiObjectMember *> members = selectedMembers(m_semanticInfo.document, m_semanticInfo.snapshot,
+                                                          startPos, endPos);
 
         if (!members.isEmpty()) {
             foreach(UiObjectMember *m, members) {
diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h
index ff1c4969c50..eccf2eb1212 100644
--- a/src/plugins/qmljseditor/qmljseditor.h
+++ b/src/plugins/qmljseditor/qmljseditor.h
@@ -274,7 +274,7 @@ private:
     virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
     bool isClosingBrace(const QList<QmlJS::Token> &tokens) const;
 
-    void setSelectedElement();
+    void setSelectedElements();
     QString wordUnderCursor() const;
 
     SemanticHighlighter::Source currentSource(bool force = false);
diff --git a/src/plugins/qmljsinspector/qmljsinspector.cpp b/src/plugins/qmljsinspector/qmljsinspector.cpp
index 9e6d7550dff..eb477773f7c 100644
--- a/src/plugins/qmljsinspector/qmljsinspector.cpp
+++ b/src/plugins/qmljsinspector/qmljsinspector.cpp
@@ -276,6 +276,7 @@ void Inspector::createPreviewForEditor(Core::IEditor *newEditor)
                     SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)),
                     SLOT(changeSelectedItems(QList<QDeclarativeDebugObjectReference>)));
             m_textPreviews.insert(newEditor->file()->fileName(), preview);
+            preview->associateEditor(newEditor);
             preview->updateDebugIds(m_clientProxy->rootObjectReference());
         }
     }
diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp
index 4e206fde448..2793d9ee6fd 100644
--- a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp
+++ b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp
@@ -211,36 +211,43 @@ void QmlJSLiveTextPreview::changeSelectedElements(QList<int> offsets, const QStr
     ClientProxy *clientProxy = ClientProxy::instance();
 
     QDeclarativeDebugObjectReference objectRefUnderCursor;
-
-    QList<QDeclarativeDebugObjectReference> refs = clientProxy->objectReferences();
-    foreach (const QDeclarativeDebugObjectReference &ref, refs) {
-        if (ref.idString() == wordAtCursor) {
-            objectRefUnderCursor = ref;
-            break;
+    if (!wordAtCursor.isEmpty() && wordAtCursor[0].isUpper()) {
+        QList<QDeclarativeDebugObjectReference> refs = clientProxy->objectReferences();
+        foreach (const QDeclarativeDebugObjectReference &ref, refs) {
+            if (ref.idString() == wordAtCursor) {
+                objectRefUnderCursor = ref;
+                break;
+            }
         }
     }
 
     QList<int> selectedReferences;
-    bool containsReference = false;
+    bool containsReferenceUnderCursor = false;
 
     foreach(int offset, offsets) {
         if (offset >= 0) {
             QList<int> list = objectReferencesForOffset(offset);
 
-            if (!containsReference && objectRefUnderCursor.debugId() != -1) {
+            if (!containsReferenceUnderCursor && objectRefUnderCursor.debugId() != -1) {
                 foreach(int id, list) {
                     if (id == objectRefUnderCursor.debugId()) {
-                        containsReference = true;
+                        containsReferenceUnderCursor = true;
                         break;
                     }
                 }
             }
+
             selectedReferences << list;
         }
     }
 
-    if (!containsReference && objectRefUnderCursor.debugId() != -1)
+    // fallback: use ref under cursor if nothing else is found
+    if (selectedReferences.isEmpty()
+        && !containsReferenceUnderCursor
+        && objectRefUnderCursor.debugId() != -1)
+    {
         selectedReferences << objectRefUnderCursor.debugId();
+    }
 
     if (!selectedReferences.isEmpty()) {
         QList<QDeclarativeDebugObjectReference> refs;
-- 
GitLab