From 7bc2ab8ac96d25adc49ba8bf24eeec331825736f Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Thu, 28 Jan 2010 14:53:35 +0100
Subject: [PATCH] Automagically pop up the completion box (experimental) for
 QML/JS code (experimental).

---
 src/plugins/qmljseditor/qmlcodecompletion.cpp | 44 +++++++++++++++++++
 src/plugins/qmljseditor/qmlcodecompletion.h   |  1 +
 src/plugins/texteditor/completionsupport.cpp  |  3 ++
 .../texteditor/icompletioncollector.cpp       |  5 +++
 src/plugins/texteditor/icompletioncollector.h |  1 +
 5 files changed, 54 insertions(+)

diff --git a/src/plugins/qmljseditor/qmlcodecompletion.cpp b/src/plugins/qmljseditor/qmlcodecompletion.cpp
index 73e88bae9f7..8eae8dbc648 100644
--- a/src/plugins/qmljseditor/qmlcodecompletion.cpp
+++ b/src/plugins/qmljseditor/qmlcodecompletion.cpp
@@ -472,6 +472,9 @@ TextEditor::ITextEditable *QmlCodeCompletion::editor() const
 int QmlCodeCompletion::startPosition() const
 { return m_startPosition; }
 
+bool QmlCodeCompletion::shouldRestartCompletion()
+{ return false; }
+
 bool QmlCodeCompletion::supportsEditor(TextEditor::ITextEditable *editor)
 {
     if (qobject_cast<QmlJSTextEditor *>(editor->widget()))
@@ -480,12 +483,53 @@ bool QmlCodeCompletion::supportsEditor(TextEditor::ITextEditable *editor)
     return false;
 }
 
+static bool checkStartOfIdentifier(const QString &word)
+{
+    if (word.isEmpty())
+        return false;
+
+    const QChar ch = word.at(0);
+
+    switch (ch.unicode()) {
+    case '_': case '$':
+        return true;
+
+    default:
+        return ch.isLetter();
+    }
+}
+
+static bool isIdentifierChar(QChar ch)
+{
+    switch (ch.unicode()) {
+    case '_': case '$':
+        return true;
+
+    default:
+        return ch.isLetterOrNumber();
+    }
+}
+
 bool QmlCodeCompletion::triggersCompletion(TextEditor::ITextEditable *editor)
 {
     const QChar ch = editor->characterAt(editor->position() - 1);
 
     if (ch == QLatin1Char('(') || ch == QLatin1Char('.'))
         return true;
+    else if (isIdentifierChar(ch)) {
+        if (QmlJSTextEditor *ed = qobject_cast<QmlJSTextEditor *>(editor->widget())) {
+            QTextCursor tc = ed->textCursor();
+            tc.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
+            const QString word = tc.selectedText();
+            if (word.length() > 2 && checkStartOfIdentifier(word)) {
+                for (int i = 0; i < word.length(); ++i) {
+                    if (! isIdentifierChar(word.at(i)))
+                        return false;
+                }
+                return true;
+            }
+        }
+    }
 
     return false;
 }
diff --git a/src/plugins/qmljseditor/qmlcodecompletion.h b/src/plugins/qmljseditor/qmlcodecompletion.h
index 57681832a58..11aa36aa986 100644
--- a/src/plugins/qmljseditor/qmlcodecompletion.h
+++ b/src/plugins/qmljseditor/qmlcodecompletion.h
@@ -60,6 +60,7 @@ public:
 
     virtual TextEditor::ITextEditable *editor() const;
     virtual int startPosition() const;
+    virtual bool shouldRestartCompletion();
     virtual bool supportsEditor(TextEditor::ITextEditable *editor);
     virtual bool triggersCompletion(TextEditor::ITextEditable *editor);
     virtual int startCompletion(TextEditor::ITextEditable *editor);
diff --git a/src/plugins/texteditor/completionsupport.cpp b/src/plugins/texteditor/completionsupport.cpp
index ea5865f3a28..5320abf0fcd 100644
--- a/src/plugins/texteditor/completionsupport.cpp
+++ b/src/plugins/texteditor/completionsupport.cpp
@@ -77,6 +77,9 @@ void CompletionSupport::cleanupCompletions()
         disconnect(m_completionList, SIGNAL(destroyed(QObject*)),
                    this, SLOT(cleanupCompletions()));
 
+    if (m_checkCompletionTrigger)
+        m_checkCompletionTrigger = m_completionCollector->shouldRestartCompletion();
+
     m_completionList = 0;
     m_completionCollector->cleanup();
 
diff --git a/src/plugins/texteditor/icompletioncollector.cpp b/src/plugins/texteditor/icompletioncollector.cpp
index cc369031036..dc5905c493b 100644
--- a/src/plugins/texteditor/icompletioncollector.cpp
+++ b/src/plugins/texteditor/icompletioncollector.cpp
@@ -167,3 +167,8 @@ void ICompletionCollector::filter(const QList<TextEditor::CompletionItem> &items
         }
     }
 }
+
+bool ICompletionCollector::shouldRestartCompletion()
+{
+    return true;
+}
diff --git a/src/plugins/texteditor/icompletioncollector.h b/src/plugins/texteditor/icompletioncollector.h
index ad2ea7fa2e6..87638aadb3b 100644
--- a/src/plugins/texteditor/icompletioncollector.h
+++ b/src/plugins/texteditor/icompletioncollector.h
@@ -77,6 +77,7 @@ public:
     virtual ~ICompletionCollector() {}
 
     virtual QList<CompletionItem> getCompletions();
+    virtual bool shouldRestartCompletion();
 
     /* Returns the current active ITextEditable */
     virtual ITextEditable *editor() const = 0;
-- 
GitLab