diff --git a/share/qtcreator/snippets/qml.xml b/share/qtcreator/snippets/qml.xml
new file mode 100644
index 00000000000..4a2c3a5f2ea
--- /dev/null
+++ b/share/qtcreator/snippets/qml.xml
@@ -0,0 +1,96 @@
+
+
+property name name : name
+
+Item {
+	id: name
+	
+	}
+
+BorderImage {
+    id: name
+    width: name; height: name
+    border.left: name; border.top: name
+    border.right: name; border.bottom: name
+    source: "name"
+}
+
+
+Image {
+    id: name
+    source: "name"
+}
+
+
+Text {
+    id: name
+    text: "name"
+}
+
+
+states: [
+    State {
+        name: "name"
+        PropertyChanges {
+            target: name
+            
+        }
+    }
+]
+
+
+State {
+    name: "name"
+    PropertyChanges {
+        target: name
+        
+    }
+}
+
+
+transitions: [
+    Transition {
+        from: "name"
+        to: "name"
+        
+     }
+]
+
+
+Transition {
+    from: "name"
+    to: "name"
+    
+}
+
+
+PropertyChanges {
+        target: name
+        
+    }
+
+
+NumberAnimation { matchTargets: "name"; matchProperties: "name"; duration: 200 }
+
+NumberAnimation { target: "name"; property: "name"; value: name; duration: 200 }
+
+PropertyAction {  matchTargets: "name"; matchProperties: "name"; duration: 200 }
+
+PropertyAction { target: "name"; property: "name"; value: name; duration: 200 }
+
+PauseAnimation { duration: name}
+
+ColorAnimation { from: name; to: name; duration: 200 }
+
+effect: Colorize { color: "name" }
+
+effect: Blur { blurRadius: "200" }
+
+effect: DropShadow {
+            blurRadius: 200
+            offset.x: 200
+            offset.y: 200
+        }
+
+
+
diff --git a/src/plugins/qmljseditor/qmlcodecompletion.cpp b/src/plugins/qmljseditor/qmlcodecompletion.cpp
index af7391854ba..56376c13c0e 100644
--- a/src/plugins/qmljseditor/qmlcodecompletion.cpp
+++ b/src/plugins/qmljseditor/qmlcodecompletion.cpp
@@ -37,6 +37,12 @@
 #include 
 #include 
 
+#include 
+
+#include 
+#include 
+#include 
+
 #include 
 
 using namespace QmlJSEditor;
@@ -134,61 +140,9 @@ int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
         }
     }
 
+    updateSnippets();
 
-    // snippets completion
-    TextEditor::CompletionItem item(this);
-    item.text = QLatin1String("Rectangle - declaration");
-    item.data = QVariant::fromValue(QString("Rectangle {\nwidth: $100$;\nheight: 100;\n$$\n}"));
-    m_completions.append(item);
-
-    item.text = QLatin1String("Item - declaration");
-    item.data = QVariant::fromValue(QString("Item {\nwidth: $100$;\nheight: 100;\n$$\n}"));
-    m_completions.append(item);
-
-    item.text = QLatin1String("BorderImage - declaration");
-    item.data = QLatin1String("BorderImage {\n"
-                              "id: $name$;\n"
-                              "width: $100$; height: $100$;\n"
-                              "border.left: $2$; border.top: $2$;\n"
-                              "border.right: $2$; border.bottom: $2$;\n"
-                              "source: \"$name$\";\n"
-                              "}\n");
-    m_completions.append(item);
-
-    item.text = QLatin1String("State - declaration");
-    item.data = QLatin1String("State {\n"
-                              "name: \"$state$;\"\n"
-                              "PropertyChanges {\n"
-                              "target: $target$;\n"
-                              "$$\n"
-                              "}\n"
-                              "}\n");
-    m_completions.append(item);
-
-    item.text = QLatin1String("states - declaration");
-    item.data = QLatin1String("states: [\n"
-                              "State {\n"
-                              "name: \"$state$\";\n"
-                              "PropertyChanges {\n"
-                              "target: $target$;\n"
-                              "$$\n"
-                              "}\n"
-                              "}\n"
-                              "]\n");
-    m_completions.append(item);
-
-    item.text = QLatin1String("property - declaration");
-    item.data = QLatin1String("property $var$ $name$: $value$;\n");
-    m_completions.append(item);
-
-    item.text = QLatin1String("readonly property - declaration");
-    item.data = QLatin1String("readonly property $var$ $name$: $value$;\n");
-    m_completions.append(item);
-
-    item.text = QLatin1String("NumericAnimation - declaration");
-    item.data = QLatin1String("NumberAnimation { matchTargets: \"$target$\"; matchProperties: \"$properties$\"; duration: $1000$ }\n");
-    m_completions.append(item);
-
+    m_completions.append(m_snippets);
     return pos;
 }
 
@@ -299,3 +253,65 @@ void QmlCodeCompletion::cleanup()
     m_completions.clear();
 }
 
+
+void QmlCodeCompletion::updateSnippets()
+{
+    QString qmlsnippets = Core::ICore::instance()->resourcePath() + QLatin1String("/snippets/qml.xml");
+    if (!QFile::exists(qmlsnippets))
+        return;
+
+    QDateTime lastModified = QFileInfo(qmlsnippets).lastModified();
+    if (!m_snippetFileLastModified.isNull() &&  lastModified == m_snippetFileLastModified)
+        return;
+
+    m_snippetFileLastModified = lastModified;
+    QFile file(qmlsnippets);
+    file.open(QIODevice::ReadOnly);
+    QXmlStreamReader xml(&file);
+    while (!xml.atEnd() && xml.readNextStartElement()) {
+        if (xml.name() == QLatin1String("snippets")) {
+            while (xml.readNextStartElement()) {
+                if (xml.name() == QLatin1String("snippet")) {
+                    TextEditor::CompletionItem item(this);
+                    QString title, data;
+                    QString description = xml.attributes().value("description").toString();
+
+                    while (!xml.atEnd()) {
+                        xml.readNext();
+                        if (xml.isEndElement()) {
+                            int i = 0;
+                            while (i < data.size() && data.at(i).isLetterOrNumber())
+                                ++i;
+                            title = data.left(i);
+                            item.text = title;
+                            if (!description.isEmpty()) {
+                                item.text +=  QLatin1Char(' ');
+                                item.text += description;
+                            }
+                            item.data = QVariant::fromValue(data);
+                            m_snippets.append(item);
+                            break;
+
+                        }
+
+                        if (xml.isCharacters())
+                            data += xml.text();
+                        else if (xml.isStartElement()) {
+                            if (xml.name() != QLatin1String("tab"))
+                                xml.raiseError(QLatin1String("invalid snippets file"));
+                            else {
+                                data += QChar::ObjectReplacementCharacter;
+                                data += xml.readElementText();
+                                data += QChar::ObjectReplacementCharacter;
+                            }
+                        }
+
+                    }
+                }
+            }
+        }
+    }
+    if (xml.hasError())
+        qWarning() << qmlsnippets << xml.errorString();
+    file.close();
+}
diff --git a/src/plugins/qmljseditor/qmlcodecompletion.h b/src/plugins/qmljseditor/qmlcodecompletion.h
index cb8687cde66..8adc066fc9f 100644
--- a/src/plugins/qmljseditor/qmlcodecompletion.h
+++ b/src/plugins/qmljseditor/qmlcodecompletion.h
@@ -32,6 +32,7 @@
 
 #include 
 #include 
+#include 
 
 namespace TextEditor {
 class ITextEditable;
@@ -69,6 +70,10 @@ private:
     QList m_completions;
     Qt::CaseSensitivity m_caseSensitivity;
     QmlJS::TypeSystem *m_typeSystem;
+
+    QList m_snippets;
+    QDateTime m_snippetFileLastModified;
+    void updateSnippets();
 };
 
 
diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp
index 7fc9eaf18fa..718e757803d 100644
--- a/src/plugins/texteditor/basetexteditor.cpp
+++ b/src/plugins/texteditor/basetexteditor.cpp
@@ -960,11 +960,15 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
     d->m_lastEventWasBlockSelectionEvent = false;
 
     if (e->key() == Qt::Key_Escape) {
-        e->accept();
-        QTextCursor cursor = textCursor();
-        cursor.clearSelection();
-        setTextCursor(cursor);
-        return;
+        if (d->m_snippetOverlay->isVisible()) {
+            e->accept();
+            d->m_snippetOverlay->hide();
+            d->m_snippetOverlay->clear();
+            QTextCursor cursor = textCursor();
+            cursor.clearSelection();
+            setTextCursor(cursor);
+            return;
+        }
     }
 
     bool ro = isReadOnly();
@@ -996,6 +1000,17 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
             || (!d->m_lineSeparatorsAllowed && e == QKeySequence::InsertLineSeparator))
         ) {
 
+        if (d->m_snippetOverlay->isVisible()) {
+            e->accept();
+            d->m_snippetOverlay->hide();
+            d->m_snippetOverlay->clear();
+            QTextCursor cursor = textCursor();
+            cursor.movePosition(QTextCursor::EndOfBlock);
+            setTextCursor(cursor);
+            return;
+        }
+
+
         QTextCursor cursor = textCursor();
         if (d->m_inBlockSelectionMode)
             cursor.clearSelection();
@@ -1190,9 +1205,10 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
         return;
     }
 
-    if (d->m_snippetOverlay->isVisible() &&
-        (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace))
+    if (d->m_snippetOverlay->isVisible()
+        && (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace)) {
         d->snippetCheckCursor(textCursor());
+    }
 
     if (ro || e->text().isEmpty() || !e->text().at(0).isPrint()) {
         QPlainTextEdit::keyPressEvent(e);
@@ -1263,21 +1279,21 @@ void BaseTextEditor::insertCodeSnippet(const QString &snippet)
     QMap positions;
 
     while (pos < snippet.size()) {
-        if (snippet.at(pos) != QLatin1Char('$')) {
+        if (snippet.at(pos) != QChar::ObjectReplacementCharacter) {
             const int start = pos;
             do { ++pos; }
-            while (pos < snippet.size() && snippet.at(pos) != QLatin1Char('$'));
+            while (pos < snippet.size() && snippet.at(pos) != QChar::ObjectReplacementCharacter);
             cursor.insertText(snippet.mid(start, pos - start));
         } else {
             // the start of a place holder.
             const int start = ++pos;
             for (; pos < snippet.size(); ++pos) {
-                if (snippet.at(pos) == QLatin1Char('$'))
+                if (snippet.at(pos) == QChar::ObjectReplacementCharacter)
                     break;
             }
 
             Q_ASSERT(pos < snippet.size());
-            Q_ASSERT(snippet.at(pos) == QLatin1Char('$'));
+            Q_ASSERT(snippet.at(pos) == QChar::ObjectReplacementCharacter);
 
             const QString textToInsert = snippet.mid(start, pos - start);
 
@@ -1319,7 +1335,12 @@ void BaseTextEditor::insertCodeSnippet(const QString &snippet)
         const QTextEdit::ExtraSelection &selection = selections.first();
 
         cursor = textCursor();
-        cursor.setPosition(selection.cursor.anchor() + 1);
+        if (selection.cursor.hasSelection()) {
+            cursor.setPosition(selection.cursor.selectionStart()+1);
+            cursor.setPosition(selection.cursor.selectionEnd(), QTextCursor::KeepAnchor);
+        } else {
+            cursor.setPosition(selection.cursor.position());
+        }
         setTextCursor(cursor);
     }
 }
@@ -1416,8 +1437,13 @@ bool BaseTextEditor::event(QEvent *e)
     d->m_contentsChanged = false;
     switch (e->type()) {
     case QEvent::ShortcutOverride:
+        if (static_cast(e)->key() == Qt::Key_Escape && d->m_snippetOverlay->isVisible()) {
+            e->accept();
+            return true;
+        }
         e->ignore(); // we are a really nice citizen
         return true;
+        break;
     default:
         break;
     }
@@ -1746,7 +1772,8 @@ void BaseTextEditorPrivate::snippetTabOrBacktab(bool forward)
     if (forward) {
         for (int i = 0; i < m_snippetOverlay->m_selections.count(); ++i){
             const OverlaySelection &selection = m_snippetOverlay->m_selections.at(i);
-            if (selection.m_cursor_begin.position() > cursor.position()) {
+            if (selection.m_cursor_begin.position() >= cursor.position()
+                && selection.m_cursor_end.position() > cursor.position()) {
                 final = selection;
                 break;
             }
diff --git a/src/plugins/texteditor/texteditoroverlay.h b/src/plugins/texteditor/texteditoroverlay.h
index 5e8c6d76874..9f98c38c9ac 100644
--- a/src/plugins/texteditor/texteditoroverlay.h
+++ b/src/plugins/texteditor/texteditoroverlay.h
@@ -72,6 +72,9 @@ public:
     bool isVisible() const { return m_visible; }
     void setVisible(bool b);
 
+    inline void hide() { setVisible(false); }
+    inline void show() { setVisible(true); }
+
     void setBorderWidth(int bw) {m_borderWidth = bw; }
 
     void update();