1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "sgviewinspector.h"
44 #include "qdeclarativeinspectorprotocol.h"
45 #include "sghighlight.h"
46 #include "sgselectiontool.h"
48 #include <QtDeclarative/private/qquickitem_p.h>
50 #include <QtDeclarative/QQuickView>
51 #include <QtDeclarative/QQuickItem>
55 namespace QmlJSDebugger {
58 * Collects all the items at the given position, from top to bottom.
60 static void collectItemsAt(QQuickItem *item, const QPointF &pos, QQuickItem *overlay,
61 QList<QQuickItem *> &resultList)
66 if (item->flags() & QQuickItem::ItemClipsChildrenToShape) {
67 if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
71 QList<QQuickItem *> children = QQuickItemPrivate::get(item)->paintOrderChildItems();
72 for (int i = children.count() - 1; i >= 0; --i) {
73 QQuickItem *child = children.at(i);
74 collectItemsAt(child, item->mapToItem(child, pos), overlay, resultList);
77 if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
80 resultList.append(item);
84 * Returns the first visible item at the given position, or 0 when no such
87 static QQuickItem *itemAt(QQuickItem *item, const QPointF &pos, QQuickItem *overlay)
92 if (!item->isVisible() || item->opacity() == 0.0)
95 if (item->flags() & QQuickItem::ItemClipsChildrenToShape) {
96 if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
100 QList<QQuickItem *> children = QQuickItemPrivate::get(item)->paintOrderChildItems();
101 for (int i = children.count() - 1; i >= 0; --i) {
102 QQuickItem *child = children.at(i);
103 if (QQuickItem *betterCandidate = itemAt(child, item->mapToItem(child, pos), overlay))
104 return betterCandidate;
107 if (!(item->flags() & QQuickItem::ItemHasContents))
110 if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
117 SGViewInspector::SGViewInspector(QQuickView *view, QObject *parent) :
118 AbstractViewInspector(parent),
120 m_overlay(new QQuickItem),
121 m_selectionTool(new SGSelectionTool(this)),
124 // Try to make sure the overlay is always on top
125 m_overlay->setZ(FLT_MAX);
127 if (QQuickItem *root = view->rootItem())
128 m_overlay->setParentItem(root);
130 view->installEventFilter(this);
131 setCurrentTool(m_selectionTool);
134 void SGViewInspector::changeCurrentObjects(const QList<QObject*> &objects)
136 QList<QQuickItem*> items;
137 foreach (QObject *obj, objects)
138 if (QQuickItem *item = qobject_cast<QQuickItem*>(obj))
141 syncSelectedItems(items);
144 void SGViewInspector::reloadView()
147 emit reloadRequested();
150 void SGViewInspector::reparentQmlObject(QObject *object, QObject *newParent)
155 object->setParent(newParent);
156 QQuickItem *newParentItem = qobject_cast<QQuickItem*>(newParent);
157 QQuickItem *item = qobject_cast<QQuickItem*>(object);
158 if (newParentItem && item)
159 item->setParentItem(newParentItem);
162 void SGViewInspector::changeTool(InspectorProtocol::Tool tool)
165 case InspectorProtocol::ColorPickerTool:
167 emit colorPickerActivated();
169 case InspectorProtocol::SelectMarqueeTool:
171 emit marqueeSelectToolActivated();
173 case InspectorProtocol::SelectTool:
174 setCurrentTool(m_selectionTool);
175 emit selectToolActivated();
177 case InspectorProtocol::ZoomTool:
179 emit zoomToolActivated();
184 QWindow *getMasterWindow(QWindow *w)
186 QWindow *p = w->parent();
194 Qt::WindowFlags SGViewInspector::windowFlags() const
196 return getMasterWindow(m_view)->windowFlags();
199 void SGViewInspector::setWindowFlags(Qt::WindowFlags flags)
201 QWindow *w = getMasterWindow(m_view);
202 w->setWindowFlags(flags);
206 QDeclarativeEngine *SGViewInspector::declarativeEngine() const
208 return m_view->engine();
211 QQuickItem *SGViewInspector::topVisibleItemAt(const QPointF &pos) const
213 QQuickItem *root = m_view->rootItem();
214 return itemAt(root, root->mapFromScene(pos), m_overlay);
217 QList<QQuickItem *> SGViewInspector::itemsAt(const QPointF &pos) const
219 QQuickItem *root = m_view->rootItem();
220 QList<QQuickItem *> resultList;
221 collectItemsAt(root, root->mapFromScene(pos), m_overlay, resultList);
225 QList<QQuickItem*> SGViewInspector::selectedItems() const
227 QList<QQuickItem *> selection;
228 foreach (const QWeakPointer<QQuickItem> &selectedItem, m_selectedItems) {
230 selection << selectedItem.data();
235 void SGViewInspector::setSelectedItems(const QList<QQuickItem *> &items)
237 if (!syncSelectedItems(items))
240 QList<QObject*> objectList;
241 foreach (QQuickItem *item, items)
244 sendCurrentObjects(objectList);
247 bool SGViewInspector::syncSelectedItems(const QList<QQuickItem *> &items)
249 bool selectionChanged = false;
251 // Disconnect and remove items that are no longer selected
252 foreach (const QWeakPointer<QQuickItem> &item, m_selectedItems) {
253 if (!item) // Don't see how this can happen due to handling of destroyed()
255 if (items.contains(item.data()))
258 selectionChanged = true;
259 item.data()->disconnect(this);
260 m_selectedItems.removeOne(item);
261 delete m_highlightItems.take(item.data());
264 // Connect and add newly selected items
265 foreach (QQuickItem *item, items) {
266 if (m_selectedItems.contains(item))
269 selectionChanged = true;
270 connect(item, SIGNAL(destroyed(QObject*)), this, SLOT(removeFromSelectedItems(QObject*)));
271 m_selectedItems.append(item);
272 m_highlightItems.insert(item, new SGSelectionHighlight(item, m_overlay));
275 return selectionChanged;
278 void SGViewInspector::removeFromSelectedItems(QObject *object)
280 if (QQuickItem *item = qobject_cast<QQuickItem*>(object)) {
281 if (m_selectedItems.removeOne(item))
282 delete m_highlightItems.take(item);
286 bool SGViewInspector::eventFilter(QObject *obj, QEvent *event)
289 return QObject::eventFilter(obj, event);
291 return AbstractViewInspector::eventFilter(obj, event);
294 bool SGViewInspector::mouseMoveEvent(QMouseEvent *event)
297 // if (QQuickItem *item = topVisibleItemAt(event->pos()))
298 // m_view->setToolTip(titleForItem(item));
300 // m_view->setToolTip(QString());
302 return AbstractViewInspector::mouseMoveEvent(event);
305 QString SGViewInspector::titleForItem(QQuickItem *item) const
307 QString className = QLatin1String(item->metaObject()->className());
308 QString objectStringId = idStringForObject(item);
310 className.remove(QRegExp(QLatin1String("_QMLTYPE_\\d+")));
311 className.remove(QRegExp(QLatin1String("_QML_\\d+")));
312 if (className.startsWith(QLatin1String("QQuick")))
313 className = className.mid(6);
315 QString constructedName;
317 if (!objectStringId.isEmpty()) {
318 constructedName = objectStringId + QLatin1String(" (") + className + QLatin1Char(')');
319 } else if (!item->objectName().isEmpty()) {
320 constructedName = item->objectName() + QLatin1String(" (") + className + QLatin1Char(')');
322 constructedName = className;
325 return constructedName;
328 } // namespace QmlJSDebugger