1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "qquickviewinspector.h"
44 #include "qdeclarativeinspectorprotocol.h"
45 #include "highlight.h"
46 #include "selectiontool.h"
48 #include <QtQuick/private/qquickitem_p.h>
50 #include <QtQuick/QQuickView>
51 #include <QtQuick/QQuickItem>
55 namespace QmlJSDebugger {
59 * Collects all the items at the given position, from top to bottom.
61 static void collectItemsAt(QQuickItem *item, const QPointF &pos, QQuickItem *overlay,
62 QList<QQuickItem *> &resultList)
67 if (item->flags() & QQuickItem::ItemClipsChildrenToShape) {
68 if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
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);
78 if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
81 resultList.append(item);
85 * Returns the first visible item at the given position, or 0 when no such
88 static QQuickItem *itemAt(QQuickItem *item, const QPointF &pos, QQuickItem *overlay)
93 if (!item->isVisible() || item->opacity() == 0.0)
96 if (item->flags() & QQuickItem::ItemClipsChildrenToShape) {
97 if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
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;
108 if (!(item->flags() & QQuickItem::ItemHasContents))
111 if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
118 QQuickViewInspector::QQuickViewInspector(QQuickView *view, QObject *parent) :
119 AbstractViewInspector(parent),
121 m_overlay(new QQuickItem),
122 m_selectionTool(new SelectionTool(this)),
125 // Try to make sure the overlay is always on top
126 m_overlay->setZ(FLT_MAX);
128 if (QQuickItem *root = view->rootItem())
129 m_overlay->setParentItem(root);
131 view->installEventFilter(this);
132 setCurrentTool(m_selectionTool);
135 void QQuickViewInspector::changeCurrentObjects(const QList<QObject*> &objects)
137 QList<QQuickItem*> items;
138 foreach (QObject *obj, objects)
139 if (QQuickItem *item = qobject_cast<QQuickItem*>(obj))
142 syncSelectedItems(items);
145 void QQuickViewInspector::reloadView()
148 emit reloadRequested();
151 void QQuickViewInspector::reparentQmlObject(QObject *object, QObject *newParent)
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);
163 void QQuickViewInspector::changeTool(InspectorProtocol::Tool tool)
166 case InspectorProtocol::ColorPickerTool:
168 emit colorPickerActivated();
170 case InspectorProtocol::SelectMarqueeTool:
172 emit marqueeSelectToolActivated();
174 case InspectorProtocol::SelectTool:
175 setCurrentTool(m_selectionTool);
176 emit selectToolActivated();
178 case InspectorProtocol::ZoomTool:
180 emit zoomToolActivated();
185 QWindow *getMasterWindow(QWindow *w)
187 QWindow *p = w->parent();
195 Qt::WindowFlags QQuickViewInspector::windowFlags() const
197 return getMasterWindow(m_view)->windowFlags();
200 void QQuickViewInspector::setWindowFlags(Qt::WindowFlags flags)
202 QWindow *w = getMasterWindow(m_view);
203 w->setWindowFlags(flags);
204 // make flags are applied
205 w->setVisible(false);
209 QDeclarativeEngine *QQuickViewInspector::declarativeEngine() const
211 return m_view->engine();
214 QQuickItem *QQuickViewInspector::topVisibleItemAt(const QPointF &pos) const
216 QQuickItem *root = m_view->rootItem();
217 return itemAt(root, root->mapFromScene(pos), m_overlay);
220 QList<QQuickItem *> QQuickViewInspector::itemsAt(const QPointF &pos) const
222 QQuickItem *root = m_view->rootItem();
223 QList<QQuickItem *> resultList;
224 collectItemsAt(root, root->mapFromScene(pos), m_overlay, resultList);
228 QList<QQuickItem*> QQuickViewInspector::selectedItems() const
230 QList<QQuickItem *> selection;
231 foreach (const QWeakPointer<QQuickItem> &selectedItem, m_selectedItems) {
233 selection << selectedItem.data();
238 void QQuickViewInspector::setSelectedItems(const QList<QQuickItem *> &items)
240 if (!syncSelectedItems(items))
243 QList<QObject*> objectList;
244 foreach (QQuickItem *item, items)
247 sendCurrentObjects(objectList);
250 bool QQuickViewInspector::syncSelectedItems(const QList<QQuickItem *> &items)
252 bool selectionChanged = false;
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()
258 if (items.contains(item.data()))
261 selectionChanged = true;
262 item.data()->disconnect(this);
263 m_selectedItems.removeOne(item);
264 delete m_highlightItems.take(item.data());
267 // Connect and add newly selected items
268 foreach (QQuickItem *item, items) {
269 if (m_selectedItems.contains(item))
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));
278 return selectionChanged;
281 void QQuickViewInspector::removeFromSelectedItems(QObject *object)
283 if (QQuickItem *item = qobject_cast<QQuickItem*>(object)) {
284 if (m_selectedItems.removeOne(item))
285 delete m_highlightItems.take(item);
289 bool QQuickViewInspector::eventFilter(QObject *obj, QEvent *event)
292 return QObject::eventFilter(obj, event);
294 return AbstractViewInspector::eventFilter(obj, event);
297 bool QQuickViewInspector::mouseMoveEvent(QMouseEvent *event)
300 // if (QQuickItem *item = topVisibleItemAt(event->pos()))
301 // m_view->setToolTip(titleForItem(item));
303 // m_view->setToolTip(QString());
305 return AbstractViewInspector::mouseMoveEvent(event);
308 QString QQuickViewInspector::titleForItem(QQuickItem *item) const
310 QString className = QLatin1String(item->metaObject()->className());
311 QString objectStringId = idStringForObject(item);
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);
318 QString constructedName;
320 if (!objectStringId.isEmpty()) {
321 constructedName = objectStringId + QLatin1String(" (") + className + QLatin1Char(')');
322 } else if (!item->objectName().isEmpty()) {
323 constructedName = item->objectName() + QLatin1String(" (") + className + QLatin1Char(')');
325 constructedName = className;
328 return constructedName;
331 } // namespace QtQuick2
332 } // namespace QmlJSDebugger