From 1175705bfc8934909db3c74385a17c8d0daba4b3 Mon Sep 17 00:00:00 2001
From: Leandro Melo <leandro.melo@nokia.com>
Date: Thu, 2 Dec 2010 17:02:23 +0100
Subject: [PATCH] Snippets: Make it easier for plugins to add snippets groups

Groups are no longer enum values but identified from snippet providers.
---
 src/plugins/cppeditor/cppeditor.pro           |   4 +-
 src/plugins/cppeditor/cppeditorconstants.h    |   2 +
 src/plugins/cppeditor/cppplugin.cpp           |   4 +-
 ...ordecorator.cpp => cppsnippetprovider.cpp} |  24 ++-
 ...editordecorator.h => cppsnippetprovider.h} |  13 +-
 src/plugins/cpptools/cppcodecompletion.cpp    |   4 +-
 src/plugins/cpptools/cppcodecompletion.h      |   4 +-
 .../qmljseditor/qmljscodecompletion.cpp       |   3 +-
 src/plugins/qmljseditor/qmljscodecompletion.h |   4 +-
 src/plugins/qmljseditor/qmljseditor.pro       |   4 +-
 .../qmljseditor/qmljseditorconstants.h        |   1 +
 src/plugins/qmljseditor/qmljseditorplugin.cpp |   4 +-
 ...decorator.cpp => qmljssnippetprovider.cpp} |  24 ++-
 ...itordecorator.h => qmljssnippetprovider.h} |  13 +-
 ...itordecorator.cpp => isnippetprovider.cpp} |   6 +-
 ...eteditordecorator.h => isnippetprovider.h} |  11 +-
 .../snippets/plaintextsnippetprovider.cpp     |  56 +++++++
 .../snippets/plaintextsnippetprovider.h       |  53 ++++++
 src/plugins/texteditor/snippets/reuse.h       |  26 ---
 src/plugins/texteditor/snippets/snippet.cpp   |  18 +-
 src/plugins/texteditor/snippets/snippet.h     |  22 +--
 ...ippetprovider.cpp => snippetcollector.cpp} |  22 +--
 .../{snippetprovider.h => snippetcollector.h} |  11 +-
 src/plugins/texteditor/snippets/snippets.xml  |   1 +
 .../snippets/snippetscollection.cpp           | 154 +++++++++++-------
 .../texteditor/snippets/snippetscollection.h  |  67 +++++---
 .../texteditor/snippets/snippetsmanager.h     |   3 +
 .../texteditor/snippets/snippetssettings.cpp  |   3 +-
 .../snippets/snippetssettingspage.cpp         | 105 ++++++------
 src/plugins/texteditor/texteditor.pro         |  10 +-
 src/plugins/texteditor/texteditorconstants.h  |   1 +
 src/plugins/texteditor/texteditorplugin.cpp   |   4 +
 32 files changed, 410 insertions(+), 271 deletions(-)
 rename src/plugins/cppeditor/{cppsnippeteditordecorator.cpp => cppsnippetprovider.cpp} (81%)
 rename src/plugins/cppeditor/{cppsnippeteditordecorator.h => cppsnippetprovider.h} (80%)
 rename src/plugins/qmljseditor/{qmljssnippeteditordecorator.cpp => qmljssnippetprovider.cpp} (79%)
 rename src/plugins/qmljseditor/{qmljssnippeteditordecorator.h => qmljssnippetprovider.h} (80%)
 rename src/plugins/texteditor/snippets/{isnippeteditordecorator.cpp => isnippetprovider.cpp} (89%)
 rename src/plugins/texteditor/snippets/{isnippeteditordecorator.h => isnippetprovider.h} (85%)
 create mode 100644 src/plugins/texteditor/snippets/plaintextsnippetprovider.cpp
 create mode 100644 src/plugins/texteditor/snippets/plaintextsnippetprovider.h
 rename src/plugins/texteditor/snippets/{snippetprovider.cpp => snippetcollector.cpp} (75%)
 rename src/plugins/texteditor/snippets/{snippetprovider.h => snippetcollector.h} (89%)

diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro
index a9bd9296ff4..9f38859a880 100644
--- a/src/plugins/cppeditor/cppeditor.pro
+++ b/src/plugins/cppeditor/cppeditor.pro
@@ -26,7 +26,7 @@ HEADERS += cppplugin.h \
     cppqtstyleindenter.h \
     cppautocompleter.h \
     cppcompleteswitch.h \
-    cppsnippeteditordecorator.h
+    cppsnippetprovider.h
 
 SOURCES += cppplugin.cpp \
     cppeditor.cpp \
@@ -47,7 +47,7 @@ SOURCES += cppplugin.cpp \
     cppqtstyleindenter.cpp \
     cppautocompleter.cpp \
     cppcompleteswitch.cpp \
-    cppsnippeteditordecorator.cpp
+    cppsnippetprovider.cpp
 
 RESOURCES += cppeditor.qrc
 OTHER_FILES += CppEditor.mimetypes.xml
diff --git a/src/plugins/cppeditor/cppeditorconstants.h b/src/plugins/cppeditor/cppeditorconstants.h
index 17c13d1186d..c90b46abbdf 100644
--- a/src/plugins/cppeditor/cppeditorconstants.h
+++ b/src/plugins/cppeditor/cppeditorconstants.h
@@ -68,6 +68,8 @@ const char * const CPP_HEADER_MIMETYPE = "text/x-c++hdr";
 const char * const WIZARD_CATEGORY = "O.C++";
 const char * const WIZARD_TR_CATEGORY = QT_TRANSLATE_NOOP("CppEditor", "C++");
 
+const char * const CPP_SNIPPETS_GROUP_ID = "C++";
+
 } // namespace Constants
 } // namespace CppEditor
 
diff --git a/src/plugins/cppeditor/cppplugin.cpp b/src/plugins/cppeditor/cppplugin.cpp
index a33a151aee7..21d0c8a6dbe 100644
--- a/src/plugins/cppeditor/cppplugin.cpp
+++ b/src/plugins/cppeditor/cppplugin.cpp
@@ -38,7 +38,7 @@
 #include "cppoutline.h"
 #include "cppquickfixcollector.h"
 #include "cpptypehierarchy.h"
-#include "cppsnippeteditordecorator.h"
+#include "cppsnippetprovider.h"
 
 #include <coreplugin/icore.h>
 #include <coreplugin/coreconstants.h>
@@ -212,7 +212,7 @@ bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMess
     addAutoReleasedObject(new CppHoverHandler);
     addAutoReleasedObject(new CppOutlineWidgetFactory);
     addAutoReleasedObject(new CppTypeHierarchyFactory);
-    addAutoReleasedObject(new CppSnippetEditorDecorator);
+    addAutoReleasedObject(new CppSnippetProvider);
 
     m_quickFixCollector = new CppQuickFixCollector;
     addAutoReleasedObject(m_quickFixCollector);
diff --git a/src/plugins/cppeditor/cppsnippeteditordecorator.cpp b/src/plugins/cppeditor/cppsnippetprovider.cpp
similarity index 81%
rename from src/plugins/cppeditor/cppsnippeteditordecorator.cpp
rename to src/plugins/cppeditor/cppsnippetprovider.cpp
index 159a6c38229..b7273f8c97a 100644
--- a/src/plugins/cppeditor/cppsnippeteditordecorator.cpp
+++ b/src/plugins/cppeditor/cppsnippetprovider.cpp
@@ -27,35 +27,41 @@
 **
 **************************************************************************/
 
-#include "cppsnippeteditordecorator.h"
+#include "cppsnippetprovider.h"
 #include "cpphighlighter.h"
 #include "cppeditor.h"
 #include "cppqtstyleindenter.h"
 #include "cppautocompleter.h"
+#include "cppeditorconstants.h"
 
 #include <texteditor/texteditorsettings.h>
 #include <texteditor/fontsettings.h>
 #include <texteditor/texteditorconstants.h>
 #include <texteditor/snippets/snippeteditor.h>
 
+#include <QtCore/QLatin1String>
+
 using namespace CppEditor;
 using namespace Internal;
 
-CppSnippetEditorDecorator::CppSnippetEditorDecorator() :
-    TextEditor::ISnippetEditorDecorator()
+CppSnippetProvider::CppSnippetProvider() :
+    TextEditor::ISnippetProvider()
 {}
 
-CppSnippetEditorDecorator::~CppSnippetEditorDecorator()
+CppSnippetProvider::~CppSnippetProvider()
 {}
 
-bool CppSnippetEditorDecorator::supports(TextEditor::Snippet::Group group) const
+QString CppSnippetProvider::groupId() const
+{
+    return QLatin1String(Constants::CPP_SNIPPETS_GROUP_ID);
+}
+
+QString CppSnippetProvider::displayName() const
 {
-    if (group == TextEditor::Snippet::Cpp)
-        return true;
-    return false;
+    return tr("C++");
 }
 
-void CppSnippetEditorDecorator::apply(TextEditor::SnippetEditor *editor) const
+void CppSnippetProvider::decorateEditor(TextEditor::SnippetEditor *editor) const
 {
     CppHighlighter *highlighter = new CppHighlighter;
     const TextEditor::FontSettings &fs = TextEditor::TextEditorSettings::instance()->fontSettings();
diff --git a/src/plugins/cppeditor/cppsnippeteditordecorator.h b/src/plugins/cppeditor/cppsnippetprovider.h
similarity index 80%
rename from src/plugins/cppeditor/cppsnippeteditordecorator.h
rename to src/plugins/cppeditor/cppsnippetprovider.h
index 605099e19c0..ba3f172be0b 100644
--- a/src/plugins/cppeditor/cppsnippeteditordecorator.h
+++ b/src/plugins/cppeditor/cppsnippetprovider.h
@@ -30,20 +30,21 @@
 #ifndef CPPSNIPPETEDITORDECORATOR_H
 #define CPPSNIPPETEDITORDECORATOR_H
 
-#include <texteditor/snippets/isnippeteditordecorator.h>
+#include <texteditor/snippets/isnippetprovider.h>
 
 namespace CppEditor {
 namespace Internal {
 
-class CppSnippetEditorDecorator : public TextEditor::ISnippetEditorDecorator
+class CppSnippetProvider : public TextEditor::ISnippetProvider
 {
 public:
-    CppSnippetEditorDecorator();
-    virtual ~CppSnippetEditorDecorator();
+    CppSnippetProvider();
+    virtual ~CppSnippetProvider();
 
 public:
-    virtual bool supports(TextEditor::Snippet::Group group) const;
-    virtual void apply(TextEditor::SnippetEditor *editor) const;
+    virtual QString groupId() const;
+    virtual QString displayName() const;
+    virtual void decorateEditor(TextEditor::SnippetEditor *editor) const;
 };
 
 } // Internal
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 479de433d10..e73e5451420 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -52,6 +52,8 @@
 #include <cplusplus/BackwardsScanner.h>
 #include <cplusplus/LookupContext.h>
 
+#include <cppeditor/cppeditorconstants.h>
+
 #include <coreplugin/icore.h>
 #include <coreplugin/mimedatabase.h>
 #include <coreplugin/editormanager/editormanager.h>
@@ -463,7 +465,7 @@ CppCodeCompletion::CppCodeCompletion(CppModelManager *manager)
       m_automaticCompletion(false),
       m_completionOperator(T_EOF_SYMBOL),
       m_objcEnabled(true),
-      m_snippetProvider(TextEditor::Snippet::Cpp,
+      m_snippetProvider(CppEditor::Constants::CPP_SNIPPETS_GROUP_ID,
                         QIcon(QLatin1String(":/texteditor/images/snippet.png")))
 {
 }
diff --git a/src/plugins/cpptools/cppcodecompletion.h b/src/plugins/cpptools/cppcodecompletion.h
index 483bf3358b2..28239823560 100644
--- a/src/plugins/cpptools/cppcodecompletion.h
+++ b/src/plugins/cpptools/cppcodecompletion.h
@@ -37,7 +37,7 @@
 #include <cplusplus/TypeOfExpression.h>
 
 #include <texteditor/icompletioncollector.h>
-#include <texteditor/snippets/snippetprovider.h>
+#include <texteditor/snippets/snippetcollector.h>
 
 #include <QtCore/QObject>
 #include <QtCore/QPointer>
@@ -153,7 +153,7 @@ private:
     unsigned m_completionOperator;
     bool m_objcEnabled;
 
-    TextEditor::SnippetProvider m_snippetProvider;
+    TextEditor::SnippetCollector m_snippetProvider;
 
     CPlusPlus::Icons m_icons;
     CPlusPlus::Overview overview;
diff --git a/src/plugins/qmljseditor/qmljscodecompletion.cpp b/src/plugins/qmljseditor/qmljscodecompletion.cpp
index 8dc714dc80e..c9c21c658e8 100644
--- a/src/plugins/qmljseditor/qmljscodecompletion.cpp
+++ b/src/plugins/qmljseditor/qmljscodecompletion.cpp
@@ -30,6 +30,7 @@
 #include "qmljscodecompletion.h"
 #include "qmlexpressionundercursor.h"
 #include "qmljseditor.h"
+#include "qmljseditorconstants.h"
 
 #include <qmljs/qmljsmodelmanagerinterface.h>
 #include <qmljs/parser/qmljsast_p.h>
@@ -487,7 +488,7 @@ CodeCompletion::CodeCompletion(ModelManagerInterface *modelManager, QObject *par
       m_editor(0),
       m_startPosition(0),
       m_restartCompletion(false),
-      m_snippetProvider(TextEditor::Snippet::Qml, iconForColor(Qt::red), SnippetOrder)
+      m_snippetProvider(Constants::QML_SNIPPETS_GROUP_ID, iconForColor(Qt::red), SnippetOrder)
 {
     Q_ASSERT(modelManager);
 }
diff --git a/src/plugins/qmljseditor/qmljscodecompletion.h b/src/plugins/qmljseditor/qmljscodecompletion.h
index d3448c4c72f..ae8c8589a43 100644
--- a/src/plugins/qmljseditor/qmljscodecompletion.h
+++ b/src/plugins/qmljseditor/qmljscodecompletion.h
@@ -32,7 +32,7 @@
 
 #include <qmljs/qmljsdocument.h>
 #include <texteditor/icompletioncollector.h>
-#include <texteditor/snippets/snippetprovider.h>
+#include <texteditor/snippets/snippetcollector.h>
 #include <QtCore/QDateTime>
 #include <QtCore/QPointer>
 
@@ -97,7 +97,7 @@ private:
     TextEditor::ITextEditable *m_editor;
     int m_startPosition;
     bool m_restartCompletion;
-    TextEditor::SnippetProvider m_snippetProvider;
+    TextEditor::SnippetCollector m_snippetProvider;
     QList<TextEditor::CompletionItem> m_completions;
     QPointer<FunctionArgumentWidget> m_functionArgumentWidget;
 };
diff --git a/src/plugins/qmljseditor/qmljseditor.pro b/src/plugins/qmljseditor/qmljseditor.pro
index 24e6caf03db..6d08513810a 100644
--- a/src/plugins/qmljseditor/qmljseditor.pro
+++ b/src/plugins/qmljseditor/qmljseditor.pro
@@ -35,7 +35,7 @@ HEADERS += \
     qmljsindenter.h \
     qmljsautocompleter.h \
     jsfilewizard.h \
-    qmljssnippeteditordecorator.h
+    qmljssnippetprovider.h
 
 SOURCES += \
     qmljscodecompletion.cpp \
@@ -64,7 +64,7 @@ SOURCES += \
     qmljsindenter.cpp \
     qmljsautocompleter.cpp \
     jsfilewizard.cpp \
-    qmljssnippeteditordecorator.cpp
+    qmljssnippetprovider.cpp
 
 RESOURCES += qmljseditor.qrc
 OTHER_FILES += QmlJSEditor.mimetypes.xml
diff --git a/src/plugins/qmljseditor/qmljseditorconstants.h b/src/plugins/qmljseditor/qmljseditorconstants.h
index 63de1bb73ba..496facce501 100644
--- a/src/plugins/qmljseditor/qmljseditorconstants.h
+++ b/src/plugins/qmljseditor/qmljseditorconstants.h
@@ -60,6 +60,7 @@ const char *const TASK_CATEGORY_QML = "Task.Category.Qml";
 const char * const WIZARD_CATEGORY_QML = "S.Qml";
 const char * const WIZARD_TR_CATEGORY_QML = QT_TRANSLATE_NOOP("QmlJsEditor", "QML");
 
+const char * const QML_SNIPPETS_GROUP_ID = "QML";
 
 } // namespace Constants
 } // namespace QmlJSEditor
diff --git a/src/plugins/qmljseditor/qmljseditorplugin.cpp b/src/plugins/qmljseditor/qmljseditorplugin.cpp
index 1d394e62015..ef362840621 100644
--- a/src/plugins/qmljseditor/qmljseditorplugin.cpp
+++ b/src/plugins/qmljseditor/qmljseditorplugin.cpp
@@ -39,7 +39,7 @@
 #include "qmljsoutline.h"
 #include "qmljspreviewrunner.h"
 #include "qmljsquickfix.h"
-#include "qmljssnippeteditordecorator.h"
+#include "qmljssnippetprovider.h"
 #include "qmltaskmanager.h"
 #include "quicktoolbar.h"
 #include "quicktoolbarsettingspage.h"
@@ -129,7 +129,7 @@ bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *e
         return false;
 
     m_modelManager = QmlJS::ModelManagerInterface::instance();
-    addAutoReleasedObject(new QmlJSSnippetEditorDecorator);
+    addAutoReleasedObject(new QmlJSSnippetProvider);
 
     Core::Context context(QmlJSEditor::Constants::C_QMLJSEDITOR_ID);
 
diff --git a/src/plugins/qmljseditor/qmljssnippeteditordecorator.cpp b/src/plugins/qmljseditor/qmljssnippetprovider.cpp
similarity index 79%
rename from src/plugins/qmljseditor/qmljssnippeteditordecorator.cpp
rename to src/plugins/qmljseditor/qmljssnippetprovider.cpp
index 0413bdf3800..9c24e197308 100644
--- a/src/plugins/qmljseditor/qmljssnippeteditordecorator.cpp
+++ b/src/plugins/qmljseditor/qmljssnippetprovider.cpp
@@ -27,35 +27,41 @@
 **
 **************************************************************************/
 
-#include "qmljssnippeteditordecorator.h"
+#include "qmljssnippetprovider.h"
 #include "qmljshighlighter.h"
 #include "qmljseditor.h"
 #include "qmljsindenter.h"
 #include "qmljsautocompleter.h"
+#include "qmljseditorconstants.h"
 
 #include <texteditor/texteditorsettings.h>
 #include <texteditor/fontsettings.h>
 #include <texteditor/texteditorconstants.h>
 #include <texteditor/snippets/snippeteditor.h>
 
+#include <QtCore/QLatin1String>
+
 using namespace QmlJSEditor;
 using namespace Internal;
 
-QmlJSSnippetEditorDecorator::QmlJSSnippetEditorDecorator() :
-    TextEditor::ISnippetEditorDecorator()
+QmlJSSnippetProvider::QmlJSSnippetProvider() :
+    TextEditor::ISnippetProvider()
 {}
 
-QmlJSSnippetEditorDecorator::~QmlJSSnippetEditorDecorator()
+QmlJSSnippetProvider::~QmlJSSnippetProvider()
 {}
 
-bool QmlJSSnippetEditorDecorator::supports(TextEditor::Snippet::Group group) const
+QString QmlJSSnippetProvider::groupId() const
+{
+    return QLatin1String(Constants::QML_SNIPPETS_GROUP_ID);
+}
+
+QString QmlJSSnippetProvider::displayName() const
 {
-    if (group == TextEditor::Snippet::Qml)
-        return true;
-    return false;
+    return tr("QML");
 }
 
-void QmlJSSnippetEditorDecorator::apply(TextEditor::SnippetEditor *editor) const
+void QmlJSSnippetProvider::decorateEditor(TextEditor::SnippetEditor *editor) const
 {
     Highlighter *highlighter = new Highlighter;
     const TextEditor::FontSettings &fs = TextEditor::TextEditorSettings::instance()->fontSettings();
diff --git a/src/plugins/qmljseditor/qmljssnippeteditordecorator.h b/src/plugins/qmljseditor/qmljssnippetprovider.h
similarity index 80%
rename from src/plugins/qmljseditor/qmljssnippeteditordecorator.h
rename to src/plugins/qmljseditor/qmljssnippetprovider.h
index d22a4785642..f3b7b18550b 100644
--- a/src/plugins/qmljseditor/qmljssnippeteditordecorator.h
+++ b/src/plugins/qmljseditor/qmljssnippetprovider.h
@@ -30,20 +30,21 @@
 #ifndef QMLJSSNIPPETEDITORDECORATOR_H
 #define QMLJSSNIPPETEDITORDECORATOR_H
 
-#include <texteditor/snippets/isnippeteditordecorator.h>
+#include <texteditor/snippets/isnippetprovider.h>
 
 namespace QmlJSEditor {
 namespace Internal {
 
-class QmlJSSnippetEditorDecorator : public TextEditor::ISnippetEditorDecorator
+class QmlJSSnippetProvider : public TextEditor::ISnippetProvider
 {
 public:
-    QmlJSSnippetEditorDecorator();
-    virtual ~QmlJSSnippetEditorDecorator();
+    QmlJSSnippetProvider();
+    virtual ~QmlJSSnippetProvider();
 
 public:
-    virtual bool supports(TextEditor::Snippet::Group group) const;
-    virtual void apply(TextEditor::SnippetEditor *editor) const;
+    virtual QString groupId() const;
+    virtual QString displayName() const;
+    virtual void decorateEditor(TextEditor::SnippetEditor *editor) const;
 };
 
 } // Internal
diff --git a/src/plugins/texteditor/snippets/isnippeteditordecorator.cpp b/src/plugins/texteditor/snippets/isnippetprovider.cpp
similarity index 89%
rename from src/plugins/texteditor/snippets/isnippeteditordecorator.cpp
rename to src/plugins/texteditor/snippets/isnippetprovider.cpp
index 5c94c6ec656..f438ad0b007 100644
--- a/src/plugins/texteditor/snippets/isnippeteditordecorator.cpp
+++ b/src/plugins/texteditor/snippets/isnippetprovider.cpp
@@ -27,12 +27,12 @@
 **
 **************************************************************************/
 
-#include "isnippeteditordecorator.h"
+#include "isnippetprovider.h"
 
 using namespace TextEditor;
 
-ISnippetEditorDecorator::ISnippetEditorDecorator() : QObject()
+ISnippetProvider::ISnippetProvider() : QObject()
 {}
 
-ISnippetEditorDecorator::~ISnippetEditorDecorator()
+ISnippetProvider::~ISnippetProvider()
 {}
diff --git a/src/plugins/texteditor/snippets/isnippeteditordecorator.h b/src/plugins/texteditor/snippets/isnippetprovider.h
similarity index 85%
rename from src/plugins/texteditor/snippets/isnippeteditordecorator.h
rename to src/plugins/texteditor/snippets/isnippetprovider.h
index 945461f308b..8f3a881e5f6 100644
--- a/src/plugins/texteditor/snippets/isnippeteditordecorator.h
+++ b/src/plugins/texteditor/snippets/isnippetprovider.h
@@ -40,17 +40,18 @@ namespace TextEditor {
 
 class SnippetEditor;
 
-class TEXTEDITOR_EXPORT ISnippetEditorDecorator : public QObject
+class TEXTEDITOR_EXPORT ISnippetProvider : public QObject
 {
     Q_OBJECT
 public:
-    virtual ~ISnippetEditorDecorator();
+    virtual ~ISnippetProvider();
 
-    virtual bool supports(Snippet::Group group) const = 0;
-    virtual void apply(SnippetEditor *editor) const = 0;
+    virtual QString groupId() const = 0;
+    virtual QString displayName() const = 0;
+    virtual void decorateEditor(SnippetEditor *editor) const = 0;
 
 protected:
-    ISnippetEditorDecorator();
+    ISnippetProvider();
 };
 
 } // TextEditor
diff --git a/src/plugins/texteditor/snippets/plaintextsnippetprovider.cpp b/src/plugins/texteditor/snippets/plaintextsnippetprovider.cpp
new file mode 100644
index 00000000000..a333e201db9
--- /dev/null
+++ b/src/plugins/texteditor/snippets/plaintextsnippetprovider.cpp
@@ -0,0 +1,56 @@
+/**************************************************************************
+**
+** 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 "plaintextsnippetprovider.h"
+
+#include <texteditor/texteditorconstants.h>
+
+#include <QtCore/QLatin1String>
+
+using namespace TextEditor;
+using namespace Internal;
+
+PlainTextSnippetProvider::PlainTextSnippetProvider()
+{}
+
+PlainTextSnippetProvider::~PlainTextSnippetProvider()
+{}
+
+QString PlainTextSnippetProvider::groupId() const
+{
+    return QLatin1String(Constants::TEXT_SNIPPET_GROUP_ID);
+}
+
+QString PlainTextSnippetProvider::displayName() const
+{
+    return tr("Text");
+}
+
+void PlainTextSnippetProvider::decorateEditor(TextEditor::SnippetEditor *) const
+{}
diff --git a/src/plugins/texteditor/snippets/plaintextsnippetprovider.h b/src/plugins/texteditor/snippets/plaintextsnippetprovider.h
new file mode 100644
index 00000000000..4d7a608d21b
--- /dev/null
+++ b/src/plugins/texteditor/snippets/plaintextsnippetprovider.h
@@ -0,0 +1,53 @@
+/**************************************************************************
+**
+** 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 PLAINTEXTSNIPPETPROVIDER_H
+#define PLAINTEXTSNIPPETPROVIDER_H
+
+#include "isnippetprovider.h"
+
+namespace TextEditor {
+namespace Internal {
+
+class PlainTextSnippetProvider : public ISnippetProvider
+{
+public:
+    PlainTextSnippetProvider();
+    virtual ~PlainTextSnippetProvider();
+
+public:
+    virtual QString groupId() const;
+    virtual QString displayName() const;
+    virtual void decorateEditor(TextEditor::SnippetEditor *editor) const;
+};
+
+} // Internal
+} // TextEditor
+
+#endif // PLAINTEXTSNIPPETPROVIDER_H
diff --git a/src/plugins/texteditor/snippets/reuse.h b/src/plugins/texteditor/snippets/reuse.h
index 5ab7b403ec6..17c4a34888f 100644
--- a/src/plugins/texteditor/snippets/reuse.h
+++ b/src/plugins/texteditor/snippets/reuse.h
@@ -30,41 +30,15 @@
 #ifndef REUSE_H
 #define REUSE_H
 
-#include "snippet.h"
-
 #include <QtCore/QString>
 #include <QtCore/QLatin1String>
 
 namespace TextEditor {
 namespace Internal {
 
-const QLatin1String kCpp("C++");
-const QLatin1String kQml("QML");
-const QLatin1String kText("Text");
 const QLatin1String kTrue("true");
 const QLatin1String kFalse("false");
 
-inline Snippet::Group toSnippetGroup(const QString &s)
-{
-    const QString &upper = s.toUpper();
-    if (upper == kCpp)
-        return Snippet::Cpp;
-    else if (upper == kQml)
-        return Snippet::Qml;
-    else
-        return Snippet::PlainText;
-}
-
-inline QString fromSnippetGroup(Snippet::Group group)
-{
-    if (group == Snippet::Cpp)
-        return kCpp;
-    else if (group == Snippet::Qml)
-        return kQml;
-    else
-        return kText;
-}
-
 inline bool toBool(const QString &s)
 {
     if (s == kTrue)
diff --git a/src/plugins/texteditor/snippets/snippet.cpp b/src/plugins/texteditor/snippets/snippet.cpp
index b00056110ce..7291e8084b5 100644
--- a/src/plugins/texteditor/snippets/snippet.cpp
+++ b/src/plugins/texteditor/snippets/snippet.cpp
@@ -37,7 +37,8 @@ using namespace TextEditor;
 
 const QChar Snippet::kVariableDelimiter(QLatin1Char('$'));
 
-Snippet::Snippet(const QString &id) : m_isRemoved(false), m_isModified(false), m_id(id)
+Snippet::Snippet(const QString &groupId, const QString &id) :
+    m_isRemoved(false), m_isModified(false), m_groupId(groupId), m_id(id)
 {}
 
 Snippet::~Snippet()
@@ -48,6 +49,11 @@ const QString &Snippet::id() const
     return m_id;
 }
 
+const QString &Snippet::groupId() const
+{
+    return m_groupId;
+}
+
 bool Snippet::isBuiltIn() const
 {
     return !m_id.isEmpty();
@@ -103,16 +109,6 @@ bool Snippet::isModified() const
     return m_isModified;
 }
 
-void Snippet::setGroup(Group group)
-{
-    m_group = group;
-}
-
-Snippet::Group Snippet::group() const
-{
-    return m_group;
-}
-
 QString Snippet::generateTip() const
 {
     static const QLatin1Char kNewLine('\n');
diff --git a/src/plugins/texteditor/snippets/snippet.h b/src/plugins/texteditor/snippets/snippet.h
index 984da3e7f9c..2ec985408b3 100644
--- a/src/plugins/texteditor/snippets/snippet.h
+++ b/src/plugins/texteditor/snippets/snippet.h
@@ -40,18 +40,11 @@ namespace TextEditor {
 class TEXTEDITOR_EXPORT Snippet
 {
 public:
-    Snippet(const QString &id = QString());
+    Snippet(const QString &groupId = QString(), const QString &id = QString());
     ~Snippet();
 
-    // Values from this enumeration need to be contiguous (they are used as indexes).
-    enum Group {
-        Cpp = 0,
-        Qml,
-        PlainText,
-        GroupSize
-    };
-
     const QString &id() const;
+    const QString &groupId() const;
 
     bool isBuiltIn() const;
 
@@ -70,9 +63,6 @@ public:
     void setIsModified(bool modified);
     bool isModified() const;
 
-    void setGroup(Group group);
-    Group group() const;
-
     QString generateTip() const;
 
     static const QChar kVariableDelimiter;
@@ -80,19 +70,13 @@ public:
 private:
     bool m_isRemoved;
     bool m_isModified;
+    QString m_groupId;
     QString m_id; // Only built-in snippets have an id.
     QString m_trigger;
     QString m_content;
     QString m_complement;
-    Group m_group;
 };
 
-inline Snippet::Group& operator++(Snippet::Group& group)
-{
-    group = Snippet::Group(group + 1);
-    return group;
-}
-
 } // TextEditor
 
 #endif // SNIPPET_H
diff --git a/src/plugins/texteditor/snippets/snippetprovider.cpp b/src/plugins/texteditor/snippets/snippetcollector.cpp
similarity index 75%
rename from src/plugins/texteditor/snippets/snippetprovider.cpp
rename to src/plugins/texteditor/snippets/snippetcollector.cpp
index 37c94380d00..0a875ca4f47 100644
--- a/src/plugins/texteditor/snippets/snippetprovider.cpp
+++ b/src/plugins/texteditor/snippets/snippetcollector.cpp
@@ -27,10 +27,12 @@
 **
 **************************************************************************/
 
-#include "snippetprovider.h"
+#include "snippetcollector.h"
 #include "snippetsmanager.h"
 #include "snippetscollection.h"
 
+#include <texteditor/texteditorconstants.h>
+
 using namespace TextEditor;
 using namespace Internal;
 
@@ -38,15 +40,15 @@ namespace {
 
 void appendSnippets(ICompletionCollector *collector,
                     QList<CompletionItem> *completionItems,
-                    Snippet::Group group,
+                    const QString &groupId,
                     const QIcon &icon,
                     int order)
 {
     QSharedPointer<SnippetsCollection> collection =
         SnippetsManager::instance()->snippetsCollection();
-    const int size = collection->totalActiveSnippets(group);
+    const int size = collection->totalActiveSnippets(groupId);
     for (int i = 0; i < size; ++i) {
-        const Snippet &snippet = collection->snippet(i, group);
+        const Snippet &snippet = collection->snippet(i, groupId);
         CompletionItem item(collector);
         item.text = snippet.trigger() + QLatin1Char(' ') + snippet.complement();
         item.data = snippet.content();
@@ -60,17 +62,17 @@ void appendSnippets(ICompletionCollector *collector,
 
 } // anonymous
 
-SnippetProvider::SnippetProvider(Snippet::Group group, const QIcon &icon, int order) :
-    m_group(group), m_icon(icon), m_order(order)
+SnippetCollector::SnippetCollector(const QString &groupId, const QIcon &icon, int order) :
+    m_groupId(groupId), m_icon(icon), m_order(order)
 {}
 
-SnippetProvider::~SnippetProvider()
+SnippetCollector::~SnippetCollector()
 {}
 
-QList<CompletionItem> SnippetProvider::getSnippets(ICompletionCollector *collector) const
+QList<CompletionItem> SnippetCollector::getSnippets(ICompletionCollector *collector) const
 {
     QList<CompletionItem> completionItems;
-    appendSnippets(collector, &completionItems, m_group, m_icon, m_order);
-    appendSnippets(collector, &completionItems, Snippet::PlainText, m_icon, m_order);
+    appendSnippets(collector, &completionItems, m_groupId, m_icon, m_order);
+    appendSnippets(collector, &completionItems, Constants::TEXT_SNIPPET_GROUP_ID, m_icon, m_order);
     return completionItems;
 }
diff --git a/src/plugins/texteditor/snippets/snippetprovider.h b/src/plugins/texteditor/snippets/snippetcollector.h
similarity index 89%
rename from src/plugins/texteditor/snippets/snippetprovider.h
rename to src/plugins/texteditor/snippets/snippetcollector.h
index 486ebcf165c..8b44b74edfc 100644
--- a/src/plugins/texteditor/snippets/snippetprovider.h
+++ b/src/plugins/texteditor/snippets/snippetcollector.h
@@ -30,26 +30,25 @@
 #ifndef SNIPPETPROVIDER_H
 #define SNIPPETPROVIDER_H
 
-#include "snippet.h"
-
 #include <texteditor/texteditor_global.h>
 #include <texteditor/icompletioncollector.h>
 
+#include <QtCore/QString>
 #include <QtCore/QList>
 #include <QtGui/QIcon>
 
 namespace TextEditor {
 
-class TEXTEDITOR_EXPORT SnippetProvider
+class TEXTEDITOR_EXPORT SnippetCollector
 {
 public:
-    SnippetProvider(Snippet::Group group, const QIcon &icon, int order = 0);
-    ~SnippetProvider();
+    SnippetCollector(const QString &groupId, const QIcon &icon, int order = 0);
+    ~SnippetCollector();
 
     QList<CompletionItem> getSnippets(ICompletionCollector *collector) const;
 
 private:
-    Snippet::Group m_group;
+    QString m_groupId;
     QIcon m_icon;
     int m_order;
 };
diff --git a/src/plugins/texteditor/snippets/snippets.xml b/src/plugins/texteditor/snippets/snippets.xml
index 0d511a8d41c..0febaac0a49 100644
--- a/src/plugins/texteditor/snippets/snippets.xml
+++ b/src/plugins/texteditor/snippets/snippets.xml
@@ -117,4 +117,5 @@ public:
 <snippet group="QML" trigger="PropertyAction" id="propertyactionwithtarget" complement="with target">PropertyAction { target: $name$; property: "$name$"; value: $value$ }</snippet>
 <snippet group="QML" trigger="PauseAnimation" id="pauseanimation">PauseAnimation { duration: $200$ }</snippet>
 <snippet group="QML" trigger="ColorAnimation" id="coloranimation">ColorAnimation { from: $"white"$; to: $"black"$; duration: $200$ }</snippet>
+<snippet group="Text" trigger="global" id="global" complement="example">// This is available in all editors.</snippet>
 </snippets>
diff --git a/src/plugins/texteditor/snippets/snippetscollection.cpp b/src/plugins/texteditor/snippets/snippetscollection.cpp
index 731f0626031..dd2531e7cce 100644
--- a/src/plugins/texteditor/snippets/snippetscollection.cpp
+++ b/src/plugins/texteditor/snippets/snippetscollection.cpp
@@ -28,15 +28,16 @@
 **************************************************************************/
 
 #include "snippetscollection.h"
+#include "isnippetprovider.h"
 #include "reuse.h"
 
 #include <coreplugin/icore.h>
+#include <extensionsystem/pluginmanager.h>
 
 #include <QtCore/QLatin1String>
 #include <QtCore/QFile>
 #include <QtCore/QFileInfo>
 #include <QtCore/QDir>
-#include <QtCore/QHash>
 #include <QtCore/QDebug>
 #include <QtCore/QXmlStreamReader>
 #include <QtCore/QXmlStreamWriter>
@@ -99,28 +100,24 @@ int SnippetsCollection::Hint::index() const
 
 // SnippetsCollection
 SnippetsCollection::SnippetsCollection() :
-    m_snippets(Snippet::GroupSize),
-    m_activeSnippetsEnd(Snippet::GroupSize),
     m_builtInSnippetsPath(QLatin1String(":/texteditor/snippets/")),
     m_userSnippetsPath(Core::ICore::instance()->userResourcePath() + QLatin1String("/snippets/")),
     m_snippetsFileName(QLatin1String("snippets.xml"))
 {
-    for (Snippet::Group group = Snippet::Cpp; group < Snippet::GroupSize; ++group)
-        m_activeSnippetsEnd[group] = m_snippets[group].end();
+    connect(Core::ICore::instance(), SIGNAL(coreOpened()), this, SLOT(identifyGroups()));
 }
 
 SnippetsCollection::~SnippetsCollection()
 {}
 
-void SnippetsCollection::insertSnippet(const Snippet &snippet, Snippet::Group group)
+void SnippetsCollection::insertSnippet(const Snippet &snippet)
 {
-    insertSnippet(snippet, group, computeInsertionHint(snippet, group));
+    insertSnippet(snippet, computeInsertionHint(snippet));
 }
 
-void SnippetsCollection::insertSnippet(const Snippet &snippet,
-                                       Snippet::Group group,
-                                       const Hint &hint)
+void SnippetsCollection::insertSnippet(const Snippet &snippet, const Hint &hint)
 {
+    const int group = groupIndex(snippet.groupId());
     if (snippet.isBuiltIn() && snippet.isRemoved()) {
         m_activeSnippetsEnd[group] = m_snippets[group].insert(m_activeSnippetsEnd[group], snippet);
     } else {
@@ -129,25 +126,23 @@ void SnippetsCollection::insertSnippet(const Snippet &snippet,
     }
 }
 
-SnippetsCollection::Hint SnippetsCollection::computeInsertionHint(const Snippet &snippet,
-                                                                  Snippet::Group group)
+SnippetsCollection::Hint SnippetsCollection::computeInsertionHint(const Snippet &snippet)
 {
+    const int group = groupIndex(snippet.groupId());
     QList<Snippet> &snippets = m_snippets[group];
     QList<Snippet>::iterator it = qUpperBound(
         snippets.begin(), m_activeSnippetsEnd.at(group), snippet, snippetComp);
     return Hint(static_cast<int>(std::distance(snippets.begin(), it)), it);
 }
 
-void SnippetsCollection::replaceSnippet(int index, const Snippet &snippet, Snippet::Group group)
+void SnippetsCollection::replaceSnippet(int index, const Snippet &snippet)
 {
-    replaceSnippet(index, snippet, group, computeReplacementHint(index, snippet, group));
+    replaceSnippet(index, snippet, computeReplacementHint(index, snippet));
 }
 
-void SnippetsCollection::replaceSnippet(int index,
-                                        const Snippet &snippet,
-                                        Snippet::Group group,
-                                        const Hint &hint)
+void SnippetsCollection::replaceSnippet(int index, const Snippet &snippet, const Hint &hint)
 {
+    const int group = groupIndex(snippet.groupId());
     Snippet replacement(snippet);
     if (replacement.isBuiltIn() && !replacement.isModified())
         replacement.setIsModified(true);
@@ -155,7 +150,7 @@ void SnippetsCollection::replaceSnippet(int index,
     if (index == hint.index()) {
         m_snippets[group][index] = replacement;
     } else {
-        insertSnippet(replacement, group, hint);
+        insertSnippet(replacement, hint);
         // Consider whether the row moved up towards the beginning or down towards the end.
         if (index < hint.index())
             m_snippets[group].removeAt(index);
@@ -166,9 +161,9 @@ void SnippetsCollection::replaceSnippet(int index,
 }
 
 SnippetsCollection::Hint SnippetsCollection::computeReplacementHint(int index,
-                                                                    const Snippet &snippet,
-                                                                    Snippet::Group group)
+                                                                    const Snippet &snippet)
 {
+    const int group = groupIndex(snippet.groupId());
     QList<Snippet> &snippets = m_snippets[group];
     QList<Snippet>::iterator it = qLowerBound(
         snippets.begin(), m_activeSnippetsEnd.at(group), snippet, snippetComp);
@@ -183,8 +178,9 @@ SnippetsCollection::Hint SnippetsCollection::computeReplacementHint(int index,
     return Hint(index);
 }
 
-void SnippetsCollection::removeSnippet(int index, Snippet::Group group)
+void SnippetsCollection::removeSnippet(int index, const QString &groupId)
 {
+    const int group = groupIndex(groupId);
     Snippet snippet(m_snippets.at(group).at(index));
     m_snippets[group].removeAt(index);
     if (snippet.isBuiltIn()) {
@@ -195,90 +191,99 @@ void SnippetsCollection::removeSnippet(int index, Snippet::Group group)
     }
 }
 
-const Snippet &SnippetsCollection::snippet(int index, Snippet::Group group) const
+const Snippet &SnippetsCollection::snippet(int index, const QString &groupId) const
 {
-    return m_snippets.at(group).at(index);
+    return m_snippets.at(groupIndex(groupId)).at(index);
 }
 
-void SnippetsCollection::setSnippetContent(int index, Snippet::Group group, const QString &content)
+void SnippetsCollection::setSnippetContent(int index,
+                                           const QString &groupId,
+                                           const QString &content)
 {
-    Snippet &snippet = m_snippets[group][index];
+    Snippet &snippet = m_snippets[groupIndex(groupId)][index];
     snippet.setContent(content);
     if (snippet.isBuiltIn() && !snippet.isModified())
         snippet.setIsModified(true);
 }
 
-int SnippetsCollection::totalActiveSnippets(Snippet::Group group) const
+int SnippetsCollection::totalActiveSnippets(const QString &groupId) const
 {
+    const int group = groupIndex(groupId);
     return std::distance<QList<Snippet>::const_iterator>(m_snippets.at(group).begin(),
                                                          m_activeSnippetsEnd.at(group));
 }
 
-int SnippetsCollection::totalSnippets(Snippet::Group group) const
+int SnippetsCollection::totalSnippets(const QString &groupId) const
 {
-    return m_snippets.at(group).size();
+    return m_snippets.at(groupIndex(groupId)).size();
 }
 
-void SnippetsCollection::clear()
+QList<QString> SnippetsCollection::groupIds() const
 {
-    for (Snippet::Group group = Snippet::Cpp; group < Snippet::GroupSize; ++group)
-        clear(group);
+    return m_groupIndexById.keys();
 }
 
-void SnippetsCollection::clear(Snippet::Group group)
+void SnippetsCollection::clearSnippets()
 {
-    m_snippets[group].clear();
-    m_activeSnippetsEnd[group] = m_snippets[group].end();
+    for (int group = 0; group < m_groupIndexById.size(); ++group)
+        clearSnippets(group);
 }
 
-void SnippetsCollection::updateActiveSnippetsEnd(Snippet::Group group)
+void SnippetsCollection::clearSnippets(int groupIndex)
 {
-    m_activeSnippetsEnd[group] = std::find_if(m_snippets[group].begin(),
-                                              m_snippets[group].end(),
-                                              removedSnippetPred);
+    m_snippets[groupIndex].clear();
+    m_activeSnippetsEnd[groupIndex] = m_snippets[groupIndex].end();
 }
 
-void SnippetsCollection::restoreRemovedSnippets(Snippet::Group group)
+void SnippetsCollection::updateActiveSnippetsEnd(int groupIndex)
+{
+    m_activeSnippetsEnd[groupIndex] = std::find_if(m_snippets[groupIndex].begin(),
+                                                   m_snippets[groupIndex].end(),
+                                                   removedSnippetPred);
+}
+
+void SnippetsCollection::restoreRemovedSnippets(const QString &groupId)
 {
     // The version restored contains the last modifications (if any) by the user.
-    // Reverting the snippet can still bring it to the original version.
+    // Reverting the snippet can still bring it to the original version
+    const int group = groupIndex(groupId);
     QVector<Snippet> toRestore(std::distance(m_activeSnippetsEnd[group], m_snippets[group].end()));
     qCopy(m_activeSnippetsEnd[group], m_snippets[group].end(), toRestore.begin());
     m_snippets[group].erase(m_activeSnippetsEnd[group], m_snippets[group].end());
     foreach (Snippet snippet, toRestore) {
         snippet.setIsRemoved(false);
-        insertSnippet(snippet, group);
+        insertSnippet(snippet);
     }
 }
 
-Snippet SnippetsCollection::revertedSnippet(int index, Snippet::Group group) const
+Snippet SnippetsCollection::revertedSnippet(int index, const QString &groupId) const
 {
-    const Snippet &candidate = snippet(index, group);
+    const Snippet &candidate = snippet(index, groupId);
     Q_ASSERT(candidate.isBuiltIn());
 
     const QList<Snippet> &builtIn =
         readXML(m_builtInSnippetsPath + m_snippetsFileName, candidate.id());
     if (builtIn.size() == 1)
         return builtIn.at(0);
-    return Snippet();
+    return Snippet(groupId);
 }
 
-void SnippetsCollection::reset(Snippet::Group group)
+void SnippetsCollection::reset(const QString &groupId)
 {
-    clear(group);
+    clearSnippets(groupIndex(groupId));
 
     const QList<Snippet> &builtInSnippets = readXML(m_builtInSnippetsPath + m_snippetsFileName);
     foreach (const Snippet &snippet, builtInSnippets)
-        if (group == snippet.group())
-            insertSnippet(snippet, snippet.group());
+        if (groupId == snippet.groupId())
+            insertSnippet(snippet);
 }
 
 void SnippetsCollection::reload()
 {
-    clear();
+    clearSnippets();
 
-    QHash<QString, Snippet> activeBuiltInSnippets;
     const QList<Snippet> &builtInSnippets = readXML(m_builtInSnippetsPath + m_snippetsFileName);
+    QHash<QString, Snippet> activeBuiltInSnippets;
     foreach (const Snippet &snippet, builtInSnippets)
         activeBuiltInSnippets.insert(snippet.id(), snippet);
 
@@ -287,11 +292,11 @@ void SnippetsCollection::reload()
         if (snippet.isBuiltIn())
             // This user snippet overrides the corresponding built-in snippet.
             activeBuiltInSnippets.remove(snippet.id());
-        insertSnippet(snippet, snippet.group());
+        insertSnippet(snippet);
     }
 
     foreach (const Snippet &snippet, activeBuiltInSnippets)
-        insertSnippet(snippet, snippet.group());
+        insertSnippet(snippet);
 }
 
 void SnippetsCollection::synchronize()
@@ -303,10 +308,10 @@ void SnippetsCollection::synchronize()
             writer.setAutoFormatting(true);
             writer.writeStartDocument();
             writer.writeStartElement(kSnippets);
-            for (Snippet::Group group = Snippet::Cpp; group < Snippet::GroupSize; ++group) {
-                const int size = totalSnippets(group);
+            foreach (const QString &groupId, m_groupIndexById.keys()) {
+                const int size = m_snippets.at(groupIndex(groupId)).size();
                 for (int i = 0; i < size; ++i) {
-                    const Snippet &current = snippet(i, group);
+                    const Snippet &current = snippet(i, groupId);
                     if (!current.isBuiltIn() || current.isRemoved() || current.isModified())
                         writeSnippetXML(current, &writer);
                 }
@@ -320,10 +325,10 @@ void SnippetsCollection::synchronize()
     reload();
 }
 
-void SnippetsCollection::writeSnippetXML(const Snippet &snippet, QXmlStreamWriter *writer)
+void SnippetsCollection::writeSnippetXML(const Snippet &snippet, QXmlStreamWriter *writer) const
 {
     writer->writeStartElement(kSnippet);
-    writer->writeAttribute(kGroup, fromSnippetGroup(snippet.group()));
+    writer->writeAttribute(kGroup, snippet.groupId());
     writer->writeAttribute(kTrigger, snippet.trigger());
     writer->writeAttribute(kId, snippet.id());
     writer->writeAttribute(kComplement, snippet.complement());
@@ -333,7 +338,7 @@ void SnippetsCollection::writeSnippetXML(const Snippet &snippet, QXmlStreamWrite
     writer->writeEndElement();
 }
 
-QList<Snippet> SnippetsCollection::readXML(const QString &fileName, const QString &snippetId)
+QList<Snippet> SnippetsCollection::readXML(const QString &fileName, const QString &snippetId) const
 {
     QList<Snippet> snippets;
     QFile file(fileName);
@@ -345,11 +350,11 @@ QList<Snippet> SnippetsCollection::readXML(const QString &fileName, const QStrin
                     if (xml.name() == kSnippet) {
                         const QXmlStreamAttributes &atts = xml.attributes();
                         const QString &id = atts.value(kId).toString();
-                        if (snippetId.isEmpty() || snippetId == id) {
-                            Snippet snippet(id);
+                        const QString &groupId = atts.value(kGroup).toString();
+                        if (isGroupKnown(groupId) && (snippetId.isEmpty() || snippetId == id)) {
+                            Snippet snippet(groupId, id);
                             snippet.setTrigger(atts.value(kTrigger).toString());
                             snippet.setComplement(atts.value(kComplement).toString());
-                            snippet.setGroup(toSnippetGroup(atts.value(kGroup).toString()));
                             snippet.setIsRemoved(toBool(atts.value(kRemoved).toString()));
                             snippet.setIsModified(toBool(atts.value(kModified).toString()));
 
@@ -383,3 +388,28 @@ QList<Snippet> SnippetsCollection::readXML(const QString &fileName, const QStrin
 
     return snippets;
 }
+
+int SnippetsCollection::groupIndex(const QString &groupId) const
+{
+    return m_groupIndexById.value(groupId);
+}
+
+void SnippetsCollection::identifyGroups()
+{
+    const QList<ISnippetProvider *> &providers =
+        ExtensionSystem::PluginManager::instance()->getObjects<ISnippetProvider>();
+    foreach (ISnippetProvider *provider, providers) {
+        const int groupIndex = m_groupIndexById.size();
+        m_groupIndexById.insert(provider->groupId(), groupIndex);
+        m_snippets.resize(groupIndex + 1);
+        m_activeSnippetsEnd.resize(groupIndex + 1);
+        m_activeSnippetsEnd[groupIndex] = m_snippets[groupIndex].end();
+    }
+
+    reload();
+}
+
+bool SnippetsCollection::isGroupKnown(const QString &groupId) const
+{
+    return m_groupIndexById.value(groupId, -1) != -1;
+}
diff --git a/src/plugins/texteditor/snippets/snippetscollection.h b/src/plugins/texteditor/snippets/snippetscollection.h
index 4282ea7af63..0926a33c5a2 100644
--- a/src/plugins/texteditor/snippets/snippetscollection.h
+++ b/src/plugins/texteditor/snippets/snippetscollection.h
@@ -34,6 +34,7 @@
 
 #include <QtCore/QVector>
 #include <QtCore/QList>
+#include <QtCore/QHash>
 
 QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
 
@@ -49,8 +50,9 @@ namespace Internal {
 // - Provide fast index access.
 // - Not thread-safe.
 
-class SnippetsCollection
+class SnippetsCollection : public QObject
 {
+    Q_OBJECT
 public:
     SnippetsCollection();
     ~SnippetsCollection();
@@ -61,43 +63,52 @@ public:
     public:
         int index() const;
     private:
-        Hint(int index);
+        explicit Hint(int index);
         Hint(int index, QList<Snippet>::iterator it);
         int m_index;
         QList<Snippet>::iterator m_it;
     };
 
-    void insertSnippet(const Snippet &snippet, Snippet::Group group);
-    void insertSnippet(const Snippet &snippet, Snippet::Group group, const Hint &hint);
-    Hint computeInsertionHint(const Snippet &snippet, Snippet::Group group);
+    void insertSnippet(const Snippet &snippet);
+    void insertSnippet(const Snippet &snippet, const Hint &hint);
+    Hint computeInsertionHint(const Snippet &snippet);
 
-    void replaceSnippet(int index, const Snippet &snippet, Snippet::Group group);
-    void replaceSnippet(int index, const Snippet &snippet, Snippet::Group group, const Hint &hint);
-    Hint computeReplacementHint(int index, const Snippet &snippet, Snippet::Group group);
+    // Replace snippets only within the same group.
+    void replaceSnippet(int index, const Snippet &snippet);
+    void replaceSnippet(int index, const Snippet &snippet, const Hint &hint);
+    Hint computeReplacementHint(int index, const Snippet &snippet);
 
-    void removeSnippet(int index, Snippet::Group group);
-    void restoreRemovedSnippets(Snippet::Group group);
+    void removeSnippet(int index, const QString &groupId);
+    void restoreRemovedSnippets(const QString &groupId);
 
-    void setSnippetContent(int index, Snippet::Group group, const QString &content);
+    void setSnippetContent(int index, const QString &groupId, const QString &content);
 
-    const Snippet &snippet(int index, Snippet::Group group) const;
-    Snippet revertedSnippet(int index, Snippet::Group group) const;
+    const Snippet &snippet(int index, const QString &groupId) const;
+    Snippet revertedSnippet(int index, const QString &groupId) const;
 
-    void reset(Snippet::Group group);
+    void reset(const QString &groupId);
 
-    int totalActiveSnippets(Snippet::Group group) const;
-    int totalSnippets(Snippet::Group group) const;
+    int totalActiveSnippets(const QString &groupId) const;
+    int totalSnippets(const QString &groupId) const;
+
+    QList<QString> groupIds() const;
 
     void reload();
     void synchronize();
 
+private slots:
+    void identifyGroups();
+
 private:
-    void clear();
-    void clear(Snippet::Group group);
-    void updateActiveSnippetsEnd(Snippet::Group group);
+    int groupIndex(const QString &groupId) const;
+
+    void clearSnippets();
+    void clearSnippets(int groupIndex);
+
+    void updateActiveSnippetsEnd(int groupIndex);
 
-    static QList<Snippet> readXML(const QString &fileName, const QString &snippetId = QString());
-    static void writeSnippetXML(const Snippet &snippet, QXmlStreamWriter *writer);
+    QList<Snippet> readXML(const QString &fileName, const QString &snippetId = QString()) const;
+    void writeSnippetXML(const Snippet &snippet, QXmlStreamWriter *writer) const;
 
     static const QLatin1String kSnippet;
     static const QLatin1String kSnippets;
@@ -108,11 +119,7 @@ private:
     static const QLatin1String kRemoved;
     static const QLatin1String kModified;
 
-    // Snippets for each group are kept in a list. However, not all of them are necessarily
-    // active. Specifically, removed built-in snippets are kept as the last ones (for each
-    // group there is a iterator that marks the logical end).
-    QVector<QList<Snippet> > m_snippets;
-    QVector<QList<Snippet>::iterator> m_activeSnippetsEnd;
+    bool isGroupKnown(const QString &groupId) const;
 
     // Built-in snippets are specified in an XML embedded as a resource. Snippets created/
     // modified/removed by the user are stored in another XML created dynamically in the
@@ -120,6 +127,14 @@ private:
     QString m_builtInSnippetsPath;
     QString m_userSnippetsPath;
     QString m_snippetsFileName;
+
+    // Snippets for each group are kept in a list. However, not all of them are necessarily
+    // active. Specifically, removed built-in snippets are kept as the last ones (for each
+    // group there is a iterator that marks the logical end).
+    QVector<QList<Snippet> > m_snippets;
+    QVector<QList<Snippet>::iterator> m_activeSnippetsEnd;
+
+    QHash<QString, int> m_groupIndexById;
 };
 
 } // Internal
diff --git a/src/plugins/texteditor/snippets/snippetsmanager.h b/src/plugins/texteditor/snippets/snippetsmanager.h
index 6a527815f78..131377948f2 100644
--- a/src/plugins/texteditor/snippets/snippetsmanager.h
+++ b/src/plugins/texteditor/snippets/snippetsmanager.h
@@ -33,6 +33,9 @@
 #include <QtCore/QSharedPointer>
 
 namespace TextEditor {
+
+class ISnippetProvider;
+
 namespace Internal {
 
 class SnippetsCollection;
diff --git a/src/plugins/texteditor/snippets/snippetssettings.cpp b/src/plugins/texteditor/snippets/snippetssettings.cpp
index e99cbaf59e8..f6ea3a64534 100644
--- a/src/plugins/texteditor/snippets/snippetssettings.cpp
+++ b/src/plugins/texteditor/snippets/snippetssettings.cpp
@@ -57,8 +57,7 @@ void SnippetsSettings::fromSettings(const QString &category, QSettings *s)
 {
     const QString &group = category + kGroupPostfix;
     s->beginGroup(group);
-    m_lastUsedSnippetGroup =
-        s->value(kLastUsedSnippetGroup, fromSnippetGroup(Snippet::Cpp)).toString();
+    m_lastUsedSnippetGroup = s->value(kLastUsedSnippetGroup, QString()).toString();
     s->endGroup();
 }
 
diff --git a/src/plugins/texteditor/snippets/snippetssettingspage.cpp b/src/plugins/texteditor/snippets/snippetssettingspage.cpp
index f73fe64673f..b9beef03839 100644
--- a/src/plugins/texteditor/snippets/snippetssettingspage.cpp
+++ b/src/plugins/texteditor/snippets/snippetssettingspage.cpp
@@ -30,7 +30,7 @@
 #include "snippetssettingspage.h"
 #include "snippetsmanager.h"
 #include "snippeteditor.h"
-#include "isnippeteditordecorator.h"
+#include "isnippetprovider.h"
 #include "snippet.h"
 #include "snippetscollection.h"
 #include "snippetssettings.h"
@@ -46,6 +46,7 @@
 #include <QtCore/QList>
 #include <QtCore/QSettings>
 #include <QtCore/QTextStream>
+#include <QtCore/QHash>
 #include <QtGui/QMessageBox>
 
 namespace TextEditor {
@@ -68,7 +69,8 @@ public:
     virtual QVariant headerData(int section, Qt::Orientation orientation,
                                 int role = Qt::DisplayRole) const;
 
-    void load(Snippet::Group group);
+    QList<QString> groupIds() const;
+    void load(const QString &groupId);
 
     QModelIndex createSnippet();
     QModelIndex insertSnippet(const Snippet &snippet);
@@ -83,13 +85,12 @@ private:
     void replaceSnippet(const Snippet &snippet, const QModelIndex &modelIndex);
     static bool isValidTrigger(const QString &s);
 
-    Snippet::Group m_activeGroup;
     QSharedPointer<SnippetsCollection> m_collection;
+    QString m_activeGroupId;
 };
 
 SnippetsTableModel::SnippetsTableModel(QObject *parent) :
     QAbstractTableModel(parent),
-    m_activeGroup(Snippet::Cpp),
     m_collection(SnippetsManager::instance()->snippetsCollection())
 {}
 
@@ -97,7 +98,7 @@ int SnippetsTableModel::rowCount(const QModelIndex &) const
 {
     if (m_collection.isNull())
         return 0;
-    return m_collection->totalActiveSnippets(m_activeGroup);
+    return m_collection->totalActiveSnippets(m_activeGroupId);
 }
 
 int SnippetsTableModel::columnCount(const QModelIndex &) const
@@ -121,7 +122,7 @@ QVariant SnippetsTableModel::data(const QModelIndex &modelIndex, int role) const
         return QVariant();
 
     if (role == Qt::DisplayRole || role == Qt::EditRole) {
-        const Snippet &snippet = m_collection->snippet(modelIndex.row(), m_activeGroup);
+        const Snippet &snippet = m_collection->snippet(modelIndex.row(), m_activeGroupId);
         if (modelIndex.column() == 0)
             return snippet.trigger();
         else
@@ -134,7 +135,7 @@ QVariant SnippetsTableModel::data(const QModelIndex &modelIndex, int role) const
 bool SnippetsTableModel::setData(const QModelIndex &modelIndex, const QVariant &value, int role)
 {
     if (modelIndex.isValid() && role == Qt::EditRole) {
-        Snippet snippet(m_collection->snippet(modelIndex.row(), m_activeGroup));
+        Snippet snippet(m_collection->snippet(modelIndex.row(), m_activeGroupId));
         if (modelIndex.column() == 0) {
             const QString &s = value.toString();
             if (!isValidTrigger(s)) {
@@ -165,25 +166,28 @@ QVariant SnippetsTableModel::headerData(int section, Qt::Orientation orientation
         return tr("Complement");
 }
 
-void SnippetsTableModel::load(Snippet::Group group)
+void SnippetsTableModel::load(const QString &groupId)
 {
-    m_activeGroup = group;
+    m_activeGroupId = groupId;
     reset();
 }
 
+QList<QString> SnippetsTableModel::groupIds() const
+{
+    return m_collection->groupIds();
+}
+
 QModelIndex SnippetsTableModel::createSnippet()
 {
-    Snippet snippet;
-    snippet.setGroup(m_activeGroup);
+    Snippet snippet(m_activeGroupId);
     return insertSnippet(snippet);
 }
 
 QModelIndex SnippetsTableModel::insertSnippet(const Snippet &snippet)
 {
-    const SnippetsCollection::Hint &hint =
-        m_collection->computeInsertionHint(snippet, m_activeGroup);
+    const SnippetsCollection::Hint &hint = m_collection->computeInsertionHint(snippet);
     beginInsertRows(QModelIndex(), hint.index(), hint.index());
-    m_collection->insertSnippet(snippet, m_activeGroup, hint);
+    m_collection->insertSnippet(snippet, hint);
     endInsertRows();
 
     return index(hint.index(), 0);
@@ -192,23 +196,23 @@ QModelIndex SnippetsTableModel::insertSnippet(const Snippet &snippet)
 void SnippetsTableModel::removeSnippet(const QModelIndex &modelIndex)
 {
     beginRemoveRows(QModelIndex(), modelIndex.row(), modelIndex.row());
-    m_collection->removeSnippet(modelIndex.row(), m_activeGroup);
+    m_collection->removeSnippet(modelIndex.row(), m_activeGroupId);
     endRemoveRows();
 }
 
 const Snippet &SnippetsTableModel::snippetAt(const QModelIndex &modelIndex) const
 {
-    return m_collection->snippet(modelIndex.row(), m_activeGroup);
+    return m_collection->snippet(modelIndex.row(), m_activeGroupId);
 }
 
 void SnippetsTableModel::setSnippetContent(const QModelIndex &modelIndex, const QString &content)
 {
-    m_collection->setSnippetContent(modelIndex.row(), m_activeGroup, content);
+    m_collection->setSnippetContent(modelIndex.row(), m_activeGroupId, content);
 }
 
 void SnippetsTableModel::revertBuitInSnippet(const QModelIndex &modelIndex)
 {
-    const Snippet &snippet = m_collection->revertedSnippet(modelIndex.row(), m_activeGroup);
+    const Snippet &snippet = m_collection->revertedSnippet(modelIndex.row(), m_activeGroupId);
     if (snippet.id().isEmpty()) {
         QMessageBox::critical(0, tr("Error"), tr("Error reverting snippet."));
         return;
@@ -218,13 +222,13 @@ void SnippetsTableModel::revertBuitInSnippet(const QModelIndex &modelIndex)
 
 void SnippetsTableModel::restoreRemovedBuiltInSnippets()
 {
-    m_collection->restoreRemovedSnippets(m_activeGroup);
+    m_collection->restoreRemovedSnippets(m_activeGroupId);
     reset();
 }
 
 void SnippetsTableModel::resetSnippets()
 {
-    m_collection->reset(m_activeGroup);
+    m_collection->reset(m_activeGroupId);
     reset();
 }
 
@@ -232,9 +236,9 @@ void SnippetsTableModel::replaceSnippet(const Snippet &snippet, const QModelInde
 {
     const int row = modelIndex.row();
     const SnippetsCollection::Hint &hint =
-        m_collection->computeReplacementHint(row, snippet, m_activeGroup);
+        m_collection->computeReplacementHint(row, snippet);
     if (modelIndex.row() == hint.index()) {
-        m_collection->replaceSnippet(row, snippet, m_activeGroup, hint);
+        m_collection->replaceSnippet(row, snippet, hint);
         emit dataChanged(modelIndex, modelIndex);
     } else {
         if (row < hint.index())
@@ -242,7 +246,7 @@ void SnippetsTableModel::replaceSnippet(const Snippet &snippet, const QModelInde
             beginMoveRows(QModelIndex(), row, row, QModelIndex(), hint.index() + 1);
         else
             beginMoveRows(QModelIndex(), row, row, QModelIndex(), hint.index());
-        m_collection->replaceSnippet(row, snippet, m_activeGroup, hint);
+        m_collection->replaceSnippet(row, snippet, hint);
         endMoveRows();
     }
 }
@@ -290,8 +294,6 @@ private:
     SnippetEditor *currentEditor() const;
     SnippetEditor *editorAt(int i) const;
 
-    static void decorateEditor(SnippetEditor *editor, Snippet::Group group);
-
     void loadSettings();
     bool settingsChanged() const;
     void writeSettings();
@@ -328,9 +330,15 @@ void SnippetsSettingsPagePrivate::configureUi(QWidget *w)
 {
     m_ui.setupUi(w);
 
-    m_ui.groupCombo->insertItem(Snippet::Cpp, fromSnippetGroup(Snippet::Cpp));
-    m_ui.groupCombo->insertItem(Snippet::Qml, fromSnippetGroup(Snippet::Qml));
-    m_ui.groupCombo->insertItem(Snippet::PlainText, fromSnippetGroup(Snippet::PlainText));
+    const QList<ISnippetProvider *> &providers =
+        ExtensionSystem::PluginManager::instance()->getObjects<ISnippetProvider>();
+    foreach (ISnippetProvider *provider, providers) {
+        m_ui.groupCombo->addItem(provider->displayName(), provider->groupId());
+        SnippetEditor *snippetEditor = new SnippetEditor(w);
+        provider->decorateEditor(snippetEditor);
+        m_ui.snippetsEditorStack->insertWidget(m_ui.groupCombo->count() - 1, snippetEditor);
+        connect(snippetEditor, SIGNAL(snippetContentChanged()), this, SLOT(setSnippetContent()));
+    }
 
     m_ui.snippetsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
     m_ui.snippetsTable->setSelectionMode(QAbstractItemView::SingleSelection);
@@ -340,13 +348,6 @@ void SnippetsSettingsPagePrivate::configureUi(QWidget *w)
     m_ui.snippetsTable->verticalHeader()->setDefaultSectionSize(20);
     m_ui.snippetsTable->setModel(m_model);
 
-    m_ui.snippetsEditorStack->insertWidget(Snippet::Cpp, new SnippetEditor(w));
-    m_ui.snippetsEditorStack->insertWidget(Snippet::Qml, new SnippetEditor(w));
-    m_ui.snippetsEditorStack->insertWidget(Snippet::PlainText, new SnippetEditor(w));
-    decorateEditor(editorAt(Snippet::Cpp), Snippet::Cpp);
-    decorateEditor(editorAt(Snippet::Qml), Snippet::Qml);
-    decorateEditor(editorAt(Snippet::PlainText), Snippet::PlainText);
-
     m_ui.revertButton->setEnabled(false);
 
     QTextStream(&m_keywords) << m_displayName;
@@ -354,13 +355,6 @@ void SnippetsSettingsPagePrivate::configureUi(QWidget *w)
     loadSettings();
     loadSnippetGroup(m_ui.groupCombo->currentIndex());
 
-    connect(editorAt(Snippet::Cpp), SIGNAL(snippetContentChanged()),
-            this, SLOT(setSnippetContent()));
-    connect(editorAt(Snippet::Qml), SIGNAL(snippetContentChanged()),
-            this, SLOT(setSnippetContent()));
-    connect(editorAt(Snippet::PlainText), SIGNAL(snippetContentChanged()),
-            this, SLOT(setSnippetContent()));
-
     connect(m_model, SIGNAL(rowsInserted(QModelIndex, int, int)),
             this, SLOT(selectSnippet(QModelIndex,int)));
     connect(m_model, SIGNAL(rowsInserted(QModelIndex, int, int)),
@@ -387,15 +381,6 @@ void SnippetsSettingsPagePrivate::configureUi(QWidget *w)
             this, SLOT(updateCurrentSnippetDependent(QModelIndex)));
 }
 
-void SnippetsSettingsPagePrivate::decorateEditor(SnippetEditor *editor, Snippet::Group group)
-{
-    const QList<ISnippetEditorDecorator *> &decorators =
-        ExtensionSystem::PluginManager::instance()->getObjects<ISnippetEditorDecorator>();
-    foreach (ISnippetEditorDecorator *decorator, decorators)
-        if (decorator->supports(group))
-            decorator->apply(editor);
-}
-
 void SnippetsSettingsPagePrivate::apply()
 {
     if (settingsChanged())
@@ -417,14 +402,25 @@ void SnippetsSettingsPagePrivate::finish()
 
 void SnippetsSettingsPagePrivate::loadSettings()
 {
+    if (m_ui.groupCombo->count() == 0)
+        return;
+
     if (QSettings *s = Core::ICore::instance()->settings()) {
         m_settings.fromSettings(m_settingsPrefix, s);
-        m_ui.groupCombo->setCurrentIndex(toSnippetGroup(m_settings.lastUsedSnippetGroup()));
+        const QString &lastGroupName = m_settings.lastUsedSnippetGroup();
+        const int index = m_ui.groupCombo->findText(lastGroupName);
+        if (index != -1)
+            m_ui.groupCombo->setCurrentIndex(index);
+        else
+            m_ui.groupCombo->setCurrentIndex(0);
     }
 }
 
 void SnippetsSettingsPagePrivate::writeSettings()
 {
+    if (m_ui.groupCombo->count() == 0)
+        return;
+
     if (QSettings *s = Core::ICore::instance()->settings()) {
         m_settings.setLastUsedSnippetGroup(m_ui.groupCombo->currentText());
         m_settings.toSettings(m_settingsPrefix, s);
@@ -440,9 +436,12 @@ bool SnippetsSettingsPagePrivate::settingsChanged() const
 
 void SnippetsSettingsPagePrivate::loadSnippetGroup(int index)
 {
+    if (index == -1)
+        return;
+
     m_ui.snippetsEditorStack->setCurrentIndex(index);
     currentEditor()->clear();
-    m_model->load(Snippet::Group(index));
+    m_model->load(m_ui.groupCombo->itemData(index).toString());
 }
 
 void SnippetsSettingsPagePrivate::markSnippetsCollection()
diff --git a/src/plugins/texteditor/texteditor.pro b/src/plugins/texteditor/texteditor.pro
index fbc8b67cd4c..bbf384a767e 100644
--- a/src/plugins/texteditor/texteditor.pro
+++ b/src/plugins/texteditor/texteditor.pro
@@ -77,10 +77,11 @@ SOURCES += texteditorplugin.cpp \
     snippets/snippet.cpp \
     snippets/snippetsmanager.cpp \
     snippets/snippeteditor.cpp \
-    snippets/isnippeteditordecorator.cpp \
     snippets/snippetscollection.cpp \
     snippets/snippetssettings.cpp \
-    snippets/snippetprovider.cpp
+    snippets/isnippetprovider.cpp \
+    snippets/snippetcollector.cpp \
+    snippets/plaintextsnippetprovider.cpp
 
 HEADERS += texteditorplugin.h \
     textfilewizard.h \
@@ -159,11 +160,12 @@ HEADERS += texteditorplugin.h \
     snippets/snippet.h \
     snippets/snippetsmanager.h \
     snippets/snippeteditor.h \
-    snippets/isnippeteditordecorator.h \
     snippets/snippetscollection.h \
     snippets/reuse.h \
     snippets/snippetssettings.h \
-    snippets/snippetprovider.h
+    snippets/isnippetprovider.h \
+    snippets/snippetcollector.h \
+    snippets/plaintextsnippetprovider.h
 
 FORMS += behaviorsettingspage.ui \
     displaysettingspage.ui \
diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h
index a22917d2cd6..0cb27722c07 100644
--- a/src/plugins/texteditor/texteditorconstants.h
+++ b/src/plugins/texteditor/texteditorconstants.h
@@ -143,6 +143,7 @@ const char * const TEXT_EDITOR_HIGHLIGHTER_SETTINGS = "E.HighlighterSettings";
 const char * const TEXT_EDITOR_SNIPPETS_SETTINGS = "F.SnippetsSettings";
 
 const char * const SNIPPET_EDITOR_ID     = "TextEditor.SnippetEditor";
+const char * const TEXT_SNIPPET_GROUP_ID = "Text";
 
 } // namespace Constants
 } // namespace TextEditor
diff --git a/src/plugins/texteditor/texteditorplugin.cpp b/src/plugins/texteditor/texteditorplugin.cpp
index 142145c9064..b547f49e822 100644
--- a/src/plugins/texteditor/texteditorplugin.cpp
+++ b/src/plugins/texteditor/texteditorplugin.cpp
@@ -41,6 +41,7 @@
 #include "storagesettings.h"
 #include "manager.h"
 #include "outlinefactory.h"
+#include "snippets/plaintextsnippetprovider.h"
 
 #include <coreplugin/icore.h>
 #include <coreplugin/coreconstants.h>
@@ -144,6 +145,9 @@ bool TextEditorPlugin::initialize(const QStringList &arguments, QString *errorMe
     connect(Core::ICore::instance(), SIGNAL(coreOpened()),
             Manager::instance(), SLOT(registerMimeTypes()));
 
+    // Add text snippet provider.
+    addAutoReleasedObject(new PlainTextSnippetProvider);
+
     m_outlineFactory = new OutlineFactory;
     addAutoReleasedObject(m_outlineFactory);
 
-- 
GitLab