diff --git a/src/tools/qml/qmlviewer/editor/boundingrecthighlighter.cpp b/src/tools/qml/qmlviewer/editor/boundingrecthighlighter.cpp index 4d447793779410728098fd65a7a183797c9130bb..a938a30504ffeac5fe7bee7f0fd58cbe1e078042 100644 --- a/src/tools/qml/qmlviewer/editor/boundingrecthighlighter.cpp +++ b/src/tools/qml/qmlviewer/editor/boundingrecthighlighter.cpp @@ -13,6 +13,51 @@ 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), + highlightPolygon(0), + highlightPolygonEdge(0) +{ + highlightPolygon = new BoundingBoxPolygonItem(parentItem); + highlightPolygonEdge = new BoundingBoxPolygonItem(parentItem); + + highlightPolygon->setPen(QPen(QColor(0, 22, 159))); + highlightPolygonEdge->setPen(QPen(QColor(158, 199, 255))); + + highlightPolygon->setFlag(QGraphicsItem::ItemIsSelectable, false); + highlightPolygonEdge->setFlag(QGraphicsItem::ItemIsSelectable, false); +} + +BoundingBox::~BoundingBox() +{ + delete highlightPolygon; + delete highlightPolygonEdge; + highlightPolygon = 0; + highlightPolygonEdge = 0; + highlightedObject.clear(); +} + BoundingBoxPolygonItem::BoundingBoxPolygonItem(QGraphicsItem *item) : QGraphicsPolygonItem(item) { QPen pen; @@ -28,8 +73,6 @@ int BoundingBoxPolygonItem::type() const BoundingRectHighlighter::BoundingRectHighlighter(QDeclarativeDesignView *view) : LayerItem(view->scene()), m_view(view), - m_highlightPolygon(0), - m_highlightPolygonEdge(0), m_animFrame(0) { m_animTimer = new QTimer(this); @@ -44,89 +87,140 @@ void BoundingRectHighlighter::animTimeout() m_animTimer->stop(); } - m_highlightPolygon->setPen(QPen(QColor(0, 22, 159))); - m_highlightPolygonEdge->setPen(QPen(QColor(158, 199, 255))); qreal alpha = m_animFrame / float(AnimFrames); - m_highlightPolygonEdge->setOpacity(alpha); + + foreach(BoundingBox *box, m_boxes) { + box->highlightPolygonEdge->setOpacity(alpha); + } } void BoundingRectHighlighter::clear() { - if (m_highlightPolygon) { - m_view->scene()->removeItem(m_highlightPolygon); - delete m_highlightPolygon; - m_highlightPolygon = 0; - delete m_highlightPolygonEdge; - m_highlightPolygonEdge = 0; + if (m_boxes.length()) { m_animTimer->stop(); - disconnect(m_highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh())); - disconnect(m_highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh())); - disconnect(m_highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh())); - disconnect(m_highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh())); - disconnect(m_highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh())); + qDeleteAll(m_boxes); + m_boxes.clear(); - m_highlightedObject.clear(); +// disconnect(m_highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh())); +// disconnect(m_highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh())); +// disconnect(m_highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh())); +// disconnect(m_highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh())); +// disconnect(m_highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh())); } } -void BoundingRectHighlighter::highlight(QGraphicsObject* item) +BoundingBox *BoundingRectHighlighter::boxFor(QGraphicsObject *item) const { - if (!item) + foreach(BoundingBox *box, m_boxes) { + if (box->highlightedObject.data() == item) { + return box; + } + } + return 0; +} + +void BoundingRectHighlighter::highlight(QList<QGraphicsObject*> items) +{ + if (items.isEmpty()) return; bool animate = false; - QGraphicsPolygonItem *polygonItem = 0; - QGraphicsPolygonItem *polygonItemEdge = 0; - if (item != m_highlightedObject.data() || !m_highlightPolygon) { - animate = true; - polygonItem = new BoundingBoxPolygonItem(this); - polygonItemEdge = new BoundingBoxPolygonItem(this); - } else { - polygonItem = m_highlightPolygon; - polygonItemEdge = m_highlightPolygonEdge; + + QList<BoundingBox*> newBoxes; + + foreach(QGraphicsObject *itemToHighlight, items) { + BoundingBox *box = boxFor(itemToHighlight); + if (!box) { + box = new BoundingBox(itemToHighlight, this); + animate = true; + } + + newBoxes << box; } + qSort(newBoxes); - QRectF itemAndChildRect = item->boundingRect() | item->childrenBoundingRect(); + if (newBoxes != m_boxes) { + clear(); + m_boxes << newBoxes; + } - QPolygonF boundingRectInSceneSpace(item->mapToScene(itemAndChildRect)); - QPolygonF boundingRectInLayerItemSpace = mapFromScene(boundingRectInSceneSpace); - QRectF bboxRect = boundingRectInLayerItemSpace.boundingRect(); - QRectF edgeRect = boundingRectInLayerItemSpace.boundingRect(); - edgeRect.adjust(-1, -1, 1, 1); + highlightAll(animate); +} - polygonItem->setPolygon(QPolygonF(bboxRect)); - polygonItem->setFlag(QGraphicsItem::ItemIsSelectable, false); +void BoundingRectHighlighter::highlight(QGraphicsObject* itemToHighlight) +{ + if (!itemToHighlight) + return; - polygonItemEdge->setPolygon(QPolygonF(edgeRect)); - polygonItemEdge->setFlag(QGraphicsItem::ItemIsSelectable, false); + bool animate = false; - if (item != m_highlightedObject.data()) - clear(); + BoundingBox *box = boxFor(itemToHighlight); + if (!box) { + box = new BoundingBox(itemToHighlight, this); + m_boxes << box; + animate = true; + qSort(m_boxes); + } - m_highlightPolygon = polygonItem; - m_highlightPolygonEdge = polygonItemEdge; - m_highlightedObject = item; + highlightAll(animate); +} - if (item != m_highlightedObject.data()) { - connect(m_highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh())); - connect(m_highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh())); - connect(m_highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh())); - connect(m_highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh())); - connect(m_highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh())); +void BoundingRectHighlighter::highlightAll(bool animate) +{ + foreach(BoundingBox *box, m_boxes) { + QGraphicsObject *item = box->highlightedObject.data(); + if (!item) { + m_boxes.removeOne(box); + continue; + } + + QRectF itemAndChildRect = item->boundingRect() | item->childrenBoundingRect(); + + QPolygonF boundingRectInSceneSpace(item->mapToScene(itemAndChildRect)); + QPolygonF boundingRectInLayerItemSpace = mapFromScene(boundingRectInSceneSpace); + QRectF bboxRect = boundingRectInLayerItemSpace.boundingRect(); + QRectF edgeRect = boundingRectInLayerItemSpace.boundingRect(); + edgeRect.adjust(-1, -1, 1, 1); + + box->highlightPolygon->setPolygon(QPolygonF(bboxRect)); + box->highlightPolygonEdge->setPolygon(QPolygonF(edgeRect)); + +// if (XXX) { +// connect(item, SIGNAL(xChanged()), this, SLOT(refresh())); +// connect(item, SIGNAL(yChanged()), this, SLOT(refresh())); +// connect(item, SIGNAL(widthChanged()), this, SLOT(refresh())); +// connect(item, SIGNAL(heightChanged()), this, SLOT(refresh())); +// connect(item, SIGNAL(rotationChanged()), this, SLOT(refresh())); +// } + + if (animate) + box->highlightPolygonEdge->setOpacity(0); } if (animate) { - m_highlightPolygonEdge->setOpacity(0); m_animFrame = 0; m_animTimer->start(); } } +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_highlightedObject.isNull()) - highlight(m_highlightedObject.data()); + if (!m_boxes.isEmpty()) + highlightAll(true); } diff --git a/src/tools/qml/qmlviewer/editor/boundingrecthighlighter.h b/src/tools/qml/qmlviewer/editor/boundingrecthighlighter.h index 81dc84579f2f3aa8d7079db48860dc4eaab120dc..2e8e52226f2337dab49de34a8c150e90d8bf6d18 100644 --- a/src/tools/qml/qmlviewer/editor/boundingrecthighlighter.h +++ b/src/tools/qml/qmlviewer/editor/boundingrecthighlighter.h @@ -15,13 +15,7 @@ QT_FORWARD_DECLARE_CLASS(QTimer); namespace QmlViewer { class QDeclarativeDesignView; - -class BoundingBoxPolygonItem : public QGraphicsPolygonItem -{ -public: - explicit BoundingBoxPolygonItem(QGraphicsItem *item); - int type() const; -}; +class BoundingBox; class BoundingRectHighlighter : public LayerItem { @@ -29,19 +23,26 @@ class BoundingRectHighlighter : public LayerItem public: explicit BoundingRectHighlighter(QDeclarativeDesignView *view); void clear(); + void highlight(QList<QGraphicsObject*> items); void highlight(QGraphicsObject* item); + void removeHighlight(QGraphicsObject *item); private slots: void refresh(); void animTimeout(); +private: + BoundingBox *boxFor(QGraphicsObject *item) const; + void highlightAll(bool animate); + private: Q_DISABLE_COPY(BoundingRectHighlighter); QDeclarativeDesignView *m_view; - QWeakPointer<QGraphicsObject> m_highlightedObject; - QGraphicsPolygonItem *m_highlightPolygon; - QGraphicsPolygonItem *m_highlightPolygonEdge; + QList<BoundingBox*> m_boxes; +// QList<QWeakPointer<QGraphicsObject> > m_highlightedObjects; +// QGraphicsPolygonItem *m_highlightPolygon; +// QGraphicsPolygonItem *m_highlightPolygonEdge; QTimer *m_animTimer; qreal m_animScale; diff --git a/src/tools/qml/qmlviewer/editor/selectiontool.cpp b/src/tools/qml/qmlviewer/editor/selectiontool.cpp index fd1e0579c0d109d80775bdd2c45e48779ee094f3..0586372b60d126cf6cd77ed1a2a27ae078b5ce50 100644 --- a/src/tools/qml/qmlviewer/editor/selectiontool.cpp +++ b/src/tools/qml/qmlviewer/editor/selectiontool.cpp @@ -222,7 +222,7 @@ void SelectionTool::contextMenuElementHovered(QAction *action) { int itemListIndex = action->data().toInt(); if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) { - view()->highlightBoundingRect(m_contextMenuItemList.at(itemListIndex)); + view()->highlight(m_contextMenuItemList.at(itemListIndex)); } } @@ -286,9 +286,9 @@ void SelectionTool::hoverMoveEvent(QMouseEvent * event) } } - view()->highlightBoundingRect(topSelectableItem); + view()->highlight(topSelectableItem); } else { - view()->clearHighlightBoundingRect(); + view()->clearHighlight(); } } diff --git a/src/tools/qml/qmlviewer/editor/subcomponenteditortool.cpp b/src/tools/qml/qmlviewer/editor/subcomponenteditortool.cpp index 240668a0c6a6dccc7687b009f4582a5c23510d4b..615e5942eb7a109cea4f82d14bae4983b569b50f 100644 --- a/src/tools/qml/qmlviewer/editor/subcomponenteditortool.cpp +++ b/src/tools/qml/qmlviewer/editor/subcomponenteditortool.cpp @@ -71,7 +71,7 @@ void SubcomponentEditorTool::mouseDoubleClickEvent(QMouseEvent *event) void SubcomponentEditorTool::hoverMoveEvent(QMouseEvent *event) { if (!containsCursor(event->pos()) && m_currentContext.size() > 1) { - view()->clearHighlightBoundingRect(); + view()->clearHighlight(); } } @@ -164,7 +164,7 @@ void SubcomponentEditorTool::setCurrentItem(QGraphicsItem* contextItem) m_animIncrement = 0.05f; m_animTimer->start(); - view()->clearHighlightBoundingRect(); + view()->clearHighlight(); view()->setSelectedItems(QList<QGraphicsItem*>()); pushContext(gfxObject); diff --git a/src/tools/qml/qmlviewer/qdeclarativedesignview.cpp b/src/tools/qml/qmlviewer/qdeclarativedesignview.cpp index 7e164ea0eba09300dd907ebd9111a1f047fd5f72..8c522f74b311dfb8967dbf5d33ef7e2630186466 100644 --- a/src/tools/qml/qmlviewer/qdeclarativedesignview.cpp +++ b/src/tools/qml/qmlviewer/qdeclarativedesignview.cpp @@ -63,7 +63,7 @@ QDeclarativeDesignView::~QDeclarativeDesignView() void QDeclarativeDesignView::reloadView() { m_subcomponentEditorTool->clear(); - clearHighlightBoundingRect(); + clearHighlight(); emit reloadRequested(); } @@ -73,7 +73,7 @@ void QDeclarativeDesignView::leaveEvent(QEvent *event) QDeclarativeView::leaveEvent(event); return; } - clearHighlightBoundingRect(); + clearHighlight(); } void QDeclarativeDesignView::mousePressEvent(QMouseEvent *event) @@ -227,7 +227,7 @@ void QDeclarativeDesignView::setDesignModeBehavior(bool value) m_designModeBehavior = value; if (m_subcomponentEditorTool) { m_subcomponentEditorTool->clear(); - clearHighlightBoundingRect(); + clearHighlight(); setSelectedItems(QList<QGraphicsItem*>()); if (rootObject()) @@ -269,22 +269,32 @@ AbstractFormEditorTool *QDeclarativeDesignView::currentTool() const return m_currentTool; } -void QDeclarativeDesignView::clearHighlightBoundingRect() +void QDeclarativeDesignView::clearHighlight() { m_boundingRectHighlighter->clear(); } -void QDeclarativeDesignView::highlightBoundingRect(QGraphicsItem *item) +void QDeclarativeDesignView::highlight(QGraphicsItem * item) { - if (!item) + highlight(QList<QGraphicsItem*>() << item); +} + +void QDeclarativeDesignView::highlight(QList<QGraphicsItem *> items) +{ + if (items.isEmpty()) return; - QGraphicsItem *itemToHighlight = m_subcomponentEditorTool->firstChildOfContext(item); - if (itemToHighlight) { - m_boundingRectHighlighter->highlight(itemToHighlight->toGraphicsObject()); - } else { - clearHighlightBoundingRect(); + QList<QGraphicsObject*> objectList; + foreach(QGraphicsItem *item, items) { + QGraphicsItem *child = m_subcomponentEditorTool->firstChildOfContext(item); + if (child) { + QGraphicsObject *childObject = child->toGraphicsObject(); + if (childObject) + objectList << childObject; + } } + + m_boundingRectHighlighter->highlight(objectList); } bool QDeclarativeDesignView::mouseInsideContextItem() const @@ -480,9 +490,9 @@ void QDeclarativeDesignView::onCurrentObjectsChanged(QList<QObject*> objects) } setSelectedItems(items); - clearHighlightBoundingRect(); + clearHighlight(); if (!items.isEmpty()) - highlightBoundingRect(items.first()); + highlight(items); } QToolBar *QDeclarativeDesignView::toolbar() const diff --git a/src/tools/qml/qmlviewer/qdeclarativedesignview.h b/src/tools/qml/qmlviewer/qdeclarativedesignview.h index d51f9041fe148f807b13dfbf7095e98589dc2016..ba2bb552a33d5807ecc23fd53921a310bf5fc146 100644 --- a/src/tools/qml/qmlviewer/qdeclarativedesignview.h +++ b/src/tools/qml/qmlviewer/qdeclarativedesignview.h @@ -35,8 +35,9 @@ public: void changeTool(Constants::DesignTool tool, Constants::ToolFlags flags = Constants::NoToolFlags); - void clearHighlightBoundingRect(); - void highlightBoundingRect(QGraphicsItem *item); + void clearHighlight(); + void highlight(QList<QGraphicsItem *> item); + void highlight(QGraphicsItem *item); bool mouseInsideContextItem() const; bool isEditorItem(QGraphicsItem *item) const;