QmlInspector: Implemented selection for SceneGraph
authorThorbjørn Lindeijer <thorbjorn.lindeijer@nokia.com>
Thu, 9 Jun 2011 15:15:23 +0000 (17:15 +0200)
committerThorbjørn Lindeijer <thorbjorn.lindeijer@nokia.com>
Thu, 23 Jun 2011 14:26:11 +0000 (16:26 +0200)
The highlight items are now based on QSGPaintedItem rather than the
internal QSGRectangle.

Change-Id: I50222116cf5f98ec93f914298a554b3d2d901c28

src/plugins/qmltooling/qmldbg_inspector/sgselectiontool.cpp
src/plugins/qmltooling/qmldbg_inspector/sgselectiontool.h
src/plugins/qmltooling/qmldbg_inspector/sgviewinspector.cpp
src/plugins/qmltooling/qmldbg_inspector/sgviewinspector.h

index c233cf6..a6c459a 100644 (file)
@@ -46,8 +46,8 @@
 #include <QtGui/QMouseEvent>
 #include <QtDeclarative/QSGView>
 #include <QtDeclarative/QSGItem>
+#include <QtDeclarative/QSGPaintedItem>
 #include <QtDeclarative/private/qsgitem_p.h>
-#include <QtDeclarative/private/qsgrectangle_p.h>
 
 namespace QmlJSDebugger {
 
@@ -85,12 +85,28 @@ static QSGItem *itemAt(QSGItem *item, const QPointF &pos, QSGItem *overlay)
 }
 
 
+class SGHoverHighlight : public QSGPaintedItem
+{
+public:
+    SGHoverHighlight(QSGItem *parent) : QSGPaintedItem(parent)
+    {
+        setZ(1); // hover highlight on top of selection indicator
+    }
+
+    void paint(QPainter *painter)
+    {
+        painter->setPen(QPen(QColor(0, 22, 159)));
+        painter->drawRect(QRect(1, 1, width() - 3, height() - 3));
+        painter->setPen(QColor(158, 199, 255));
+        painter->drawRect(QRect(0, 0, width() - 1, height() - 1));
+    }
+};
+
+
 SGSelectionTool::SGSelectionTool(SGViewInspector *inspector) :
     AbstractTool(inspector),
-    m_hoverHighlight(new QSGRectangle(inspector->overlay()))
+    m_hoverHighlight(new SGHoverHighlight(inspector->overlay()))
 {
-    m_hoverHighlight->border()->setColor(QColor(64, 128, 255));
-    m_hoverHighlight->setColor(Qt::transparent);
 }
 
 void SGSelectionTool::leaveEvent(QEvent *)
@@ -98,6 +114,16 @@ void SGSelectionTool::leaveEvent(QEvent *)
     m_hoverHighlight->setVisible(false);
 }
 
+void SGSelectionTool::mousePressEvent(QMouseEvent *event)
+{
+    SGViewInspector *sgInspector = static_cast<SGViewInspector*>(inspector());
+    QSGItem *root = sgInspector->view()->rootItem();
+    QPointF mappedPos = root->mapFromScene(event->pos());
+    QSGItem *item = itemAt(root, mappedPos, sgInspector->overlay());
+    if (item && item != root)
+        sgInspector->setSelectedItems(QList<QSGItem*>() << item);
+}
+
 void SGSelectionTool::hoverMoveEvent(QMouseEvent *event)
 {
     SGViewInspector *sgInspector = static_cast<SGViewInspector*>(inspector());
@@ -109,7 +135,7 @@ void SGSelectionTool::hoverMoveEvent(QMouseEvent *event)
         return;
     }
 
-    m_hoverHighlight->setSize(QSizeF(item->width() - 1, item->height() - 1));
+    m_hoverHighlight->setSize(QSizeF(item->width(), item->height()));
     m_hoverHighlight->setPos(root->mapFromItem(item->parentItem(), item->pos()));
     m_hoverHighlight->setVisible(true);
 }
index f794691..e76bd20 100644 (file)
 
 #include <QtCore/QList>
 
-QT_FORWARD_DECLARE_CLASS(QSGRectangle)
-
 namespace QmlJSDebugger {
 
 class SGViewInspector;
+class SGHoverHighlight;
 
 class SGSelectionTool : public AbstractTool
 {
@@ -60,7 +59,7 @@ public:
 
     void leaveEvent(QEvent *);
 
-    void mousePressEvent(QMouseEvent *) {}
+    void mousePressEvent(QMouseEvent *);
     void mouseMoveEvent(QMouseEvent *) {}
     void mouseReleaseEvent(QMouseEvent *) {}
     void mouseDoubleClickEvent(QMouseEvent *) {}
@@ -71,13 +70,8 @@ public:
     void keyPressEvent(QKeyEvent *) {}
     void keyReleaseEvent(QKeyEvent *) {}
 
-signals:
-
-public slots:
-
 private:
-    QList<QSGRectangle*> m_highlightItems;
-    QSGRectangle *m_hoverHighlight;
+    SGHoverHighlight *m_hoverHighlight;
 };
 
 } // namespace QmlJSDebugger
index ec68ef9..4d79ac6 100644 (file)
 
 #include <QtDeclarative/QSGView>
 #include <QtDeclarative/QSGItem>
+#include <QtDeclarative/QSGPaintedItem>
 #include <QtGui/QMouseEvent>
 
 #include <cfloat>
 
 namespace QmlJSDebugger {
 
+class SGSelectionHighlight : public QSGPaintedItem
+{
+public:
+    SGSelectionHighlight(QSGItem *parent) : QSGPaintedItem(parent)
+    { }
+
+    void paint(QPainter *painter)
+    {
+        painter->setPen(QColor(108, 141, 221));
+        painter->drawRect(QRect(0, 0, width() - 1, height() - 1));
+    }
+};
+
+
 SGViewInspector::SGViewInspector(QSGView *view, QObject *parent) :
     AbstractViewInspector(parent),
     m_view(view),
@@ -82,7 +97,7 @@ void SGViewInspector::changeCurrentObjects(const QList<QObject*> &objects)
         if (QSGItem *item = qobject_cast<QSGItem*>(obj))
             items << item;
 
-    setSelectedItems(items);
+    syncSelectedItems(items);
 }
 
 void SGViewInspector::reloadView()
@@ -147,32 +162,70 @@ QList<QSGItem*> SGViewInspector::selectedItems() const
 
 void SGViewInspector::setSelectedItems(const QList<QSGItem *> &items)
 {
+    if (!syncSelectedItems(items))
+        return;
+
+    QList<QObject*> objectList;
+    foreach (QSGItem *item, items)
+        objectList << item;
+
+    sendCurrentObjects(objectList);
+}
+
+bool SGViewInspector::syncSelectedItems(const QList<QSGItem *> &items)
+{
+    bool selectionChanged = false;
+
     // Disconnect and remove items that are no longer selected
     foreach (const QWeakPointer<QSGItem> &item, m_selectedItems) {
-        if (!item)
+        if (!item) // Don't see how this can happen due to handling of destroyed()
+            continue;
+        if (items.contains(item.data()))
             continue;
 
-        if (!items.contains(item.data())) {
-            QObject::disconnect(item.data(), SIGNAL(destroyed(QObject*)),
-                                this, SLOT(removeFromSelection(QObject*)));
-            m_selectedItems.removeOne(item);
-        }
+        selectionChanged = true;
+        item.data()->disconnect(this);
+        m_selectedItems.removeOne(item);
+        delete m_highlightItems.take(item.data());
     }
 
     // Connect and add newly selected items
     foreach (QSGItem *item, items) {
-        if (!m_selectedItems.contains(item)) {
-            QObject::connect(item, SIGNAL(destroyed(QObject*)),
-                             this, SLOT(removeFromSelection(QObject*)));
-            m_selectedItems.append(item);
-        }
+        if (m_selectedItems.contains(item))
+            continue;
+
+        selectionChanged = true;
+        connect(item, SIGNAL(destroyed(QObject*)), this, SLOT(removeFromSelectedItems(QObject*)));
+        connect(item, SIGNAL(xChanged()), this, SLOT(adjustSelectionHighlight()));
+        connect(item, SIGNAL(yChanged()), this, SLOT(adjustSelectionHighlight()));
+        connect(item, SIGNAL(widthChanged()), this, SLOT(adjustSelectionHighlight()));
+        connect(item, SIGNAL(heightChanged()), this, SLOT(adjustSelectionHighlight()));
+        connect(item, SIGNAL(rotationChanged()), this, SLOT(adjustSelectionHighlight()));
+        m_selectedItems.append(item);
+        m_highlightItems.insert(item, new SGSelectionHighlight(m_overlay));
+        adjustSelectionHighlight(item);
     }
+
+    return selectionChanged;
 }
 
 void SGViewInspector::removeFromSelectedItems(QObject *object)
 {
-    if (QSGItem *item = qobject_cast<QSGItem*>(object))
-        m_selectedItems.removeOne(item);
+    if (QSGItem *item = qobject_cast<QSGItem*>(object)) {
+        if (m_selectedItems.removeOne(item))
+            delete m_highlightItems.take(item);
+    }
+}
+
+void SGViewInspector::adjustSelectionHighlight(QSGItem *item)
+{
+    if (!item)
+        item = static_cast<QSGItem*>(sender());
+
+    SGSelectionHighlight *highlight = m_highlightItems.value(item);
+
+    highlight->setSize(QSizeF(item->width(), item->height()));
+    highlight->setPos(m_overlay->mapFromItem(item->parentItem(), item->pos()));
 }
 
 bool SGViewInspector::eventFilter(QObject *obj, QEvent *event)
index 2a7cb6c..a54036d 100644 (file)
@@ -45,6 +45,7 @@
 #include "abstractviewinspector.h"
 
 #include <QtCore/QWeakPointer>
+#include <QtCore/QHash>
 
 QT_BEGIN_NAMESPACE
 class QSGView;
@@ -54,6 +55,7 @@ QT_END_NAMESPACE
 namespace QmlJSDebugger {
 
 class SGSelectionTool;
+class SGSelectionHighlight;
 
 class SGViewInspector : public AbstractViewInspector
 {
@@ -79,14 +81,18 @@ public:
 
 private slots:
     void removeFromSelectedItems(QObject *);
+    void adjustSelectionHighlight(QSGItem *item = 0);
 
 private:
+    bool syncSelectedItems(const QList<QSGItem*> &items);
+
     QSGView *m_view;
     QSGItem *m_overlay;
 
     SGSelectionTool *m_selectionTool;
 
     QList<QWeakPointer<QSGItem> > m_selectedItems;
+    QHash<QSGItem*, SGSelectionHighlight*> m_highlightItems;
 
     bool m_designMode;
 };