From d2b3258e5938372c96bf9603fbe8a0143b9389c9 Mon Sep 17 00:00:00 2001
From: Marco Bubke <marco.bubke@nokia.com>
Date: Tue, 21 Sep 2010 16:21:35 +0200
Subject: [PATCH] QmlDesigner.FormEditor: Test if a qml item is valid to
 prevent crashes

---
 .../components/formeditor/formeditorscene.cpp | 13 ++--
 .../components/formeditor/itemcreatortool.cpp |  3 +
 .../components/formeditor/movemanipulator.cpp | 57 +++++++++++-----
 .../components/formeditor/movetool.cpp        |  4 +-
 .../formeditor/resizecontroller.cpp           | 65 ++++++++++---------
 .../components/formeditor/resizeindicator.cpp |  4 +-
 .../formeditor/resizemanipulator.cpp          |  2 +-
 .../rubberbandselectionmanipulator.cpp        |  5 +-
 .../formeditor/selectionindicator.cpp         |  3 +
 .../components/formeditor/selectiontool.cpp   |  4 +-
 .../formeditor/singleselectionmanipulator.cpp |  1 +
 .../formeditor/snappinglinecreator.cpp        |  7 ++
 12 files changed, 111 insertions(+), 57 deletions(-)

diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp
index 342bc7ee5de..14058de2ac2 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp
@@ -128,12 +128,15 @@ AbstractFormEditorTool* FormEditorScene::currentTool() const
 //This method calculates the possible parent for reparent
 FormEditorItem* FormEditorScene::calulateNewParent(FormEditorItem *formEditorItem)
 {
-    QList<QGraphicsItem *> list = items(formEditorItem->qmlItemNode().instanceBoundingRect().center());
-    foreach (QGraphicsItem *graphicsItem, list) {
-        if (qgraphicsitem_cast<FormEditorItem*>(graphicsItem) &&
-            graphicsItem->collidesWithItem(formEditorItem, Qt::ContainsItemShape))
-            return qgraphicsitem_cast<FormEditorItem*>(graphicsItem);
+    if (formEditorItem->qmlItemNode().isValid()) {
+        QList<QGraphicsItem *> list = items(formEditorItem->qmlItemNode().instanceBoundingRect().center());
+        foreach (QGraphicsItem *graphicsItem, list) {
+            if (qgraphicsitem_cast<FormEditorItem*>(graphicsItem) &&
+                graphicsItem->collidesWithItem(formEditorItem, Qt::ContainsItemShape))
+                return qgraphicsitem_cast<FormEditorItem*>(graphicsItem);
+        }
     }
+
     return 0;
 }
 
diff --git a/src/plugins/qmldesigner/components/formeditor/itemcreatortool.cpp b/src/plugins/qmldesigner/components/formeditor/itemcreatortool.cpp
index 2f07c5b1811..3bc9b1d6742 100644
--- a/src/plugins/qmldesigner/components/formeditor/itemcreatortool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/itemcreatortool.cpp
@@ -160,6 +160,9 @@ void ItemCreatorTool::createAtItem(const QRectF &rect)
     QPointF pos = rect.topLeft();
 
     QmlItemNode parentNode = view()->rootQmlItemNode();
+    if (!parentNode.isValid())
+        return;
+
     FormEditorItem *parentItem = calculateContainer(pos);
     if (parentItem) {
         parentNode = parentItem->qmlItemNode();
diff --git a/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp
index b02d2e4b472..13609a05157 100644
--- a/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp
@@ -100,7 +100,9 @@ void MoveManipulator::updateHashes()
 bool MoveManipulator::itemsCanReparented() const
 {
     foreach (FormEditorItem* item, m_itemList) {
-        if (!item->qmlItemNode().canReparent())
+        if (item
+            && item->qmlItemNode().isValid()
+            && !item->qmlItemNode().canReparent())
             return false;
     }
 
@@ -114,26 +116,32 @@ void MoveManipulator::begin(const QPointF &beginPoint)
     m_snapper.updateSnappingLines(m_itemList);
 
 
-    foreach (FormEditorItem* item, m_itemList)
-        m_beginItemRectHash.insert(item, m_snapper.containerFormEditorItem()->mapRectFromItem(item, item->qmlItemNode().instanceBoundingRect()));
-
     foreach (FormEditorItem* item, m_itemList) {
-        QPointF positionInParentSpace(item->qmlItemNode().instancePosition());
-        QPointF positionInScenesSpace = m_snapper.containerFormEditorItem()->mapToScene(positionInParentSpace);
-        m_beginPositionInSceneSpaceHash.insert(item, positionInScenesSpace);
+        if (item && item->qmlItemNode().isValid())
+            m_beginItemRectHash.insert(item, m_snapper.containerFormEditorItem()->mapRectFromItem(item, item->qmlItemNode().instanceBoundingRect()));
     }
 
     foreach (FormEditorItem* item, m_itemList) {
-        QPointF positionInParentSpace = m_snapper.containerFormEditorItem()->mapFromScene(m_beginPositionInSceneSpaceHash.value(item));
-        m_beginPositionHash.insert(item, positionInParentSpace);
+        if (item && item->qmlItemNode().isValid()) {
+            QPointF positionInParentSpace(item->qmlItemNode().instancePosition());
+            QPointF positionInScenesSpace = m_snapper.containerFormEditorItem()->mapToScene(positionInParentSpace);
+            m_beginPositionInSceneSpaceHash.insert(item, positionInScenesSpace);
+        }
+    }
 
-        QmlAnchors anchors(item->qmlItemNode().anchors());
-        m_beginTopMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Top));
-        m_beginLeftMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Left));
-        m_beginRightMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Right));
-        m_beginBottomMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Bottom));
-        m_beginHorizontalCenterHash.insert(item, anchors.instanceMargin(AnchorLine::HorizontalCenter));
-        m_beginVerticalCenterHash.insert(item, anchors.instanceMargin(AnchorLine::VerticalCenter));
+    foreach (FormEditorItem* item, m_itemList) {
+        if (item && item->qmlItemNode().isValid()) {
+            QPointF positionInParentSpace = m_snapper.containerFormEditorItem()->mapFromScene(m_beginPositionInSceneSpaceHash.value(item));
+            m_beginPositionHash.insert(item, positionInParentSpace);
+
+            QmlAnchors anchors(item->qmlItemNode().anchors());
+            m_beginTopMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Top));
+            m_beginLeftMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Left));
+            m_beginRightMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Right));
+            m_beginBottomMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Bottom));
+            m_beginHorizontalCenterHash.insert(item, anchors.instanceMargin(AnchorLine::HorizontalCenter));
+            m_beginVerticalCenterHash.insert(item, anchors.instanceMargin(AnchorLine::VerticalCenter));
+        }
     }
 
     m_beginPoint = beginPoint;
@@ -159,6 +167,10 @@ QPointF MoveManipulator::findSnappingOffset(const QHash<FormEditorItem*, QRectF>
         hashIterator.next();
         FormEditorItem *formEditorItem = hashIterator.key();
         QRectF boundingRect = hashIterator.value();
+
+        if (!formEditorItem || !formEditorItem->qmlItemNode().isValid())
+            continue;
+
         if (!formEditorItem->qmlItemNode().hasBindingProperty("x")) {
             double verticalOffset = m_snapper.snappedVerticalOffset(boundingRect);
             if (verticalOffset < std::numeric_limits<double>::max())
@@ -203,6 +215,10 @@ QHash<FormEditorItem*, QRectF> MoveManipulator::tanslatedBoundingRects(const QHa
         hashIterator.next();
         FormEditorItem *formEditorItem = hashIterator.key();
         QRectF boundingRect = hashIterator.value();
+
+        if (!formEditorItem || !formEditorItem->qmlItemNode().isValid())
+            continue;
+
         if (formEditorItem->qmlItemNode().hasBindingProperty("x"))
             alignedOffset.setX(0);
         if (formEditorItem->qmlItemNode().hasBindingProperty("y"))
@@ -245,6 +261,9 @@ void MoveManipulator::update(const QPointF& updatePoint, Snapping useSnapping, S
         foreach (FormEditorItem* item, m_itemList) {
             QPointF positionInContainerSpace(m_beginPositionHash.value(item) + offsetVector);
 
+            if (!item || !item->qmlItemNode().isValid())
+                continue;
+
             // don't support anchors for base state because it is not needed by the droptool
             if (stateToBeManipulated == UseActualState) {
                 QmlAnchors anchors(item->qmlItemNode().anchors());
@@ -311,6 +330,9 @@ void MoveManipulator::reparentTo(FormEditorItem *newParent)
         return;
 
     foreach (FormEditorItem* item, m_itemList) {
+        if (!item || !item->qmlItemNode().isValid())
+            continue;
+
         QmlItemNode parent(newParent->qmlItemNode());
         if (parent.isValid()) {
             if (parent.hasDefaultProperty())
@@ -340,6 +362,9 @@ void MoveManipulator::end(const QPointF &/*endPoint*/)
 void MoveManipulator::moveBy(double deltaX, double deltaY)
 {
     foreach (FormEditorItem* item, m_itemList) {
+        if (!item || !item->qmlItemNode().isValid())
+            continue;
+
         QmlAnchors anchors(item->qmlItemNode().anchors());
 
         if (anchors.instanceHasAnchor(AnchorLine::Top)) {
diff --git a/src/plugins/qmldesigner/components/formeditor/movetool.cpp b/src/plugins/qmldesigner/components/formeditor/movetool.cpp
index 5d2aef73b25..ae76d6455f9 100644
--- a/src/plugins/qmldesigner/components/formeditor/movetool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/movetool.cpp
@@ -296,7 +296,9 @@ void MoveTool::beginWithPoint(const QPointF &beginPoint)
 static bool isNotAncestorOfItemInList(FormEditorItem *formEditorItem, const QList<FormEditorItem*> &itemList)
 {
     foreach (FormEditorItem *item, itemList) {
-        if (item->qmlItemNode().isAncestorOf(formEditorItem->qmlItemNode()))
+        if (item
+            && item->qmlItemNode().isValid()
+            && item->qmlItemNode().isAncestorOf(formEditorItem->qmlItemNode()))
             return false;
     }
 
diff --git a/src/plugins/qmldesigner/components/formeditor/resizecontroller.cpp b/src/plugins/qmldesigner/components/formeditor/resizecontroller.cpp
index fef15f6ce5b..d4c424fc9b4 100644
--- a/src/plugins/qmldesigner/components/formeditor/resizecontroller.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/resizecontroller.cpp
@@ -136,7 +136,7 @@ ResizeController::ResizeController(LayerItem *layerItem, FormEditorItem *formEdi
 
 bool ResizeController::isValid() const
 {
-    return m_data->formEditorItem != 0;
+    return m_data->formEditorItem && m_data->formEditorItem->qmlItemNode().isValid();
 }
 
 void ResizeController::show()
@@ -186,36 +186,39 @@ static QPointF bottomCenter(const QRectF &rect)
 
 void ResizeController::updatePosition()
 {
-    QRectF boundingRect = m_data->formEditorItem->qmlItemNode().instanceBoundingRect();
-    QPointF topLeftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
-                                                                       boundingRect.topLeft()));
-    QPointF topRightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
-                                                                        boundingRect.topRight()));
-    QPointF bottomLeftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
-                                                                          boundingRect.bottomLeft()));
-    QPointF bottomRightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
-                                                                           boundingRect.bottomRight()));
-
-    QPointF topPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
-                                                                   topCenter(boundingRect)));
-    QPointF leftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
-                                                                    leftCenter(boundingRect)));
-
-    QPointF rightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
-                                                                     rightCenter(boundingRect)));
-    QPointF bottomPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
-                                                                      bottomCenter(boundingRect)));
-
-
-
-    m_data->topRightItem->setHandlePosition(topRightPointInLayerSpace, boundingRect.topRight());
-    m_data->topLeftItem->setHandlePosition(topLeftPointInLayerSpace, boundingRect.topLeft());
-    m_data->bottomLeftItem->setHandlePosition(bottomLeftPointInLayerSpace, boundingRect.bottomLeft());
-    m_data->bottomRightItem->setHandlePosition(bottomRightPointInLayerSpace, boundingRect.bottomRight());
-    m_data->topItem->setHandlePosition(topPointInLayerSpace, topCenter(boundingRect));
-    m_data->leftItem->setHandlePosition(leftPointInLayerSpace, leftCenter(boundingRect));
-    m_data->rightItem->setHandlePosition(rightPointInLayerSpace, rightCenter(boundingRect));
-    m_data->bottomItem->setHandlePosition(bottomPointInLayerSpace, bottomCenter(boundingRect));
+    if (isValid()) {
+
+        QRectF boundingRect = m_data->formEditorItem->qmlItemNode().instanceBoundingRect();
+        QPointF topLeftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+                                                                           boundingRect.topLeft()));
+        QPointF topRightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+                                                                            boundingRect.topRight()));
+        QPointF bottomLeftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+                                                                              boundingRect.bottomLeft()));
+        QPointF bottomRightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+                                                                               boundingRect.bottomRight()));
+
+        QPointF topPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+                                                                       topCenter(boundingRect)));
+        QPointF leftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+                                                                        leftCenter(boundingRect)));
+
+        QPointF rightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+                                                                         rightCenter(boundingRect)));
+        QPointF bottomPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+                                                                          bottomCenter(boundingRect)));
+
+
+
+        m_data->topRightItem->setHandlePosition(topRightPointInLayerSpace, boundingRect.topRight());
+        m_data->topLeftItem->setHandlePosition(topLeftPointInLayerSpace, boundingRect.topLeft());
+        m_data->bottomLeftItem->setHandlePosition(bottomLeftPointInLayerSpace, boundingRect.bottomLeft());
+        m_data->bottomRightItem->setHandlePosition(bottomRightPointInLayerSpace, boundingRect.bottomRight());
+        m_data->topItem->setHandlePosition(topPointInLayerSpace, topCenter(boundingRect));
+        m_data->leftItem->setHandlePosition(leftPointInLayerSpace, leftCenter(boundingRect));
+        m_data->rightItem->setHandlePosition(rightPointInLayerSpace, rightCenter(boundingRect));
+        m_data->bottomItem->setHandlePosition(bottomPointInLayerSpace, bottomCenter(boundingRect));
+    }
 }
 
 
diff --git a/src/plugins/qmldesigner/components/formeditor/resizeindicator.cpp b/src/plugins/qmldesigner/components/formeditor/resizeindicator.cpp
index b3bfd100af6..a1b5b56fcba 100644
--- a/src/plugins/qmldesigner/components/formeditor/resizeindicator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/resizeindicator.cpp
@@ -71,7 +71,9 @@ void ResizeIndicator::setItems(const QList<FormEditorItem*> &itemList)
     clear();
 
     foreach (FormEditorItem* item, itemList) {
-        if (item->qmlItemNode().isRootNode())
+        if (item
+            && item->qmlItemNode().isValid()
+            && item->qmlItemNode().isRootNode())
             continue;
         ResizeController controller(m_layerItem, item);
         m_itemControllerHash.insert(item, controller);
diff --git a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp
index 7229c786245..19ffc860e86 100644
--- a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp
@@ -396,7 +396,7 @@ void ResizeManipulator::end()
 
 void ResizeManipulator::moveBy(double deltaX, double deltaY)
 {
-    if (resizeHandle()) {
+    if (resizeHandle() && m_resizeController.isValid()) {
         QmlItemNode qmlItemNode(m_resizeController.formEditorItem()->qmlItemNode());
         QmlAnchors anchors(qmlItemNode.anchors());
 
diff --git a/src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.cpp
index 672d5e3d064..18804d88e44 100644
--- a/src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.cpp
@@ -101,6 +101,7 @@ void RubberBandSelectionManipulator::select(SelectionType selectionType)
         FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
 
         if (formEditorItem
+           && formEditorItem->qmlItemNode().isValid()
            && m_beginFormEditorItem->childItems().contains(formEditorItem)
            && !formEditorItem->qmlItemNode().isRootNode())
         {
@@ -108,7 +109,9 @@ void RubberBandSelectionManipulator::select(SelectionType selectionType)
         }
     }
 
-    if (newNodeList.isEmpty() && !m_beginFormEditorItem->qmlItemNode().isRootNode())
+    if (newNodeList.isEmpty()
+        && m_beginFormEditorItem->qmlItemNode().isValid()
+        && !m_beginFormEditorItem->qmlItemNode().isRootNode())
          newNodeList.append(m_beginFormEditorItem->qmlItemNode());
 
     QList<QmlItemNode> nodeList;
diff --git a/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp b/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp
index 13925f8462c..e5c12648f95 100644
--- a/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp
@@ -85,6 +85,9 @@ void SelectionIndicator::setItems(const QList<FormEditorItem*> &itemList)
     clear();
 
     foreach (FormEditorItem *item, itemList) {
+        if (item->qmlItemNode().isValid())
+            continue;
+
         QGraphicsPolygonItem *newSelectionIndicatorGraphicsItem = new QGraphicsPolygonItem(m_layerItem.data());
         m_indicatorShapeHash.insert(item, newSelectionIndicatorGraphicsItem);
         QPolygonF boundingRectInSceneSpace(item->mapToScene(item->qmlItemNode().instanceBoundingRect()));
diff --git a/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp b/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp
index 27ad9b8f2d2..787fedef094 100644
--- a/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp
@@ -65,7 +65,9 @@ void SelectionTool::mousePressEvent(const QList<QGraphicsItem*> &itemList,
 {
     m_mousePressTimer.start();
     FormEditorItem* formEditorItem = topFormEditorItem(itemList);
-    if (formEditorItem && !formEditorItem->qmlItemNode().hasChildren()) {
+    if (formEditorItem
+        && formEditorItem->qmlItemNode().isValid()
+        && !formEditorItem->qmlItemNode().hasChildren()) {
         m_singleSelectionManipulator.begin(event->scenePos());
 
         if (event->modifiers().testFlag(Qt::ControlModifier))
diff --git a/src/plugins/qmldesigner/components/formeditor/singleselectionmanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/singleselectionmanipulator.cpp
index e32eb3aa764..cc38edb07ea 100644
--- a/src/plugins/qmldesigner/components/formeditor/singleselectionmanipulator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/singleselectionmanipulator.cpp
@@ -80,6 +80,7 @@ void SingleSelectionManipulator::select(SelectionType selectionType, bool select
         FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
 
         if (formEditorItem
+           && formEditorItem->qmlItemNode().isValid()
            && !formEditorItem->qmlItemNode().isRootNode()
            && (formEditorItem->qmlItemNode().hasShowContent() || !selectOnlyContentItems))
         {
diff --git a/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp b/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp
index 3def27ea41c..ebcf19c2aea 100644
--- a/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp
@@ -88,6 +88,9 @@ void SnappingLineCreator::addOffsets(const QRectF &rectInSceneSpace, FormEditorI
 void SnappingLineCreator::generateLines(const QList<FormEditorItem*> &exceptionList,
                                         FormEditorItem *transformationSpaceItem)
 {
+    if (!m_formEditorItem->qmlItemNode().isValid())
+        return;
+
     Q_ASSERT(transformationSpaceItem);
     {
         QRectF containerBoundingRectInTransformationSpace = m_formEditorItem->mapRectToItem(transformationSpaceItem,
@@ -99,6 +102,10 @@ void SnappingLineCreator::generateLines(const QList<FormEditorItem*> &exceptionL
     }
 
     foreach (FormEditorItem *item, m_formEditorItem->childFormEditorItems()) {
+
+        if (!item || !item->qmlItemNode().isValid())
+            continue;
+
         if (exceptionList.contains(item))
             continue;
         QRectF boundingRectInContainerSpace;
-- 
GitLab