Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / plugins / qmltooling / qmldbg_qtquick2 / qquickviewinspector.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qquickviewinspector.h"
43
44 #include "qdeclarativeinspectorprotocol.h"
45 #include "highlight.h"
46 #include "selectiontool.h"
47
48 #include <QtQuick/private/qquickitem_p.h>
49
50 #include <QtQuick/QQuickView>
51 #include <QtQuick/QQuickItem>
52
53 #include <cfloat>
54
55 namespace QmlJSDebugger {
56 namespace QtQuick2 {
57
58 /*
59  * Collects all the items at the given position, from top to bottom.
60  */
61 static void collectItemsAt(QQuickItem *item, const QPointF &pos, QQuickItem *overlay,
62                            QList<QQuickItem *> &resultList)
63 {
64     if (item == overlay)
65         return;
66
67     if (item->flags() & QQuickItem::ItemClipsChildrenToShape) {
68         if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
69             return;
70     }
71
72     QList<QQuickItem *> children = QQuickItemPrivate::get(item)->paintOrderChildItems();
73     for (int i = children.count() - 1; i >= 0; --i) {
74         QQuickItem *child = children.at(i);
75         collectItemsAt(child, item->mapToItem(child, pos), overlay, resultList);
76     }
77
78     if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
79         return;
80
81     resultList.append(item);
82 }
83
84 /*
85  * Returns the first visible item at the given position, or 0 when no such
86  * child exists.
87  */
88 static QQuickItem *itemAt(QQuickItem *item, const QPointF &pos, QQuickItem *overlay)
89 {
90     if (item == overlay)
91         return 0;
92
93     if (!item->isVisible() || item->opacity() == 0.0)
94         return 0;
95
96     if (item->flags() & QQuickItem::ItemClipsChildrenToShape) {
97         if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
98             return 0;
99     }
100
101     QList<QQuickItem *> children = QQuickItemPrivate::get(item)->paintOrderChildItems();
102     for (int i = children.count() - 1; i >= 0; --i) {
103         QQuickItem *child = children.at(i);
104         if (QQuickItem *betterCandidate = itemAt(child, item->mapToItem(child, pos), overlay))
105             return betterCandidate;
106     }
107
108     if (!(item->flags() & QQuickItem::ItemHasContents))
109         return 0;
110
111     if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
112         return 0;
113
114     return item;
115 }
116
117
118 QQuickViewInspector::QQuickViewInspector(QQuickView *view, QObject *parent) :
119     AbstractViewInspector(parent),
120     m_view(view),
121     m_overlay(new QQuickItem),
122     m_selectionTool(new SelectionTool(this)),
123     m_designMode(true)
124 {
125     // Try to make sure the overlay is always on top
126     m_overlay->setZ(FLT_MAX);
127
128     if (QQuickItem *root = view->rootItem())
129         m_overlay->setParentItem(root);
130
131     view->installEventFilter(this);
132     setCurrentTool(m_selectionTool);
133 }
134
135 void QQuickViewInspector::changeCurrentObjects(const QList<QObject*> &objects)
136 {
137     QList<QQuickItem*> items;
138     foreach (QObject *obj, objects)
139         if (QQuickItem *item = qobject_cast<QQuickItem*>(obj))
140             items << item;
141
142     syncSelectedItems(items);
143 }
144
145 void QQuickViewInspector::reloadView()
146 {
147     // TODO
148     emit reloadRequested();
149 }
150
151 void QQuickViewInspector::reparentQmlObject(QObject *object, QObject *newParent)
152 {
153     if (!newParent)
154         return;
155
156     object->setParent(newParent);
157     QQuickItem *newParentItem = qobject_cast<QQuickItem*>(newParent);
158     QQuickItem *item = qobject_cast<QQuickItem*>(object);
159     if (newParentItem && item)
160         item->setParentItem(newParentItem);
161 }
162
163 void QQuickViewInspector::changeTool(InspectorProtocol::Tool tool)
164 {
165     switch (tool) {
166     case InspectorProtocol::ColorPickerTool:
167         // TODO
168         emit colorPickerActivated();
169         break;
170     case InspectorProtocol::SelectMarqueeTool:
171         // TODO
172         emit marqueeSelectToolActivated();
173         break;
174     case InspectorProtocol::SelectTool:
175         setCurrentTool(m_selectionTool);
176         emit selectToolActivated();
177         break;
178     case InspectorProtocol::ZoomTool:
179         // TODO
180         emit zoomToolActivated();
181         break;
182     }
183 }
184
185 QWindow *getMasterWindow(QWindow *w)
186 {
187     QWindow *p = w->parent();
188     while (p) {
189         w = p;
190         p = p->parent();
191     }
192     return w;
193 }
194
195 Qt::WindowFlags QQuickViewInspector::windowFlags() const
196 {
197     return getMasterWindow(m_view)->windowFlags();
198 }
199
200 void QQuickViewInspector::setWindowFlags(Qt::WindowFlags flags)
201 {
202     QWindow *w = getMasterWindow(m_view);
203     w->setWindowFlags(flags);
204     // make flags are applied
205     w->setVisible(false);
206     w->setVisible(true);
207 }
208
209 QDeclarativeEngine *QQuickViewInspector::declarativeEngine() const
210 {
211     return m_view->engine();
212 }
213
214 QQuickItem *QQuickViewInspector::topVisibleItemAt(const QPointF &pos) const
215 {
216     QQuickItem *root = m_view->rootItem();
217     return itemAt(root, root->mapFromScene(pos), m_overlay);
218 }
219
220 QList<QQuickItem *> QQuickViewInspector::itemsAt(const QPointF &pos) const
221 {
222     QQuickItem *root = m_view->rootItem();
223     QList<QQuickItem *> resultList;
224     collectItemsAt(root, root->mapFromScene(pos), m_overlay, resultList);
225     return resultList;
226 }
227
228 QList<QQuickItem*> QQuickViewInspector::selectedItems() const
229 {
230     QList<QQuickItem *> selection;
231     foreach (const QWeakPointer<QQuickItem> &selectedItem, m_selectedItems) {
232         if (selectedItem)
233             selection << selectedItem.data();
234     }
235     return selection;
236 }
237
238 void QQuickViewInspector::setSelectedItems(const QList<QQuickItem *> &items)
239 {
240     if (!syncSelectedItems(items))
241         return;
242
243     QList<QObject*> objectList;
244     foreach (QQuickItem *item, items)
245         objectList << item;
246
247     sendCurrentObjects(objectList);
248 }
249
250 bool QQuickViewInspector::syncSelectedItems(const QList<QQuickItem *> &items)
251 {
252     bool selectionChanged = false;
253
254     // Disconnect and remove items that are no longer selected
255     foreach (const QWeakPointer<QQuickItem> &item, m_selectedItems) {
256         if (!item) // Don't see how this can happen due to handling of destroyed()
257             continue;
258         if (items.contains(item.data()))
259             continue;
260
261         selectionChanged = true;
262         item.data()->disconnect(this);
263         m_selectedItems.removeOne(item);
264         delete m_highlightItems.take(item.data());
265     }
266
267     // Connect and add newly selected items
268     foreach (QQuickItem *item, items) {
269         if (m_selectedItems.contains(item))
270             continue;
271
272         selectionChanged = true;
273         connect(item, SIGNAL(destroyed(QObject*)), this, SLOT(removeFromSelectedItems(QObject*)));
274         m_selectedItems.append(item);
275         m_highlightItems.insert(item, new SelectionHighlight(item, m_overlay));
276     }
277
278     return selectionChanged;
279 }
280
281 void QQuickViewInspector::removeFromSelectedItems(QObject *object)
282 {
283     if (QQuickItem *item = qobject_cast<QQuickItem*>(object)) {
284         if (m_selectedItems.removeOne(item))
285             delete m_highlightItems.take(item);
286     }
287 }
288
289 bool QQuickViewInspector::eventFilter(QObject *obj, QEvent *event)
290 {
291     if (obj != m_view)
292         return QObject::eventFilter(obj, event);
293
294     return AbstractViewInspector::eventFilter(obj, event);
295 }
296
297 bool QQuickViewInspector::mouseMoveEvent(QMouseEvent *event)
298 {
299     // TODO
300 //    if (QQuickItem *item = topVisibleItemAt(event->pos()))
301 //        m_view->setToolTip(titleForItem(item));
302 //    else
303 //        m_view->setToolTip(QString());
304
305     return AbstractViewInspector::mouseMoveEvent(event);
306 }
307
308 QString QQuickViewInspector::titleForItem(QQuickItem *item) const
309 {
310     QString className = QLatin1String(item->metaObject()->className());
311     QString objectStringId = idStringForObject(item);
312
313     className.remove(QRegExp(QLatin1String("_QMLTYPE_\\d+")));
314     className.remove(QRegExp(QLatin1String("_QML_\\d+")));
315     if (className.startsWith(QLatin1String("QQuick")))
316         className = className.mid(6);
317
318     QString constructedName;
319
320     if (!objectStringId.isEmpty()) {
321         constructedName = objectStringId + QLatin1String(" (") + className + QLatin1Char(')');
322     } else if (!item->objectName().isEmpty()) {
323         constructedName = item->objectName() + QLatin1String(" (") + className + QLatin1Char(')');
324     } else {
325         constructedName = className;
326     }
327
328     return constructedName;
329 }
330
331 } // namespace QtQuick2
332 } // namespace QmlJSDebugger