2be8e6168a89b2b9a995f1d087925228f9f83a4b
[profile/ivi/qtdeclarative.git] / src / plugins / qmltooling / qmldbg_qtquick1 / boundingrecthighlighter.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "boundingrecthighlighter.h"
43
44 #include "qdeclarativeviewinspector.h"
45 #include "qmlinspectorconstants.h"
46
47 #include <QtWidgets/QGraphicsPolygonItem>
48
49 #include <QtCore/QTimer>
50 #include <QtCore/QObject>
51 #include <QtCore/QDebug>
52
53 namespace QmlJSDebugger {
54 namespace QtQuick1 {
55
56 BoundingBox::BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem,
57                          QObject *parent)
58     : QObject(parent),
59       highlightedObject(itemToHighlight),
60       highlightPolygon(0),
61       highlightPolygonEdge(0)
62 {
63     highlightPolygon = new BoundingBoxPolygonItem(parentItem);
64     highlightPolygonEdge = new BoundingBoxPolygonItem(parentItem);
65
66     highlightPolygon->setPen(QPen(QColor(0, 22, 159)));
67     highlightPolygonEdge->setPen(QPen(QColor(158, 199, 255)));
68
69     highlightPolygon->setFlag(QGraphicsItem::ItemIsSelectable, false);
70     highlightPolygonEdge->setFlag(QGraphicsItem::ItemIsSelectable, false);
71 }
72
73 BoundingBox::~BoundingBox()
74 {
75     highlightedObject.clear();
76 }
77
78 BoundingBoxPolygonItem::BoundingBoxPolygonItem(QGraphicsItem *item) : QGraphicsPolygonItem(item)
79 {
80     QPen pen;
81     pen.setColor(QColor(108, 141, 221));
82     pen.setWidth(1);
83     setPen(pen);
84 }
85
86 int BoundingBoxPolygonItem::type() const
87 {
88     return Constants::EditorItemType;
89 }
90
91 BoundingRectHighlighter::BoundingRectHighlighter(QDeclarativeViewInspector *view) :
92     LiveLayerItem(view->declarativeView()->scene()),
93     m_view(view)
94 {
95 }
96
97 BoundingRectHighlighter::~BoundingRectHighlighter()
98 {
99
100 }
101
102 void BoundingRectHighlighter::clear()
103 {
104     foreach (BoundingBox *box, m_boxes)
105         freeBoundingBox(box);
106 }
107
108 BoundingBox *BoundingRectHighlighter::boxFor(QGraphicsObject *item) const
109 {
110     foreach (BoundingBox *box, m_boxes) {
111         if (box->highlightedObject.data() == item)
112             return box;
113     }
114     return 0;
115 }
116
117 void BoundingRectHighlighter::highlight(QList<QGraphicsObject*> items)
118 {
119     if (items.isEmpty())
120         return;
121
122     QList<BoundingBox *> newBoxes;
123     foreach (QGraphicsObject *itemToHighlight, items) {
124         BoundingBox *box = boxFor(itemToHighlight);
125         if (!box)
126             box = createBoundingBox(itemToHighlight);
127
128         newBoxes << box;
129     }
130     qSort(newBoxes);
131
132     if (newBoxes != m_boxes) {
133         clear();
134         m_boxes << newBoxes;
135     }
136
137     highlightAll();
138 }
139
140 void BoundingRectHighlighter::highlight(QGraphicsObject* itemToHighlight)
141 {
142     if (!itemToHighlight)
143         return;
144
145     BoundingBox *box = boxFor(itemToHighlight);
146     if (!box) {
147         box = createBoundingBox(itemToHighlight);
148         m_boxes << box;
149         qSort(m_boxes);
150     }
151
152     highlightAll();
153 }
154
155 BoundingBox *BoundingRectHighlighter::createBoundingBox(QGraphicsObject *itemToHighlight)
156 {
157     if (!m_freeBoxes.isEmpty()) {
158         BoundingBox *box = m_freeBoxes.last();
159         if (box->highlightedObject.isNull()) {
160             box->highlightedObject = itemToHighlight;
161             box->highlightPolygon->show();
162             box->highlightPolygonEdge->show();
163             m_freeBoxes.removeLast();
164             return box;
165         }
166     }
167
168     BoundingBox *box = new BoundingBox(itemToHighlight, this, this);
169
170     connect(itemToHighlight, SIGNAL(xChanged()), this, SLOT(refresh()));
171     connect(itemToHighlight, SIGNAL(yChanged()), this, SLOT(refresh()));
172     connect(itemToHighlight, SIGNAL(widthChanged()), this, SLOT(refresh()));
173     connect(itemToHighlight, SIGNAL(heightChanged()), this, SLOT(refresh()));
174     connect(itemToHighlight, SIGNAL(rotationChanged()), this, SLOT(refresh()));
175     connect(itemToHighlight, SIGNAL(destroyed(QObject*)), this, SLOT(itemDestroyed(QObject*)));
176
177     return box;
178 }
179
180 void BoundingRectHighlighter::removeBoundingBox(BoundingBox *box)
181 {
182     delete box;
183     box = 0;
184 }
185
186 void BoundingRectHighlighter::freeBoundingBox(BoundingBox *box)
187 {
188     if (!box->highlightedObject.isNull()) {
189         disconnect(box->highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh()));
190         disconnect(box->highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh()));
191         disconnect(box->highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh()));
192         disconnect(box->highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh()));
193         disconnect(box->highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh()));
194     }
195
196     box->highlightedObject.clear();
197     box->highlightPolygon->hide();
198     box->highlightPolygonEdge->hide();
199     m_boxes.removeOne(box);
200     m_freeBoxes << box;
201 }
202
203 void BoundingRectHighlighter::itemDestroyed(QObject *obj)
204 {
205     foreach (BoundingBox *box, m_boxes) {
206         if (box->highlightedObject.data() == obj) {
207             freeBoundingBox(box);
208             break;
209         }
210     }
211 }
212
213 void BoundingRectHighlighter::highlightAll()
214 {
215     foreach (BoundingBox *box, m_boxes) {
216         if (box && box->highlightedObject.isNull()) {
217             // clear all highlights
218             clear();
219             return;
220         }
221         QGraphicsObject *item = box->highlightedObject.data();
222
223         QRectF boundingRectInSceneSpace(item->mapToScene(item->boundingRect()).boundingRect());
224         QRectF boundingRectInLayerItemSpace = mapRectFromScene(boundingRectInSceneSpace);
225         QRectF bboxRect = m_view->adjustToScreenBoundaries(boundingRectInLayerItemSpace);
226         QRectF edgeRect = bboxRect;
227         edgeRect.adjust(-1, -1, 1, 1);
228
229         box->highlightPolygon->setPolygon(QPolygonF(bboxRect));
230         box->highlightPolygonEdge->setPolygon(QPolygonF(edgeRect));
231     }
232 }
233
234 void BoundingRectHighlighter::refresh()
235 {
236     if (!m_boxes.isEmpty())
237         highlightAll();
238 }
239
240 } // namespace QtQuick1
241 } // namespace QmlJSDebugger