018127ddbd0e389a20ea858a3dec0cb15453dec9
[profile/ivi/qtdeclarative.git] / src / plugins / qmltooling / qmldbg_qtquick1 / qdeclarativeviewinspector.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 "qdeclarativeviewinspector.h"
43 #include "qdeclarativeviewinspector_p.h"
44
45 #include "liveselectiontool.h"
46 #include "zoomtool.h"
47 #include "colorpickertool.h"
48 #include "livelayeritem.h"
49 #include "boundingrecthighlighter.h"
50
51 #include <QtQuick1/QDeclarativeItem>
52 #include <QtGui/QMouseEvent>
53
54 namespace QmlJSDebugger {
55 namespace QtQuick1 {
56
57 QDeclarativeViewInspectorPrivate::QDeclarativeViewInspectorPrivate(QDeclarativeViewInspector *q) :
58     q(q)
59 {
60 }
61
62 QDeclarativeViewInspectorPrivate::~QDeclarativeViewInspectorPrivate()
63 {
64 }
65
66 QDeclarativeViewInspector::QDeclarativeViewInspector(QDeclarativeView *view,
67                                                    QObject *parent) :
68     AbstractViewInspector(parent),
69     data(new QDeclarativeViewInspectorPrivate(this))
70 {
71     data->view = view;
72     data->manipulatorLayer = new LiveLayerItem(view->scene());
73     data->selectionTool = new LiveSelectionTool(this);
74     data->zoomTool = new ZoomTool(this);
75     data->colorPickerTool = new ColorPickerTool(this);
76     data->boundingRectHighlighter = new BoundingRectHighlighter(this);
77     setCurrentTool(data->selectionTool);
78
79     // to capture ChildRemoved event when viewport changes
80     data->view->installEventFilter(this);
81
82     data->setViewport(data->view->viewport());
83
84     connect(data->view, SIGNAL(statusChanged(QDeclarativeView::Status)),
85             data.data(), SLOT(_q_onStatusChanged(QDeclarativeView::Status)));
86
87     connect(data->colorPickerTool, SIGNAL(selectedColorChanged(QColor)),
88             SIGNAL(selectedColorChanged(QColor)));
89     connect(data->colorPickerTool, SIGNAL(selectedColorChanged(QColor)),
90             this, SLOT(sendColorChanged(QColor)));
91
92     changeTool(InspectorProtocol::SelectTool);
93 }
94
95 QDeclarativeViewInspector::~QDeclarativeViewInspector()
96 {
97 }
98
99 void QDeclarativeViewInspector::changeCurrentObjects(const QList<QObject*> &objects)
100 {
101     QList<QGraphicsItem*> items;
102     QList<QGraphicsObject*> gfxObjects;
103     foreach (QObject *obj, objects) {
104         if (QDeclarativeItem *declarativeItem = qobject_cast<QDeclarativeItem*>(obj)) {
105             items << declarativeItem;
106             gfxObjects << declarativeItem;
107         }
108     }
109     if (designModeBehavior()) {
110         data->setSelectedItemsForTools(items);
111         data->clearHighlight();
112         data->highlight(gfxObjects);
113     }
114 }
115
116 void QDeclarativeViewInspector::reloadView()
117 {
118     data->clearHighlight();
119     emit reloadRequested();
120 }
121
122 void QDeclarativeViewInspector::changeTool(InspectorProtocol::Tool tool)
123 {
124     switch (tool) {
125     case InspectorProtocol::ColorPickerTool:
126         data->changeToColorPickerTool();
127         break;
128     case InspectorProtocol::SelectMarqueeTool:
129         data->changeToMarqueeSelectTool();
130         break;
131     case InspectorProtocol::SelectTool:
132         data->changeToSingleSelectTool();
133         break;
134     case InspectorProtocol::ZoomTool:
135         data->changeToZoomTool();
136         break;
137     }
138 }
139
140 Qt::WindowFlags QDeclarativeViewInspector::windowFlags() const
141 {
142     return declarativeView()->window()->windowFlags();
143 }
144
145 void QDeclarativeViewInspector::setWindowFlags(Qt::WindowFlags flags)
146 {
147     declarativeView()->window()->setWindowFlags(flags);
148     declarativeView()->window()->show();
149 }
150
151 AbstractLiveEditTool *QDeclarativeViewInspector::currentTool() const
152 {
153     return static_cast<AbstractLiveEditTool*>(AbstractViewInspector::currentTool());
154 }
155
156 QDeclarativeEngine *QDeclarativeViewInspector::declarativeEngine() const
157 {
158     return data->view->engine();
159 }
160
161 void QDeclarativeViewInspectorPrivate::setViewport(QWidget *widget)
162 {
163     if (viewport.data() == widget)
164         return;
165
166     if (viewport)
167         viewport.data()->removeEventFilter(q);
168
169     viewport = widget;
170     if (viewport) {
171         // make sure we get mouse move events
172         viewport.data()->setMouseTracking(true);
173         viewport.data()->installEventFilter(q);
174     }
175 }
176
177 void QDeclarativeViewInspectorPrivate::clearEditorItems()
178 {
179     clearHighlight();
180     setSelectedItems(QList<QGraphicsItem*>());
181 }
182
183 bool QDeclarativeViewInspector::eventFilter(QObject *obj, QEvent *event)
184 {
185     if (obj == data->view) {
186         // Event from view
187         if (event->type() == QEvent::ChildRemoved) {
188             // Might mean that viewport has changed
189             if (data->view->viewport() != data->viewport.data())
190                 data->setViewport(data->view->viewport());
191         }
192         return QObject::eventFilter(obj, event);
193     }
194
195     return AbstractViewInspector::eventFilter(obj, event);
196 }
197
198 bool QDeclarativeViewInspector::leaveEvent(QEvent *event)
199 {
200     data->clearHighlight();
201     return AbstractViewInspector::leaveEvent(event);
202 }
203
204 bool QDeclarativeViewInspector::mouseMoveEvent(QMouseEvent *event)
205 {
206     QList<QGraphicsItem*> selItems = data->selectableItems(event->pos());
207     if (!selItems.isEmpty()) {
208         declarativeView()->setToolTip(currentTool()->titleForItem(selItems.first()));
209     } else {
210         declarativeView()->setToolTip(QString());
211     }
212
213     return AbstractViewInspector::mouseMoveEvent(event);
214 }
215
216 void QDeclarativeViewInspector::reparentQmlObject(QObject *object, QObject *newParent)
217 {
218     if (!newParent)
219         return;
220
221     object->setParent(newParent);
222     QDeclarativeItem *newParentItem = qobject_cast<QDeclarativeItem*>(newParent);
223     QDeclarativeItem *item    = qobject_cast<QDeclarativeItem*>(object);
224     if (newParentItem && item)
225         item->setParentItem(newParentItem);
226 }
227
228 void QDeclarativeViewInspectorPrivate::_q_removeFromSelection(QObject *obj)
229 {
230     QList<QGraphicsItem*> items = selectedItems();
231     if (QGraphicsItem *item = qobject_cast<QGraphicsObject*>(obj))
232         items.removeOne(item);
233     setSelectedItems(items);
234 }
235
236 void QDeclarativeViewInspectorPrivate::setSelectedItemsForTools(const QList<QGraphicsItem *> &items)
237 {
238     foreach (const QWeakPointer<QGraphicsObject> &obj, currentSelection) {
239         if (QGraphicsItem *item = obj.data()) {
240             if (!items.contains(item)) {
241                 QObject::disconnect(obj.data(), SIGNAL(destroyed(QObject*)),
242                                     this, SLOT(_q_removeFromSelection(QObject*)));
243                 currentSelection.removeOne(obj);
244             }
245         }
246     }
247
248     foreach (QGraphicsItem *item, items) {
249         if (QGraphicsObject *obj = item->toGraphicsObject()) {
250             if (!currentSelection.contains(obj)) {
251                 QObject::connect(obj, SIGNAL(destroyed(QObject*)),
252                                  this, SLOT(_q_removeFromSelection(QObject*)));
253                 currentSelection.append(obj);
254             }
255         }
256     }
257
258     q->currentTool()->updateSelectedItems();
259 }
260
261 void QDeclarativeViewInspectorPrivate::setSelectedItems(const QList<QGraphicsItem *> &items)
262 {
263     QList<QWeakPointer<QGraphicsObject> > oldList = currentSelection;
264     setSelectedItemsForTools(items);
265     if (oldList != currentSelection) {
266         QList<QObject*> objectList;
267         foreach (const QWeakPointer<QGraphicsObject> &graphicsObject, currentSelection) {
268             if (graphicsObject)
269                 objectList << graphicsObject.data();
270         }
271
272         q->sendCurrentObjects(objectList);
273     }
274 }
275
276 QList<QGraphicsItem *> QDeclarativeViewInspectorPrivate::selectedItems() const
277 {
278     QList<QGraphicsItem *> selection;
279     foreach (const QWeakPointer<QGraphicsObject> &selectedObject, currentSelection) {
280         if (selectedObject.data())
281             selection << selectedObject.data();
282     }
283
284     return selection;
285 }
286
287 void QDeclarativeViewInspector::setSelectedItems(QList<QGraphicsItem *> items)
288 {
289     data->setSelectedItems(items);
290 }
291
292 QList<QGraphicsItem *> QDeclarativeViewInspector::selectedItems() const
293 {
294     return data->selectedItems();
295 }
296
297 QDeclarativeView *QDeclarativeViewInspector::declarativeView() const
298 {
299     return data->view;
300 }
301
302 void QDeclarativeViewInspectorPrivate::clearHighlight()
303 {
304     boundingRectHighlighter->clear();
305 }
306
307 void QDeclarativeViewInspectorPrivate::highlight(const QList<QGraphicsObject *> &items)
308 {
309     if (items.isEmpty())
310         return;
311
312     QList<QGraphicsObject*> objectList;
313     foreach (QGraphicsItem *item, items) {
314         QGraphicsItem *child = item;
315
316         if (child) {
317             QGraphicsObject *childObject = child->toGraphicsObject();
318             if (childObject)
319                 objectList << childObject;
320         }
321     }
322
323     boundingRectHighlighter->highlight(objectList);
324 }
325
326 QList<QGraphicsItem*> QDeclarativeViewInspectorPrivate::selectableItems(
327     const QPointF &scenePos) const
328 {
329     QList<QGraphicsItem*> itemlist = view->scene()->items(scenePos);
330     return filterForSelection(itemlist);
331 }
332
333 QList<QGraphicsItem*> QDeclarativeViewInspectorPrivate::selectableItems(const QPoint &pos) const
334 {
335     QList<QGraphicsItem*> itemlist = view->items(pos);
336     return filterForSelection(itemlist);
337 }
338
339 QList<QGraphicsItem*> QDeclarativeViewInspectorPrivate::selectableItems(
340     const QRectF &sceneRect, Qt::ItemSelectionMode selectionMode) const
341 {
342     QList<QGraphicsItem*> itemlist = view->scene()->items(sceneRect, selectionMode);
343     return filterForSelection(itemlist);
344 }
345
346 void QDeclarativeViewInspectorPrivate::changeToSingleSelectTool()
347 {
348     selectionTool->setRubberbandSelectionMode(false);
349
350     changeToSelectTool();
351
352     emit q->selectToolActivated();
353     q->sendCurrentTool(Constants::SelectionToolMode);
354 }
355
356 void QDeclarativeViewInspectorPrivate::changeToSelectTool()
357 {
358     if (q->currentTool() == selectionTool)
359         return;
360
361     q->currentTool()->clear();
362     q->setCurrentTool(selectionTool);
363     q->currentTool()->clear();
364     q->currentTool()->updateSelectedItems();
365 }
366
367 void QDeclarativeViewInspectorPrivate::changeToMarqueeSelectTool()
368 {
369     changeToSelectTool();
370     selectionTool->setRubberbandSelectionMode(true);
371
372     emit q->marqueeSelectToolActivated();
373     q->sendCurrentTool(Constants::MarqueeSelectionToolMode);
374 }
375
376 void QDeclarativeViewInspectorPrivate::changeToZoomTool()
377 {
378     q->currentTool()->clear();
379     q->setCurrentTool(zoomTool);
380     q->currentTool()->clear();
381
382     emit q->zoomToolActivated();
383     q->sendCurrentTool(Constants::ZoomMode);
384 }
385
386 void QDeclarativeViewInspectorPrivate::changeToColorPickerTool()
387 {
388     if (q->currentTool() == colorPickerTool)
389         return;
390
391     q->currentTool()->clear();
392     q->setCurrentTool(colorPickerTool);
393     q->currentTool()->clear();
394
395     emit q->colorPickerActivated();
396     q->sendCurrentTool(Constants::ColorPickerMode);
397 }
398
399
400 static bool isEditorItem(QGraphicsItem *item)
401 {
402     return (item->type() == Constants::EditorItemType
403             || item->type() == Constants::ResizeHandleItemType
404             || item->data(Constants::EditorItemDataKey).toBool());
405 }
406
407 QList<QGraphicsItem*> QDeclarativeViewInspectorPrivate::filterForSelection(
408     QList<QGraphicsItem*> &itemlist) const
409 {
410     foreach (QGraphicsItem *item, itemlist) {
411         if (isEditorItem(item))
412             itemlist.removeOne(item);
413     }
414
415     return itemlist;
416 }
417
418 void QDeclarativeViewInspectorPrivate::_q_onStatusChanged(QDeclarativeView::Status status)
419 {
420     if (status == QDeclarativeView::Ready)
421         q->sendReloaded();
422 }
423
424 // adjusts bounding boxes on edges of screen to be visible
425 QRectF QDeclarativeViewInspector::adjustToScreenBoundaries(const QRectF &boundingRectInSceneSpace)
426 {
427     int marginFromEdge = 1;
428     QRectF boundingRect(boundingRectInSceneSpace);
429     if (qAbs(boundingRect.left()) - 1 < 2)
430         boundingRect.setLeft(marginFromEdge);
431
432     QRect rect = data->view->rect();
433
434     if (boundingRect.right() >= rect.right())
435         boundingRect.setRight(rect.right() - marginFromEdge);
436
437     if (qAbs(boundingRect.top()) - 1 < 2)
438         boundingRect.setTop(marginFromEdge);
439
440     if (boundingRect.bottom() >= rect.bottom())
441         boundingRect.setBottom(rect.bottom() - marginFromEdge);
442
443     return boundingRect;
444 }
445
446 } // namespace QtQuick1
447 } // namespace QmlJSDebugger