From 198d81735c7abc40066ea7bd97261f3399374ef7 Mon Sep 17 00:00:00 2001
From: Thomas Hartmann <Thomas.Hartmann@nokia.com>
Date: Tue, 7 Sep 2010 16:30:57 +0200
Subject: [PATCH] QuickDesigner.navigator: Display all QGraphicsObject-type
 node properties

The navigator now displays all properties whose type is a sub class
of QGraphicsObject, except for those properties inherited by Qt/Item.
The contents of the default property are displayed as direct children
of the model node's tree node.
Reparenting into and from the displayed properties is supported.

original author: Joerg Schummer
---
 .../navigator/navigatortreemodel.cpp          | 270 +++++++++++++-----
 .../components/navigator/navigatortreemodel.h |  22 +-
 .../navigator/navigatortreeview.cpp           |  97 ++++---
 .../components/navigator/navigatortreeview.h  |   4 +-
 .../components/navigator/navigatorview.cpp    |   9 +-
 5 files changed, 278 insertions(+), 124 deletions(-)

diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
index dc561294638..ec66ff71bb8 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
@@ -31,14 +31,21 @@
 
 #include <nodeabstractproperty.h>
 #include <nodelistproperty.h>
+#include <nodeproperty.h>
+#include <metainfo.h>
+#include <propertymetainfo.h>
+#include <qgraphicswidget.h>
 #include <abstractview.h>
 #include <invalididexception.h>
 
 #include <QMimeData>
 #include <QMessageBox>
+#include <QApplication>
 
 namespace QmlDesigner {
 
+const int NavigatorTreeModel::NavigatorRole = Qt::UserRole;
+
 NavigatorTreeModel::NavigatorTreeModel(QObject *parent)
     : QStandardItemModel(parent),
       m_blockItemChangedSignal(false)
@@ -90,7 +97,7 @@ QMimeData *NavigatorTreeModel::mimeData(const QModelIndexList &indexList) const
              continue;
 
          rowAlreadyUsedSet.insert(idIndex);
-         stream << idIndex.data(Qt::UserRole).toUInt();
+         stream << idIndex.data(NavigatorRole).toUInt();
      }
 
      mimeData->setData("application/vnd.modelnode.list", encodedData);
@@ -98,21 +105,11 @@ QMimeData *NavigatorTreeModel::mimeData(const QModelIndexList &indexList) const
      return mimeData;
 }
 
-static bool isAnchestorInList(const ModelNode &node, const QList<ModelNode> &nodeList)
-{
-    foreach (const ModelNode &nodeInList, nodeList) {
-        if (nodeInList.isAncestorOf(node))
-            return true;
-    }
-
-    return false;
-}
-
 bool NavigatorTreeModel::dropMimeData(const QMimeData *data,
                   Qt::DropAction action,
                   int row,
                   int column,
-                  const QModelIndex &parentIndex)
+                  const QModelIndex &dropIndex)
 {
     if (action == Qt::IgnoreAction)
         return true;
@@ -122,59 +119,57 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *data,
         return false;
     if (column > 1)
         return false;
-    if (parentIndex.model() != this)
+    if (dropIndex.model() != this)
         return false;
 
+    QModelIndex parentIndex, parentItemIndex;
+    QString parentPropertyName;
+    int targetIndex;
 
-    QModelIndex parentIdIndex = parentIndex;
-    parentIdIndex = parentIdIndex.sibling(parentIdIndex.row(), 0);
-
-    Q_ASSERT(parentIdIndex.isValid());
+    parentIndex = dropIndex.sibling(dropIndex.row(), 0);
+    targetIndex = (row > -1)? row : rowCount(parentIndex);
 
-    int targetIndex = 0;
-    if (row > -1) {
-        targetIndex = row;
-    } else {
-        targetIndex = rowCount(parentIdIndex);
+    if (this->data(parentIndex, NavigatorRole).isValid()) {
+        parentItemIndex = parentIndex;
+        ModelNode parentNode = nodeForIndex(parentItemIndex);
+        if (!parentNode.metaInfo().hasDefaultProperty())
+            return false;
+        targetIndex -= visibleProperties(parentNode).count();
+        parentPropertyName = parentNode.metaInfo().defaultProperty();
+    }
+    else {
+        parentItemIndex = parentIndex.parent();
+        parentPropertyName = parentIndex.data(Qt::DisplayRole).toString();
     }
 
+    // Disallow dropping items between properties, which are listed first.
+    if (targetIndex < 0)
+        return false;
+
+    Q_ASSERT(parentItemIndex.isValid());
+
     QByteArray encodedData = data->data("application/vnd.modelnode.list");
     QDataStream stream(&encodedData, QIODevice::ReadOnly);
 
-    ModelNode parentNode(nodeForIndex(parentIdIndex));
-
     QList<ModelNode> nodeList;
-
     while (!stream.atEnd()) {
         uint nodeHash;
         stream >> nodeHash;
-        ModelNode node(nodeForHash(nodeHash));
-        if (!node.isValid() || (parentNode == node) || node.isAncestorOf(parentNode))
-            continue;
-        nodeList.append(node);
+        if (containsNodeHash(nodeHash)) {
+            ModelNode node(nodeForHash(nodeHash));
+            nodeList.append(node);
+        }
     }
 
-    RewriterTransaction transaction = m_view->beginRewriterTransaction();
-    foreach (const ModelNode &node, nodeList) {
-        if (!isAnchestorInList(node, nodeList)) {
-            if (node.parentProperty().parentModelNode() != parentNode) {
-                if (node != parentNode) {
-                    reparentModelNode(parentNode, node);
-                }
-            }
+    ModelNode parentNode(nodeForIndex(parentItemIndex));
+    NodeAbstractProperty parentProperty = parentNode.nodeAbstractProperty(parentPropertyName);
 
-            if (node.parentProperty().isNodeListProperty()) {
-                int index = node.parentProperty().toNodeListProperty().toModelNodeList().indexOf(node);
-                if (index < targetIndex) { // item is first removed from oldIndex, then inserted at new index
-                    --targetIndex;
-                }
-                if (index != targetIndex) {
-                    node.parentProperty().toNodeListProperty().slide(index, targetIndex);
-                }
-            }
-        }
+    if (parentProperty.isNodeProperty() &&
+        nodeList.count() > 1) {
+        return false;
     }
 
+    moveNodesInteractive(parentProperty, nodeList, targetIndex);
     propagateInvisible(parentNode, isNodeInvisible(parentNode));
 
     return false; // don't let the view do drag&drop on its own
@@ -192,7 +187,7 @@ NavigatorTreeModel::ItemRow NavigatorTreeModel::createItemRow(const ModelNode &n
     idItem->setDragEnabled(true);
     idItem->setDropEnabled(dropEnabled);
     idItem->setEditable(true);
-    idItem->setData(hash, Qt::UserRole);
+    idItem->setData(hash, NavigatorRole);
 
 #    ifdef _LOCK_ITEMS_
     QStandardItem *lockItem = new QStandardItem;
@@ -200,28 +195,40 @@ NavigatorTreeModel::ItemRow NavigatorTreeModel::createItemRow(const ModelNode &n
     lockItem->setDropEnabled(dropEnabled);
     lockItem->setEditable(false);
     lockItem->setCheckable(true);
-    lockItem->setData(hash, Qt::UserRole);
+    lockItem->setData(hash, NavigatorRole);
 #    endif
 
     QStandardItem *visibilityItem = new QStandardItem;
     visibilityItem->setDropEnabled(dropEnabled);
     visibilityItem->setCheckable(true);
     visibilityItem->setEditable(false);
-    visibilityItem->setData(hash, Qt::UserRole);
+    visibilityItem->setData(hash, NavigatorRole);
     if (node.isRootNode()) {
         visibilityItem->setCheckable(false);
     }
 
-#    ifdef _LOCK_ITEMS_
-    return ItemRow(idItem, lockItem, visibilityItem);
-#    else
-    return ItemRow(idItem, visibilityItem);
-#    endif
+    QMap<QString, QStandardItem *> propertyItems;
+    foreach (QString propertyName, visibleProperties(node)) {
+        QStandardItem *propertyItem = new QStandardItem;
+        propertyItem->setSelectable(false);
+        propertyItem->setDragEnabled(false);
+        propertyItem->setDropEnabled(dropEnabled);
+        propertyItem->setEditable(false);
+        propertyItem->setData(propertyName, Qt::DisplayRole);
+        propertyItems.insert(propertyName, propertyItem);
+        idItem->appendRow(propertyItem);
+    }
+
+#   ifdef _LOCK_ITEMS_
+    return ItemRow(idItem, lockItem, visibilityItem, propertyItems);
+#   else
+    return ItemRow(idItem, visibilityItem, propertyItems);
+#   endif
 }
 
 void NavigatorTreeModel::updateItemRow(const ModelNode &node, ItemRow items)
 {
-    bool blockSignal = blockItemChangedSignal(true);
+    bool blockSignal = blockItemChangedSignal(true);    
 
     items.idItem->setText(node.id());
     items.visibilityItem->setCheckState(node.auxiliaryData("invisible").toBool() ? Qt::Unchecked : Qt::Checked);
@@ -243,20 +250,34 @@ void NavigatorTreeModel::updateItemRow(const ModelNode &node)
 /**
   Updates the sibling position of the item, depending on the position in the model.
   */
-void NavigatorTreeModel::updateItemRowOrder(const ModelNode &node)
+void NavigatorTreeModel::updateItemRowOrder(const NodeListProperty &listProperty, const ModelNode &node, int oldIndex)
 {
+    Q_UNUSED(oldIndex);
+
     if (!containsNode(node))
         return;
 
     ItemRow itemRow = itemRowForNode(node);
     int currentRow = itemRow.idItem->row();
-    int newRow = currentRow;
-    if (node.parentProperty().parentModelNode().isValid())
-        newRow = modelNodeChildren(node.parentProperty().parentModelNode()).indexOf(node);
+    int newRow = listProperty.toModelNodeList().indexOf(node);
+
     Q_ASSERT(newRow >= 0);
 
+    QStandardItem *parentIdItem = 0;
+    if (containsNode(listProperty.parentModelNode())) {
+        ItemRow parentRow = itemRowForNode(listProperty.parentModelNode());
+        parentIdItem = parentRow.propertyItems.value(listProperty.name());
+        if (!parentIdItem) {
+            parentIdItem = parentRow.idItem;
+            newRow += visibleProperties(listProperty.parentModelNode()).count();
+        }
+    }
+    else {
+        parentIdItem = itemRow.idItem->parent();
+    }
+    Q_ASSERT(parentIdItem);
+
     if (currentRow != newRow) {
-        QStandardItem *parentIdItem = itemRow.idItem->parent();
         QList<QStandardItem*> items = parentIdItem->takeRow(currentRow);
         parentIdItem->insertRow(newRow, items);
     }
@@ -266,8 +287,10 @@ void NavigatorTreeModel::handleChangedItem(QStandardItem *item)
 {
     if (m_blockItemChangedSignal)
         return;
+    if (!data(item->index(), NavigatorRole).isValid())
+        return;
 
-    uint nodeHash = item->data(Qt::UserRole).toUInt();
+    uint nodeHash = item->data(NavigatorRole).toUInt();
     Q_ASSERT(nodeHash && containsNodeHash(nodeHash));
     ModelNode node = nodeForHash(nodeHash);
 
@@ -323,7 +346,12 @@ NavigatorTreeModel::ItemRow NavigatorTreeModel::itemRowForNode(const ModelNode &
 void NavigatorTreeModel::setView(AbstractView *view)
 {
     m_view = view;
-    addSubTree(view->rootModelNode());
+    m_hiddenProperties.clear();
+    if (view) {
+        ModelNode sampleItemNode(m_view->createModelNode("Qt/Item", 4, 7));
+        m_hiddenProperties << visibleProperties(sampleItemNode);
+        addSubTree(view->rootModelNode());
+    }
 }
 
 void NavigatorTreeModel::clearView()
@@ -346,7 +374,7 @@ QModelIndex NavigatorTreeModel::indexForNode(const ModelNode &node) const
 ModelNode NavigatorTreeModel::nodeForIndex(const QModelIndex &index) const
 {
     Q_ASSERT(index.isValid());
-    uint hash = index.data(Qt::UserRole).toUInt();
+    uint hash = index.data(NavigatorRole).toUInt();
     Q_ASSERT(hash);
     Q_ASSERT(containsNodeHash(hash));
     return nodeForHash(hash);
@@ -380,6 +408,8 @@ void NavigatorTreeModel::addSubTree(const ModelNode &node)
     Q_ASSERT(node.isValid());
     Q_ASSERT(!containsNodeHash(qHash(node)));
 
+    //updateItemRow(node, newRow);
+
     // only add items that are in the modelNodeChildren list (that means, visible in the editor)
     if (!node.isRootNode()
         && !modelNodeChildren(node.parentProperty().parentModelNode()).contains(node)) {
@@ -397,9 +427,16 @@ void NavigatorTreeModel::addSubTree(const ModelNode &node)
 
     // We assume that the node is always added to the _end_ of the property list.
     if (node.hasParentProperty()) {
-        ItemRow parentRow = itemRowForNode(node.parentProperty().parentModelNode());
-        if (parentRow.idItem)
-            parentRow.idItem->appendRow(newRow.toList());
+        AbstractProperty property(node.parentProperty());
+        ItemRow parentRow = itemRowForNode(property.parentModelNode());
+        QStandardItem *parentItem = parentRow.propertyItems.value(property.name());
+        if (!parentItem) {
+            // Child nodes in the default property are added directly under the
+            // parent.
+            parentItem = parentRow.idItem;
+        }
+        if (parentItem)
+            parentItem->appendRow(newRow.toList());
     } else {
         appendRow(newRow.toList());
     }
@@ -431,26 +468,111 @@ void NavigatorTreeModel::removeSubTree(const ModelNode &node)
     m_nodeItemHash.remove(node);
 }
 
-void NavigatorTreeModel::reparentModelNode(const ModelNode &parentNode, const ModelNode &node)
+void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty parentProperty, const QList<ModelNode> &modelNodes, int targetIndex)
 {
-    parentNode.nodeListProperty("data").reparentHere(node);
+    QString propertyQmlType = qmlTypeInQtContainer(parentProperty.metaInfo().type());
+
+    RewriterTransaction transaction = m_view->beginRewriterTransaction();
+    foreach (const ModelNode &node, modelNodes) {
+        if (!node.isValid())
+            continue;
+
+        if (node != parentProperty.parentModelNode() &&
+            !node.isAncestorOf(parentProperty.parentModelNode()) &&
+            node.metaInfo().isSubclassOf(propertyQmlType, -1, -1)) {
+
+            if (node.parentProperty() != parentProperty) {
+
+                if (parentProperty.isNodeProperty()) {
+                    ModelNode propertyNode = parentProperty.toNodeProperty().modelNode();
+                    // Destruction of ancestors is not allowed
+                    if (propertyNode.isAncestorOf(node)) {
+                        continue;
+                    }
+                    if (propertyNode.isValid()) {
+                        QApplication::setOverrideCursor(Qt::ArrowCursor);
+                        if (QMessageBox::warning(0, tr("Warning"), tr("Reparenting the component %1 here will cause the component %2 to be deleted. Do you want to proceed?").arg(node.id(), propertyNode.id()), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) {
+                            QApplication::restoreOverrideCursor();
+                            continue;
+                        }
+                        QApplication::restoreOverrideCursor();
+                        propertyNode.destroy();
+                    }
+                }
+
+                parentProperty.reparentHere(node);
+            }
+
+            if (parentProperty.isNodeListProperty()) {
+                int index = parentProperty.toNodeListProperty().toModelNodeList().indexOf(node);
+                if (index < targetIndex) { // item is first removed from oldIndex, then inserted at new index
+                    --targetIndex;
+                }
+                if (index != targetIndex) {
+                    parentProperty.toNodeListProperty().slide(index, targetIndex);
+                }
+            }
+        }
+    }
 }
 
 QList<ModelNode> NavigatorTreeModel::modelNodeChildren(const ModelNode &parentNode)
 {
     QList<ModelNode> children;
+    QStringList properties;
 
-    if (parentNode.hasProperty("children")) {
-        children.append(parentNode.nodeListProperty("children").toModelNodeList());
-    }
+    if (parentNode.metaInfo().hasDefaultProperty())
+        properties << parentNode.metaInfo().defaultProperty();
 
-    if (parentNode.hasProperty("data")) {
-        children.append(parentNode.nodeListProperty("data").toModelNodeList());
+    properties << visibleProperties(parentNode);
+
+    foreach (QString propertyName, properties) {
+        AbstractProperty property(parentNode.property(propertyName));
+        if (property.isNodeProperty())
+            children << property.toNodeProperty().modelNode();
+        else if (property.isNodeListProperty())
+            children << property.toNodeListProperty().toModelNodeList();
     }
 
     return children;
 }
 
+QString NavigatorTreeModel::qmlTypeInQtContainer(const QString &qtContainerType) const
+{
+    QString typeName(qtContainerType);
+    if (typeName.startsWith("QDeclarativeListProperty<") &&
+        typeName.endsWith(">")) {
+        typeName.remove(0, 25);
+        typeName.chop(1);
+    }
+    if (typeName.endsWith('*'))
+        typeName.chop(1);
+
+    return m_view->model()->metaInfo().fromQtTypes(typeName);
+}
+
+
+QStringList NavigatorTreeModel::visibleProperties(const ModelNode &node) const
+{
+    QStringList propertyList;
+
+    foreach (PropertyMetaInfo propertyMetaInfo, node.metaInfo().properties().values()) {
+        if (!m_hiddenProperties.contains(propertyMetaInfo.name()) &&
+            propertyMetaInfo.name() != node.metaInfo().defaultProperty() &&
+            propertyMetaInfo.isReadable() &&
+            propertyMetaInfo.isWriteable()) {
+
+            QString qmlType = qmlTypeInQtContainer(propertyMetaInfo.type());
+            if (node.metaInfo().metaInfo().hasNodeMetaInfo(qmlType) &&
+                node.metaInfo().metaInfo().nodeMetaInfo(qmlType).isSubclassOf("QGraphicsObject", -1, -1)) {
+                propertyList << propertyMetaInfo.name();
+            }
+        }
+    }    
+
+    return propertyList;
+}
+
 // along the lines of QObject::blockSignals
 bool NavigatorTreeModel::blockItemChangedSignal(bool block)
 {
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h
index 279ef7abf9c..7cc3e1128e3 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h
@@ -50,8 +50,8 @@ class NavigatorTreeModel : public QStandardItemModel
     struct ItemRow {
         ItemRow()
             : idItem(0), lockItem(0), visibilityItem(0) {}
-        ItemRow(QStandardItem *id, QStandardItem *lock, QStandardItem *visibility)
-            : idItem(id), lockItem(lock), visibilityItem(visibility) {}
+        ItemRow(QStandardItem *id, QStandardItem *lock, QStandardItem *visibility, const PropertyItemMap &properties)
+            : idItem(id), lockItem(lock), visibilityItem(visibility), propertyItems(properties) {}
 
         QList<QStandardItem*> toList() const {
             return QList<QStandardItem*>() << idItem << lockItem << visibilityItem;
@@ -60,13 +60,14 @@ class NavigatorTreeModel : public QStandardItemModel
         QStandardItem *idItem;
         QStandardItem *lockItem;
         QStandardItem *visibilityItem;
+        QMap<QString, QStandardItem *> propertyItems;
     };
 #else
     struct ItemRow {
         ItemRow()
             : idItem(0), visibilityItem(0) {}
-        ItemRow(QStandardItem *id, QStandardItem *visibility)
-            : idItem(id), visibilityItem(visibility) {}
+        ItemRow(QStandardItem *id, QStandardItem *visibility, const QMap<QString, QStandardItem *> &properties)
+            : idItem(id), visibilityItem(visibility), propertyItems(properties) {}
 
         QList<QStandardItem*> toList() const {
             return QList<QStandardItem*>() << idItem << visibilityItem;
@@ -74,9 +75,12 @@ class NavigatorTreeModel : public QStandardItemModel
 
         QStandardItem *idItem;
         QStandardItem *visibilityItem;
+        QMap<QString, QStandardItem *> propertyItems;
     };
 #endif
 
+    static const int NavigatorRole;
+
 public:
     NavigatorTreeModel(QObject *parent = 0);
     ~NavigatorTreeModel();
@@ -105,7 +109,7 @@ public:
     void addSubTree(const ModelNode &node);
     void removeSubTree(const ModelNode &node);
     void updateItemRow(const ModelNode &node);
-    void updateItemRowOrder(const ModelNode &node);
+    void updateItemRowOrder(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex);
 
     void setId(const QModelIndex &index, const QString &id);
     void setVisible(const QModelIndex &index, bool visible);
@@ -123,9 +127,13 @@ private:
     ItemRow createItemRow(const ModelNode &node);
     void updateItemRow(const ModelNode &node, ItemRow row);
 
-    void reparentModelNode(const ModelNode &parentNode, const ModelNode &node);
+    void moveNodesInteractive(NodeAbstractProperty parentProperty, const QList<ModelNode> &modelNodes, int targetIndex);
+
     QList<ModelNode> modelNodeChildren(const ModelNode &parentNode);
 
+    QString qmlTypeInQtContainer(const QString &qtContainerType) const;
+    QStringList visibleProperties(const ModelNode &node) const;
+
     bool blockItemChangedSignal(bool block);
 
 private:
@@ -134,6 +142,8 @@ private:
     QWeakPointer<AbstractView> m_view;
 
     bool m_blockItemChangedSignal;
+
+    QStringList m_hiddenProperties;
 };
 
 } // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp
index a363d7c57b0..77fb47453af 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp
@@ -127,12 +127,19 @@ QSize IconCheckboxItemDelegate::sizeHint(const QStyleOptionViewItem &option,
 {
     Q_UNUSED(option);
     Q_UNUSED(index);
-    return QSize(15,20);
+
+    if (!index.data(Qt::UserRole).isValid())
+        return QSize();
+
+    return QSize(15, 20);
 }
 
 void IconCheckboxItemDelegate::paint(QPainter *painter,
                                      const QStyleOptionViewItem &option, const QModelIndex &index) const
 {
+    if (!index.data(Qt::UserRole).isValid())
+        return;
+
     painter->save();
     if (option.state & QStyle::State_Selected)
         drawSelectionBackground(painter, option);
@@ -152,70 +159,84 @@ void IconCheckboxItemDelegate::paint(QPainter *painter,
     painter->restore();
 }
 
-void IdItemDelegate::paint(QPainter *painter,
+void NameItemDelegate::paint(QPainter *painter,
                const QStyleOptionViewItem &option, const QModelIndex &index) const
 {
     if (option.state & QStyle::State_Selected)
         drawSelectionBackground(painter, option);
 
+    QString displayString;
+    QPoint displayStringOffset;
+
     painter->save();
 
-    if (m_TreeModel->isNodeInvisible( index ))
-        painter->setOpacity(0.5);
+    if (index.data(Qt::UserRole).isValid()) {
 
-    ModelNode node = m_TreeModel->nodeForIndex(index);
+        int pixmapSide = 16;
 
-    QIcon icon;
-    if (node.metaInfo().isValid()) {
-        icon=node.metaInfo().icon();
-        if (icon.isNull())
-        {
-            // if node has no own icon, search for it in the itemlibrary
-            const NodeMetaInfo typeInfo = node.metaInfo();
-            const ItemLibraryInfo *libraryInfo = node.metaInfo().metaInfo().itemLibraryInfo();
-            QList <ItemLibraryEntry> infoList = libraryInfo->entriesForType(typeInfo.typeName(),
-                                                                            typeInfo.majorVersion(),
-                                                                            typeInfo.minorVersion());
-            foreach (const ItemLibraryEntry &entry, infoList) {
-                if (!icon.isNull()) {
-                    icon = entry.icon();
-                    break;
+        if (m_TreeModel->isNodeInvisible( index ))
+            painter->setOpacity(0.5);
+
+        ModelNode node = m_TreeModel->nodeForIndex(index);
+
+        QIcon icon;
+        if (node.metaInfo().isValid()) {
+            icon=node.metaInfo().icon();
+            if (icon.isNull())
+            {
+                // if node has no own icon, search for it in the itemlibrary
+                const NodeMetaInfo typeInfo = node.metaInfo();
+                const ItemLibraryInfo *libraryInfo = node.metaInfo().metaInfo().itemLibraryInfo();
+                QList <ItemLibraryEntry> infoList = libraryInfo->entriesForType(typeInfo.typeName(),
+                                                                                typeInfo.majorVersion(),
+                                                                                typeInfo.minorVersion());
+                foreach (const ItemLibraryEntry &entry, infoList) {
+                    if (!icon.isNull()) {
+                        icon = entry.icon();
+                        break;
+                    }
                 }
             }
         }
-    }
 
     // if the library was also empty, use the default icon
     if (icon.isNull())
         icon = QIcon(QLatin1String(":/ItemLibrary/images/item-default-icon.png"));
 
-    // If no icon is present, leave an empty space of 24 pixels anyway
-    int pixmapSide = 16;
-    QPixmap pixmap = icon.pixmap(pixmapSide, pixmapSide);
-    painter->drawPixmap(option.rect.x()+1,option.rect.y()+2,pixmap);
+        // If no icon is present, leave an empty space of 24 pixels anyway
+        QPixmap pixmap = icon.pixmap(pixmapSide, pixmapSide);
+        painter->drawPixmap(option.rect.x()+1,option.rect.y()+2,pixmap);
 
-    QString myString = node.id();
-    if (myString.isEmpty())
-        myString = node.simplifiedTypeName();
+        displayString = node.id();
+        if (displayString.isEmpty())
+            displayString = node.simplifiedTypeName();
 
-    // Check text length does not exceed available space
-    int extraSpace=12+pixmapSide;
-    QFontMetrics fm(option.font);
-    myString = fm.elidedText(myString,Qt::ElideMiddle,option.rect.width()-extraSpace);
+        // Check text length does not exceed available space
+        int extraSpace=12+pixmapSide;
+        QFontMetrics fm(option.font);
+        displayString = fm.elidedText(displayString,Qt::ElideMiddle,option.rect.width()-extraSpace);
+        displayStringOffset = QPoint(5+pixmapSide,-5);
+    }
+    else {
+        displayString = index.data(Qt::DisplayRole).toString();
+        displayStringOffset = QPoint(0, -2);
+    }
 
-    painter->drawText(option.rect.bottomLeft()+QPoint(5+pixmapSide,-5),myString);
+    painter->drawText(option.rect.bottomLeft()+displayStringOffset,displayString);
 
     painter->restore();
 }
 
-QWidget *IdItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
+QWidget *NameItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
 {
     Q_UNUSED(option);
-    Q_UNUSED(index);
+    if (!index.data(Qt::UserRole).isValid())
+        return 0;
+
     return new QLineEdit(parent);
 }
 
-void IdItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
+void NameItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
 {
     ModelNode node = m_TreeModel->nodeForIndex(index);
     QString value = node.id();
@@ -224,7 +245,7 @@ void IdItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) co
     lineEdit->setText(value);
 }
 
-void IdItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
+void NameItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
 {
     Q_UNUSED(model);
     QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
@@ -232,7 +253,7 @@ void IdItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, co
     lineEdit->clearFocus();
 }
 
-void IdItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void NameItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
 {
     Q_UNUSED(index);
     QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreeview.h b/src/plugins/qmldesigner/components/navigator/navigatortreeview.h
index 303c805c453..e406e5a4c50 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreeview.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreeview.h
@@ -70,10 +70,10 @@ class IconCheckboxItemDelegate : public QStyledItemDelegate
 
 };
 
-class IdItemDelegate : public QStyledItemDelegate
+class NameItemDelegate : public QStyledItemDelegate
 {
     public:
-    explicit IdItemDelegate(QObject *parent=0, NavigatorTreeModel *treeModel=NULL) : QStyledItemDelegate(parent),m_TreeModel(treeModel) {}
+    explicit NameItemDelegate(QObject *parent=0, NavigatorTreeModel *treeModel=NULL) : QStyledItemDelegate(parent),m_TreeModel(treeModel) {}
 
     void paint(QPainter *painter,
                const QStyleOptionViewItem &option, const QModelIndex &index) const;
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
index 44e940b3a6d..55281be45b9 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
@@ -49,7 +49,7 @@ NavigatorView::NavigatorView(QObject* parent) :
     connect(treeWidget()->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(changeSelection(QItemSelection,QItemSelection)));
     treeWidget()->setIndentation(treeWidget()->indentation() * 0.5);
 
-    IdItemDelegate *idDelegate = new IdItemDelegate(this,m_treeModel.data());
+    NameItemDelegate *idDelegate = new NameItemDelegate(this,m_treeModel.data());
     IconCheckboxItemDelegate *showDelegate = new IconCheckboxItemDelegate(this,":/qmldesigner/images/eye_open.png",
                                                           ":/qmldesigner/images/placeholder.png",m_treeModel.data());
 
@@ -191,10 +191,10 @@ void NavigatorView::scriptFunctionsChanged(const ModelNode &/*node*/, const QStr
 }
 
 
-void NavigatorView::nodeOrderChanged(const NodeListProperty &/*listProperty*/, const ModelNode &node, int /*oldIndex*/)
+void NavigatorView::nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &node, int oldIndex)
 {
     if (m_treeModel->isInTree(node))
-        m_treeModel->updateItemRowOrder(node);
+        m_treeModel->updateItemRowOrder(listProperty, node, oldIndex);
 }
 
 void NavigatorView::changeSelection(const QItemSelection & /*newSelection*/, const QItemSelection &/*deselected*/)
@@ -203,7 +203,8 @@ void NavigatorView::changeSelection(const QItemSelection & /*newSelection*/, con
         return;
     QSet<ModelNode> nodeSet;
     foreach (const QModelIndex &index, treeWidget()->selectionModel()->selectedIndexes()) {
-        nodeSet.insert(m_treeModel->nodeForIndex(index));
+        if (m_treeModel->data(index, Qt::UserRole).isValid())
+            nodeSet.insert(m_treeModel->nodeForIndex(index));
     }
 
     bool blocked = blockSelectionChangedSignal(true);
-- 
GitLab