From 96e5cae4c83adfd55dad8f5f76cbb97660d91040 Mon Sep 17 00:00:00 2001
From: Erik Verbruggen <erik.verbruggen@nokia.com>
Date: Mon, 7 Dec 2009 16:57:31 +0100
Subject: [PATCH] Added metainfo classes from Bauhaus for use in the QML
 editor.

---
 src/plugins/qmleditor/qmlcodecompletion.cpp   |  12 +-
 src/plugins/qmleditor/qmlcodecompletion.h     |   4 +-
 src/plugins/qmleditor/qmleditor.cpp           |   8 +-
 src/plugins/qmleditor/qmleditor.h             |   7 +
 src/plugins/qmleditor/qmleditorplugin.cpp     |   4 +-
 .../qmleditor/qmlexpressionundercursor.cpp    |   5 +-
 .../qmleditor/qmlexpressionundercursor.h      |   4 +-
 src/plugins/qmleditor/qmlhoverhandler.cpp     |   5 +-
 src/plugins/qmleditor/qmllookupcontext.cpp    | 138 +---
 src/plugins/qmleditor/qmllookupcontext.h      |  27 +-
 .../qmleditor/qmlmodelmanagerinterface.h      |   1 +
 .../qmleditor/qmlresolveexpression.cpp        |   4 +-
 src/plugins/qmleditor/qmlresolveexpression.h  |   8 +-
 .../qml/metatype/QmlMetaTypeBackend.cpp       |  14 +
 src/shared/qml/metatype/QmlMetaTypeBackend.h  |  33 +
 .../metatype/QtDeclarativeMetaTypeBackend.cpp | 232 ++++++
 .../metatype/QtDeclarativeMetaTypeBackend.h   |  47 ++
 src/shared/qml/metatype/exception.cpp         | 163 ++++
 src/shared/qml/metatype/exception.h           |  42 ++
 .../qml/metatype/invalidmetainfoexception.cpp |  35 +
 .../qml/metatype/invalidmetainfoexception.h   |  21 +
 src/shared/qml/metatype/metainfo.cpp          | 461 ++++++++++++
 src/shared/qml/metatype/metainfo.h            |  83 +++
 src/shared/qml/metatype/nodemetainfo.cpp      | 695 ++++++++++++++++++
 src/shared/qml/metatype/nodemetainfo.h        | 103 +++
 src/shared/qml/metatype/propertymetainfo.cpp  | 378 ++++++++++
 src/shared/qml/metatype/propertymetainfo.h    |  84 +++
 src/shared/qml/metatype/qmltypesystem.cpp     |  42 ++
 src/shared/qml/metatype/qmltypesystem.h       |  34 +
 src/shared/qml/qml.pri                        |  30 +-
 src/shared/qml/qmldocument.cpp                |   3 +-
 src/shared/qml/qmldocument.h                  |   8 +-
 src/shared/qml/qmlidcollector.cpp             |  10 +-
 src/shared/qml/qmlidcollector.h               |  14 +-
 src/shared/qml/qmlpackageinfo.cpp             |  10 +
 src/shared/qml/qmlpackageinfo.h               |  32 +
 src/shared/qml/qmlsymbol.cpp                  |  11 +-
 src/shared/qml/qmlsymbol.h                    |  51 +-
 38 files changed, 2687 insertions(+), 176 deletions(-)
 create mode 100644 src/shared/qml/metatype/QmlMetaTypeBackend.cpp
 create mode 100644 src/shared/qml/metatype/QmlMetaTypeBackend.h
 create mode 100644 src/shared/qml/metatype/QtDeclarativeMetaTypeBackend.cpp
 create mode 100644 src/shared/qml/metatype/QtDeclarativeMetaTypeBackend.h
 create mode 100644 src/shared/qml/metatype/exception.cpp
 create mode 100644 src/shared/qml/metatype/exception.h
 create mode 100644 src/shared/qml/metatype/invalidmetainfoexception.cpp
 create mode 100644 src/shared/qml/metatype/invalidmetainfoexception.h
 create mode 100644 src/shared/qml/metatype/metainfo.cpp
 create mode 100644 src/shared/qml/metatype/metainfo.h
 create mode 100644 src/shared/qml/metatype/nodemetainfo.cpp
 create mode 100644 src/shared/qml/metatype/nodemetainfo.h
 create mode 100644 src/shared/qml/metatype/propertymetainfo.cpp
 create mode 100644 src/shared/qml/metatype/propertymetainfo.h
 create mode 100644 src/shared/qml/metatype/qmltypesystem.cpp
 create mode 100644 src/shared/qml/metatype/qmltypesystem.h
 create mode 100644 src/shared/qml/qmlpackageinfo.cpp
 create mode 100644 src/shared/qml/qmlpackageinfo.h

diff --git a/src/plugins/qmleditor/qmlcodecompletion.cpp b/src/plugins/qmleditor/qmlcodecompletion.cpp
index 6ee377ccb09..49bac438959 100644
--- a/src/plugins/qmleditor/qmlcodecompletion.cpp
+++ b/src/plugins/qmleditor/qmlcodecompletion.cpp
@@ -42,14 +42,16 @@
 using namespace QmlEditor;
 using namespace QmlEditor::Internal;
 
-QmlCodeCompletion::QmlCodeCompletion(QmlModelManagerInterface *modelManager,QObject *parent)
+QmlCodeCompletion::QmlCodeCompletion(QmlModelManagerInterface *modelManager, Qml::MetaType::QmlTypeSystem *typeSystem, QObject *parent)
     : TextEditor::ICompletionCollector(parent),
       m_modelManager(modelManager),
       m_editor(0),
       m_startPosition(0),
-      m_caseSensitivity(Qt::CaseSensitive)
+      m_caseSensitivity(Qt::CaseSensitive),
+      m_typeSystem(typeSystem)
 {
     Q_ASSERT(modelManager);
+    Q_ASSERT(typeSystem);
 }
 
 QmlCodeCompletion::~QmlCodeCompletion()
@@ -119,13 +121,13 @@ int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
             cursor.setPosition(pos);
             expressionUnderCursor(cursor, qmlDocument);
 
-            QmlLookupContext context(expressionUnderCursor.expressionScopes(), qmlDocument, m_modelManager->snapshot());
+            QmlLookupContext context(expressionUnderCursor.expressionScopes(), qmlDocument, m_modelManager->snapshot(), m_typeSystem);
             QmlResolveExpression resolver(context);
 //            qDebug()<<"*** expression under cursor:"<<expressionUnderCursor.expressionNode();
-            QList<QmlSymbol*> symbols = resolver.visibleSymbols(expressionUnderCursor.expressionNode());
+            QList<Qml::QmlSymbol*> symbols = resolver.visibleSymbols(expressionUnderCursor.expressionNode());
 //            qDebug()<<"***"<<symbols.size()<<"visible symbols";
 
-            foreach (QmlSymbol *symbol, symbols) {
+            foreach (Qml::QmlSymbol *symbol, symbols) {
                 QString word;
 
                 if (symbol->isIdSymbol()) {
diff --git a/src/plugins/qmleditor/qmlcodecompletion.h b/src/plugins/qmleditor/qmlcodecompletion.h
index 8ed9aaf05a2..0b8c8edfa88 100644
--- a/src/plugins/qmleditor/qmlcodecompletion.h
+++ b/src/plugins/qmleditor/qmlcodecompletion.h
@@ -1,6 +1,7 @@
 #ifndef QMLCODECOMPLETION_H
 #define QMLCODECOMPLETION_H
 
+#include <qml/metatype/qmltypesystem.h>
 #include <texteditor/icompletioncollector.h>
 
 namespace TextEditor {
@@ -18,7 +19,7 @@ class QmlCodeCompletion: public TextEditor::ICompletionCollector
     Q_OBJECT
 
 public:
-    QmlCodeCompletion(QmlModelManagerInterface *modelManager, QObject *parent = 0);
+    QmlCodeCompletion(QmlModelManagerInterface *modelManager, Qml::MetaType::QmlTypeSystem *typeSystem, QObject *parent = 0);
     virtual ~QmlCodeCompletion();
 
     Qt::CaseSensitivity caseSensitivity() const;
@@ -38,6 +39,7 @@ private:
     int m_startPosition;
     QList<TextEditor::CompletionItem> m_completions;
     Qt::CaseSensitivity m_caseSensitivity;
+    Qml::MetaType::QmlTypeSystem *m_typeSystem;
 };
 
 
diff --git a/src/plugins/qmleditor/qmleditor.cpp b/src/plugins/qmleditor/qmleditor.cpp
index ab312bc2588..6cc759496a2 100644
--- a/src/plugins/qmleditor/qmleditor.cpp
+++ b/src/plugins/qmleditor/qmleditor.cpp
@@ -37,6 +37,7 @@
 #include "qmllookupcontext.h"
 #include "qmlresolveexpression.h"
 
+#include <qml/metatype/qmltypesystem.h>
 #include <qml/parser/qmljsastvisitor_p.h>
 #include <qml/parser/qmljsast_p.h>
 #include <qml/parser/qmljsengine_p.h>
@@ -68,6 +69,7 @@ enum {
     UPDATE_DOCUMENT_DEFAULT_INTERVAL = 250
 };
 
+using namespace Qml;
 using namespace QmlJS;
 using namespace QmlJS::AST;
 using namespace SharedTools;
@@ -378,7 +380,8 @@ ScriptEditorEditable::ScriptEditorEditable(ScriptEditor *editor)
 ScriptEditor::ScriptEditor(QWidget *parent) :
     TextEditor::BaseTextEditor(parent),
     m_methodCombo(0),
-    m_modelManager(0)
+    m_modelManager(0),
+    m_typeSystem(0)
 {
     setParenthesesMatchingEnabled(true);
     setMarksVisible(true);
@@ -397,6 +400,7 @@ ScriptEditor::ScriptEditor(QWidget *parent) :
     baseTextDocument()->setSyntaxHighlighter(new QmlHighlighter);
 
     m_modelManager = ExtensionSystem::PluginManager::instance()->getObject<QmlModelManagerInterface>();
+    m_typeSystem = ExtensionSystem::PluginManager::instance()->getObject<Qml::MetaType::QmlTypeSystem>();
 
     if (m_modelManager) {
         connect(m_modelManager, SIGNAL(documentUpdated(QmlEditor::QmlDocument::Ptr)),
@@ -768,7 +772,7 @@ TextEditor::BaseTextEditor::Link ScriptEditor::findLinkAt(const QTextCursor &cur
     QmlExpressionUnderCursor expressionUnderCursor;
     expressionUnderCursor(expressionCursor, doc);
 
-    QmlLookupContext context(expressionUnderCursor.expressionScopes(), doc, snapshot);
+    QmlLookupContext context(expressionUnderCursor.expressionScopes(), doc, snapshot, m_typeSystem);
     QmlResolveExpression resolver(context);
     QmlSymbol *symbol = resolver.typeOf(expressionUnderCursor.expressionNode());
 
diff --git a/src/plugins/qmleditor/qmleditor.h b/src/plugins/qmleditor/qmleditor.h
index 90af86fe9c7..6ad1c2c32c5 100644
--- a/src/plugins/qmleditor/qmleditor.h
+++ b/src/plugins/qmleditor/qmleditor.h
@@ -43,6 +43,12 @@ namespace Core {
 class ICore;
 }
 
+namespace Qml {
+    namespace MetaType {
+        class QmlTypeSystem;
+    }
+}
+
 namespace QmlEditor {
 
 class QmlModelManagerInterface;
@@ -146,6 +152,7 @@ private:
     QList<QmlJS::DiagnosticMessage> m_diagnosticMessages;
     QmlDocument::Ptr m_document;
     QmlModelManagerInterface *m_modelManager;
+    Qml::MetaType::QmlTypeSystem *m_typeSystem;
 };
 
 } // namespace Internal
diff --git a/src/plugins/qmleditor/qmleditorplugin.cpp b/src/plugins/qmleditor/qmleditorplugin.cpp
index 8e1441f7c5f..3e1d032ee74 100644
--- a/src/plugins/qmleditor/qmleditorplugin.cpp
+++ b/src/plugins/qmleditor/qmleditorplugin.cpp
@@ -94,6 +94,8 @@ bool QmlEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err
 
     m_modelManager = new QmlModelManager(this);
     addAutoReleasedObject(m_modelManager);
+    Qml::MetaType::QmlTypeSystem *typeSystem = new Qml::MetaType::QmlTypeSystem;
+    addAutoReleasedObject(typeSystem);
 
     QList<int> context;
     context<< core->uniqueIDManager()->uniqueIdentifier(QmlEditor::Constants::C_QMLEDITOR);
@@ -122,7 +124,7 @@ bool QmlEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err
     cmd = am->command(TextEditor::Constants::UN_COMMENT_SELECTION);
     contextMenu->addAction(cmd);
 
-    m_completion = new QmlCodeCompletion(m_modelManager);
+    m_completion = new QmlCodeCompletion(m_modelManager, typeSystem);
     addAutoReleasedObject(m_completion);
 
     addAutoReleasedObject(new QmlHoverHandler());
diff --git a/src/plugins/qmleditor/qmlexpressionundercursor.cpp b/src/plugins/qmleditor/qmlexpressionundercursor.cpp
index 5fd7c5031f3..b664d5d410f 100644
--- a/src/plugins/qmleditor/qmlexpressionundercursor.cpp
+++ b/src/plugins/qmleditor/qmlexpressionundercursor.cpp
@@ -9,6 +9,7 @@
 
 #include <QDebug>
 
+using namespace Qml;
 using namespace QmlJS;
 using namespace QmlJS::AST;
 
@@ -118,7 +119,7 @@ namespace QmlEditor {
 
             virtual bool visit(UiObjectBinding *ast)
             {
-                if (ast->initializer && ast->initializer->rbraceToken.offset < _pos && _pos <= ast->initializer->lbraceToken.end()) {
+                if (ast->initializer && ast->initializer->lbraceToken.offset < _pos && _pos <= ast->initializer->rbraceToken.end()) {
                     push(ast);
                     Node::accept(ast->initializer, this);
                 }
@@ -128,7 +129,7 @@ namespace QmlEditor {
 
             virtual bool visit(UiObjectDefinition *ast)
             {
-                if (ast->initializer && ast->initializer->rbraceToken.offset < _pos && _pos <= ast->initializer->lbraceToken.end()) {
+                if (ast->initializer && ast->initializer->lbraceToken.offset < _pos && _pos <= ast->initializer->rbraceToken.end()) {
                     push(ast);
                     Node::accept(ast->initializer, this);
                 }
diff --git a/src/plugins/qmleditor/qmlexpressionundercursor.h b/src/plugins/qmleditor/qmlexpressionundercursor.h
index 94681905806..29c9b4b1d7d 100644
--- a/src/plugins/qmleditor/qmlexpressionundercursor.h
+++ b/src/plugins/qmleditor/qmlexpressionundercursor.h
@@ -26,7 +26,7 @@ public:
 
     void operator()(const QTextCursor &cursor, const QmlDocument::Ptr &doc);
 
-    QStack<QmlSymbol *> expressionScopes() const
+    QStack<Qml::QmlSymbol *> expressionScopes() const
     { return _expressionScopes; }
 
     QmlJS::AST::Node *expressionNode() const
@@ -45,7 +45,7 @@ private:
     QmlJS::AST::UiObjectMember *tryBinding(const QString &text);
 
 private:
-    QStack<QmlSymbol *> _expressionScopes;
+    QStack<Qml::QmlSymbol *> _expressionScopes;
     QmlJS::AST::Node *_expressionNode;
     int _expressionOffset;
     int _expressionLength;
diff --git a/src/plugins/qmleditor/qmlhoverhandler.cpp b/src/plugins/qmleditor/qmlhoverhandler.cpp
index a23e6607669..4e045539739 100644
--- a/src/plugins/qmleditor/qmlhoverhandler.cpp
+++ b/src/plugins/qmleditor/qmlhoverhandler.cpp
@@ -52,6 +52,7 @@
 #include <QtHelp/QHelpEngineCore>
 
 using namespace Core;
+using namespace Qml;
 using namespace QmlEditor;
 using namespace QmlEditor::Internal;
 
@@ -186,7 +187,9 @@ void QmlHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
         QmlExpressionUnderCursor expressionUnderCursor;
         expressionUnderCursor(tc, doc);
 
-        QmlLookupContext context(expressionUnderCursor.expressionScopes(), doc, m_modelManager->snapshot());
+        Qml::MetaType::QmlTypeSystem *typeSystem = ExtensionSystem::PluginManager::instance()->getObject<Qml::MetaType::QmlTypeSystem>();
+
+        QmlLookupContext context(expressionUnderCursor.expressionScopes(), doc, m_modelManager->snapshot(), typeSystem);
         QmlResolveExpression resolver(context);
         QmlSymbol *resolvedSymbol = resolver.typeOf(expressionUnderCursor.expressionNode());
 
diff --git a/src/plugins/qmleditor/qmllookupcontext.cpp b/src/plugins/qmleditor/qmllookupcontext.cpp
index d5869c0bfcb..e4fc0336565 100644
--- a/src/plugins/qmleditor/qmllookupcontext.cpp
+++ b/src/plugins/qmleditor/qmllookupcontext.cpp
@@ -2,11 +2,14 @@
 #include "qmllookupcontext.h"
 #include "qmlresolveexpression.h"
 
+#include <qml/metatype/qmltypesystem.h>
 #include <qml/parser/qmljsast_p.h>
 #include <qml/parser/qmljsengine_p.h>
 
 #include <QDebug>
 
+using namespace Qml;
+using namespace Qml::MetaType;
 using namespace QmlEditor;
 using namespace QmlEditor::Internal;
 using namespace QmlJS;
@@ -14,11 +17,14 @@ using namespace QmlJS::AST;
 
 QmlLookupContext::QmlLookupContext(const QStack<QmlSymbol *> &scopes,
                                    const QmlDocument::Ptr &doc,
-                                   const Snapshot &snapshot):
+                                   const Snapshot &snapshot,
+                                   QmlTypeSystem *typeSystem):
         _scopes(scopes),
         _doc(doc),
-        _snapshot(snapshot)
+        _snapshot(snapshot),
+        m_typeSystem(typeSystem)
 {
+    Q_ASSERT(typeSystem != 0);
 }
 
 static inline int findFirstQmlObjectScope(const QStack<QmlSymbol*> &scopes, int startIdx)
@@ -114,104 +120,12 @@ QmlSymbol *QmlLookupContext::resolveType(const QString &name, const QString &fil
     return resolveBuildinType(name);
 }
 
-// FIXME: use a REAL mete-type system here!
-static QSet<QString> qmlMetaTypes = QSet<QString>()
-                             << QLatin1String("AnchorChanges")
-                             << QLatin1String("AnimatedImage")
-                             << QLatin1String("Animation")
-                             << QLatin1String("Behavior")
-                             << QLatin1String("Binding")
-                             << QLatin1String("BorderImage")
-                             << QLatin1String("ColorAnimation")
-                             << QLatin1String("Column")
-                             << QLatin1String("Component")
-                             << QLatin1String("Connection")
-                             << QLatin1String("DateTimeFormatter")
-                             << QLatin1String("EaseFollow")
-                             << QLatin1String("Flickable")
-                             << QLatin1String("Flipable")
-                             << QLatin1String("FocusPanel")
-                             << QLatin1String("FocusScope")
-                             << QLatin1String("FolderListModel")
-                             << QLatin1String("FontLoader")
-                             << QLatin1String("Gradient")
-                             << QLatin1String("GradientStop")
-                             << QLatin1String("GraphicsObjectContainer")
-                             << QLatin1String("Grid")
-                             << QLatin1String("GridView")
-                             << QLatin1String("Image")
-                             << QLatin1String("Item")
-                             << QLatin1String("KeyEvent")
-                             << QLatin1String("Keys")
-                             << QLatin1String("LayoutItem")
-                             << QLatin1String("ListModel")
-                             << QLatin1String("ListView")
-                             << QLatin1String("Loader")
-                             << QLatin1String("MouseEvent")
-                             << QLatin1String("MouseRegion")
-                             << QLatin1String("NumberAnimation")
-                             << QLatin1String("NumberFormatter")
-                             << QLatin1String("ParallelAnimation")
-                             << QLatin1String("ParentAction")
-                             << QLatin1String("ParentChange")
-                             << QLatin1String("ParticleMotionGravity")
-                             << QLatin1String("ParticleMotionLinear")
-                             << QLatin1String("ParticleMotionWander")
-                             << QLatin1String("Particles")
-                             << QLatin1String("Path")
-                             << QLatin1String("PathAttribute")
-                             << QLatin1String("PathCubic")
-                             << QLatin1String("PathElement")
-                             << QLatin1String("PathLine")
-                             << QLatin1String("PathPercent")
-                             << QLatin1String("PathQuad")
-                             << QLatin1String("PathView")
-                             << QLatin1String("PauseAnimation")
-                             << QLatin1String("PropertyAction")
-                             << QLatin1String("PropertyAnimation")
-                             << QLatin1String("PropertyChanges")
-                             << QLatin1String("Rectangle")
-                             << QLatin1String("Repeater")
-                             << QLatin1String("Rotation")
-                             << QLatin1String("Row")
-                             << QLatin1String("Scale")
-                             << QLatin1String("Script")
-                             << QLatin1String("ScriptAction")
-                             << QLatin1String("SequentialAnimation")
-                             << QLatin1String("SpringFollow")
-                             << QLatin1String("SqlBind")
-                             << QLatin1String("SqlConnection")
-                             << QLatin1String("SqlQuery")
-                             << QLatin1String("State")
-                             << QLatin1String("StateChangeScript")
-                             << QLatin1String("SystemPalette")
-                             << QLatin1String("Text")
-                             << QLatin1String("TextEdit")
-                             << QLatin1String("TextInput")
-                             << QLatin1String("Timer")
-                             << QLatin1String("Transform")
-                             << QLatin1String("Transition")
-                             << QLatin1String("VisualItemModel")
-                             << QLatin1String("WebView")
-                             << QLatin1String("XmlListModel")
-                             << QLatin1String("XmlRole");
-
 QmlSymbol *QmlLookupContext::resolveBuildinType(const QString &name)
 {
-    // FIXME: use a REAL mete-type system here!
-
-    if (name == "Rectangle") {
-        QmlBuildInSymbol *rectSymbol = new QmlBuildInSymbol(name);
-        rectSymbol->addMember(new QmlBuildInSymbol("x"));
-        rectSymbol->addMember(new QmlBuildInSymbol("y"));
-        rectSymbol->addMember(new QmlBuildInSymbol("height"));
-        rectSymbol->addMember(new QmlBuildInSymbol("width"));
-        return rectSymbol;
-    } else if (qmlMetaTypes.contains(name)) {
-        return new QmlBuildInSymbol(name);
-    } else {
-        return 0;
-    }
+    QList<Qml::PackageInfo> packages;
+    // FIXME:
+    packages.append(PackageInfo("Qt", 4, 6));
+    return m_typeSystem->resolve(name, packages);
 }
 
 QmlSymbol *QmlLookupContext::resolveProperty(const QString &name, QmlSymbol *scope, const QString &fileName)
@@ -270,7 +184,11 @@ QList<QmlSymbol*> QmlLookupContext::visibleSymbolsInScope()
     if (!_scopes.isEmpty()) {
         QmlSymbol *scope = _scopes.top();
 
+        // add members defined in this symbol:
         result.append(scope->members());
+
+        // add the members of the type of this scope (= object):
+        result.append(expandType(scope));
     }
 
     return result;
@@ -301,9 +219,27 @@ QList<QmlSymbol*> QmlLookupContext::visibleTypes()
         }
     }
 
-    // TODO: handle Qt imports, hack for now:
-    foreach (const QString &name, qmlMetaTypes)
-        result.append(resolveBuildinType(name));
+    result.append(m_typeSystem->availableTypes("Qt", 4, 6));
 
     return result;
 }
+
+QList<QmlSymbol*> QmlLookupContext::expandType(Qml::QmlSymbol *symbol)
+{
+    if (symbol == 0) {
+        return QList<QmlSymbol*>();
+    } else if (QmlBuildInSymbol *buildInSymbol = symbol->asBuildInSymbol()) {
+        return buildInSymbol->members(true);
+    } else if (QmlSymbolFromFile *symbolFromFile = symbol->asSymbolFromFile()){
+        QList<QmlSymbol*> result;
+
+        if (QmlSymbol *superTypeSymbol = resolveType(symbolFromFile->name(), symbolFromFile->fileName())) {
+            result.append(superTypeSymbol->members());
+            result.append(expandType(superTypeSymbol));
+        }
+
+        return result;
+    } else {
+        return QList<QmlSymbol*>();
+    }
+}
diff --git a/src/plugins/qmleditor/qmllookupcontext.h b/src/plugins/qmleditor/qmllookupcontext.h
index 32b508a3cc7..e9708dc853e 100644
--- a/src/plugins/qmleditor/qmllookupcontext.h
+++ b/src/plugins/qmleditor/qmllookupcontext.h
@@ -1,6 +1,7 @@
 #ifndef QMLLOOKUPCONTEXT_H
 #define QMLLOOKUPCONTEXT_H
 
+#include <qml/metatype/qmltypesystem.h>
 #include <qml/parser/qmljsastvisitor_p.h>
 #include <qml/qmldocument.h>
 #include <qml/qmlsymbol.h>
@@ -13,33 +14,37 @@ namespace Internal {
 class QmlLookupContext
 {
 public:
-    QmlLookupContext(const QStack<QmlSymbol *> &scopes,
+    QmlLookupContext(const QStack<Qml::QmlSymbol *> &scopes,
                      const QmlDocument::Ptr &doc,
-                     const Snapshot &snapshot);
+                     const Snapshot &snapshot,
+                     Qml::MetaType::QmlTypeSystem *typeSystem);
 
-    QmlSymbol *resolve(const QString &name);
-    QmlSymbol *resolveType(const QString &name)
+    Qml::QmlSymbol *resolve(const QString &name);
+    Qml::QmlSymbol *resolveType(const QString &name)
     { return resolveType(name, _doc->fileName()); }
-    QmlSymbol *resolveType(QmlJS::AST::UiQualifiedId *name)
+    Qml::QmlSymbol *resolveType(QmlJS::AST::UiQualifiedId *name)
     { return resolveType(toString(name), _doc->fileName()); }
 
     QmlDocument::Ptr document() const
     { return _doc; }
 
-    QList<QmlSymbol*> visibleSymbolsInScope();
-    QList<QmlSymbol*> visibleTypes();
+    QList<Qml::QmlSymbol*> visibleSymbolsInScope();
+    QList<Qml::QmlSymbol*> visibleTypes();
+
+    QList<Qml::QmlSymbol*> expandType(Qml::QmlSymbol *symbol);
 
 private:
-    QmlSymbol *resolveType(const QString &name, const QString &fileName);
-    QmlSymbol *resolveProperty(const QString &name, QmlSymbol *scope, const QString &fileName);
-    QmlSymbol *resolveBuildinType(const QString &name);
+    Qml::QmlSymbol *resolveType(const QString &name, const QString &fileName);
+    Qml::QmlSymbol *resolveProperty(const QString &name, Qml::QmlSymbol *scope, const QString &fileName);
+    Qml::QmlSymbol *resolveBuildinType(const QString &name);
 
     static QString toString(QmlJS::AST::UiQualifiedId *id);
 
 private:
-    QStack<QmlSymbol *> _scopes;
+    QStack<Qml::QmlSymbol *> _scopes;
     QmlDocument::Ptr _doc;
     Snapshot _snapshot;
+    Qml::MetaType::QmlTypeSystem *m_typeSystem;
 };
 
 } // namespace Internal
diff --git a/src/plugins/qmleditor/qmlmodelmanagerinterface.h b/src/plugins/qmleditor/qmlmodelmanagerinterface.h
index 3599f44672b..896f76a871d 100644
--- a/src/plugins/qmleditor/qmlmodelmanagerinterface.h
+++ b/src/plugins/qmleditor/qmlmodelmanagerinterface.h
@@ -37,6 +37,7 @@
 #include <QSharedPointer>
 
 #include <qml/qmldocument.h>
+#include <qml/metatype/qmltypesystem.h>
 
 namespace QmlEditor {
 
diff --git a/src/plugins/qmleditor/qmlresolveexpression.cpp b/src/plugins/qmleditor/qmlresolveexpression.cpp
index 1c798cd58f9..fa09b07aca8 100644
--- a/src/plugins/qmleditor/qmlresolveexpression.cpp
+++ b/src/plugins/qmleditor/qmlresolveexpression.cpp
@@ -3,6 +3,7 @@
 #include <qml/parser/qmljsast_p.h>
 #include <qml/parser/qmljsengine_p.h>
 
+using namespace Qml;
 using namespace QmlEditor;
 using namespace QmlEditor::Internal;
 using namespace QmlJS;
@@ -16,8 +17,7 @@ QmlResolveExpression::QmlResolveExpression(const QmlLookupContext &context)
 QmlSymbol *QmlResolveExpression::typeOf(Node *node)
 {
     QmlSymbol *previousValue = switchValue(0);
-    if (node)
-        node->accept(this);
+    Node::accept(node, this);
     return switchValue(previousValue);
 }
 
diff --git a/src/plugins/qmleditor/qmlresolveexpression.h b/src/plugins/qmleditor/qmlresolveexpression.h
index 6030f1c29c7..d876afaf2e7 100644
--- a/src/plugins/qmleditor/qmlresolveexpression.h
+++ b/src/plugins/qmleditor/qmlresolveexpression.h
@@ -14,13 +14,13 @@ class QmlResolveExpression: protected QmlJS::AST::Visitor
 public:
     QmlResolveExpression(const QmlLookupContext &context);
 
-    QmlSymbol *typeOf(QmlJS::AST::Node *node);
-    QList<QmlSymbol*> visibleSymbols(QmlJS::AST::Node *node);
+    Qml::QmlSymbol *typeOf(QmlJS::AST::Node *node);
+    QList<Qml::QmlSymbol*> visibleSymbols(QmlJS::AST::Node *node);
 
 protected:
     using QmlJS::AST::Visitor::visit;
 
-    QmlSymbol *switchValue(QmlSymbol *symbol);
+    Qml::QmlSymbol *switchValue(Qml::QmlSymbol *symbol);
 
     virtual bool visit(QmlJS::AST::FieldMemberExpression *ast);
     virtual bool visit(QmlJS::AST::IdentifierExpression *ast);
@@ -28,7 +28,7 @@ protected:
 
 private:
     QmlLookupContext _context;
-    QmlSymbol *_value;
+    Qml::QmlSymbol *_value;
 };
 
 } // namespace Internal
diff --git a/src/shared/qml/metatype/QmlMetaTypeBackend.cpp b/src/shared/qml/metatype/QmlMetaTypeBackend.cpp
new file mode 100644
index 00000000000..ec65714989b
--- /dev/null
+++ b/src/shared/qml/metatype/QmlMetaTypeBackend.cpp
@@ -0,0 +1,14 @@
+#include "QmlMetaTypeBackend.h"
+#include "qmltypesystem.h"
+
+using namespace Qml::MetaType;
+
+QmlMetaTypeBackend::QmlMetaTypeBackend(QmlTypeSystem *typeSystem):
+        m_typeSystem(typeSystem)
+{
+    Q_ASSERT(typeSystem);
+}
+
+QmlMetaTypeBackend::~QmlMetaTypeBackend()
+{
+}
diff --git a/src/shared/qml/metatype/QmlMetaTypeBackend.h b/src/shared/qml/metatype/QmlMetaTypeBackend.h
new file mode 100644
index 00000000000..cd400bfa66a
--- /dev/null
+++ b/src/shared/qml/metatype/QmlMetaTypeBackend.h
@@ -0,0 +1,33 @@
+#ifndef QMLMETATYPEBACKEND_H
+#define QMLMETATYPEBACKEND_H
+
+#include <qml/qml_global.h>
+#include <qml/qmlpackageinfo.h>
+#include <qml/qmlsymbol.h>
+
+namespace Qml {
+namespace MetaType {
+
+class QmlTypeSystem;
+
+class QML_EXPORT QmlMetaTypeBackend
+{
+public:
+    QmlMetaTypeBackend(QmlTypeSystem *typeSystem);
+    virtual ~QmlMetaTypeBackend() = 0;
+
+    virtual QList<QmlSymbol *> availableTypes(const QString &package, int majorVersion, int minorVersion) = 0;
+    virtual QmlSymbol *resolve(const QString &typeName, const QList<PackageInfo> &packages) = 0;
+
+protected:
+    QmlTypeSystem *typeSystem() const
+    { return m_typeSystem; }
+
+private:
+    QmlTypeSystem *m_typeSystem;
+};
+
+} // namespace MetaType
+} // namespace Qml
+
+#endif // QMLMETATYPEBACKEND_H
diff --git a/src/shared/qml/metatype/QtDeclarativeMetaTypeBackend.cpp b/src/shared/qml/metatype/QtDeclarativeMetaTypeBackend.cpp
new file mode 100644
index 00000000000..53c1308b9ae
--- /dev/null
+++ b/src/shared/qml/metatype/QtDeclarativeMetaTypeBackend.cpp
@@ -0,0 +1,232 @@
+#include "metainfo.h"
+#include "QtDeclarativeMetaTypeBackend.h"
+
+#include <QDebug>
+
+namespace Qml {
+namespace MetaType {
+namespace Internal {
+
+class QmlDeclarativeSymbol: public QmlBuildInSymbol
+{
+public:
+    virtual ~QmlDeclarativeSymbol()
+    {}
+
+protected:
+    QmlDeclarativeSymbol(QtDeclarativeMetaTypeBackend* backend):
+            m_backend(backend)
+    { Q_ASSERT(backend); }
+    
+    QtDeclarativeMetaTypeBackend* backend() const
+    { return m_backend; }
+
+private:
+    QtDeclarativeMetaTypeBackend* m_backend;
+};
+
+class QmlDeclarativeObjectSymbol: public QmlDeclarativeSymbol
+{
+    QmlDeclarativeObjectSymbol(const QmlDeclarativeObjectSymbol &);
+    QmlDeclarativeObjectSymbol &operator=(const QmlDeclarativeObjectSymbol &);
+
+public:
+    QmlDeclarativeObjectSymbol(const QKineticDesigner::NodeMetaInfo &metaInfo, QtDeclarativeMetaTypeBackend* backend):
+            QmlDeclarativeSymbol(backend),
+            m_metaInfo(metaInfo)
+    {
+        Q_ASSERT(metaInfo.isValid());
+
+        m_name = m_metaInfo.typeName();
+        const int slashIdx = m_name.indexOf('/');
+        if (slashIdx != -1)
+            m_name = m_name.mid(slashIdx + 1);
+    }
+
+    virtual ~QmlDeclarativeObjectSymbol()
+    { qDeleteAll(m_members); }
+
+    virtual const QString name() const
+    { return m_name; }
+
+    virtual QmlBuildInSymbol *type() const
+    { return 0; }
+
+    virtual const List members()
+    {
+        if (m_membersToBeDone)
+            initMembers();
+
+        return m_members;
+    }
+
+    virtual List members(bool includeBaseClassMembers)
+    {
+        List result = members();
+
+        if (includeBaseClassMembers)
+            result.append(backend()->inheritedMembers(m_metaInfo));
+
+        return result;
+    }
+
+public:
+    static QString key(const QKineticDesigner::NodeMetaInfo &metaInfo)
+    {
+        return key(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion());
+    }
+
+    static QString key(const QString &typeNameWithPackage, int majorVersion, int minorVersion)
+    {
+        return QString(typeNameWithPackage)
+                + QLatin1Char('@')
+                + QString::number(majorVersion)
+                + QLatin1Char('.')
+                + QString::number(minorVersion);
+    }
+
+    static QString key(const QString &packageName, const QString &typeName, int majorVersion, int minorVersion)
+    {
+        return packageName
+                + QLatin1Char('/')
+                + typeName
+                + QLatin1Char('@')
+                + QString::number(majorVersion)
+                + QLatin1Char('.')
+                + QString::number(minorVersion);
+    }
+
+private:
+    void initMembers()
+    {
+        if (!m_membersToBeDone)
+            return;
+        m_membersToBeDone = false;
+
+        m_members = backend()->members(m_metaInfo);
+    }
+
+private:
+    QKineticDesigner::NodeMetaInfo m_metaInfo;
+    QString m_name;
+
+    bool m_membersToBeDone;
+    List m_members;
+};
+
+class QmlDeclarativePropertySymbol: public QmlDeclarativeSymbol
+{
+    QmlDeclarativePropertySymbol(const QmlDeclarativePropertySymbol &);
+    QmlDeclarativePropertySymbol &operator=(const QmlDeclarativePropertySymbol &);
+
+public:
+    QmlDeclarativePropertySymbol(const QKineticDesigner::PropertyMetaInfo &metaInfo, QtDeclarativeMetaTypeBackend* backend):
+            QmlDeclarativeSymbol(backend),
+            m_metaInfo(metaInfo)
+    {
+    }
+
+    virtual ~QmlDeclarativePropertySymbol()
+    {}
+
+    virtual const QString name() const
+    { return m_metaInfo.name(); }
+
+    virtual QmlBuildInSymbol *type() const
+    { return backend()->typeOf(m_metaInfo); }
+
+    virtual const List members()
+    {
+        return List();
+    }
+
+    virtual List members(bool /*includeBaseClassMembers*/)
+    {
+        return members();
+    }
+
+private:
+    QKineticDesigner::PropertyMetaInfo m_metaInfo;
+};
+    
+} // namespace Internal
+} // namespace MetaType
+} // namespace Qml
+
+using namespace Qml;
+using namespace Qml::MetaType;
+using namespace Qml::MetaType::Internal;
+
+QtDeclarativeMetaTypeBackend::QtDeclarativeMetaTypeBackend(QmlTypeSystem *typeSystem):
+        QmlMetaTypeBackend(typeSystem)
+{
+    foreach (const QKineticDesigner::NodeMetaInfo &metaInfo, QKineticDesigner::MetaInfo::global().allTypes()) {
+        m_symbols.insert(QmlDeclarativeObjectSymbol::key(metaInfo), new QmlDeclarativeObjectSymbol(metaInfo, this));
+    }
+}
+
+QtDeclarativeMetaTypeBackend::~QtDeclarativeMetaTypeBackend()
+{
+    qDeleteAll(m_symbols.values());
+}
+
+QList<QmlSymbol *> QtDeclarativeMetaTypeBackend::availableTypes(const QString &package, int majorVersion, int minorVersion)
+{
+    QList<QmlSymbol *> result;
+    const QString prefix = package + QLatin1Char('/');
+
+    foreach (const QKineticDesigner::NodeMetaInfo &metaInfo, QKineticDesigner::MetaInfo::global().allTypes()) {
+        if (metaInfo.typeName().startsWith(prefix) && metaInfo.majorVersion() == majorVersion && metaInfo.minorVersion() == minorVersion)
+            result.append(getSymbol(metaInfo));
+    }
+
+    return result;
+}
+
+QmlSymbol *QtDeclarativeMetaTypeBackend::resolve(const QString &typeName, const QList<PackageInfo> &packages)
+{
+    QList<QmlSymbol *> result;
+
+    foreach (const PackageInfo &package, packages) {
+        if (QmlSymbol *symbol = m_symbols.value(QmlDeclarativeObjectSymbol::key(package.name(), typeName, package.majorVersion(), package.minorVersion()), 0))
+            return symbol;
+    }
+
+    return 0;
+}
+
+QList<QmlSymbol *> QtDeclarativeMetaTypeBackend::members(const QKineticDesigner::NodeMetaInfo &metaInfo)
+{
+    QList<QmlSymbol *> result;
+
+    foreach (const QKineticDesigner::PropertyMetaInfo &propertyInfo, metaInfo.properties(false).values()) {
+        result.append(new QmlDeclarativePropertySymbol(propertyInfo, this));
+    }
+
+    return result;
+}
+
+QList<QmlSymbol *> QtDeclarativeMetaTypeBackend::inheritedMembers(const QKineticDesigner::NodeMetaInfo &metaInfo)
+{
+    QList<QmlSymbol *> result;
+
+    foreach (const QKineticDesigner::NodeMetaInfo &superNode, metaInfo.directSuperClasses()) {
+        result.append(getSymbol(superNode)->members(true));
+    }
+
+    return result;
+}
+
+QmlDeclarativeSymbol *QtDeclarativeMetaTypeBackend::typeOf(const QKineticDesigner::PropertyMetaInfo &metaInfo)
+{
+    const QString key = QmlDeclarativeObjectSymbol::key(metaInfo.type(), metaInfo.typeMajorVersion(), metaInfo.typeMinorVersion());
+
+    return m_symbols.value(key, 0);
+}
+
+QmlDeclarativeSymbol *QtDeclarativeMetaTypeBackend::getSymbol(const QKineticDesigner::NodeMetaInfo &metaInfo)
+{
+    const QString key = QmlDeclarativeObjectSymbol::key(metaInfo);
+
+    return m_symbols.value(key, 0);
+}
diff --git a/src/shared/qml/metatype/QtDeclarativeMetaTypeBackend.h b/src/shared/qml/metatype/QtDeclarativeMetaTypeBackend.h
new file mode 100644
index 00000000000..e0693c124ce
--- /dev/null
+++ b/src/shared/qml/metatype/QtDeclarativeMetaTypeBackend.h
@@ -0,0 +1,47 @@
+#ifndef QTDECLARATIVEMETATYPEBACKEND_H
+#define QTDECLARATIVEMETATYPEBACKEND_H
+
+#include <qml/metatype/QmlMetaTypeBackend.h>
+#include <qml/metatype/nodemetainfo.h>
+#include <qml/metatype/propertymetainfo.h>
+
+#include <QtCore/QList>
+
+namespace Qml {
+namespace MetaType {
+namespace Internal {
+
+class QmlDeclarativeSymbol;
+class QmlDeclarativeObjectSymbol;
+class QmlDeclarativePropertySymbol;
+
+class QtDeclarativeMetaTypeBackend: public QmlMetaTypeBackend
+{
+    friend class QmlDeclarativeSymbol;
+    friend class QmlDeclarativeObjectSymbol;
+    friend class QmlDeclarativePropertySymbol;
+
+public:
+    QtDeclarativeMetaTypeBackend(QmlTypeSystem *typeSystem);
+    ~QtDeclarativeMetaTypeBackend();
+
+    virtual QList<QmlSymbol *> availableTypes(const QString &package, int majorVersion, int minorVersion);
+    virtual QmlSymbol *resolve(const QString &typeName, const QList<PackageInfo> &packages);
+
+protected:
+    QList<QmlSymbol *> members(const QKineticDesigner::NodeMetaInfo &metaInfo);
+    QList<QmlSymbol *> inheritedMembers(const QKineticDesigner::NodeMetaInfo &metaInfo);
+    QmlDeclarativeSymbol *typeOf(const QKineticDesigner::PropertyMetaInfo &metaInfo);
+
+private:
+    QmlDeclarativeSymbol *getSymbol(const QKineticDesigner::NodeMetaInfo &metaInfo);
+
+private:
+    QMap<QString, QmlDeclarativeSymbol*> m_symbols;
+};
+
+} // namespace Internal
+} // namespace MetaType
+} // namespace Qml
+
+#endif // QTDECLARATIVEMETATYPEBACKEND_H
diff --git a/src/shared/qml/metatype/exception.cpp b/src/shared/qml/metatype/exception.cpp
new file mode 100644
index 00000000000..1d836476e2c
--- /dev/null
+++ b/src/shared/qml/metatype/exception.cpp
@@ -0,0 +1,163 @@
+#include "exception.h"
+
+#ifdef Q_OS_LINUX
+#include <execinfo.h>
+#include <cxxabi.h>
+#endif
+
+#include <QRegExp>
+
+/*!
+\defgroup CoreExceptions
+*/
+/*!
+\class QKineticDesigner::Exception
+\ingroup CoreExceptions
+\brief This is the abstract base class for all excetions.
+    Exceptions should be used in cases there is no other way to say something goes wrong. For example
+    the result would be a inconsistent model or a crash.
+*/
+
+
+namespace QKineticDesigner {
+
+#ifdef Q_OS_LINUX
+const char* demangle(const char* name)
+{
+   char buf[1024];
+   size_t size = 1024;
+   int status;
+   char* res;
+   res = abi::__cxa_demangle(name,
+     buf,
+     &size,
+     &status);
+   return res;
+}
+#else
+const char* demangle(const char* name)
+{
+   return name;
+}
+#endif
+
+
+bool Exception::s_shouldAssert = true;
+
+void Exception::setShouldAssert(bool assert)
+{
+    s_shouldAssert = assert;
+}
+
+bool Exception::shouldAssert()
+{
+    return s_shouldAssert;
+}
+
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+*/
+Exception::Exception(int line,
+              const QString &function,
+              const QString &file)
+  : m_line(line),
+    m_function(function),
+    m_file(file)
+{
+#ifdef Q_OS_LINUX
+    void * array[50];
+    int nSize = backtrace(array, 50);
+    char ** symbols = backtrace_symbols(array, nSize);
+
+    for (int i = 0; i < nSize; i++)
+    {
+        m_backTrace.append(QString("%1\n").arg(symbols[i]));
+    }
+
+    free(symbols);
+#endif
+
+if (s_shouldAssert)
+    Q_ASSERT_X(false, function.toLatin1(), QString("%1:%2 - %3").arg(file).arg(line).arg(function).toLatin1());
+}
+
+Exception::~Exception()
+{
+}
+
+/*!
+\brief Returns the unmangled backtrace of this exception
+
+\returns the backtrace as a string
+*/
+QString Exception::backTrace() const
+{
+    return m_backTrace;
+}
+
+/*!
+\brief Returns the optional description of this exception
+
+\returns the description as string
+*/
+QString Exception::description() const
+{
+    return QString();
+}
+
+/*!
+\brief Returns the line number where this exception was thrown
+
+\returns the line number as integer
+*/
+int Exception::line() const
+{
+    return m_line;
+}
+
+/*!
+\brief Returns the function name where this exception was thrown
+
+\returns the function name as string
+*/
+QString Exception::function() const
+{
+    return m_function;
+}
+
+/*!
+\brief Returns the file name where this exception was thrown
+
+\returns the file name as string
+*/
+QString Exception::file() const
+{
+    return m_file;
+}
+
+QDebug operator<<(QDebug debug, const Exception &exception)
+{
+    debug.nospace() << "Exception: " << exception.type() << "\n"
+                       "Function:  " << exception.function() << "\n"
+                       "File:      " << exception.file() << "\n"
+                       "Line:      " << exception.line() << "\n";
+    if (!exception.description().isEmpty())
+        debug.nospace() << exception.description();
+
+    if (!exception.backTrace().isEmpty())
+        debug.nospace() << exception.backTrace();
+
+    return debug.space();
+}
+
+/*!
+\fn QString Exception::type() const
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+}
diff --git a/src/shared/qml/metatype/exception.h b/src/shared/qml/metatype/exception.h
new file mode 100644
index 00000000000..093859db6bf
--- /dev/null
+++ b/src/shared/qml/metatype/exception.h
@@ -0,0 +1,42 @@
+#ifndef EXCEPTION_H
+#define EXCEPTION_H
+
+#include <qml/qml_global.h>
+
+#include <QString>
+#include <QtDebug>
+
+namespace QKineticDesigner {
+
+class QML_EXPORT Exception
+{
+public:
+    Exception(int line,
+              const QString &function,
+              const QString &file);
+    virtual ~Exception();
+
+    virtual QString type() const=0;
+    virtual QString description() const;
+
+    int line() const;
+    QString function() const;
+    QString file() const;
+    QString backTrace() const;
+
+    static void setShouldAssert(bool assert);
+    static bool shouldAssert();
+
+private:
+    int m_line;
+    QString m_function;
+    QString m_file;
+    QString m_backTrace;
+    static bool s_shouldAssert;
+};
+
+QML_EXPORT QDebug operator<<(QDebug debug, const Exception &exception);
+
+}
+
+#endif // EXCEPTION_H
diff --git a/src/shared/qml/metatype/invalidmetainfoexception.cpp b/src/shared/qml/metatype/invalidmetainfoexception.cpp
new file mode 100644
index 00000000000..a6caa45b5f9
--- /dev/null
+++ b/src/shared/qml/metatype/invalidmetainfoexception.cpp
@@ -0,0 +1,35 @@
+#include "invalidmetainfoexception.h"
+
+/*!
+\class QKineticDesigner::InvalidMetaInfoException
+\ingroup CoreExceptions
+\brief Exception for a invalid meta info
+
+\see NodeMetaInfo PropertyMetaInfo MetaInfo
+*/
+namespace QKineticDesigner {
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+*/
+InvalidMetaInfoException::InvalidMetaInfoException(int line,
+                                                           const QString &function,
+                                                           const QString &file)
+ : Exception(line, function, file)
+{
+}
+
+/*!
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+QString InvalidMetaInfoException::type() const
+{
+    return "InvalidMetaInfoException";
+}
+
+}
diff --git a/src/shared/qml/metatype/invalidmetainfoexception.h b/src/shared/qml/metatype/invalidmetainfoexception.h
new file mode 100644
index 00000000000..883616884a9
--- /dev/null
+++ b/src/shared/qml/metatype/invalidmetainfoexception.h
@@ -0,0 +1,21 @@
+#ifndef INVALIDMETAINFOEXCEPTION_H
+#define INVALIDMETAINFOEXCEPTION_H
+
+#include "exception.h"
+
+namespace QKineticDesigner {
+
+class QML_EXPORT InvalidMetaInfoException : public Exception
+{
+public:
+    InvalidMetaInfoException(int line,
+                             const QString &function,
+                             const QString &file);
+
+    QString type() const;
+
+};
+
+}
+
+#endif // INVALIDMETAINFOEXCEPTION_H
diff --git a/src/shared/qml/metatype/metainfo.cpp b/src/shared/qml/metatype/metainfo.cpp
new file mode 100644
index 00000000000..356c6805b44
--- /dev/null
+++ b/src/shared/qml/metatype/metainfo.cpp
@@ -0,0 +1,461 @@
+#include "invalidmetainfoexception.h"
+#include "metainfo.h"
+#include "propertymetainfo.h"
+
+#include <QPair>
+#include <QtAlgorithms>
+#include <QMetaProperty>
+#include <QmlMetaType>
+
+enum {
+    debug = false
+};
+
+namespace QKineticDesigner {
+namespace Internal {
+
+class MetaInfoPrivate
+{
+    Q_DISABLE_COPY(MetaInfoPrivate)
+public:
+    typedef QSharedPointer<MetaInfoPrivate> Pointer;
+    typedef QWeakPointer<MetaInfoPrivate> WeakPointer;
+
+
+    MetaInfoPrivate(MetaInfo *q);
+    void clear();
+
+    void initialize();
+    void parseQmlTypes();
+    void parseNonQmlTypes();
+    void parseValueTypes();
+    void parseNonQmlClassRecursively(const QMetaObject *qMetaObject);
+    void parseProperties(NodeMetaInfo &nodeMetaInfo, const QMetaObject *qMetaObject) const;
+    void parseClassInfo(NodeMetaInfo &nodeMetaInfo, const QMetaObject *qMetaObject) const;
+
+    QString typeName(const QMetaObject *qMetaObject) const;
+
+    void parseXmlFiles();
+
+    QMultiHash<QString, QString> m_superClassHash; // the list of direct superclasses
+    QHash<QString, NodeMetaInfo> m_nodeMetaInfoHash;
+    QHash<QString, QString> m_QtTypesToQmlTypes;
+
+    MetaInfo *m_q;
+    bool m_isInitialized;
+};
+
+MetaInfoPrivate::MetaInfoPrivate(MetaInfo *q) :
+        m_q(q),
+        m_isInitialized(false)
+{
+}
+
+void MetaInfoPrivate::clear()
+{
+    m_superClassHash.clear();
+    m_nodeMetaInfoHash.clear();
+    m_isInitialized = false;
+}
+
+void MetaInfoPrivate::initialize()
+{
+    parseQmlTypes();
+    parseNonQmlTypes();
+//    parseValueTypes();
+//    parseXmlFiles();
+
+    m_isInitialized = true;
+}
+
+
+
+void MetaInfoPrivate::parseProperties(NodeMetaInfo &nodeMetaInfo, const QMetaObject *qMetaObject) const
+{
+    Q_ASSERT_X(qMetaObject, Q_FUNC_INFO, "invalid QMetaObject");
+    Q_ASSERT_X(nodeMetaInfo.isValid(), Q_FUNC_INFO, "invalid NodeMetaInfo");
+
+    for (int i = qMetaObject->propertyOffset(); i < qMetaObject->propertyCount(); ++i) {
+        QMetaProperty qProperty = qMetaObject->property(i);
+
+        PropertyMetaInfo propertyInfo;
+
+        propertyInfo.setName(QLatin1String(qProperty.name()));
+
+        QString typeName(qProperty.typeName());
+        QString noStar = typeName;
+        bool star = false;
+        while (noStar.contains('*')) {//strip star
+            noStar.chop(1);
+            star = true;
+        }
+        if (m_QtTypesToQmlTypes.contains(noStar)) {
+            typeName = star ? m_QtTypesToQmlTypes.value(noStar) + '*' : m_QtTypesToQmlTypes.value(noStar);
+            //### versions
+        }
+        int majorVersion = -1, minorVersion = -1;
+        if (QmlType *propertyType = QmlMetaType::qmlType(qMetaObject)) {
+            majorVersion = propertyType->majorVersion();
+            minorVersion = propertyType->minorVersion();
+        }
+
+        propertyInfo.setType(typeName, majorVersion, minorVersion);
+        propertyInfo.setValid(true);
+        propertyInfo.setReadable(qProperty.isReadable());
+        propertyInfo.setWritable(qProperty.isWritable());
+        propertyInfo.setResettable(qProperty.isResettable());
+        propertyInfo.setEnumType(qProperty.isEnumType());
+        propertyInfo.setFlagType(qProperty.isFlagType());
+
+//        if (propertyInfo.isEnumType()) {
+//            EnumeratorMetaInfo enumerator;
+//
+//            QMetaEnum qEnumerator = qProperty.enumerator();
+//            enumerator.setValid(qEnumerator.isValid());
+//            enumerator.setIsFlagType(qEnumerator.isFlag());
+//            enumerator.setScope(qEnumerator.scope());
+//            enumerator.setName(qEnumerator.name());
+//            for (int i = 0 ;i < qEnumerator.keyCount(); i++)
+//            {
+//                enumerator.addElement(qEnumerator.valueToKey(i), i);
+//            }
+//
+//            propertyInfo.setEnumerator(enumerator);
+//        }
+
+        nodeMetaInfo.addProperty(propertyInfo);
+    }
+}
+
+void MetaInfoPrivate::parseClassInfo(NodeMetaInfo &nodeMetaInfo, const QMetaObject *qMetaObject) const
+{
+    Q_ASSERT_X(qMetaObject, Q_FUNC_INFO, "invalid QMetaObject");
+    Q_ASSERT_X(nodeMetaInfo.isValid(), Q_FUNC_INFO, "invalid NodeMetaInfo");
+    for (int index = qMetaObject->classInfoCount() - 1 ; index >= 0 ; --index) {
+        QMetaClassInfo classInfo = qMetaObject->classInfo(index);
+        if (QLatin1String(classInfo.name()) == QLatin1String("DefaultProperty")) {
+            nodeMetaInfo.setDefaultProperty(classInfo.value());
+            return;
+        }
+    }
+}
+
+void MetaInfoPrivate::parseNonQmlClassRecursively(const QMetaObject *qMetaObject)
+{
+    Q_ASSERT_X(qMetaObject, Q_FUNC_INFO, "invalid QMetaObject");
+    const QString className = qMetaObject->className();
+    if ( !m_q->hasNodeMetaInfo(className)
+        && !QmlMetaType::qmlTypeNames().contains(typeName(qMetaObject).toAscii()) ) {
+        NodeMetaInfo nodeMetaInfo(*m_q);
+        nodeMetaInfo.setTypeName(typeName(qMetaObject));
+        parseProperties(nodeMetaInfo, qMetaObject);
+        parseClassInfo(nodeMetaInfo, qMetaObject);
+
+        if (debug)
+            qDebug() << "adding non qml type" << className << typeName(qMetaObject) << ", parent type" << typeName(qMetaObject->superClass());
+        m_q->addNodeInfo(nodeMetaInfo, typeName(qMetaObject->superClass()));
+    }
+
+    if (const QMetaObject *superClass = qMetaObject->superClass()) {
+        parseNonQmlClassRecursively(superClass);
+    }
+}
+
+
+QString MetaInfoPrivate::typeName(const QMetaObject *qMetaObject) const
+{
+    if (!qMetaObject)
+        return QString();
+    QString className = qMetaObject->className();
+    if (QmlType *qmlType = QmlMetaType::qmlType(qMetaObject)) {
+        QString qmlClassName(qmlType->qmlTypeName());
+        if (!qmlClassName.isEmpty())
+            className = qmlType->qmlTypeName(); // Ensure that we always use the qml name,
+                                            // if available.
+    }
+    return className;
+}
+
+void MetaInfoPrivate::parseQmlTypes()
+{
+    foreach (QmlType *qmlType, QmlMetaType::qmlTypes()) {
+        const QString qtTypeName(qmlType->typeName());
+        const QString qmlTypeName(qmlType->qmlTypeName());
+        m_QtTypesToQmlTypes.insert(qtTypeName, qmlTypeName);
+    }
+    foreach (QmlType *qmlType, QmlMetaType::qmlTypes()) {
+        const QMetaObject *qMetaObject = qmlType->metaObject();
+
+        // parseQmlTypes is called iteratively e.g. when plugins are loaded
+        if (m_q->hasNodeMetaInfo(qmlType->qmlTypeName(), qmlType->majorVersion(), qmlType->minorVersion()))
+            continue;
+
+        NodeMetaInfo nodeMetaInfo(*m_q);
+        nodeMetaInfo.setTypeName(qmlType->qmlTypeName());
+        nodeMetaInfo.setMajorVersion(qmlType->majorVersion());
+        nodeMetaInfo.setMinorVersion(qmlType->minorVersion());
+
+        parseProperties(nodeMetaInfo, qMetaObject);
+        parseClassInfo(nodeMetaInfo, qMetaObject);
+
+        QString superTypeName = typeName(qMetaObject->superClass());
+        if (qmlType->baseMetaObject() != qMetaObject) {
+            // type is declared with Q_DECLARE_EXTENDED_TYPE
+            // also parse properties of original type
+            parseProperties(nodeMetaInfo, qmlType->baseMetaObject());
+            superTypeName = typeName(qmlType->baseMetaObject()->superClass());
+        }
+
+        m_q->addNodeInfo(nodeMetaInfo, superTypeName);
+    }
+}
+
+void MetaInfoPrivate::parseNonQmlTypes()
+{
+    foreach (QmlType *qmlType, QmlMetaType::qmlTypes()) {
+        parseNonQmlClassRecursively(qmlType->metaObject());
+    }
+}
+
+} // namespace Internal
+
+using QKineticDesigner::Internal::MetaInfoPrivate;
+
+MetaInfo MetaInfo::s_global;
+QStringList MetaInfo::s_pluginDirs;
+
+
+/*!
+\class QKineticDesigner::MetaInfo
+\ingroup CoreModel
+\brief The MetaInfo class provides meta information about qml types and properties.
+
+The MetaInfo, NodeMetaInfo, PropertyMetaInfo and EnumeratorMetaInfo
+classes provide information about the (static and dynamic) qml types available in
+a specific model. Just like their Model, ModelNode and AbstractProperty counterparts,
+objects of these classes are handles - that means, they are implicitly shared, and
+should be created on the stack.
+
+The MetaInfo object should always be accessed via the model (see Model::metaInfo()).
+Otherwise types specific to a model (like sub components) might
+be missed.
+
+\see Model::metaInfo(), QKineticDesigner::NodeMetaInfo, QKineticDesigner::PropertyMetaInfo, QKineticDesigner::EnumeratorMetaInfo
+*/
+
+/*!
+  \brief Constructs a copy of the given meta info.
+  */
+MetaInfo::MetaInfo(const MetaInfo &metaInfo) :
+        m_p(metaInfo.m_p)
+{
+}
+
+/*!
+  \brief Creates a meta information object with just the qml types registered statically.
+  You almost always want to use Model::metaInfo() instead!
+
+  You almost certainly want to access the meta information for the model.
+
+  \see Model::metaInfo()
+  */
+MetaInfo::MetaInfo() :
+        m_p(new MetaInfoPrivate(this))
+{
+}
+
+MetaInfo::~MetaInfo()
+{
+}
+
+/*!
+  \brief Assigns other to this meta information and returns a reference to this meta information.
+  */
+MetaInfo& MetaInfo::operator=(const MetaInfo &other)
+{
+    m_p = other.m_p;
+    return *this;
+}
+
+QList<NodeMetaInfo> MetaInfo::allTypes() const
+{
+    return m_p->m_nodeMetaInfoHash.values();
+}
+
+/*!
+  \brief Returns whether a type with the given name is registered in the meta system.
+  */
+bool MetaInfo::hasNodeMetaInfo(const QString &typeName, int /*majorVersion*/, int /*minorVersion*/) const
+{
+    if (m_p->m_nodeMetaInfoHash.contains(typeName))
+        return true;
+    if (!isGlobal())
+        return global().hasNodeMetaInfo(typeName);
+    return false;
+}
+
+/*!
+  \brief Returns meta information for a qml type. An invalid NodeMetaInfo object if the type is unknown.
+  */
+NodeMetaInfo MetaInfo::nodeMetaInfo(const QString &typeName, int /*majorVersion*/, int /*minorVersion*/) const
+{
+    if (m_p->m_nodeMetaInfoHash.contains(typeName))
+        return m_p->m_nodeMetaInfoHash.value(typeName, NodeMetaInfo());
+    if (!isGlobal())
+        return global().nodeMetaInfo(typeName);
+
+    return NodeMetaInfo();
+}
+
+QStringList MetaInfo::superClasses(const QString &className) const
+{
+    QStringList ancestorList = m_p->m_superClassHash.values(className);
+    foreach (const QString &ancestor, ancestorList) {
+        QStringList superClassList = superClasses(ancestor);
+        if (!superClassList.isEmpty())
+            ancestorList += superClassList;
+    }
+    if (!isGlobal())
+        ancestorList += global().superClasses(className);
+    return ancestorList;
+}
+
+QStringList MetaInfo::directSuperClasses(const QString &className) const
+{
+    QStringList directAncestorList = m_p->m_superClassHash.values(className);
+    if (!isGlobal())
+        directAncestorList += global().directSuperClasses(className);
+    return directAncestorList;
+}
+
+QList<NodeMetaInfo> MetaInfo::superClasses(const NodeMetaInfo &nodeInfo) const
+{
+    if (!nodeInfo.isValid()) {
+        Q_ASSERT_X(nodeInfo.isValid(), Q_FUNC_INFO, "Invalid nodeInfo argument");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    QList<NodeMetaInfo> superClassList;
+
+    foreach (const QString &typeName, superClasses(nodeInfo.typeName())) {
+        if (!hasNodeMetaInfo(typeName))
+            continue;
+        const NodeMetaInfo superClass = nodeMetaInfo(typeName);
+        if (!superClassList.contains(superClass))
+            superClassList.append(superClass);
+    }
+    return superClassList;
+}
+
+QList<NodeMetaInfo> MetaInfo::directSuperClasses(const NodeMetaInfo &nodeInfo) const
+{
+    if (!nodeInfo.isValid()) {
+        Q_ASSERT_X(nodeInfo.isValid(), Q_FUNC_INFO, "Invalid nodeInfo argument");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    QList<NodeMetaInfo> superClassList;
+
+    foreach (const QString &typeName, directSuperClasses(nodeInfo.typeName())) {
+        if (!hasNodeMetaInfo(typeName))
+            continue;
+        const NodeMetaInfo superClass = nodeMetaInfo(typeName);
+        if (!superClassList.contains(superClass))
+            superClassList.append(superClass);
+    }
+    return superClassList;
+}
+
+QStringList MetaInfo::itemLibraryItems() const
+{
+    QStringList completeList = m_p->m_nodeMetaInfoHash.keys();
+    QStringList finalList;
+    foreach (const QString &name, completeList) {
+        if (nodeMetaInfo(name).isVisibleToItemLibrary())
+            finalList.append(name);
+    }
+
+    if (!isGlobal())
+        finalList += global().itemLibraryItems();
+
+    return finalList;
+}
+
+/*!
+  \brief Returns whether className is the same type or a type derived from superClassName.
+  */
+bool MetaInfo::isSubclassOf(const QString &className, const QString &superClassName) const
+{
+    return (className == superClassName) || superClasses(className).contains(superClassName);
+}
+
+/*!
+  \brief Access to the global meta information object.
+  You almost always want to use Model::metaInfo() instead.
+
+  Internally all meta information objects share this "global" object
+  where static qml type information is stored.
+  */
+MetaInfo MetaInfo::global()
+{
+    if (!s_global.m_p->m_isInitialized) {
+        s_global.m_p = QSharedPointer<MetaInfoPrivate>(new MetaInfoPrivate(&s_global));
+        s_global.m_p->initialize();
+    }
+    return s_global;
+}
+
+/*!
+  \brief Clears the global meta information object.
+
+  This method should be called once on application shutdown to free static data structures.
+  */
+void MetaInfo::clearGlobal()
+{
+    MetaInfo::global().m_p->clear();
+}
+
+void MetaInfo::setPluginPaths(const QStringList &paths)
+{
+    s_pluginDirs = paths;
+}
+
+/*!
+  This bypasses the notifications to the model that the metatype has changed.
+  Use MetaInfo::addNodeInfo() instead
+  */
+void MetaInfo::addSuperClassRelationship(const QString &superClassName, const QString &className)
+{
+    m_p->m_superClassHash.insert(className, superClassName);
+}
+
+void MetaInfo::addNodeInfo(NodeMetaInfo &nodeInfo, const QString &baseType)
+{
+    if (nodeInfo.typeName().isEmpty() || nodeInfo.metaInfo() != *this)
+        throw new InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+
+    if (nodeInfo.typeName() == baseType) // prevent simple recursion
+        throw new InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+
+    m_p->m_nodeMetaInfoHash.insert(nodeInfo.typeName(), nodeInfo);
+
+    if (!baseType.isEmpty()) {
+        m_p->m_superClassHash.insert(nodeInfo.typeName(), baseType);
+    }
+}
+
+bool MetaInfo::isGlobal() const
+{
+    return (this->m_p == s_global.m_p);
+}
+
+bool operator==(const MetaInfo &first, const MetaInfo &second)
+{
+    return first.m_p == second.m_p;
+}
+
+bool operator!=(const MetaInfo &first, const MetaInfo &second)
+{
+    return !(first == second);
+}
+} //namespace QKineticDesigner
diff --git a/src/shared/qml/metatype/metainfo.h b/src/shared/qml/metatype/metainfo.h
new file mode 100644
index 00000000000..86a2447c7f5
--- /dev/null
+++ b/src/shared/qml/metatype/metainfo.h
@@ -0,0 +1,83 @@
+#ifndef METAINFO_H
+#define METAINFO_H
+
+#include <qml/qml_global.h>
+#include <qml/metatype/nodemetainfo.h>
+#include <qml/metatype/propertymetainfo.h>
+
+#include <QMultiHash>
+#include <QString>
+#include <QStringList>
+#include <QtCore/QSharedPointer>
+
+namespace QKineticDesigner {
+
+class ModelNode;
+class AbstractProperty;
+
+namespace Internal {
+    class MetaInfoPrivate;
+    class ModelPrivate;
+    class SubComponentManagerPrivate;
+    typedef QSharedPointer<MetaInfoPrivate> MetaInfoPrivatePointer;
+}
+
+QML_EXPORT bool operator==(const MetaInfo &first, const MetaInfo &second);
+QML_EXPORT bool operator!=(const MetaInfo &first, const MetaInfo &second);
+
+class QML_EXPORT MetaInfo
+{
+    friend class QKineticDesigner::Internal::MetaInfoPrivate;
+    friend class QKineticDesigner::Internal::MetaInfoParser;
+    friend class QKineticDesigner::NodeMetaInfo;
+    friend bool QKineticDesigner::operator==(const MetaInfo &, const MetaInfo &);
+
+public:
+    MetaInfo(const MetaInfo &metaInfo);
+    ~MetaInfo();
+    MetaInfo& operator=(const MetaInfo &other);
+
+    QList<NodeMetaInfo> allTypes() const;
+
+    bool hasNodeMetaInfo(const QString &typeName, int majorVersion = 4, int minorVersion = 6) const;
+    // ### makes no sense since ModelNode has minor/major version
+    NodeMetaInfo nodeMetaInfo(const ModelNode &node) const;
+    NodeMetaInfo nodeMetaInfo(const QString &typeName, int majorVersion = 4, int minorVersion = 6) const;
+
+    // TODO: Move these to private
+    bool isSubclassOf(const QString &className, const QString &superClassName) const;
+    bool isSubclassOf(const ModelNode &modelNode, const QString &superClassName) const;
+
+    bool hasEnumerator(const QString &enumeratorName) const;
+
+    QStringList itemLibraryItems() const;
+
+public:
+    static MetaInfo global();
+    static void clearGlobal();
+
+    static void setPluginPaths(const QStringList &paths);
+
+private:
+    QStringList superClasses(const QString &className) const;
+    QStringList directSuperClasses(const QString &className) const;
+    QList<NodeMetaInfo> superClasses(const NodeMetaInfo &nodeMetaInfo) const;
+    QList<NodeMetaInfo> directSuperClasses(const NodeMetaInfo &nodeMetaInfo) const;
+
+    void addSuperClassRelationship(const QString &superClassName, const QString &className);
+
+    void addNodeInfo(NodeMetaInfo &info, const QString &baseType);
+
+    bool isGlobal() const;
+
+private:
+    MetaInfo();
+
+    Internal::MetaInfoPrivatePointer m_p;
+    static MetaInfo s_global;
+    static QStringList s_pluginDirs;
+};
+
+} //namespace QKineticDesigner
+
+#endif // METAINFO_H
diff --git a/src/shared/qml/metatype/nodemetainfo.cpp b/src/shared/qml/metatype/nodemetainfo.cpp
new file mode 100644
index 00000000000..b3b136c076e
--- /dev/null
+++ b/src/shared/qml/metatype/nodemetainfo.cpp
@@ -0,0 +1,695 @@
+#include "invalidmetainfoexception.h"
+#include "metainfo.h"
+#include "nodemetainfo.h"
+#include "propertymetainfo.h"
+
+#include <QtCore/QSharedData>
+#include <QtCore/QtDebug>
+#include <QtGui/QIcon>
+#include <QtDeclarative/QmlMetaType>
+#include <QtDeclarative/QmlContext>
+#include <QtDeclarative/QmlEngine>
+#include <QtDeclarative/QmlComponent>
+#include <private/qmlvaluetype_p.h>
+
+namespace QKineticDesigner {
+
+namespace Internal {
+
+class NodeMetaInfoData : public QSharedData
+{
+public:
+    typedef enum {
+        No = -1,
+        Unknown = 0,
+        Yes = 1,
+    } TristateBoolean;
+
+public:
+    NodeMetaInfoData(const MetaInfo &metaInfo) :
+            metaInfo(metaInfo),
+            isContainer(false),
+            isVisibleToItemLibrary(false),
+            isFXItem(Unknown),
+            icon(),
+            category("misc")
+    { }
+
+    MetaInfo metaInfo;
+    QString typeName;
+    bool isContainer;
+    bool isVisibleToItemLibrary;
+    TristateBoolean isFXItem;
+    QHash<QString, PropertyMetaInfo> propertyMetaInfoHash;
+    QIcon icon;
+    QString category;
+    QString qmlFile;
+    QString defaultProperty;
+    int majorVersion;
+    int minorVersion;
+};
+
+} // namespace Internal
+
+/*!
+\class QKineticDesigner::NodeMetaInfo
+\ingroup CoreModel
+\brief The NodeMetaInfo class provides meta information about a qml type.
+
+A NodeMetaInfo object can be created via ModelNode::metaInfo, or MetaInfo::nodeMetaInfo.
+
+The object can be invalid - you can check this by calling isValid().
+The object is invalid if you ask for meta information for
+an non-existing qml property. Also the node meta info can become invalid
+if the enclosing type is deregistered from the meta type system (e.g.
+a sub component qml file is deleted). Trying to call any accessor methods on an invalid
+NodeMetaInfo object will result in an InvalidMetaInfoException being thrown.
+
+\see QKineticDesigner::MetaInfo, QKineticDesigner::PropertyMetaInfo, QKineticDesigner::EnumeratorMetaInfo
+*/
+
+NodeMetaInfo::NodeMetaInfo()
+    : m_data(0)
+{
+    // create invalid node
+}
+
+NodeMetaInfo::NodeMetaInfo(const MetaInfo &metaInfo)
+    : m_data(new Internal::NodeMetaInfoData(metaInfo))
+{
+}
+
+NodeMetaInfo::~NodeMetaInfo()
+{
+}
+
+/*!
+  \brief Creates a copy of the handle.
+  */
+NodeMetaInfo::NodeMetaInfo(const NodeMetaInfo &other)
+    : m_data(other.m_data)
+{
+}
+
+/*!
+  \brief Copies the handle.
+  */
+NodeMetaInfo &NodeMetaInfo::operator=(const NodeMetaInfo &other)
+{
+    if (this != &other)
+        this->m_data = other.m_data;
+
+    return *this;
+}
+
+/*!
+  \brief Returns whether the meta information system knows about this type.
+  */
+bool NodeMetaInfo::isValid() const
+{
+    return (m_data.data() != 0);
+}
+
+MetaInfo NodeMetaInfo::metaInfo() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    return m_data->metaInfo;
+}
+
+/*!
+  \brief Creates an instance of the qml type in the given qml context.
+
+  \throws InvalidArgumentException when the context argument is a null pointer
+  \throws InvalidMetaInfoException if the object is not valid
+  */
+QObject *NodeMetaInfo::createInstance(QmlContext *parentContext) const
+{
+    if (!parentContext) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Context cannot be null");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    QObject *object = 0;
+    if (isComponent()) {
+        // qml component
+        // TODO: This is maybe expensive ...
+        QmlComponent component(parentContext->engine(), QUrl::fromLocalFile(m_data->qmlFile));
+        object = component.create(parentContext);
+    } else {
+        // primitive
+        object = QmlMetaType::qmlType(typeName().toAscii(), 4, 6)->create();
+        if (object && parentContext)
+            QmlEngine::setContextForObject(object, new QmlContext(parentContext, object));
+    }
+    return object;
+}
+
+/*!
+  \brief Returns all (direct and indirect) ancestor types.
+
+  \throws InvalidMetaInfoException if the object is not valid
+  */
+QList<NodeMetaInfo> NodeMetaInfo::superClasses() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    return m_data->metaInfo.superClasses(*this);
+}
+
+/*!
+  \brief Returns direct ancestor types.
+
+  \throws InvalidMetaInfoException if the object is not valid
+  */
+QList<NodeMetaInfo> NodeMetaInfo::directSuperClasses() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    return m_data->metaInfo.directSuperClasses(*this);
+}
+
+/*!
+  \brief Returns meta information for all properties, including properties inherited from base types.
+
+  Returns a Hash with the name of the property as key and property meta information as value. Node
+  In case there are multiple properties with the same name in the hierarchy the property defined
+  in the more concrete subclass is chosen.
+
+  \throws InvalidMetaInfoException if the object is not valid
+  */
+QHash<QString,PropertyMetaInfo> NodeMetaInfo::properties(bool resolveDotSyntax ) const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    QHash<QString,PropertyMetaInfo> propertiesInfo;
+    propertiesInfo = m_data->propertyMetaInfoHash;
+    foreach (const NodeMetaInfo &nodeInfo, directSuperClasses()) {
+        QHash<QString,PropertyMetaInfo> superClassProperties = nodeInfo.properties();
+        QHashIterator<QString,PropertyMetaInfo> iter(superClassProperties);
+        while (iter.hasNext()) {
+            iter.next();
+            if (!propertiesInfo.contains(iter.key()))
+                propertiesInfo.insert(iter.key(), iter.value());
+        }
+    }
+    if (resolveDotSyntax) {
+        QHashIterator<QString,PropertyMetaInfo> iter(dotProperties());
+        while (iter.hasNext()) {
+            iter.next();
+            if (!propertiesInfo.contains(iter.key()))
+                propertiesInfo.insert(iter.key(), iter.value());
+        }
+    }
+    return propertiesInfo;
+}
+
+/*!
+  \brief Returns meta information for all dot properties, including properties inherited from base types.
+
+  */
+QHash<QString,PropertyMetaInfo> NodeMetaInfo::dotProperties() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    QHash<QString,PropertyMetaInfo> propertiesInfo;
+
+    foreach (const QString &propertyName, properties().keys()) {
+        if (property(propertyName).hasDotSubProperties()) {
+                QString propertyType = property(propertyName).type();
+                if (propertyType.right(1) == "*")
+                    propertyType = propertyType.left(propertyType.size() - 1).trimmed();
+                NodeMetaInfo nodeInfo(m_data->metaInfo.nodeMetaInfo(propertyType, majorVersion(), minorVersion()));
+                if (nodeInfo.isValid()) {
+                    QHashIterator<QString,PropertyMetaInfo> iter(nodeInfo.properties());
+                    while (iter.hasNext()) {
+                        iter.next();
+                        if (!propertiesInfo.contains(iter.key()) && iter.key() != "objectName")
+                            propertiesInfo.insert(propertyName + "." + iter.key(), iter.value());
+                    }
+            }
+        }
+    }
+    return propertiesInfo;
+}
+
+/*!
+  \brief Returns meta information for a property. An invalid PropertyMetaInfo object if the given property name is unknown.
+
+  \throws InvalidMetaInfoException if the object is not valid
+  */
+PropertyMetaInfo NodeMetaInfo::property(const QString &propertyName, bool resolveDotSyntax) const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    if (resolveDotSyntax && propertyName.contains('.')) {
+        const QStringList nameParts = propertyName.split('.');
+        NodeMetaInfo nodeInfo = *this;
+        const int partCount = nameParts.size();
+        for (int i = 0; i < partCount; ++i) {
+            const QString namePart(nameParts.at(i));
+            const PropertyMetaInfo propInfo = nodeInfo.property(namePart, false);
+
+            if (!propInfo.isValid())
+                break;
+
+            if (i + 1 == partCount)
+                return propInfo;
+
+            QString propertyType = propInfo.type();
+            if (propertyType.right(1) == "*")
+                propertyType = propertyType.left(propertyType.size() - 1).trimmed();
+            nodeInfo = m_data->metaInfo.nodeMetaInfo(propertyType, majorVersion(), minorVersion());
+            if (!nodeInfo.isValid()) {
+                qDebug() << "no type info available for" << propertyType;
+                break;
+            }
+        }
+
+        return PropertyMetaInfo();
+    } else {
+        PropertyMetaInfo propertyMetaInfo;
+
+        if (hasLocalProperty(propertyName)) {
+            propertyMetaInfo = m_data->propertyMetaInfoHash.value(propertyName, PropertyMetaInfo());
+        } else {
+            foreach (const NodeMetaInfo &superTypeMetaInfo, directSuperClasses()) {
+                Q_ASSERT(superTypeMetaInfo.isValid());
+                propertyMetaInfo = superTypeMetaInfo.property(propertyName);
+                if (propertyMetaInfo.isValid())
+                    break;
+            }
+        }
+
+        return propertyMetaInfo;
+    }
+}
+
+/*!
+  \brief Returns whether the type has a (not inherited) property.
+
+  \throws InvalidMetaInfoException if the object is not valid
+  */
+bool NodeMetaInfo::hasLocalProperty(const QString &propertyName, bool resolveDotSyntax) const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    if (resolveDotSyntax && propertyName.contains('.')) {
+        const QStringList nameParts = propertyName.split('.');
+        NodeMetaInfo nodeInfo = *this;
+        const int partCount = nameParts.size();
+        for (int i = 0; i < partCount; ++i) {
+            QString namePart(nameParts.at(i));
+            const PropertyMetaInfo propInfo = nodeInfo.property(namePart, false);
+
+            if (!propInfo.isValid())
+                break;
+
+            if (i + 1 == partCount)
+                return true;
+
+            QString propertyType = propInfo.type();
+            if (propertyType.right(1) == "*")
+                propertyType = propertyType.left(propertyType.size() - 1).trimmed();
+            nodeInfo = m_data->metaInfo.nodeMetaInfo(propertyType, majorVersion(), minorVersion());
+            if (!nodeInfo.isValid()) {
+                qDebug() << "no type info available for" << propertyType;
+                break;
+            }
+        }
+
+        return false;
+    } else {
+        return m_data->propertyMetaInfoHash.contains(propertyName);
+    }
+}
+
+/*!
+  \brief Returns whether the type has a (inherited or not inherited) property.
+
+  \throws InvalidMetaInfoException if the object is not valid
+  */
+bool NodeMetaInfo::hasProperty(const QString &propertyName, bool resolveDotSyntax) const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    if (hasLocalProperty(propertyName, resolveDotSyntax))
+        return true;
+
+    foreach (const NodeMetaInfo &nodeMetaInfo, directSuperClasses()) {
+        if (nodeMetaInfo.hasProperty(propertyName, resolveDotSyntax))
+            return true;
+    }
+
+    return false;
+}
+
+void NodeMetaInfo::addProperty(const PropertyMetaInfo &property)
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    m_data->propertyMetaInfoHash.insert(property.name(), property);
+}
+
+/*!
+  \brief Returns the name of the qml type.
+
+  This is not necessarily the class name: E.g. the class defining "Item" is QmlGraphicsItem.
+
+  \throws InvalidMetaInfoException if the object is not valid
+  */
+QString NodeMetaInfo::typeName() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    return m_data->typeName;
+}
+
+/*!
+  \brief Returns the name of the major number of the qml type.
+
+  \throws InvalidMetaInfoException if the object is not valid
+*/
+int NodeMetaInfo::majorVersion() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    return 4;
+}
+
+
+/*!
+  \brief Returns the name of the minor number of the qml type to which the type is used.
+
+  \throws InvalidMetaInfoException if the object is not valid
+*/
+int NodeMetaInfo::minorVersion() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    return m_data->minorVersion;
+}
+
+bool NodeMetaInfo::hasDefaultProperty() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    return m_data->defaultProperty.isNull();
+}
+
+QString NodeMetaInfo::defaultProperty() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    return m_data->defaultProperty;
+}
+
+void NodeMetaInfo::setDefaultProperty(const QString &defaultProperty)
+{
+     if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    m_data->defaultProperty = defaultProperty;
+}
+
+void NodeMetaInfo::setMajorVersion(int version)
+{
+    m_data->majorVersion = version;
+}
+
+void NodeMetaInfo::setMinorVersion(int version)
+{
+     m_data->minorVersion = version;
+}
+
+void NodeMetaInfo::setInvalid()
+{
+    if (!isValid())
+        return;
+
+    m_data = 0;
+}
+
+void NodeMetaInfo::setTypeName(const QString &typeName)
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    m_data->typeName = typeName;
+}
+
+uint qHash(const NodeMetaInfo &nodeMetaInfo)
+{
+    if (!nodeMetaInfo.isValid())
+        return 0;
+    return qHash(nodeMetaInfo.m_data->typeName);
+}
+
+bool operator==(const NodeMetaInfo &firstNodeInfo,
+                const NodeMetaInfo &secondNodeInfo)
+{
+    if (!firstNodeInfo.isValid() || !secondNodeInfo.isValid())
+        return false;
+    return firstNodeInfo.m_data->typeName == secondNodeInfo.m_data->typeName;
+}
+
+/*!
+  \brief Returns whether objects of these type can have children.
+
+  \throws InvalidMetaInfoException if the object is not valid
+  */
+bool NodeMetaInfo::isContainer() const
+{
+    // TODO KAI: Is this too generic?
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    return m_data->isContainer;
+}
+
+bool NodeMetaInfo::isVisibleToItemLibrary() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    return m_data->isVisibleToItemLibrary;
+}
+
+void NodeMetaInfo::setIsContainer(bool isContainer)
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    m_data->isContainer = isContainer;
+}
+
+void NodeMetaInfo::setIsVisibleToItemLibrary(bool isVisibleToItemLibrary)
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    m_data->isVisibleToItemLibrary = isVisibleToItemLibrary;
+}
+
+QIcon NodeMetaInfo::icon() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    return m_data->icon;
+}
+
+QString NodeMetaInfo::category() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    return m_data->category;
+}
+
+void NodeMetaInfo::setIcon(const QIcon &icon)
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    m_data->icon = icon;
+}
+
+void NodeMetaInfo::setCategory(const QString &category)
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    m_data->category = category;
+}
+
+/*!
+  \brief Returns whether the type inherits from "QWidget".
+
+  \throws InvalidMetaInfoException if the object is not valid
+  */
+bool NodeMetaInfo::isWidget() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    return m_data->metaInfo.isSubclassOf(m_data->typeName, "Qt/QWidget");
+}
+
+/*!
+  \brief Returns whether the type inherits from "QGraphicsWidget".
+
+  \throws InvalidMetaInfoException if the object is not valid
+  */
+bool NodeMetaInfo::isGraphicsWidget() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    return m_data->metaInfo.isSubclassOf(m_data->typeName, "Qt/QGraphicsWidget");
+}
+
+/*!
+  \brief Returns whether the type inherits from "QGraphicsObject".
+
+  \throws InvalidMetaInfoException if the object is not valid
+  */
+bool NodeMetaInfo::isGraphicsObject() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    return m_data->metaInfo.isSubclassOf(m_data->typeName, "QGraphicsObject");
+}
+
+/*!
+  \brief Returns whether the type inherits from "Item/QmlGraphicsItem".
+
+  \throws InvalidMetaInfoException if the object is not valid
+  */
+bool NodeMetaInfo::isQmlGraphicsItem() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+
+    if (m_data->isFXItem == Internal::NodeMetaInfoData::Unknown) {
+        m_data->isFXItem = m_data->metaInfo.isSubclassOf(m_data->typeName, "Qt/Item") ? Internal::NodeMetaInfoData::Yes : Internal::NodeMetaInfoData::No;
+    }
+
+    return m_data->isFXItem == Internal::NodeMetaInfoData::Yes;
+}
+
+bool NodeMetaInfo::isComponent() const
+{
+    return !m_data->qmlFile.isEmpty();
+}
+
+/*!
+  \brief Returns whether the type inherits from a type.
+
+  \throws InvalidMetaInfoException if the object is not valid
+  */
+bool NodeMetaInfo::isSubclassOf(const QString &type, int /*majorVersion*/, int /*minorVersion*/) const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    return m_data->metaInfo.isSubclassOf(m_data->typeName, type);
+}
+
+void NodeMetaInfo::setQmlFile(const QString &filePath)
+{
+    if (!isValid()) {
+        Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+    }
+    m_data->qmlFile = filePath;
+}
+
+//QDataStream& operator<<(QDataStream& stream, const NodeMetaInfo& nodeMetaInfo)
+//{
+//    stream << nodeMetaInfo.typeName();
+//    stream << nodeMetaInfo.majorVersion();
+//    stream << nodeMetaInfo.minorVersionTo();
+//
+//    return stream;
+//}
+//
+//QDataStream& operator>>(QDataStream& stream, NodeMetaInfo& nodeMetaInfo)
+//{
+//    QString typeName;
+//    int minorVersion;
+//    int majorVersion;
+//
+//    stream >> minorVersion;
+//    stream >> majorVersion;
+//    stream >> typeName;
+//
+//    nodeMetaInfo = MetaInfo::global().nodeMetaInfo(typeName/*, majorVersion ,minorVersion*/);
+//
+//    return stream;
+//}
+
+} // namespace QKineticDesigner
diff --git a/src/shared/qml/metatype/nodemetainfo.h b/src/shared/qml/metatype/nodemetainfo.h
new file mode 100644
index 00000000000..1d1215a90d3
--- /dev/null
+++ b/src/shared/qml/metatype/nodemetainfo.h
@@ -0,0 +1,103 @@
+#ifndef NODEMETAINFO_H
+#define NODEMETAINFO_H
+
+#include <qml/qml_global.h>
+
+#include <QList>
+#include <QString>
+#include <QExplicitlySharedDataPointer>
+#include <QIcon>
+
+class QmlContext;
+
+namespace QKineticDesigner {
+
+class MetaInfo;
+
+namespace Internal {
+    class MetaInfoPrivate;
+    class MetaInfoParser;
+    class NodeMetaInfoData;
+    class SubComponentManagerPrivate;
+    class ItemLibraryInfoData;
+}
+
+class PropertyMetaInfo;
+
+class QML_EXPORT NodeMetaInfo
+{
+    friend class QKineticDesigner::MetaInfo;
+    friend class QKineticDesigner::Internal::ItemLibraryInfoData;
+    friend class QKineticDesigner::Internal::MetaInfoPrivate;
+    friend class QKineticDesigner::Internal::MetaInfoParser;
+    friend QML_EXPORT uint qHash(const NodeMetaInfo &nodeMetaInfo);
+    friend QML_EXPORT bool operator ==(const NodeMetaInfo &firstNodeInfo, const NodeMetaInfo &secondNodeInfo);
+
+public:
+    ~NodeMetaInfo();
+
+    NodeMetaInfo(const NodeMetaInfo &other);
+    NodeMetaInfo &operator=(const NodeMetaInfo &other);
+
+    bool isValid() const;
+    MetaInfo metaInfo() const;
+
+    QObject *createInstance(QmlContext *parentContext) const;
+
+    PropertyMetaInfo property(const QString &propertyName, bool resolveDotSyntax = false) const;
+
+    QList<NodeMetaInfo> superClasses() const;
+    QList<NodeMetaInfo> directSuperClasses() const;
+    QHash<QString,PropertyMetaInfo> properties(bool resolveDotSyntax = false) const;
+
+
+    QString typeName() const;
+    int majorVersion() const;
+    int minorVersion() const;
+
+    bool hasDefaultProperty() const;
+    QString defaultProperty() const;
+
+    bool hasProperty(const QString &propertyName, bool resolveDotSyntax = false) const;
+    bool isContainer() const;
+    bool isVisibleToItemLibrary() const;
+
+    bool isWidget() const;
+    bool isGraphicsWidget() const;
+    bool isGraphicsObject() const;
+    bool isQmlGraphicsItem() const;
+    bool isComponent() const;
+    bool isSubclassOf(const QString& type, int majorVersion = 4, int minorVersion = 6) const;
+
+    QIcon icon() const;
+    QString category() const;
+
+private:
+    NodeMetaInfo();
+    NodeMetaInfo(const MetaInfo &metaInfo);
+
+    void setInvalid();
+    void setTypeName(const QString &typeName);
+    void addProperty(const PropertyMetaInfo &property);
+    void setIsContainer(bool isContainer);
+    void setIsVisibleToItemLibrary(bool isVisibleToItemLibrary);
+    void setIcon(const QIcon &icon);
+    void setCategory(const QString &category);
+    void setQmlFile(const QString &filePath);
+    void setDefaultProperty(const QString &defaultProperty);
+    void setMajorVersion(int version);
+    void setMinorVersion(int version);
+
+    bool hasLocalProperty(const QString &propertyName, bool resolveDotSyntax = false) const;
+    QHash<QString,PropertyMetaInfo> dotProperties() const;
+
+private:
+    QExplicitlySharedDataPointer<Internal::NodeMetaInfoData> m_data;
+};
+
+QML_EXPORT uint qHash(const NodeMetaInfo &nodeMetaInfo);
+QML_EXPORT bool operator ==(const NodeMetaInfo &firstNodeInfo,
+                            const NodeMetaInfo &secondNodeInfo);
+}
+
+#endif // NODEMETAINFO_H
diff --git a/src/shared/qml/metatype/propertymetainfo.cpp b/src/shared/qml/metatype/propertymetainfo.cpp
new file mode 100644
index 00000000000..fae7fa49bef
--- /dev/null
+++ b/src/shared/qml/metatype/propertymetainfo.cpp
@@ -0,0 +1,378 @@
+#include "propertymetainfo.h"
+
+#include <QSharedData>
+
+#include "invalidmetainfoexception.h"
+#include "metainfo.h"
+#include <private/qmlvaluetype_p.h>
+
+namespace QKineticDesigner {
+
+namespace Internal
+{
+
+class PropertyMetaInfoData : public QSharedData
+{
+public:
+    PropertyMetaInfoData()
+        : QSharedData(),
+          isValid(false),
+          readable(false),
+          writeable(false),
+          resettable(false),
+          enumType(false),
+          flagType(false),
+          isVisible(false)
+    {}
+
+    QString name;
+    QString type;
+    int majorVersion;
+    int minorVersion;
+    bool isValid;
+
+    bool readable;
+    bool writeable;
+    bool resettable;
+
+    bool enumType;
+    bool flagType;
+    bool isVisible;
+
+    QHash<QString, QVariant> defaultValueHash;
+};
+
+}
+
+/*!
+\class QKineticDesigner::PropertyMetaInfo
+\ingroup CoreModel
+\brief The PropertyMetaInfo class provides meta information about a qml type property.
+
+A PropertyMetaInfo object can be NodeMetaInfo, or AbstractProperty::metaInfo.
+
+The object can be invalid - you can check this by calling isValid().
+The object is invalid if you ask for meta information for
+an non-existing qml type. Also the node meta info can become invalid
+if the type is deregistered from the meta type system (e.g.
+a sub component qml file is deleted). Trying to call any accessor methods on an invalid
+PropertyMetaInfo object will result in an InvalidMetaInfoException being thrown.
+
+
+\see QKineticDesigner::MetaInfo, QKineticDesigner::NodeMetaInfo, QKineticDesigner::EnumeratorMetaInfo
+*/
+
+PropertyMetaInfo::PropertyMetaInfo()
+    : m_data(new Internal::PropertyMetaInfoData)
+{
+}
+
+PropertyMetaInfo::~PropertyMetaInfo()
+{
+}
+
+/*!
+  \brief Creates a copy of the handle.
+  */
+PropertyMetaInfo::PropertyMetaInfo(const PropertyMetaInfo &other)
+    :  m_data(other.m_data)
+{
+}
+
+/*!
+  \brief Copies the handle.
+  */
+PropertyMetaInfo &PropertyMetaInfo::operator=(const PropertyMetaInfo &other)
+{
+    if (this != &other)
+        m_data = other.m_data;
+
+    return *this;
+}
+
+/*!
+  \brief Returns whether the meta information system knows about this property.
+  */
+bool PropertyMetaInfo::isValid() const
+{
+    return m_data->isValid;
+}
+
+/*!
+  \brief Returns the name of the property.
+  */
+QString PropertyMetaInfo::name() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+    return m_data->name;
+}
+
+/*!
+  \brief Returns the type name of the property.
+  */
+QString PropertyMetaInfo::type() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+    return m_data->type;
+}
+
+int PropertyMetaInfo::typeMajorVersion() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+    return m_data->majorVersion;
+}
+
+int PropertyMetaInfo::typeMinorVersion() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+    return m_data->minorVersion;
+}
+
+bool PropertyMetaInfo::isVisibleToPropertyEditor() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+    return m_data->isVisible;
+}
+
+void PropertyMetaInfo::setIsVisibleToPropertyEditor(bool isVisible)
+{
+    m_data->isVisible = isVisible;
+}
+
+/*!
+  \brief Returns the QVariant type of the property.
+  */
+QVariant::Type PropertyMetaInfo::variantTypeId() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+    Q_ASSERT(!m_data->type.isEmpty());
+    return QVariant::nameToType(m_data->type.toLatin1().data());
+}
+
+/*!
+  \brief Returns whether the propery is readable.
+  */
+bool PropertyMetaInfo::isReadable() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+    return m_data->readable;
+}
+
+/*!
+  \brief Returns whether the propery is writeable.
+  */
+bool PropertyMetaInfo::isWriteable() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+    return m_data->writeable;
+}
+
+/*!
+  \brief Returns whether the propery is resettable.
+  */
+bool PropertyMetaInfo::isResettable() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+    return m_data->resettable;
+}
+
+/*!
+  \brief Returns whether the propery is complex value type.
+  */
+bool PropertyMetaInfo::isValueType() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+
+    QmlValueType *valueType(QmlValueTypeFactory::valueType(variantTypeId()));
+    return valueType;
+}
+
+/*!
+  \brief Returns whether the propery is a QmlList.
+  */
+bool PropertyMetaInfo::isListProperty() const
+{
+      if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+
+    return type().contains("QmlList");
+}
+
+/*!
+  \brief Returns whether the propery has sub properties with "." syntax e.g. font
+  */
+bool PropertyMetaInfo::hasDotSubProperties() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+
+    return isValueType() || !isWriteable();
+}
+
+/*!
+  \brief Returns whether the propery stores an enum value.
+  */
+bool PropertyMetaInfo::isEnumType() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+    return m_data->enumType;
+}
+
+/*!
+  \brief Returns whether the propery stores a flag value.
+  */
+bool PropertyMetaInfo::isFlagType() const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+    return m_data->flagType;
+}
+
+/*!
+  \brief Returns a default value if there is one specified, an invalid QVariant otherwise.
+  */
+QVariant PropertyMetaInfo::defaultValue(const NodeMetaInfo &nodeMetaInfoArg) const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+
+    QList<NodeMetaInfo> nodeMetaInfoList(nodeMetaInfoArg.superClasses());
+    nodeMetaInfoList.prepend(nodeMetaInfoArg);
+    foreach (const NodeMetaInfo &nodeMetaInfo, nodeMetaInfoList) {
+        if (m_data->defaultValueHash.contains(nodeMetaInfo.typeName()))
+            return m_data->defaultValueHash.value(nodeMetaInfo.typeName());
+    }
+
+    return QVariant();
+}
+
+void PropertyMetaInfo::setName(const QString &name)
+{
+    m_data->name = name;
+}
+
+void PropertyMetaInfo::setType(const QString &type, int majorVersion, int minorVersion)
+{
+    m_data->type = type;
+    m_data->majorVersion = majorVersion;
+    m_data->minorVersion = minorVersion;
+}
+
+void PropertyMetaInfo::setValid(bool isValid)
+{
+    m_data->isValid = isValid;
+}
+
+void PropertyMetaInfo::setReadable(bool isReadable)
+{
+    m_data->readable = isReadable;
+}
+
+void PropertyMetaInfo::setWritable(bool isWritable)
+{
+    m_data->writeable = isWritable;
+}
+
+void PropertyMetaInfo::setResettable(bool isRessetable)
+{
+    m_data->resettable = isRessetable;
+}
+
+void PropertyMetaInfo::setEnumType(bool isEnumType)
+{
+    m_data->enumType = isEnumType;
+}
+
+void PropertyMetaInfo::setFlagType(bool isFlagType)
+{
+    m_data->flagType = isFlagType;
+}
+
+void  PropertyMetaInfo::setDefaultValue(const NodeMetaInfo &nodeMetaInfo, const QVariant &value)
+{
+    m_data->defaultValueHash.insert(nodeMetaInfo.typeName(), value);
+}
+
+/*!
+  \brief cast value type of QVariant parameter
+
+  If the type of the passed variant does not correspond to type(), the method tries to convert
+  the value according to QVariant::convert(). Returns a new QVariant with casted value type
+  if successful, an invalid QVariant otherwise.
+
+  \param variant the QVariant to take the value from
+  \returns QVariant with aligned value type, or invalid QVariant
+  */
+QVariant PropertyMetaInfo::castedValue(const QVariant &originalVariant) const
+{
+    if (!isValid()) {
+        Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+        throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+    }
+
+    QVariant variant = originalVariant;
+    if (m_data->enumType) {
+        return variant;
+    }
+
+    QVariant::Type typeId = variantTypeId();
+
+    if (typeId == QVariant::UserType && m_data->type == QLatin1String("QVariant")) {
+        return variant;
+    } else if (variant.type() == QVariant::List && variant.type() == QVariant::List) {
+        // TODO: check the contents of the list
+        return variant;
+    } else if (type() == "var" || type() == "variant") {
+        return variant;
+    } else if (type() == "alias") {
+        // TODO: The Qml compiler resolves the alias type. We probably should do the same.
+        return variant;
+    } else if (variant.convert(typeId)) {
+        return variant;
+    } else {
+        return QVariant();
+    }
+}
+
+}
diff --git a/src/shared/qml/metatype/propertymetainfo.h b/src/shared/qml/metatype/propertymetainfo.h
new file mode 100644
index 00000000000..d24b340b784
--- /dev/null
+++ b/src/shared/qml/metatype/propertymetainfo.h
@@ -0,0 +1,84 @@
+#ifndef PROPERTYMETAINFO_H
+#define PROPERTYMETAINFO_H
+
+#include <qml/qml_global.h>
+
+#include <QString>
+#include <QExplicitlySharedDataPointer>
+#include <QVariant>
+
+namespace QKineticDesigner {
+
+class MetaInfo;
+class NodeMetaInfo;
+
+namespace Internal {
+
+class MetaInfoPrivate;
+class MetaInfoParser;
+class PropertyMetaInfoData;
+
+}
+
+class QML_EXPORT PropertyMetaInfo
+{
+    friend class QKineticDesigner::Internal::MetaInfoPrivate;
+    friend class QKineticDesigner::Internal::MetaInfoParser;
+    friend class QKineticDesigner::MetaInfo;
+    friend class QKineticDesigner::NodeMetaInfo;
+public:
+    PropertyMetaInfo();
+    ~PropertyMetaInfo();
+
+    PropertyMetaInfo(const PropertyMetaInfo &other);
+    PropertyMetaInfo& operator=(const PropertyMetaInfo &other);
+
+    bool isValid() const;
+
+    QString name() const;
+    QString type() const;
+    int typeMajorVersion() const;
+    int typeMinorVersion() const;
+
+    QVariant::Type variantTypeId() const;
+
+    bool isReadable() const;
+    bool isWriteable() const;
+    bool isResettable() const;
+    bool isValueType() const;
+    bool isListProperty() const;
+
+    bool isEnumType() const;
+    bool isFlagType() const;
+
+    QVariant defaultValue(const NodeMetaInfo &nodeMetaInfo) const;
+    bool isVisibleToPropertyEditor() const;
+
+    QVariant castedValue(const QVariant &variant) const;
+
+private:
+    void setName(const QString &name);
+    void setType(const QString &type, int majorVersion, int minorVersion);
+    void setValid(bool isValid);
+
+    void setReadable(bool isReadable);
+    void setWritable(bool isWritable);
+    void setResettable(bool isRessetable);
+
+    void setEnumType(bool isEnumType);
+    void setFlagType(bool isFlagType);
+
+    void setDefaultValue(const NodeMetaInfo &nodeMetaInfo, const QVariant &value);
+    void setIsVisibleToPropertyEditor(bool isVisible);
+
+    bool hasDotSubProperties() const;
+
+
+private:
+    QExplicitlySharedDataPointer<Internal::PropertyMetaInfoData> m_data;
+};
+
+}
+
+
+#endif // PROPERTYMETAINFO_H
diff --git a/src/shared/qml/metatype/qmltypesystem.cpp b/src/shared/qml/metatype/qmltypesystem.cpp
new file mode 100644
index 00000000000..4186151eacc
--- /dev/null
+++ b/src/shared/qml/metatype/qmltypesystem.cpp
@@ -0,0 +1,42 @@
+#include "QmlMetaTypeBackend.h"
+#include "qmltypesystem.h"
+
+#ifdef BUILD_DECLARATIVE_BACKEND
+#  include "QtDeclarativeMetaTypeBackend.h"
+#endif // BUILD_DECLARATIVE_BACKEND
+
+#include <QDebug>
+
+using namespace Qml;
+using namespace Qml::MetaType;
+
+QmlTypeSystem::QmlTypeSystem()
+{
+#ifdef BUILD_DECLARATIVE_BACKEND
+    backends.append(new Internal::QtDeclarativeMetaTypeBackend(this));
+#endif // BUILD_DECLARATIVE_BACKEND
+}
+
+QmlTypeSystem::~QmlTypeSystem()
+{
+    qDeleteAll(backends);
+}
+
+QList<QmlSymbol *> QmlTypeSystem::availableTypes(const QString &package, int majorVersion, int minorVersion)
+{
+    QList<QmlSymbol *> results;
+
+    foreach (QmlMetaTypeBackend *backend, backends)
+        results.append(backend->availableTypes(package, majorVersion, minorVersion));
+
+    return results;
+}
+
+QmlSymbol *QmlTypeSystem::resolve(const QString &typeName, const QList<PackageInfo> &packages)
+{
+    foreach (QmlMetaTypeBackend *backend, backends)
+        if (QmlSymbol *symbol = backend->resolve(typeName, packages))
+            return symbol;
+
+    return 0;
+}
diff --git a/src/shared/qml/metatype/qmltypesystem.h b/src/shared/qml/metatype/qmltypesystem.h
new file mode 100644
index 00000000000..d12b1726867
--- /dev/null
+++ b/src/shared/qml/metatype/qmltypesystem.h
@@ -0,0 +1,34 @@
+#ifndef QMLTYPESYSTEM_H
+#define QMLTYPESYSTEM_H
+
+#include <qml/qml_global.h>
+#include <qml/qmlpackageinfo.h>
+#include <qml/qmlsymbol.h>
+
+#include <QtCore/QList>
+#include <QtCore/QObject>
+
+namespace Qml {
+namespace MetaType {
+
+class QmlMetaTypeBackend;
+
+class QML_EXPORT QmlTypeSystem: public QObject
+{
+    Q_OBJECT
+
+public:
+    QmlTypeSystem();
+    virtual ~QmlTypeSystem();
+
+    QList<QmlSymbol *> availableTypes(const QString &package, int majorVersion, int minorVersion);
+    QmlSymbol *resolve(const QString &typeName, const QList<PackageInfo> &packages);
+
+private:
+    QList<QmlMetaTypeBackend *> backends;
+};
+
+} // namespace MetaType
+} // namespace Qml
+
+#endif // QMLTYPESYSTEM_H
diff --git a/src/shared/qml/qml.pri b/src/shared/qml/qml.pri
index 2fa88866729..caafdd10ab2 100644
--- a/src/shared/qml/qml.pri
+++ b/src/shared/qml/qml.pri
@@ -7,11 +7,37 @@ HEADERS += \
     $$PWD/qml_global.h \
     $$PWD/qmlidcollector.h \
     $$PWD/qmldocument.h \
-    $$PWD/qmlsymbol.h
+    $$PWD/qmlpackageinfo.h \
+    $$PWD/qmlsymbol.h \
+    $$PWD/metatype/QmlMetaTypeBackend.h \
+    $$PWD/metatype/qmltypesystem.h
 
 SOURCES += \
     $$PWD/qmlidcollector.cpp \
     $$PWD/qmldocument.cpp \
-    $$PWD/qmlsymbol.cpp
+    $$PWD/qmlsymbol.cpp \
+    $$PWD/qmlpackageinfo.cpp \
+    $$PWD/metatype/QmlMetaTypeBackend.cpp \
+    $$PWD/metatype/qmltypesystem.cpp
 
+contains(QT_CONFIG, declarative) {
+    QT += declarative
 
+    DEFINES += BUILD_DECLARATIVE_BACKEND
+
+    HEADERS += \
+        $$PWD/metatype/metainfo.h \
+        $$PWD/metatype/nodemetainfo.h \
+        $$PWD/metatype/propertymetainfo.h \
+        $$PWD/metatype/QtDeclarativeMetaTypeBackend.h \
+        $$PWD/metatype/invalidmetainfoexception.h \
+        $$PWD/metatype/exception.h
+
+    SOURCES += \
+        $$PWD/metatype/metainfo.cpp \
+        $$PWD/metatype/nodemetainfo.cpp \
+        $$PWD/metatype/propertymetainfo.cpp \
+        $$PWD/metatype/QtDeclarativeMetaTypeBackend.cpp \
+        $$PWD/metatype/invalidmetainfoexception.cpp \
+        $$PWD/metatype/exception.cpp
+}
diff --git a/src/shared/qml/qmldocument.cpp b/src/shared/qml/qmldocument.cpp
index a71152119fd..06e11626730 100644
--- a/src/shared/qml/qmldocument.cpp
+++ b/src/shared/qml/qmldocument.cpp
@@ -35,6 +35,7 @@
 #include "qmljsnodepool_p.h"
 #include "qmljsastfwd_p.h"
 
+using namespace Qml;
 using namespace QmlEditor;
 using namespace QmlJS;
 
@@ -115,7 +116,7 @@ bool QmlDocument::parse()
                 _symbols.append(new QmlSymbolFromFile(_fileName, iter->member));
 
          Internal::QmlIdCollector collect;
-        _ids = collect(this);
+        _ids = collect(*this);
     }
 
     return _parsedCorrectly;
diff --git a/src/shared/qml/qmldocument.h b/src/shared/qml/qmldocument.h
index 5797d7299e5..c45a3af09d6 100644
--- a/src/shared/qml/qmldocument.h
+++ b/src/shared/qml/qmldocument.h
@@ -46,7 +46,7 @@ class QML_EXPORT QmlDocument
 public:
     typedef QSharedPointer<QmlDocument> Ptr;
     typedef QList<QmlDocument::Ptr> PtrList;
-    typedef QMap<QString, QmlIdSymbol*> IdTable;
+    typedef QMap<QString, Qml::QmlIdSymbol*> IdTable;
 
 protected:
     QmlDocument(const QString &fileName);
@@ -73,8 +73,8 @@ public:
     QString path() const { return _path; }
     QString componentName() const { return _componentName; }
 
-    QmlSymbolFromFile *findSymbol(QmlJS::AST::Node *node) const;
-    QmlSymbol::List symbols() const
+    Qml::QmlSymbolFromFile *findSymbol(QmlJS::AST::Node *node) const;
+    Qml::QmlSymbol::List symbols() const
     { return _symbols; }
 
 private:
@@ -88,7 +88,7 @@ private:
     QString _source;
     bool _parsedCorrectly;
     IdTable _ids;
-    QmlSymbol::List _symbols;
+    Qml::QmlSymbol::List _symbols;
 };
 
 class QML_EXPORT Snapshot: public QMap<QString, QmlDocument::Ptr>
diff --git a/src/shared/qml/qmlidcollector.cpp b/src/shared/qml/qmlidcollector.cpp
index a06ae2dde35..0b348c5d74e 100644
--- a/src/shared/qml/qmlidcollector.cpp
+++ b/src/shared/qml/qmlidcollector.cpp
@@ -6,16 +6,16 @@
 
 using namespace QmlJS;
 using namespace QmlJS::AST;
-using namespace QmlEditor;
-using namespace QmlEditor::Internal;
+using namespace Qml;
+using namespace Qml::Internal;
 
-QMap<QString, QmlIdSymbol*> QmlIdCollector::operator()(QmlDocument *doc)
+QMap<QString, QmlIdSymbol*> QmlIdCollector::operator()(QmlEditor::QmlDocument &doc)
 {
-    _doc = doc;
+    _doc = &doc;
     _ids.clear();
     _currentSymbol = 0;
 
-    Node::accept(doc->program(), this);
+    Node::accept(doc.program(), this);
 
     return _ids;
 }
diff --git a/src/shared/qml/qmlidcollector.h b/src/shared/qml/qmlidcollector.h
index 0e8c88df3b6..5a0a92fb44d 100644
--- a/src/shared/qml/qmlidcollector.h
+++ b/src/shared/qml/qmlidcollector.h
@@ -10,13 +10,13 @@
 #include <qml/qmldocument.h>
 #include <qml/qmlsymbol.h>
 
-namespace QmlEditor {
+namespace Qml {
 namespace Internal {
 
 class QML_EXPORT QmlIdCollector: protected QmlJS::AST::Visitor
 {
 public:
-    QMap<QString, QmlIdSymbol*> operator()(QmlDocument *doc);
+    QMap<QString, Qml::QmlIdSymbol*> operator()(QmlEditor::QmlDocument &doc);
 
 protected:
     virtual bool visit(QmlJS::AST::UiArrayBinding *ast);
@@ -25,16 +25,16 @@ protected:
     virtual bool visit(QmlJS::AST::UiScriptBinding *ast);
 
 private:
-    QmlSymbolFromFile *switchSymbol(QmlJS::AST::UiObjectMember *node);
+    Qml::QmlSymbolFromFile *switchSymbol(QmlJS::AST::UiObjectMember *node);
     void addId(const QString &id, QmlJS::AST::UiScriptBinding *ast);
 
 private:
-    QmlDocument *_doc;
-    QMap<QString, QmlIdSymbol*> _ids;
-    QmlSymbolFromFile *_currentSymbol;
+    QmlEditor::QmlDocument *_doc;
+    QMap<QString, Qml::QmlIdSymbol*> _ids;
+    Qml::QmlSymbolFromFile *_currentSymbol;
 };
 
 } // namespace Internal
-} // namespace QmlEditor
+} // namespace Qml
 
 #endif // QMLIDCOLLECTOR_H
diff --git a/src/shared/qml/qmlpackageinfo.cpp b/src/shared/qml/qmlpackageinfo.cpp
new file mode 100644
index 00000000000..d9223877bc5
--- /dev/null
+++ b/src/shared/qml/qmlpackageinfo.cpp
@@ -0,0 +1,10 @@
+#include "qmlpackageinfo.h"
+
+using namespace Qml;
+
+PackageInfo::PackageInfo(const QString &name, int majorVersion, int minorVersion):
+        m_name(name),
+        m_majorVersion(majorVersion),
+        m_minorVersion(minorVersion)
+{
+}
diff --git a/src/shared/qml/qmlpackageinfo.h b/src/shared/qml/qmlpackageinfo.h
new file mode 100644
index 00000000000..770606904b6
--- /dev/null
+++ b/src/shared/qml/qmlpackageinfo.h
@@ -0,0 +1,32 @@
+#ifndef PACKAGEINFO_H
+#define PACKAGEINFO_H
+
+#include <qml/qml_global.h>
+
+#include <QtCore/QString>
+
+namespace Qml {
+
+class QML_EXPORT PackageInfo
+{
+public:
+    PackageInfo(const QString &name, int majorVersion, int minorVersion);
+
+    QString name() const
+    { return m_name; }
+
+    int majorVersion() const
+    { return m_majorVersion; }
+
+    int minorVersion() const
+    { return m_minorVersion; }
+
+private:
+    QString m_name;
+    int m_majorVersion;
+    int m_minorVersion;
+};
+
+} // namespace Qml
+
+#endif // PACKAGEINFO_H
diff --git a/src/shared/qml/qmlsymbol.cpp b/src/shared/qml/qmlsymbol.cpp
index afd0f7e719d..ad8491685b5 100644
--- a/src/shared/qml/qmlsymbol.cpp
+++ b/src/shared/qml/qmlsymbol.cpp
@@ -2,13 +2,12 @@
 #include "qmljsengine_p.h"
 #include "qmlsymbol.h"
 
-using namespace QmlEditor;
+using namespace Qml;
 using namespace QmlJS;
 using namespace QmlJS::AST;
 
 QmlSymbol::~QmlSymbol()
 {
-    qDeleteAll(_members);
 }
 
 bool QmlSymbol::isBuildInSymbol()
@@ -35,15 +34,17 @@ QmlIdSymbol *QmlSymbol::asIdSymbol()
 QmlPropertyDefinitionSymbol *QmlSymbol::asPropertyDefinitionSymbol()
 { return 0; }
 
-const QmlSymbol::List QmlSymbol::members()
-{ return _members; }
-
 QmlBuildInSymbol::~QmlBuildInSymbol()
 {}
 
 QmlBuildInSymbol *QmlBuildInSymbol::asBuildInSymbol()
 { return this; }
 
+QmlSymbolWithMembers::~QmlSymbolWithMembers()
+{ qDeleteAll(_members); }
+
+const QmlSymbol::List QmlSymbolWithMembers::members()
+{ return _members; }
 
 QmlSymbolFromFile::QmlSymbolFromFile(const QString &fileName, QmlJS::AST::UiObjectMember *node):
         _fileName(fileName),
diff --git a/src/shared/qml/qmlsymbol.h b/src/shared/qml/qmlsymbol.h
index 159badf0bbb..33561daa069 100644
--- a/src/shared/qml/qmlsymbol.h
+++ b/src/shared/qml/qmlsymbol.h
@@ -1,24 +1,24 @@
 #ifndef QMLSYMBOL_H
 #define QMLSYMBOL_H
 
-#include <QList>
-#include <QString>
-
 #include <qml/parser/qmljsastfwd_p.h>
 #include <qml/qml_global.h>
 
-namespace QmlEditor {
+#include <QList>
+#include <QString>
+
+namespace Qml {
 
 class QML_EXPORT QmlSymbol
 {
 public:
-    typedef QList<QmlSymbol*> List;
+    typedef QList<QmlSymbol *> List;
 
 public:
-    virtual ~QmlSymbol();
+    virtual ~QmlSymbol() = 0;
 
     virtual const QString name() const = 0;
-    virtual const List members();
+    virtual const List members() = 0;
 
     bool isBuildInSymbol();
     bool isSymbolFromFile();
@@ -29,30 +29,41 @@ public:
     virtual class QmlSymbolFromFile *asSymbolFromFile();
     virtual class QmlIdSymbol *asIdSymbol();
     virtual class QmlPropertyDefinitionSymbol *asPropertyDefinitionSymbol();
-
-protected:
-    List _members;
 };
 
 class QML_EXPORT QmlBuildInSymbol: public QmlSymbol
 {
 public:
-    QmlBuildInSymbol(const QString &name): _name(name) {}
-    virtual ~QmlBuildInSymbol();
+    virtual ~QmlBuildInSymbol() = 0;
 
     virtual QmlBuildInSymbol *asBuildInSymbol();
 
-    virtual const QString name() const
-    { return _name; }
+    virtual QmlBuildInSymbol *type() const = 0;
+    virtual List members(bool includeBaseClassMembers) = 0;
+};
 
-    void addMember(QmlBuildInSymbol *symbol)
-    { _members.append(symbol); }
+class QML_EXPORT QmlPrimitiveSymbol: public QmlBuildInSymbol
+{
+public:
+    virtual ~QmlPrimitiveSymbol() = 0;
 
-private:
-    QString _name;
+    virtual bool isString() const = 0;
+    virtual bool isNumber() const = 0;
+    virtual bool isObject() const = 0;
+};
+
+class QML_EXPORT QmlSymbolWithMembers: public QmlSymbol
+{
+public:
+    virtual ~QmlSymbolWithMembers() = 0;
+
+    virtual const List members();
+
+protected:
+    List _members;
 };
 
-class QML_EXPORT QmlSymbolFromFile: public QmlSymbol
+class QML_EXPORT QmlSymbolFromFile: public QmlSymbolWithMembers
 {
 public:
     QmlSymbolFromFile(const QString &fileName, QmlJS::AST::UiObjectMember *node);
@@ -125,6 +136,6 @@ private:
     QmlJS::AST::UiPublicMember *propertyNode() const;
 };
 
-} // namespace QmlEditor
+} // namespace Qml
 
 #endif // QMLSYMBOL_H
-- 
GitLab