OSDN Git Service

Initial work on the code completion for GLSL files.
authorRoberto Raggi <roberto.raggi@nokia.com>
Fri, 12 Nov 2010 16:11:20 +0000 (17:11 +0100)
committerRoberto Raggi <roberto.raggi@nokia.com>
Fri, 12 Nov 2010 16:13:43 +0000 (17:13 +0100)
src/plugins/glsleditor/glslcodecompletion.cpp [new file with mode: 0644]
src/plugins/glsleditor/glslcodecompletion.h [new file with mode: 0644]
src/plugins/glsleditor/glsleditor.pro
src/plugins/glsleditor/glsleditorplugin.cpp

diff --git a/src/plugins/glsleditor/glslcodecompletion.cpp b/src/plugins/glsleditor/glslcodecompletion.cpp
new file mode 100644 (file)
index 0000000..359e483
--- /dev/null
@@ -0,0 +1,267 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+#include "glslcodecompletion.h"
+#include "glsleditor.h"
+#include <QtCore/QDebug>
+
+using namespace GLSLEditor;
+
+static const char *glsl_keywords[] =
+{ // ### TODO: get the keywords from the lexer
+  "attribute",
+  "bool",
+  "break",
+  "bvec2",
+  "bvec3",
+  "bvec4",
+  "case",
+  "centroid",
+  "const",
+  "continue",
+  "default",
+  "discard",
+  "dmat2",
+  "dmat2x2",
+  "dmat2x3",
+  "dmat2x4",
+  "dmat3",
+  "dmat3x2",
+  "dmat3x3",
+  "dmat3x4",
+  "dmat4",
+  "dmat4x2",
+  "dmat4x3",
+  "dmat4x4",
+  "do",
+  "double",
+  "dvec2",
+  "dvec3",
+  "dvec4",
+  "else",
+  "false",
+  "flat",
+  "float",
+  "for",
+  "highp",
+  "if",
+  "in",
+  "inout",
+  "int",
+  "invariant",
+  "isampler1D",
+  "isampler1DArray",
+  "isampler2D",
+  "isampler2DArray",
+  "isampler2DMS",
+  "isampler2DMSArray",
+  "isampler2DRect",
+  "isampler3D",
+  "isamplerBuffer",
+  "isamplerCube",
+  "isamplerCubeArray",
+  "ivec2",
+  "ivec3",
+  "ivec4",
+  "layout",
+  "lowp",
+  "mat2",
+  "mat2x2",
+  "mat2x3",
+  "mat2x4",
+  "mat3",
+  "mat3x2",
+  "mat3x3",
+  "mat3x4",
+  "mat4",
+  "mat4x2",
+  "mat4x3",
+  "mat4x4",
+  "mediump",
+  "noperspective",
+  "out",
+  "patch",
+  "precision",
+  "return",
+  "sample",
+  "sampler1D",
+  "sampler1DArray",
+  "sampler1DArrayShadow",
+  "sampler1DShadow",
+  "sampler2D",
+  "sampler2DArray",
+  "sampler2DArrayShadow",
+  "sampler2DMS",
+  "sampler2DMSArray",
+  "sampler2DRect",
+  "sampler2DRectShadow",
+  "sampler2DShadow",
+  "sampler3D",
+  "samplerBuffer",
+  "samplerCube",
+  "samplerCubeArray",
+  "samplerCubeArrayShadow",
+  "samplerCubeShadow",
+  "smooth",
+  "struct",
+  "subroutine",
+  "switch",
+  "true",
+  "uint",
+  "uniform",
+  "usampler1D",
+  "usampler1DArray",
+  "usampler2D",
+  "usampler2DArray",
+  "usampler2DMS",
+  "usampler2DMSarray",
+  "usampler2DRect",
+  "usampler3D",
+  "usamplerBuffer",
+  "usamplerCube",
+  "usamplerCubeArray",
+  "uvec2",
+  "uvec3",
+  "uvec4",
+  "varying",
+  "vec2",
+  "vec3",
+  "vec4",
+  "void",
+  "while",
+  0
+};
+
+CodeCompletion::CodeCompletion(QObject *parent)
+    : ICompletionCollector(parent),
+      m_editor(0),
+      m_startPosition(-1),
+      m_restartCompletion(false)
+{
+    for (const char **it = glsl_keywords; *it; ++it) {
+        TextEditor::CompletionItem item(this);
+        item.text = QString::fromLatin1(*it);
+        m_keywordCompletions.append(item);
+    }
+}
+
+CodeCompletion::~CodeCompletion()
+{
+}
+
+TextEditor::ITextEditable *CodeCompletion::editor() const
+{
+    return m_editor;
+}
+
+int CodeCompletion::startPosition() const
+{
+    return m_startPosition;
+}
+
+bool CodeCompletion::supportsEditor(TextEditor::ITextEditable *editor)
+{
+    if (qobject_cast<GLSLTextEditor *>(editor->widget()) != 0)
+        return true;
+
+    return false;
+}
+
+bool CodeCompletion::triggersCompletion(TextEditor::ITextEditable *editor)
+{
+    Q_UNUSED(editor);
+    return false;
+}
+
+int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
+{
+    m_editor = editor;
+
+    int pos = editor->position() - 1;
+    QChar ch = editor->characterAt(pos);
+    while (ch.isLetterOrNumber())
+        ch = editor->characterAt(--pos);
+
+    m_completions += m_keywordCompletions;
+
+    m_startPosition = pos + 1;
+    return m_startPosition;
+}
+
+void CodeCompletion::completions(QList<TextEditor::CompletionItem> *completions)
+{
+    const int length = m_editor->position() - m_startPosition;
+
+    if (length == 0)
+        *completions = m_completions;
+    else if (length > 0) {
+        const QString key = m_editor->textAt(m_startPosition, length);
+
+        filter(m_completions, completions, key);
+
+        if (completions->size() == 1) {
+            if (key == completions->first().text)
+                completions->clear();
+        }
+    }
+}
+
+bool CodeCompletion::typedCharCompletes(const TextEditor::CompletionItem &item, QChar typedChar)
+{
+    Q_UNUSED(item);
+    Q_UNUSED(typedChar);
+    return false;
+}
+
+void CodeCompletion::complete(const TextEditor::CompletionItem &item, QChar typedChar)
+{
+    Q_UNUSED(typedChar);
+
+    QString toInsert = item.text;
+
+    const int length = m_editor->position() - m_startPosition;
+    m_editor->setCurPos(m_startPosition);
+    m_editor->replace(length, toInsert);
+
+    if (toInsert.endsWith(QLatin1Char('.')) || toInsert.endsWith(QLatin1Char('(')))
+        m_restartCompletion = true;
+}
+
+bool CodeCompletion::partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems)
+{
+    return ICompletionCollector::partiallyComplete(completionItems);
+}
+
+void CodeCompletion::cleanup()
+{
+    m_editor = 0;
+    m_completions.clear();
+    m_restartCompletion = false;
+    m_startPosition = -1;
+}
+
diff --git a/src/plugins/glsleditor/glslcodecompletion.h b/src/plugins/glsleditor/glslcodecompletion.h
new file mode 100644 (file)
index 0000000..d75c195
--- /dev/null
@@ -0,0 +1,103 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+#ifndef GLSLCODECOMPLETION_H
+#define GLSLCODECOMPLETION_H
+
+#include <texteditor/icompletioncollector.h>
+
+namespace GLSLEditor {
+
+class CodeCompletion: public TextEditor::ICompletionCollector
+{
+    Q_OBJECT
+
+public:
+    CodeCompletion(QObject *parent = 0);
+    virtual ~CodeCompletion();
+
+    /* Returns the current active ITextEditable */
+    virtual TextEditor::ITextEditable *editor() const;
+    virtual int startPosition() const;
+
+    /*
+     * Returns true if this completion collector can be used with the given editor.
+     */
+    virtual bool supportsEditor(TextEditor::ITextEditable *editor);
+
+    /* This method should return whether the cursor is at a position which could
+     * trigger an autocomplete. It will be called each time a character is typed in
+     * the text editor.
+     */
+    virtual bool triggersCompletion(TextEditor::ITextEditable *editor);
+
+    // returns starting position
+    virtual int startCompletion(TextEditor::ITextEditable *editor);
+
+    /* This method should add all the completions it wants to show into the list,
+     * based on the given cursor position.
+     */
+    virtual void completions(QList<TextEditor::CompletionItem> *completions);
+
+    /**
+     * This method should return true when the given typed character should cause
+     * the selected completion item to be completed.
+     */
+    virtual bool typedCharCompletes(const TextEditor::CompletionItem &item, QChar typedChar);
+
+    /**
+     * This method should complete the given completion item.
+     *
+     * \param typedChar Non-null when completion was triggered by typing a
+     *                  character. Possible values depend on typedCharCompletes()
+     */
+    virtual void complete(const TextEditor::CompletionItem &item, QChar typedChar);
+
+    /* This method gives the completion collector a chance to partially complete
+     * based on a set of items. The general use case is to complete the common
+     * prefix shared by all possible completion items.
+     *
+     * Returns whether the completion popup should be closed.
+     */
+    virtual bool partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems);
+
+    /* Called when it's safe to clean up the completion items.
+     */
+    virtual void cleanup();
+
+private:
+    QList<TextEditor::CompletionItem> m_completions;
+    QList<TextEditor::CompletionItem> m_keywordCompletions;
+    TextEditor::ITextEditable *m_editor;
+    int m_startPosition;
+    bool m_restartCompletion;
+};
+
+} // namespace GLSLEditor
+
+#endif // GLSLCODECOMPLETION_H
index 6eb0334..1eb24f3 100644 (file)
@@ -15,7 +15,8 @@ glsleditorconstants.h \
 glsleditoreditable.h \
 glsleditorfactory.h \
 glsleditorplugin.h \
-    glslhighlighter.h
+    glslhighlighter.h \
+    glslcodecompletion.h
 
 SOURCES += \
 glsleditor.cpp \
@@ -23,7 +24,8 @@ glsleditoractionhandler.cpp \
 glsleditoreditable.cpp \
 glsleditorfactory.cpp \
 glsleditorplugin.cpp \
-    glslhighlighter.cpp
+    glslhighlighter.cpp \
+    glslcodecompletion.cpp
 
 OTHER_FILES += GLSLEditor.mimetypes.xml
 RESOURCES += glsleditor.qrc
index 2c8de08..7608ab3 100644 (file)
@@ -31,6 +31,7 @@
 #include "glsleditor.h"
 #include "glsleditorconstants.h"
 #include "glsleditorfactory.h"
+#include "glslcodecompletion.h"
 
 #include <coreplugin/icore.h>
 #include <coreplugin/coreconstants.h>
@@ -107,6 +108,9 @@ bool GLSLEditorPlugin::initialize(const QStringList & /*arguments*/, QString *er
     m_editor = new GLSLEditorFactory(this);
     addObject(m_editor);
 
+    CodeCompletion *completion = new CodeCompletion(this);
+    addAutoReleasedObject(completion);
+
     m_actionHandler = new TextEditor::TextEditorActionHandler(GLSLEditor::Constants::C_GLSLEDITOR_ID,
                                                               TextEditor::TextEditorActionHandler::Format
                                                               | TextEditor::TextEditorActionHandler::UnCommentSelection
@@ -122,7 +126,7 @@ bool GLSLEditorPlugin::initialize(const QStringList & /*arguments*/, QString *er
     menu->setTitle(tr("GLSL"));
     am->actionContainer(Core::Constants::M_TOOLS)->addMenu(glslToolsMenu);
 
-    Core::Command *cmd;
+    Core::Command *cmd = 0;
 
     // Insert marker for "Refactoring" menu:
     Core::Context globalContext(Core::Constants::C_GLOBAL);
@@ -137,10 +141,10 @@ bool GLSLEditorPlugin::initialize(const QStringList & /*arguments*/, QString *er
     contextMenu->addAction(cmd);
 
     // Set completion settings and keep them up to date
-//    TextEditor::TextEditorSettings *textEditorSettings = TextEditor::TextEditorSettings::instance();
-//    completion->setCompletionSettings(textEditorSettings->completionSettings());
-//    connect(textEditorSettings, SIGNAL(completionSettingsChanged(TextEditor::CompletionSettings)),
-//            completion, SLOT(setCompletionSettings(TextEditor::CompletionSettings)));
+    TextEditor::TextEditorSettings *textEditorSettings = TextEditor::TextEditorSettings::instance();
+    completion->setCompletionSettings(textEditorSettings->completionSettings());
+    connect(textEditorSettings, SIGNAL(completionSettingsChanged(TextEditor::CompletionSettings)),
+            completion, SLOT(setCompletionSettings(TextEditor::CompletionSettings)));
 
     error_message->clear();
 
@@ -170,8 +174,8 @@ void GLSLEditorPlugin::initializeEditor(GLSLEditor::GLSLTextEditor *editor)
     TextEditor::TextEditorSettings::instance()->initializeEditor(editor);
 
 //    // auto completion
-//    connect(editor, SIGNAL(requestAutoCompletion(TextEditor::ITextEditable*, bool)),
-//            TextEditor::CompletionSupport::instance(), SLOT(autoComplete(TextEditor::ITextEditable*, bool)));
+    connect(editor, SIGNAL(requestAutoCompletion(TextEditor::ITextEditable*, bool)),
+            TextEditor::CompletionSupport::instance(), SLOT(autoComplete(TextEditor::ITextEditable*, bool)));
 
 //    // quick fix
 //    connect(editor, SIGNAL(requestQuickFix(TextEditor::ITextEditable*)),