From 000e468d00ef7080935b86ff16bba8609a820cc8 Mon Sep 17 00:00:00 2001
From: Lasse Holmstedt <lasse.holmstedt@nokia.com>
Date: Wed, 4 Aug 2010 18:53:01 +0200
Subject: [PATCH] QML Observer: Fixed bug w/selection boxes being visible after
 delesect

---
 .../editor/boundingrecthighlighter.cpp        | 120 +++++++++---------
 .../editor/boundingrecthighlighter.h          |  34 ++++-
 .../editor/selectionindicator.cpp             |  43 ++++---
 .../qmljsdebugger/editor/selectiontool.cpp    |  35 ++---
 .../qmljsdebugger/qdeclarativedesignview.cpp  |  17 ++-
 .../qmljsdebugger/qdeclarativedesignview_p.h  |   4 +-
 6 files changed, 142 insertions(+), 111 deletions(-)

diff --git a/src/libs/qmljsdebugger/editor/boundingrecthighlighter.cpp b/src/libs/qmljsdebugger/editor/boundingrecthighlighter.cpp
index 90fb9446ebb..9ac50433fd2 100644
--- a/src/libs/qmljsdebugger/editor/boundingrecthighlighter.cpp
+++ b/src/libs/qmljsdebugger/editor/boundingrecthighlighter.cpp
@@ -4,6 +4,7 @@
 
 #include <QGraphicsPolygonItem>
 #include <QTimer>
+#include <QObject>
 
 #include <QDebug>
 
@@ -13,29 +14,9 @@ const qreal AnimDelta = 0.025f;
 const int AnimInterval = 30;
 const int AnimFrames = 10;
 
-class BoundingBoxPolygonItem : public QGraphicsPolygonItem
-{
-public:
-    explicit BoundingBoxPolygonItem(QGraphicsItem *item);
-    int type() const;
-};
-
-class BoundingBox
-{
-public:
-    explicit BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem);
-    ~BoundingBox();
-    QWeakPointer<QGraphicsObject> highlightedObject;
-    QGraphicsPolygonItem *highlightPolygon;
-    QGraphicsPolygonItem *highlightPolygonEdge;
-
-private:
-    Q_DISABLE_COPY(BoundingBox);
-
-};
-
-BoundingBox::BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem)
-    : highlightedObject(itemToHighlight),
+BoundingBox::BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem, QObject *parent)
+    : QObject(parent),
+      highlightedObject(itemToHighlight),
       highlightPolygon(0),
       highlightPolygonEdge(0)
 {
@@ -51,10 +32,6 @@ BoundingBox::BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parent
 
 BoundingBox::~BoundingBox()
 {
-    delete highlightPolygon;
-    delete highlightPolygonEdge;
-    highlightPolygon = 0;
-    highlightPolygonEdge = 0;
     highlightedObject.clear();
 }
 
@@ -80,6 +57,11 @@ BoundingRectHighlighter::BoundingRectHighlighter(QDeclarativeDesignView *view) :
     connect(m_animTimer, SIGNAL(timeout()), SLOT(animTimeout()));
 }
 
+BoundingRectHighlighter::~BoundingRectHighlighter()
+{
+
+}
+
 void BoundingRectHighlighter::animTimeout()
 {
     ++m_animFrame;
@@ -100,17 +82,8 @@ void BoundingRectHighlighter::clear()
         m_animTimer->stop();
 
         foreach(BoundingBox *box, m_boxes) {
-            if (!box->highlightedObject.isNull()) {
-                disconnect(box->highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh()));
-                disconnect(box->highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh()));
-                disconnect(box->highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh()));
-                disconnect(box->highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh()));
-                disconnect(box->highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh()));
-            }
+            freeBoundingBox(box);
         }
-
-        qDeleteAll(m_boxes);
-        m_boxes.clear();
     }
 }
 
@@ -131,8 +104,7 @@ void BoundingRectHighlighter::highlight(QList<QGraphicsObject*> items)
 
     bool animate = false;
 
-    QList<BoundingBox*> newBoxes;
-
+    QList<BoundingBox *> newBoxes;
     foreach(QGraphicsObject *itemToHighlight, items) {
         BoundingBox *box = boxFor(itemToHighlight);
         if (!box) {
@@ -172,26 +144,71 @@ void BoundingRectHighlighter::highlight(QGraphicsObject* itemToHighlight)
 
 BoundingBox *BoundingRectHighlighter::createBoundingBox(QGraphicsObject *itemToHighlight)
 {
-    BoundingBox *box = new BoundingBox(itemToHighlight, this);
+    if (!m_freeBoxes.isEmpty()) {
+        BoundingBox *box = m_freeBoxes.last();
+        if (box->highlightedObject.isNull()) {
+            box->highlightedObject = itemToHighlight;
+            box->highlightPolygon->show();
+            box->highlightPolygonEdge->show();
+            m_freeBoxes.removeLast();
+            return box;
+        }
+    }
+
+    BoundingBox *box = new BoundingBox(itemToHighlight, this, this);
 
     connect(itemToHighlight, SIGNAL(xChanged()), this, SLOT(refresh()));
     connect(itemToHighlight, SIGNAL(yChanged()), this, SLOT(refresh()));
     connect(itemToHighlight, SIGNAL(widthChanged()), this, SLOT(refresh()));
     connect(itemToHighlight, SIGNAL(heightChanged()), this, SLOT(refresh()));
     connect(itemToHighlight, SIGNAL(rotationChanged()), this, SLOT(refresh()));
+    connect(itemToHighlight, SIGNAL(destroyed(QObject*)), this, SLOT(itemDestroyed(QObject*)));
 
     return box;
 }
 
-void BoundingRectHighlighter::highlightAll(bool animate)
+void BoundingRectHighlighter::removeBoundingBox(BoundingBox *box)
+{
+    delete box;
+    box = 0;
+}
+
+void BoundingRectHighlighter::freeBoundingBox(BoundingBox *box)
+{
+    if (!box->highlightedObject.isNull()) {
+        disconnect(box->highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh()));
+        disconnect(box->highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh()));
+        disconnect(box->highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh()));
+        disconnect(box->highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh()));
+        disconnect(box->highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh()));
+    }
+
+    box->highlightedObject.clear();
+    box->highlightPolygon->hide();
+    box->highlightPolygonEdge->hide();
+    m_boxes.removeOne(box);
+    m_freeBoxes << box;
+}
+
+void BoundingRectHighlighter::itemDestroyed(QObject *obj)
 {
     foreach(BoundingBox *box, m_boxes) {
-        QGraphicsObject *item = box->highlightedObject.data();
-        if (box->highlightedObject.isNull()) {
-            m_boxes.removeOne(box);
-            continue;
+        if (box->highlightedObject.data() == obj) {
+            freeBoundingBox(box);
+            break;
         }
+    }
+}
 
+void BoundingRectHighlighter::highlightAll(bool animate)
+{
+    foreach(BoundingBox *box, m_boxes) {
+        if (box && box->highlightedObject.isNull()) {
+            // clear all highlights
+            clear();
+            return;
+        }
+        QGraphicsObject *item = box->highlightedObject.data();
         QRectF itemAndChildRect = item->boundingRect() | item->childrenBoundingRect();
 
         QPolygonF boundingRectInSceneSpace(item->mapToScene(itemAndChildRect));
@@ -213,19 +230,6 @@ void BoundingRectHighlighter::highlightAll(bool animate)
     }
 }
 
-void BoundingRectHighlighter::removeHighlight(QGraphicsObject *item)
-{
-    if (!item)
-        return;
-
-    BoundingBox *box = boxFor(item);
-    if (box) {
-        m_boxes.removeOne(box);
-        delete box;
-        box = 0;
-    }
-}
-
 void BoundingRectHighlighter::refresh()
 {
     if (!m_boxes.isEmpty())
diff --git a/src/libs/qmljsdebugger/editor/boundingrecthighlighter.h b/src/libs/qmljsdebugger/editor/boundingrecthighlighter.h
index 948de90b13b..139b1ac7877 100644
--- a/src/libs/qmljsdebugger/editor/boundingrecthighlighter.h
+++ b/src/libs/qmljsdebugger/editor/boundingrecthighlighter.h
@@ -22,35 +22,57 @@ class BoundingRectHighlighter : public LayerItem
     Q_OBJECT
 public:
     explicit BoundingRectHighlighter(QDeclarativeDesignView *view);
+    ~BoundingRectHighlighter();
     void clear();
     void highlight(QList<QGraphicsObject*> items);
     void highlight(QGraphicsObject* item);
-    void removeHighlight(QGraphicsObject *item);
 
 private slots:
     void refresh();
     void animTimeout();
+    void itemDestroyed(QObject *);
 
 private:
     BoundingBox *boxFor(QGraphicsObject *item) const;
     void highlightAll(bool animate);
     BoundingBox *createBoundingBox(QGraphicsObject *itemToHighlight);
+    void removeBoundingBox(BoundingBox *box);
+    void freeBoundingBox(BoundingBox *box);
 
 private:
     Q_DISABLE_COPY(BoundingRectHighlighter);
 
     QDeclarativeDesignView *m_view;
-    QList<BoundingBox*> m_boxes;
-//    QList<QWeakPointer<QGraphicsObject> > m_highlightedObjects;
-//    QGraphicsPolygonItem *m_highlightPolygon;
-//    QGraphicsPolygonItem *m_highlightPolygonEdge;
-
+    QList<BoundingBox* > m_boxes;
+    QList<BoundingBox* > m_freeBoxes;
     QTimer *m_animTimer;
     qreal m_animScale;
     int m_animFrame;
 
 };
 
+class BoundingBox : public QObject
+{
+    Q_OBJECT
+public:
+    explicit BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem, QObject *parent = 0);
+    ~BoundingBox();
+    QWeakPointer<QGraphicsObject> highlightedObject;
+    QGraphicsPolygonItem *highlightPolygon;
+    QGraphicsPolygonItem *highlightPolygonEdge;
+
+private:
+    Q_DISABLE_COPY(BoundingBox);
+
+};
+
+class BoundingBoxPolygonItem : public QGraphicsPolygonItem
+{
+public:
+    explicit BoundingBoxPolygonItem(QGraphicsItem *item);
+    int type() const;
+};
+
 } // namespace QmlViewer
 
 #endif // BOUNDINGRECTHIGHLIGHTER_H
diff --git a/src/libs/qmljsdebugger/editor/selectionindicator.cpp b/src/libs/qmljsdebugger/editor/selectionindicator.cpp
index e1e1a718531..8b303276b81 100644
--- a/src/libs/qmljsdebugger/editor/selectionindicator.cpp
+++ b/src/libs/qmljsdebugger/editor/selectionindicator.cpp
@@ -34,6 +34,7 @@
 #include <QPen>
 #include <cmath>
 #include <QGraphicsScene>
+#include <QDebug>
 
 namespace QmlViewer {
 
@@ -61,11 +62,17 @@ void SelectionIndicator::hide()
 
 void SelectionIndicator::clear()
 {
-    if (m_layerItem) {
-        foreach (QGraphicsItem *item, m_indicatorShapeHash.values())
-            m_layerItem->scene()->removeItem(item);
+    if (!m_layerItem.isNull()) {
+        QHashIterator<QGraphicsItem*, QGraphicsPolygonItem *> iter(m_indicatorShapeHash);
+        while(iter.hasNext()) {
+            iter.next();
+            m_layerItem->scene()->removeItem(iter.value());
+            delete iter.value();
+        }
     }
+
     m_indicatorShapeHash.clear();
+
 }
 
 QPolygonF SelectionIndicator::addBoundingRectToPolygon(QGraphicsItem *item, QPolygonF &polygon)
@@ -94,20 +101,22 @@ void SelectionIndicator::setItems(const QList<QWeakPointer<QGraphicsObject> > &i
         QGraphicsItem *item = obj.data();
 
         QGraphicsPolygonItem *newSelectionIndicatorGraphicsItem = new QGraphicsPolygonItem(m_layerItem.data());
-        m_indicatorShapeHash.insert(item, newSelectionIndicatorGraphicsItem);
-
-        QPolygonF boundingShapeInSceneSpace;
-        addBoundingRectToPolygon(item, boundingShapeInSceneSpace);
-
-        QRectF boundingRect = m_view->adjustToScreenBoundaries(boundingShapeInSceneSpace.boundingRect());
-        QPolygonF boundingRectInLayerItemSpace = m_layerItem->mapFromScene(boundingRect);
-
-        QPen pen;
-        pen.setColor(QColor(108, 141, 221));
-        newSelectionIndicatorGraphicsItem->setData(Constants::EditorItemDataKey, QVariant(true));
-        newSelectionIndicatorGraphicsItem->setFlag(QGraphicsItem::ItemIsSelectable, false);
-        newSelectionIndicatorGraphicsItem->setPolygon(boundingRectInLayerItemSpace);
-        newSelectionIndicatorGraphicsItem->setPen(pen);
+        if (!m_indicatorShapeHash.contains(item)) {
+            m_indicatorShapeHash.insert(item, newSelectionIndicatorGraphicsItem);
+
+            QPolygonF boundingShapeInSceneSpace;
+            addBoundingRectToPolygon(item, boundingShapeInSceneSpace);
+
+            QRectF boundingRect = m_view->adjustToScreenBoundaries(boundingShapeInSceneSpace.boundingRect());
+            QPolygonF boundingRectInLayerItemSpace = m_layerItem->mapFromScene(boundingRect);
+
+            QPen pen;
+            pen.setColor(QColor(108, 141, 221));
+            newSelectionIndicatorGraphicsItem->setData(Constants::EditorItemDataKey, QVariant(true));
+            newSelectionIndicatorGraphicsItem->setFlag(QGraphicsItem::ItemIsSelectable, false);
+            newSelectionIndicatorGraphicsItem->setPolygon(boundingRectInLayerItemSpace);
+            newSelectionIndicatorGraphicsItem->setPen(pen);
+        }
     }
 }
 
diff --git a/src/libs/qmljsdebugger/editor/selectiontool.cpp b/src/libs/qmljsdebugger/editor/selectiontool.cpp
index d40457e9fc8..004b926b5e6 100644
--- a/src/libs/qmljsdebugger/editor/selectiontool.cpp
+++ b/src/libs/qmljsdebugger/editor/selectiontool.cpp
@@ -223,7 +223,8 @@ void SelectionTool::contextMenuElementHovered(QAction *action)
 {
     int itemListIndex = action->data().toInt();
     if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) {
-        QDeclarativeDesignViewPrivate::get(view())->highlight(m_contextMenuItemList.at(itemListIndex));
+        QGraphicsObject *item = m_contextMenuItemList.at(itemListIndex)->toGraphicsObject();
+        QDeclarativeDesignViewPrivate::get(view())->highlight(item);
     }
 }
 
@@ -258,9 +259,10 @@ void SelectionTool::mouseMoveEvent(QMouseEvent *event)
 
 void SelectionTool::hoverMoveEvent(QMouseEvent * event)
 {
-    QList<QGraphicsItem*> itemList = view()->items(event->pos());
-    if (!itemList.isEmpty() && !m_rubberbandSelectionMode) {
-
+// ### commented out until move tool is re-enabled
+//    QList<QGraphicsItem*> itemList = view()->items(event->pos());
+//    if (!itemList.isEmpty() && !m_rubberbandSelectionMode) {
+//
 //        foreach(QGraphicsItem *item, itemList) {
 //            if (item->type() == Constants::ResizeHandleItemType) {
 //                ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(item);
@@ -271,27 +273,17 @@ void SelectionTool::hoverMoveEvent(QMouseEvent * event)
 //        }
 //        if (topSelectedItemIsMovable(itemList))
 //            view()->changeTool(Constants::MoveToolMode);
-    }
-
-    QList<QGraphicsItem*> selectableItemList = view()->items(event->pos());
+//    }
+    QList<QGraphicsItem*> selectableItemList = QDeclarativeDesignViewPrivate::get(view())->selectableItems(event->pos());
     if (!selectableItemList.isEmpty()) {
-        QGraphicsItem *topSelectableItem = 0;
-        foreach(QGraphicsItem* item, selectableItemList)
-        {
-            if (!QDeclarativeDesignViewPrivate::get(view())->isEditorItem(item)
-                /*&& !item->qmlItemNode().isRootNode()
-                && (QGraphicsItem->qmlItemNode().hasShowContent() || !m_selectOnlyContentItems)*/)
-            {
-                topSelectableItem = item;
-                break;
-            }
-        }
+        QGraphicsObject *item = selectableItemList.first()->toGraphicsObject();
+        if (item)
+            QDeclarativeDesignViewPrivate::get(view())->highlight(item);
 
-        QDeclarativeDesignViewPrivate::get(view())->highlight(topSelectableItem);
-    } else {
-        QDeclarativeDesignViewPrivate::get(view())->clearHighlight();
+        return;
     }
 
+    QDeclarativeDesignViewPrivate::get(view())->clearHighlight();
 }
 
 void SelectionTool::mouseReleaseEvent(QMouseEvent *event)
@@ -416,6 +408,7 @@ void SelectionTool::selectedItemsChanged(const QList<QGraphicsItem*> &itemList)
             disconnect(obj.data(), SIGNAL(rotationChanged()), this, SLOT(repaintBoundingRects()));
         }
     }
+
     QList<QGraphicsObject*> objects = toGraphicsObjectList(itemList);
     m_selectedItemList.clear();
 
diff --git a/src/libs/qmljsdebugger/qdeclarativedesignview.cpp b/src/libs/qmljsdebugger/qdeclarativedesignview.cpp
index 80c6140e8cb..db6901b58d7 100644
--- a/src/libs/qmljsdebugger/qdeclarativedesignview.cpp
+++ b/src/libs/qmljsdebugger/qdeclarativedesignview.cpp
@@ -406,18 +406,17 @@ QList<QGraphicsItem *> QDeclarativeDesignView::selectedItems()
     return data->selectedItems();
 }
 
-
 void QDeclarativeDesignViewPrivate::clearHighlight()
 {
     boundingRectHighlighter->clear();
 }
 
-void QDeclarativeDesignViewPrivate::highlight(QGraphicsItem * item, ContextFlags flags)
+void QDeclarativeDesignViewPrivate::highlight(QGraphicsObject * item, ContextFlags flags)
 {
-    highlight(QList<QGraphicsItem*>() << item, flags);
+    highlight(QList<QGraphicsObject*>() << item, flags);
 }
 
-void QDeclarativeDesignViewPrivate::highlight(QList<QGraphicsItem *> items, ContextFlags flags)
+void QDeclarativeDesignViewPrivate::highlight(QList<QGraphicsObject *> items, ContextFlags flags)
 {
     if (items.isEmpty())
         return;
@@ -627,15 +626,19 @@ void QDeclarativeDesignViewPrivate::_q_onStatusChanged(QDeclarativeView::Status
 void QDeclarativeDesignViewPrivate::_q_onCurrentObjectsChanged(QList<QObject*> objects)
 {
     QList<QGraphicsItem*> items;
+    QList<QGraphicsObject*> gfxObjects;
     foreach(QObject *obj, objects) {
         QDeclarativeItem* declarativeItem = qobject_cast<QDeclarativeItem*>(obj);
-        if (declarativeItem)
+        if (declarativeItem) {
             items << declarativeItem;
+            QGraphicsObject *gfxObj = declarativeItem->toGraphicsObject();
+            if (gfxObj)
+                gfxObjects << gfxObj;
+        }
     }
-
     setSelectedItemsForTools(items);
     clearHighlight();
-    highlight(items, QDeclarativeDesignViewPrivate::IgnoreContext);
+    highlight(gfxObjects, QDeclarativeDesignViewPrivate::IgnoreContext);
 }
 
 QString QDeclarativeDesignView::idStringForObject(QObject *obj)
diff --git a/src/libs/qmljsdebugger/qdeclarativedesignview_p.h b/src/libs/qmljsdebugger/qdeclarativedesignview_p.h
index 9ff33421f71..c06c018d0a6 100644
--- a/src/libs/qmljsdebugger/qdeclarativedesignview_p.h
+++ b/src/libs/qmljsdebugger/qdeclarativedesignview_p.h
@@ -102,8 +102,8 @@ public:
                     Constants::ToolFlags flags = Constants::NoToolFlags);
 
     void clearHighlight();
-    void highlight(QList<QGraphicsItem *> item, ContextFlags flags = ContextSensitive);
-    void highlight(QGraphicsItem *item, ContextFlags flags = ContextSensitive);
+    void highlight(QList<QGraphicsObject *> item, ContextFlags flags = ContextSensitive);
+    void highlight(QGraphicsObject *item, ContextFlags flags = ContextSensitive);
 
     bool mouseInsideContextItem() const;
     bool isEditorItem(QGraphicsItem *item) const;
-- 
GitLab