From a1cdeba0e16c487fdc479fcb3b2d0bd5a5493f1a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Fri, 10 Jun 2011 17:47:33 +0200 Subject: [PATCH] QmlInspector: Implemented context menu for SceneGraph Change-Id: I467bdba42af0ff4b680c31a3545e059a56016a57 --- .../qmldbg_inspector/sgselectiontool.cpp | 77 +++++++++++++++++--- .../qmltooling/qmldbg_inspector/sgselectiontool.h | 12 +++ .../qmldbg_inspector/sgviewinspector.cpp | 36 +++++++++- .../qmltooling/qmldbg_inspector/sgviewinspector.h | 7 +- 4 files changed, 116 insertions(+), 16 deletions(-) diff --git a/src/plugins/qmltooling/qmldbg_inspector/sgselectiontool.cpp b/src/plugins/qmltooling/qmldbg_inspector/sgselectiontool.cpp index 2d911a8..7260933 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/sgselectiontool.cpp +++ b/src/plugins/qmltooling/qmldbg_inspector/sgselectiontool.cpp @@ -43,6 +43,7 @@ #include "sgviewinspector.h" +#include #include #include #include @@ -58,6 +59,13 @@ public: setZ(1); // hover highlight on top of selection indicator } + void setItem(QSGItem *item) + { + setSize(QSizeF(item->width(), item->height())); + setPos(parentItem()->mapFromItem(item, QPointF())); + setVisible(true); + } + void paint(QPainter *painter) { painter->setPen(QPen(QColor(0, 22, 159))); @@ -81,25 +89,70 @@ void SGSelectionTool::leaveEvent(QEvent *) void SGSelectionTool::mousePressEvent(QMouseEvent *event) { - SGViewInspector *sgInspector = static_cast(inspector()); - QSGItem *item = sgInspector->topVisibleItemAt(event->pos()); - if (item) - sgInspector->setSelectedItems(QList() << item); + if (event->button() == Qt::LeftButton) { + if (QSGItem *item = inspector()->topVisibleItemAt(event->pos())) + inspector()->setSelectedItems(QList() << item); + } else if (event->button() == Qt::RightButton) { + QList items = inspector()->itemsAt(event->pos()); + createContextMenu(items, event->globalPos()); + } } void SGSelectionTool::hoverMoveEvent(QMouseEvent *event) { - SGViewInspector *sgInspector = static_cast(inspector()); - QSGItem *item = sgInspector->topVisibleItemAt(event->pos()); - if (!item) { + QSGItem *item = inspector()->topVisibleItemAt(event->pos()); + if (!item) m_hoverHighlight->setVisible(false); - return; + else + m_hoverHighlight->setItem(item); +} + +void SGSelectionTool::createContextMenu(const QList &items, QPoint pos) +{ + QMenu contextMenu; + connect(&contextMenu, SIGNAL(hovered(QAction*)), + this, SLOT(contextMenuElementHovered(QAction*))); + + const QList selectedItems = inspector()->selectedItems(); + int shortcutKey = Qt::Key_1; + + foreach (QSGItem *item, items) { + const QString title = inspector()->titleForItem(item); + QAction *elementAction = contextMenu.addAction(title); + elementAction->setData(QVariant::fromValue(item)); + + connect(elementAction, SIGNAL(triggered()), this, SLOT(contextMenuElementSelected())); + + if (selectedItems.contains(item)) { + QFont font = elementAction->font(); + font.setBold(true); + elementAction->setFont(font); + } + + if (shortcutKey <= Qt::Key_9) { + elementAction->setShortcut(QKeySequence(shortcutKey)); + shortcutKey++; + } } - QSGItem *root = sgInspector->view()->rootItem(); - m_hoverHighlight->setSize(QSizeF(item->width(), item->height())); - m_hoverHighlight->setPos(root->mapFromItem(item->parentItem(), item->pos())); - m_hoverHighlight->setVisible(true); + contextMenu.exec(pos); +} + +void SGSelectionTool::contextMenuElementHovered(QAction *action) +{ + if (QSGItem *item = action->data().value()) + m_hoverHighlight->setItem(item); +} + +void SGSelectionTool::contextMenuElementSelected() +{ + if (QSGItem *item = static_cast(sender())->data().value()) + inspector()->setSelectedItems(QList() << item); +} + +SGViewInspector *SGSelectionTool::inspector() const +{ + return static_cast(AbstractTool::inspector()); } } // namespace QmlJSDebugger diff --git a/src/plugins/qmltooling/qmldbg_inspector/sgselectiontool.h b/src/plugins/qmltooling/qmldbg_inspector/sgselectiontool.h index e76bd20..9f2171f 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/sgselectiontool.h +++ b/src/plugins/qmltooling/qmldbg_inspector/sgselectiontool.h @@ -45,6 +45,10 @@ #include "abstracttool.h" #include +#include + +QT_FORWARD_DECLARE_CLASS(QAction) +QT_FORWARD_DECLARE_CLASS(QSGItem) namespace QmlJSDebugger { @@ -70,7 +74,15 @@ public: void keyPressEvent(QKeyEvent *) {} void keyReleaseEvent(QKeyEvent *) {} +private slots: + void contextMenuElementHovered(QAction *action); + void contextMenuElementSelected(); + private: + void createContextMenu(const QList &items, QPoint pos); + + SGViewInspector *inspector() const; + SGHoverHighlight *m_hoverHighlight; }; diff --git a/src/plugins/qmltooling/qmldbg_inspector/sgviewinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/sgviewinspector.cpp index fd9b29b..b1d1918 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/sgviewinspector.cpp +++ b/src/plugins/qmltooling/qmldbg_inspector/sgviewinspector.cpp @@ -58,6 +58,32 @@ namespace QmlJSDebugger { /* + * Collects all the items at the given position, from top to bottom. + */ +static void collectItemsAt(QSGItem *item, const QPointF &pos, QSGItem *overlay, + QList &resultList) +{ + if (item == overlay) + return; + + if (item->flags() & QSGItem::ItemClipsChildrenToShape) { + if (!QRectF(0, 0, item->width(), item->height()).contains(pos)) + return; + } + + QList children = QSGItemPrivate::get(item)->paintOrderChildItems(); + for (int i = children.count() - 1; i >= 0; --i) { + QSGItem *child = children.at(i); + collectItemsAt(child, item->mapToItem(child, pos), overlay, resultList); + } + + if (!QRectF(0, 0, item->width(), item->height()).contains(pos)) + return; + + resultList.append(item); +} + +/* * Returns the first visible item at the given position, or 0 when no such * child exists. */ @@ -185,12 +211,20 @@ QWidget *SGViewInspector::viewWidget() const return m_view; } -QSGItem *SGViewInspector::topVisibleItemAt(const QPointF &pos) +QSGItem *SGViewInspector::topVisibleItemAt(const QPointF &pos) const { QSGItem *root = m_view->rootItem(); return itemAt(root, root->mapFromScene(pos), m_overlay); } +QList SGViewInspector::itemsAt(const QPointF &pos) const +{ + QSGItem *root = m_view->rootItem(); + QList resultList; + collectItemsAt(root, root->mapFromScene(pos), m_overlay, resultList); + return resultList; +} + QList SGViewInspector::selectedItems() const { QList selection; diff --git a/src/plugins/qmltooling/qmldbg_inspector/sgviewinspector.h b/src/plugins/qmltooling/qmldbg_inspector/sgviewinspector.h index 8cde72d..d1f6499 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/sgviewinspector.h +++ b/src/plugins/qmltooling/qmldbg_inspector/sgviewinspector.h @@ -74,11 +74,14 @@ public: QSGView *view() const { return m_view; } QSGItem *overlay() const { return m_overlay; } - QSGItem *topVisibleItemAt(const QPointF &pos); + QSGItem *topVisibleItemAt(const QPointF &pos) const; + QList itemsAt(const QPointF &pos) const; QList selectedItems() const; void setSelectedItems(const QList &items); + QString titleForItem(QSGItem *item) const; + protected: bool eventFilter(QObject *obj, QEvent *event); @@ -91,8 +94,6 @@ private slots: private: bool syncSelectedItems(const QList &items); - QString titleForItem(QSGItem *item) const; - QSGView *m_view; QSGItem *m_overlay; -- 1.7.2.5