aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@theqtcompany.com>2015-11-19 17:14:23 +0100
committerSimon Hausmann <simon.hausmann@theqtcompany.com>2016-01-12 18:00:47 +0000
commit258638f3726f63b308b6275090b1dad596f4fb56 (patch)
treecbbcfe5772a90b8e2dd0cfe493be465f9bc2003f /src/plugins
parent11bd376d1399faff71ff17af9ee10f61b959901b (diff)
Rewrite inspector service
The inspector service had bitrotted to a point where there was little code to be rescued. Apparently it was never really finished and quite some code didn't make any sense. This change removes some features that were unused or didn't work correctly: 1. Panning and Zooming with mouse wheel and touch interaction. This might be useful in some contexts, but the implementation was so broken that it wasn't worth trying to fix it. The whole idea of doing this on the layer of QQuickItems is not so great because there is no distinction between spontaneous changes triggered by the application and debugging interaction triggered from outside. It might be better to implement such functionality on a lower level, e.g. in the renderer. 2. Reloading the scene with debug changes. Use one of the other debug services to change properties. Clearing the component cache is a rather drastic measure and not necessary here. In turn, we get support for inspecting multiple windows, and all subclasses of QQuickWindow are supported now. Also, show-on-top works now. Task-number: QTBUG-33376 Change-Id: I65497f49c6b46128a600b0e3a31483eeef40313c Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/abstracttool.cpp50
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp416
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.h126
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp400
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/globalinspector.h (renamed from src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.h)78
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp277
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/inspecttool.h57
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro14
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp91
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.cpp377
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.cpp226
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.h (renamed from src/plugins/qmltooling/qmldbg_inspector/abstracttool.h)57
12 files changed, 782 insertions, 1387 deletions
diff --git a/src/plugins/qmltooling/qmldbg_inspector/abstracttool.cpp b/src/plugins/qmltooling/qmldbg_inspector/abstracttool.cpp
deleted file mode 100644
index 3e059bed13..0000000000
--- a/src/plugins/qmltooling/qmldbg_inspector/abstracttool.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "abstracttool.h"
-
-#include "abstractviewinspector.h"
-
-QT_BEGIN_NAMESPACE
-
-namespace QmlJSDebugger {
-
-AbstractTool::AbstractTool(AbstractViewInspector *inspector) :
- QObject(inspector),
- m_inspector(inspector)
-{
-}
-
-} // namespace QmlJSDebugger
-
-QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp
deleted file mode 100644
index daf620805f..0000000000
--- a/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp
+++ /dev/null
@@ -1,416 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "abstractviewinspector.h"
-#include "abstracttool.h"
-#include "qqmldebugpacket.h"
-
-#include <QtCore/QDebug>
-#include <QtQml/QQmlEngine>
-#include <QtQml/QQmlComponent>
-#include <QtCore/private/qabstractanimation_p.h>
-#include <QtQml/private/qqmldebugconnector_p.h>
-#include <QtQml/private/qqmlcontext_p.h>
-
-#include <QtGui/QMouseEvent>
-#include <QtGui/QTouchEvent>
-
-//INSPECTOR SERVICE PROTOCOL
-// <HEADER><COMMAND><DATA>
-// <HEADER> : <type{request, response, event}><requestId/eventId>[<response_success_bool>]
-// <COMMAND> : {"enable", "disable", "select", "reload", "setAnimationSpeed",
-// "showAppOnTop", "createObject", "destroyObject", "moveObject",
-// "clearCache"}
-// <DATA> : select: <debugIds_int_list>
-// reload: <hash<changed_filename_string, filecontents_bytearray>>
-// setAnimationSpeed: <speed_real>
-// showAppOnTop: <set_bool>
-// createObject: <qml_string><parentId_int><imports_string_list><filename_string>
-// destroyObject: <debugId_int>
-// moveObject: <debugId_int><newParentId_int>
-// clearCache: void
-// Response for "destroyObject" carries the <debugId_int> of the destroyed object.
-
-QT_BEGIN_NAMESPACE
-
-const char REQUEST[] = "request";
-const char RESPONSE[] = "response";
-const char EVENT[] = "event";
-const char ENABLE[] = "enable";
-const char DISABLE[] = "disable";
-const char SELECT[] = "select";
-const char RELOAD[] = "reload";
-const char SET_ANIMATION_SPEED[] = "setAnimationSpeed";
-const char SHOW_APP_ON_TOP[] = "showAppOnTop";
-const char CREATE_OBJECT[] = "createObject";
-const char DESTROY_OBJECT[] = "destroyObject";
-const char MOVE_OBJECT[] = "moveObject";
-const char CLEAR_CACHE[] = "clearCache";
-
-namespace QmlJSDebugger {
-
-
-AbstractViewInspector::AbstractViewInspector(QQmlDebugService *service, QObject *parent) :
- QObject(parent),
- m_enabled(false),
- m_debugService(service),
- m_eventId(0),
- m_reloadEventId(-1)
-{
-}
-
-void AbstractViewInspector::createQmlObject(const QString &qml, QObject *parent,
- const QStringList &importList,
- const QString &filename)
-{
- if (!parent)
- return;
-
- QString imports;
- foreach (const QString &s, importList) {
- imports += s;
- imports += QLatin1Char('\n');
- }
-
- QQmlContext *parentContext = declarativeEngine()->contextForObject(parent);
- QQmlComponent component(declarativeEngine());
- QByteArray constructedQml = QString(imports + qml).toLatin1();
-
- component.setData(constructedQml, QUrl::fromLocalFile(filename));
- QObject *newObject = component.create(parentContext);
- if (newObject)
- reparentQmlObject(newObject, parent);
-}
-
-void AbstractViewInspector::clearComponentCache()
-{
- declarativeEngine()->clearComponentCache();
-}
-
-void AbstractViewInspector::setEnabled(bool value)
-{
- if (m_enabled == value)
- return;
-
- m_enabled = value;
- foreach (AbstractTool *tool, m_tools)
- tool->enable(m_enabled);
-}
-
-void AbstractViewInspector::setAnimationSpeed(qreal slowDownFactor)
-{
- QUnifiedTimer::instance()->setSlowModeEnabled(slowDownFactor != 1.0);
- QUnifiedTimer::instance()->setSlowdownFactor(slowDownFactor);
-}
-
-bool AbstractViewInspector::eventFilter(QObject *obj, QEvent *event)
-{
- if (!enabled())
- return QObject::eventFilter(obj, event);
-
- switch (event->type()) {
- case QEvent::Leave:
- if (leaveEvent(event))
- return true;
- break;
- case QEvent::MouseButtonPress:
- if (mousePressEvent(static_cast<QMouseEvent*>(event)))
- return true;
- break;
- case QEvent::MouseMove:
- if (mouseMoveEvent(static_cast<QMouseEvent*>(event)))
- return true;
- break;
- case QEvent::MouseButtonRelease:
- if (mouseReleaseEvent(static_cast<QMouseEvent*>(event)))
- return true;
- break;
- case QEvent::KeyPress:
- if (keyPressEvent(static_cast<QKeyEvent*>(event)))
- return true;
- break;
- case QEvent::KeyRelease:
- if (keyReleaseEvent(static_cast<QKeyEvent*>(event)))
- return true;
- break;
- case QEvent::MouseButtonDblClick:
- if (mouseDoubleClickEvent(static_cast<QMouseEvent*>(event)))
- return true;
- break;
-#ifndef QT_NO_WHEELEVENT
- case QEvent::Wheel:
- if (wheelEvent(static_cast<QWheelEvent*>(event)))
- return true;
- break;
-#endif
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate:
- case QEvent::TouchEnd:
- if (touchEvent(static_cast<QTouchEvent*>(event)))
- return true;
- break;
- default:
- break;
- }
-
- return QObject::eventFilter(obj, event);
-}
-
-bool AbstractViewInspector::leaveEvent(QEvent *event)
-{
- foreach (AbstractTool *tool, m_tools)
- tool->leaveEvent(event);
- return true;
-}
-
-bool AbstractViewInspector::mousePressEvent(QMouseEvent *event)
-{
- foreach (AbstractTool *tool, m_tools)
- tool->mousePressEvent(event);
- return true;
-}
-
-bool AbstractViewInspector::mouseMoveEvent(QMouseEvent *event)
-{
- if (event->buttons()) {
- foreach (AbstractTool *tool, m_tools)
- tool->mouseMoveEvent(event);
- } else {
- foreach (AbstractTool *tool, m_tools)
- tool->hoverMoveEvent(event);
- }
- return true;
-}
-
-bool AbstractViewInspector::mouseReleaseEvent(QMouseEvent *event)
-{
- foreach (AbstractTool *tool, m_tools)
- tool->mouseReleaseEvent(event);
- return true;
-}
-
-bool AbstractViewInspector::keyPressEvent(QKeyEvent *event)
-{
- foreach (AbstractTool *tool, m_tools)
- tool->keyPressEvent(event);
- return true;
-}
-
-bool AbstractViewInspector::keyReleaseEvent(QKeyEvent *event)
-{
- foreach (AbstractTool *tool, m_tools)
- tool->keyReleaseEvent(event);
- return true;
-}
-
-bool AbstractViewInspector::mouseDoubleClickEvent(QMouseEvent *event)
-{
- foreach (AbstractTool *tool, m_tools)
- tool->mouseDoubleClickEvent(event);
- return true;
-}
-
-#ifndef QT_NO_WHEELEVENT
-bool AbstractViewInspector::wheelEvent(QWheelEvent *event)
-{
- foreach (AbstractTool *tool, m_tools)
- tool->wheelEvent(event);
- return true;
-}
-#endif
-
-bool AbstractViewInspector::touchEvent(QTouchEvent *event)
-{
- foreach (AbstractTool *tool, m_tools)
- tool->touchEvent(event);
- return true;
-}
-
-void AbstractViewInspector::onQmlObjectDestroyed(QObject *object)
-{
- if (!m_hashObjectsTobeDestroyed.contains(object))
- return;
-
- QPair<int, int> ids = m_hashObjectsTobeDestroyed.take(object);
-
- QQmlDebugPacket rs;
- rs << QByteArray(RESPONSE) << ids.first << true << ids.second;
-
- emit m_debugService->messageToClient(m_debugService->name(), rs.data());
-}
-
-void AbstractViewInspector::handleMessage(const QByteArray &message)
-{
- bool success = true;
- QQmlDebugPacket ds(message);
-
- QByteArray type;
- ds >> type;
-
- int requestId = -1;
- if (type == REQUEST) {
- QByteArray command;
- ds >> requestId >> command;
-
- if (command == ENABLE) {
- setEnabled(true);
-
- } else if (command == DISABLE) {
- setEnabled(false);
-
- } else if (command == SELECT) {
- QList<int> debugIds;
- ds >> debugIds;
-
- QList<QObject*> selectedObjects;
- foreach (int debugId, debugIds) {
- if (QObject *obj = QQmlDebugService::objectForId(debugId))
- selectedObjects << obj;
- }
- if (m_enabled)
- changeCurrentObjects(selectedObjects);
-
- } else if (command == RELOAD) {
- QHash<QString, QByteArray> changesHash;
- ds >> changesHash;
- m_reloadEventId = requestId;
- reloadQmlFile(changesHash);
- return;
-
- } else if (command == SET_ANIMATION_SPEED) {
- qreal speed;
- ds >> speed;
- setAnimationSpeed(speed);
-
- } else if (command == SHOW_APP_ON_TOP) {
- bool showOnTop;
- ds >> showOnTop;
- setShowAppOnTop(showOnTop);
-
- } else if (command == CREATE_OBJECT) {
- QString qml;
- int parentId;
- QString filename;
- QStringList imports;
- ds >> qml >> parentId >> imports >> filename;
- createQmlObject(qml, QQmlDebugService::objectForId(parentId),
- imports, filename);
-
- } else if (command == DESTROY_OBJECT) {
- int debugId;
- ds >> debugId;
- if (QObject *obj = QQmlDebugService::objectForId(debugId)) {
- QPair<int, int> ids(requestId, debugId);
- m_hashObjectsTobeDestroyed.insert(obj, ids);
- connect(obj, SIGNAL(destroyed(QObject*)), SLOT(onQmlObjectDestroyed(QObject*)));
- obj->deleteLater();
- }
- return;
-
- } else if (command == MOVE_OBJECT) {
- int debugId, newParent;
- ds >> debugId >> newParent;
- reparentQmlObject(QQmlDebugService::objectForId(debugId),
- QQmlDebugService::objectForId(newParent));
-
- } else if (command == CLEAR_CACHE) {
- clearComponentCache();
-
- } else {
- qWarning() << "Warning: Not handling command:" << command;
- success = false;
-
- }
- } else {
- qWarning() << "Warning: Not handling type:" << type << REQUEST;
- success = false;
-
- }
-
- QQmlDebugPacket rs;
- rs << QByteArray(RESPONSE) << requestId << success;
- emit m_debugService->messageToClient(m_debugService->name(), rs.data());
-}
-
-void AbstractViewInspector::sendCurrentObjects(const QList<QObject*> &objects)
-{
- QQmlDebugPacket ds;
-
- ds << QByteArray(EVENT) << m_eventId++ << QByteArray(SELECT);
-
- QList<int> debugIds;
- debugIds.reserve(objects.count());
- foreach (QObject *object, objects)
- debugIds << QQmlDebugService::idForObject(object);
- ds << debugIds;
-
- emit m_debugService->messageToClient(m_debugService->name(), ds.data());
-}
-
-void AbstractViewInspector::sendQmlFileReloaded(bool success)
-{
- if (m_reloadEventId == -1)
- return;
-
- QByteArray response;
-
- QQmlDebugPacket rs;
- rs << QByteArray(RESPONSE) << m_reloadEventId << success;
-
- emit m_debugService->messageToClient(m_debugService->name(), rs.data());
-}
-
-QString AbstractViewInspector::idStringForObject(QObject *obj) const
-{
- QQmlContext *context = qmlContext(obj);
- if (context) {
- QQmlContextData *cdata = QQmlContextData::get(context);
- if (cdata)
- return cdata->findObjectId(obj);
- }
- return QString();
-}
-
-void AbstractViewInspector::appendTool(AbstractTool *tool)
-{
- m_tools.append(tool);
-}
-
-void AbstractViewInspector::removeTool(AbstractTool *tool)
-{
- m_tools.removeOne(tool);
-}
-
-} // namespace QmlJSDebugger
-
-QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.h b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.h
deleted file mode 100644
index 8f7ad4ac5b..0000000000
--- a/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef ABSTRACTVIEWINSPECTOR_H
-#define ABSTRACTVIEWINSPECTOR_H
-
-#include <QtCore/QHash>
-#include <QtCore/QObject>
-#include <QtCore/QStringList>
-
-QT_BEGIN_NAMESPACE
-class QQmlEngine;
-class QQmlDebugService;
-class QKeyEvent;
-class QMouseEvent;
-class QWheelEvent;
-class QTouchEvent;
-
-namespace QmlJSDebugger {
-
-class AbstractTool;
-
-/*
- * The common code between QQuickView and QQuickView inspectors lives here,
- */
-class AbstractViewInspector : public QObject
-{
- Q_OBJECT
-
-public:
- explicit AbstractViewInspector(QQmlDebugService *service, QObject *parent = 0);
-
- void handleMessage(const QByteArray &message);
-
- void createQmlObject(const QString &qml, QObject *parent,
- const QStringList &importList,
- const QString &filename = QString());
- void clearComponentCache();
-
- bool enabled() const { return m_enabled; }
-
- void sendCurrentObjects(const QList<QObject*> &);
-
- void sendQmlFileReloaded(bool success);
-
- QString idStringForObject(QObject *obj) const;
-
- virtual void changeCurrentObjects(const QList<QObject*> &objects) = 0;
- virtual void reparentQmlObject(QObject *object, QObject *newParent) = 0;
- virtual Qt::WindowFlags windowFlags() const = 0;
- virtual void setWindowFlags(Qt::WindowFlags flags) = 0;
- virtual QQmlEngine *declarativeEngine() const = 0;
- virtual void reloadQmlFile(const QHash<QString, QByteArray> &changesHash) = 0;
-
- void appendTool(AbstractTool *tool);
- void removeTool(AbstractTool *tool);
-
-protected:
- bool eventFilter(QObject *, QEvent *);
-
- virtual bool leaveEvent(QEvent *);
- virtual bool mousePressEvent(QMouseEvent *event);
- virtual bool mouseMoveEvent(QMouseEvent *event);
- virtual bool mouseReleaseEvent(QMouseEvent *event);
- virtual bool keyPressEvent(QKeyEvent *event);
- virtual bool keyReleaseEvent(QKeyEvent *keyEvent);
- virtual bool mouseDoubleClickEvent(QMouseEvent *event);
-#ifndef QT_NO_WHEELEVENT
- virtual bool wheelEvent(QWheelEvent *event);
-#endif
- virtual bool touchEvent(QTouchEvent *event);
- virtual void setShowAppOnTop(bool) = 0;
-
-private slots:
- void onQmlObjectDestroyed(QObject *object);
-
-private:
- void setEnabled(bool value);
-
- void setAnimationSpeed(qreal factor);
-
- bool m_enabled;
-
- QQmlDebugService *m_debugService;
- QList<AbstractTool *> m_tools;
- int m_eventId;
- int m_reloadEventId;
- // Hash< object to be destroyed, QPair<destroy eventId, object debugId> >
- QHash<QObject *, QPair<int, int> > m_hashObjectsTobeDestroyed;
-};
-
-} // namespace QmlJSDebugger
-
-QT_END_NAMESPACE
-
-#endif // ABSTRACTVIEWINSPECTOR_H
diff --git a/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp
new file mode 100644
index 0000000000..9ef16911bc
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp
@@ -0,0 +1,400 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "globalinspector.h"
+#include "highlight.h"
+#include "inspecttool.h"
+#include "qqmldebugpacket.h"
+
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qabstractanimation_p.h>
+#include <private/qqmlcomponent_p.h>
+
+#include <QtGui/qwindow.h>
+
+//INSPECTOR SERVICE PROTOCOL
+// <HEADER><COMMAND><DATA>
+// <HEADER> : <type{request, response, event}><requestId/eventId>[<response_success_bool>]
+// <COMMAND> : {"enable", "disable", "select", "setAnimationSpeed",
+// "showAppOnTop", "createObject", "destroyObject", "moveObject"}
+// <DATA> : select: <debugIds_int_list>
+// setAnimationSpeed: <speed_real>
+// showAppOnTop: <set_bool>
+// createObject: <qml_string><parentId_int><imports_string_list><filename_string>
+// destroyObject: <debugId_int>
+// moveObject: <debugId_int><newParentId_int>
+// Response for "destroyObject" carries the <debugId_int> of the destroyed object.
+
+QT_BEGIN_NAMESPACE
+
+const char REQUEST[] = "request";
+const char RESPONSE[] = "response";
+const char EVENT[] = "event";
+const char ENABLE[] = "enable";
+const char DISABLE[] = "disable";
+const char SELECT[] = "select";
+const char SET_ANIMATION_SPEED[] = "setAnimationSpeed";
+const char SHOW_APP_ON_TOP[] = "showAppOnTop";
+const char CREATE_OBJECT[] = "createObject";
+const char DESTROY_OBJECT[] = "destroyObject";
+const char MOVE_OBJECT[] = "moveObject";
+
+namespace QmlJSDebugger {
+
+void GlobalInspector::removeFromSelectedItems(QObject *object)
+{
+ if (QQuickItem *item = qobject_cast<QQuickItem*>(object)) {
+ if (m_selectedItems.removeOne(item))
+ delete m_highlightItems.take(item);
+ }
+}
+
+void GlobalInspector::setSelectedItems(const QList<QQuickItem *> &items)
+{
+ if (!syncSelectedItems(items))
+ return;
+
+ QList<QObject*> objectList;
+ objectList.reserve(items.count());
+ foreach (QQuickItem *item, items)
+ objectList << item;
+
+ sendCurrentObjects(objectList);
+}
+
+void GlobalInspector::showSelectedItemName(QQuickItem *item, const QPointF &point)
+{
+ SelectionHighlight *highlightItem = m_highlightItems.value(item, 0);
+ if (highlightItem)
+ highlightItem->showName(point);
+}
+
+void GlobalInspector::sendCurrentObjects(const QList<QObject*> &objects)
+{
+ QQmlDebugPacket ds;
+
+ ds << QByteArray(EVENT) << m_eventId++ << QByteArray(SELECT);
+
+ QList<int> debugIds;
+ debugIds.reserve(objects.count());
+ foreach (QObject *object, objects)
+ debugIds << QQmlDebugService::idForObject(object);
+ ds << debugIds;
+
+ emit messageToClient(QQmlInspectorService::s_key, ds.data());
+}
+
+static bool reparentQmlObject(QObject *object, QObject *newParent)
+{
+ if (!newParent)
+ return false;
+
+ object->setParent(newParent);
+ QQuickItem *newParentItem = qobject_cast<QQuickItem*>(newParent);
+ QQuickItem *item = qobject_cast<QQuickItem*>(object);
+ if (newParentItem && item)
+ item->setParentItem(newParentItem);
+ return true;
+}
+
+class ObjectCreator : public QObject
+{
+ Q_OBJECT
+public:
+ ObjectCreator(int requestId, QQmlEngine *engine, QObject *parent) :
+ QObject(parent), m_component(engine), m_requestId(requestId)
+ {
+ connect(&m_component, &QQmlComponent::statusChanged, this, &ObjectCreator::tryCreateObject);
+ }
+
+ void run(const QByteArray &qml, const QUrl &filename)
+ {
+ m_component.setData(qml, filename);
+ }
+
+signals:
+ void result(int requestId, bool success);
+
+public slots:
+ void tryCreateObject(QQmlComponent::Status status)
+ {
+ switch (status) {
+ case QQmlComponent::Error:
+ emit result(m_requestId, false);
+ delete this;
+ return;
+ case QQmlComponent::Ready: {
+ // Stuff might have changed. We have to lookup the parentContext again.
+ QQmlContext *parentContext = QQmlEngine::contextForObject(parent());
+ if (!parentContext) {
+ emit result(m_requestId, false);
+ } else {
+ QObject *newObject = m_component.create(parentContext);
+ if (newObject && reparentQmlObject(newObject, parent()))
+ emit result(m_requestId, true);
+ else
+ emit result(m_requestId, false);
+ }
+ delete this;
+ return;
+ }
+ default:
+ break;
+ }
+ }
+
+private:
+ QQmlComponent m_component;
+ int m_requestId;
+};
+
+bool GlobalInspector::createQmlObject(int requestId, const QString &qml, QObject *parent,
+ const QStringList &importList, const QString &filename)
+{
+ if (!parent)
+ return false;
+
+ QQmlContext *parentContext = QQmlEngine::contextForObject(parent);
+ if (!parentContext)
+ return false;
+
+ QString imports;
+ foreach (const QString &s, importList)
+ imports += s + QLatin1Char('\n');
+
+ ObjectCreator *objectCreator = new ObjectCreator(requestId, parentContext->engine(), parent);
+ connect(objectCreator, &ObjectCreator::result, this, &GlobalInspector::sendResult);
+ objectCreator->run((imports + qml).toUtf8(), QUrl::fromLocalFile(filename));
+ return true;
+}
+
+void GlobalInspector::addWindow(QQuickWindow *window)
+{
+ m_windowInspectors.append(new QQuickWindowInspector(window, this));
+}
+
+void GlobalInspector::removeWindow(QQuickWindow *window)
+{
+ for (QList<QmlJSDebugger::QQuickWindowInspector *>::Iterator i = m_windowInspectors.begin();
+ i != m_windowInspectors.end();) {
+ if ((*i)->quickWindow() == window) {
+ delete *i;
+ i = m_windowInspectors.erase(i);
+ } else {
+ ++i;
+ }
+ }
+}
+
+void GlobalInspector::setParentWindow(QQuickWindow *window, QWindow *parentWindow)
+{
+ foreach (QmlJSDebugger::QQuickWindowInspector *inspector, m_windowInspectors) {
+ if (inspector->quickWindow() == window)
+ inspector->setParentWindow(parentWindow);
+ }
+}
+
+bool GlobalInspector::syncSelectedItems(const QList<QQuickItem *> &items)
+{
+ bool selectionChanged = false;
+
+ // Disconnect and remove items that are no longer selected
+ foreach (const QPointer<QQuickItem> &item, m_selectedItems) {
+ if (!item) // Don't see how this can happen due to handling of destroyed()
+ continue;
+ if (items.contains(item))
+ continue;
+
+ selectionChanged = true;
+ item->disconnect(this);
+ m_selectedItems.removeOne(item);
+ delete m_highlightItems.take(item);
+ }
+
+ // Connect and add newly selected items
+ foreach (QQuickItem *item, items) {
+ if (m_selectedItems.contains(item))
+ continue;
+
+ selectionChanged = true;
+ connect(item, &QObject::destroyed, this, &GlobalInspector::removeFromSelectedItems);
+ m_selectedItems.append(item);
+ foreach (QQuickWindowInspector *inspector, m_windowInspectors) {
+ if (inspector->isEnabled() && inspector->quickWindow() == item->window()) {
+ m_highlightItems.insert(item, new SelectionHighlight(titleForItem(item), item,
+ inspector->overlay()));
+ break;
+ }
+ }
+ }
+
+ return selectionChanged;
+}
+
+QString GlobalInspector::titleForItem(QQuickItem *item) const
+{
+ QString className = QLatin1String(item->metaObject()->className());
+ QString objectStringId = idStringForObject(item);
+
+ className.remove(QRegExp(QLatin1String("_QMLTYPE_\\d+")));
+ className.remove(QRegExp(QLatin1String("_QML_\\d+")));
+ if (className.startsWith(QLatin1String("QQuick")))
+ className = className.mid(6);
+
+ QString constructedName;
+
+ if (!objectStringId.isEmpty()) {
+ constructedName = objectStringId + QLatin1String(" (") + className + QLatin1Char(')');
+ } else if (!item->objectName().isEmpty()) {
+ constructedName = item->objectName() + QLatin1String(" (") + className + QLatin1Char(')');
+ } else {
+ constructedName = className;
+ }
+
+ return constructedName;
+}
+
+QString GlobalInspector::idStringForObject(QObject *obj) const
+{
+ QQmlContext *context = qmlContext(obj);
+ if (context) {
+ QQmlContextData *cdata = QQmlContextData::get(context);
+ if (cdata)
+ return cdata->findObjectId(obj);
+ }
+ return QString();
+}
+
+void GlobalInspector::processMessage(const QByteArray &message)
+{
+ bool success = true;
+ QQmlDebugPacket ds(message);
+
+ QByteArray type;
+ ds >> type;
+
+ int requestId = -1;
+ if (type == REQUEST) {
+ QByteArray command;
+ ds >> requestId >> command;
+
+ if (command == ENABLE) {
+ foreach (QQuickWindowInspector *inspector, m_windowInspectors)
+ inspector->setEnabled(true);
+ success = !m_windowInspectors.isEmpty();
+ } else if (command == DISABLE) {
+ setSelectedItems(QList<QQuickItem*>());
+ foreach (QQuickWindowInspector *inspector, m_windowInspectors)
+ inspector->setEnabled(false);
+ success = !m_windowInspectors.isEmpty();
+ } else if (command == SELECT) {
+ QList<int> debugIds;
+ ds >> debugIds;
+
+ QList<QQuickItem *> selectedObjects;
+ foreach (int debugId, debugIds) {
+ if (QQuickItem *obj =
+ qobject_cast<QQuickItem *>(QQmlDebugService::objectForId(debugId)))
+ selectedObjects << obj;
+ }
+ syncSelectedItems(selectedObjects);
+ } else if (command == SET_ANIMATION_SPEED) {
+ qreal speed;
+ ds >> speed;
+ QUnifiedTimer::instance()->setSlowModeEnabled(speed != 1.0);
+ QUnifiedTimer::instance()->setSlowdownFactor(speed);
+ } else if (command == SHOW_APP_ON_TOP) {
+ bool showOnTop;
+ ds >> showOnTop;
+ foreach (QmlJSDebugger::QQuickWindowInspector *inspector, m_windowInspectors)
+ inspector->setShowAppOnTop(showOnTop);
+ success = !m_windowInspectors.isEmpty();
+ } else if (command == CREATE_OBJECT) {
+ QString qml;
+ int parentId;
+ QString filename;
+ QStringList imports;
+ ds >> qml >> parentId >> imports >> filename;
+ if (QObject *parent = QQmlDebugService::objectForId(parentId)) {
+ if (createQmlObject(requestId, qml, parent, imports, filename))
+ return; // will callback for result
+ else {
+ success = false;
+ }
+ } else {
+ success = false;
+ }
+
+ } else if (command == DESTROY_OBJECT) {
+ int debugId;
+ ds >> debugId;
+ if (QObject *obj = QQmlDebugService::objectForId(debugId))
+ delete obj;
+ else
+ success = false;
+
+ } else if (command == MOVE_OBJECT) {
+ int debugId, newParent;
+ ds >> debugId >> newParent;
+ success = reparentQmlObject(QQmlDebugService::objectForId(debugId),
+ QQmlDebugService::objectForId(newParent));
+ } else {
+ qWarning() << "Warning: Not handling command:" << command;
+ success = false;
+ }
+ } else {
+ qWarning() << "Warning: Not handling type:" << type << REQUEST;
+ success = false;
+ }
+
+ sendResult(requestId, success);
+}
+
+void GlobalInspector::sendResult(int requestId, bool success)
+{
+ QQmlDebugPacket rs;
+ rs << QByteArray(RESPONSE) << requestId << success;
+ emit messageToClient(QQmlInspectorService::s_key, rs.data());
+}
+
+GlobalInspector::~GlobalInspector()
+{
+ // Everything else is parented
+ qDeleteAll(m_highlightItems);
+}
+
+}
+
+QT_END_NAMESPACE
+
+#include <globalinspector.moc>
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.h b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.h
index e823e5a03d..8c4e07527d 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.h
@@ -31,79 +31,63 @@
**
****************************************************************************/
-#ifndef QQUICKVIEWINSPECTOR_H
-#define QQUICKVIEWINSPECTOR_H
+#ifndef GLOBALINSPECTOR_H
+#define GLOBALINSPECTOR_H
-#include "abstractviewinspector.h"
+#include "qquickwindowinspector.h"
+#include <QtCore/QObject>
#include <QtCore/QPointer>
#include <QtCore/QHash>
-#include <QtQuick/QQuickView>
+#include <QtQuick/QQuickItem>
QT_BEGIN_NAMESPACE
-class QQuickView;
-class QQuickItem;
namespace QmlJSDebugger {
-class InspectTool;
class SelectionHighlight;
-class QQuickViewInspector : public AbstractViewInspector
+class GlobalInspector : public QObject
{
Q_OBJECT
public:
- explicit QQuickViewInspector(QQmlDebugService *service, QQuickView *view, QObject *parent = 0);
+ GlobalInspector(QObject *parent = 0) : QObject(parent), m_eventId(0) {}
+ ~GlobalInspector();
- // AbstractViewInspector
- void changeCurrentObjects(const QList<QObject*> &objects);
- void reparentQmlObject(QObject *object, QObject *newParent);
- Qt::WindowFlags windowFlags() const;
- void setWindowFlags(Qt::WindowFlags flags);
- QQmlEngine *declarativeEngine() const;
-
- QQuickView *view() const { return m_view; }
- QQuickItem *overlay() const { return m_overlay; }
-
- QQuickItem *topVisibleItemAt(const QPointF &pos) const;
- QList<QQuickItem *> itemsAt(const QPointF &pos) const;
-
- QList<QQuickItem *> selectedItems() const;
- void setSelectedItems(const QList<QQuickItem*> &items);
-
- QString titleForItem(QQuickItem *item) const;
+ void setSelectedItems(const QList<QQuickItem *> &items);
void showSelectedItemName(QQuickItem *item, const QPointF &point);
- void reloadQmlFile(const QHash<QString, QByteArray> &changesHash);
+ void addWindow(QQuickWindow *window);
+ void setParentWindow(QQuickWindow *window, QWindow *parentWindow);
+ void setQmlEngine(QQuickWindow *window, QQmlEngine *engine);
+ void removeWindow(QQuickWindow *window);
+ void processMessage(const QByteArray &message);
-protected:
- bool eventFilter(QObject *obj, QEvent *event);
-
- bool mouseMoveEvent(QMouseEvent *);
-
- void setShowAppOnTop(bool appOnTop);
+signals:
+ void messageToClient(const QString &name, const QByteArray &data);
private slots:
- void removeFromSelectedItems(QObject *);
- void onViewStatus(QQuickView::Status status);
- void applyAppOnTop();
+ void sendResult(int requestId, bool success);
private:
- bool syncSelectedItems(const QList<QQuickItem*> &items);
-
- QQuickView *m_view;
- QQuickItem *m_overlay;
-
- InspectTool *m_inspectTool;
+ void sendCurrentObjects(const QList<QObject *> &objects);
+ void removeFromSelectedItems(QObject *object);
+ QString titleForItem(QQuickItem *item) const;
+ QString idStringForObject(QObject *obj) const;
+ bool createQmlObject(int requestId, const QString &qml, QObject *parent,
+ const QStringList &importList, const QString &filename);
+ bool destroyQmlObject(QObject *object, int requestId, int debugId);
+ bool syncSelectedItems(const QList<QQuickItem *> &items);
+ // Hash< object to be destroyed, QPair<destroy eventId, object debugId> >
QList<QPointer<QQuickItem> > m_selectedItems;
- QHash<QQuickItem*, SelectionHighlight*> m_highlightItems;
- bool m_sendQmlReloadedMessage;
- bool m_appOnTop;
+ QHash<QQuickItem *, SelectionHighlight *> m_highlightItems;
+ QList<QQuickWindowInspector *> m_windowInspectors;
+ int m_eventId;
};
-} // namespace QmlJSDebugger
+} // QmlJSDebugger
QT_END_NAMESPACE
-#endif // QQUICKVIEWINSPECTOR_H
+#endif // GLOBALINSPECTOR_H
diff --git a/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp
index 0e12f29869..59fd911db8 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp
@@ -32,14 +32,13 @@
****************************************************************************/
#include "inspecttool.h"
-
#include "highlight.h"
-#include "qquickviewinspector.h"
+#include "qquickwindowinspector.h"
+#include "globalinspector.h"
#include <QtCore/QLineF>
#include <QtGui/QMouseEvent>
-#include <QtGui/QWheelEvent>
#include <QtGui/QTouchEvent>
#include <QtGui/QKeyEvent>
#include <QtGui/QGuiApplication>
@@ -52,61 +51,23 @@ QT_BEGIN_NAMESPACE
namespace QmlJSDebugger {
-static const double ZoomSnapDelta = 0.04;
-static const int PressAndHoldTimeout = 800;
-
-InspectTool::InspectTool(QQuickViewInspector *inspector, QQuickView *view) :
- AbstractTool(inspector),
- m_originalSmooth(view->contentItem()->smooth()),
- m_dragStarted(false),
- m_pinchStarted(false),
- m_didPressAndHold(false),
- m_tapEvent(false),
+InspectTool::InspectTool(QQuickWindowInspector *inspector, QQuickWindow *view) :
+ QObject(inspector),
m_contentItem(view->contentItem()),
- m_originalPosition(view->contentItem()->position()),
- m_smoothScaleFactor(ZoomSnapDelta),
- m_minScale(0.125f),
- m_maxScale(48.0f),
- m_originalScale(view->contentItem()->scale()),
m_touchTimestamp(0),
m_hoverHighlight(new HoverHighlight(inspector->overlay())),
m_lastItem(0),
m_lastClickedItem(0)
{
- //Press and Hold Timer
- m_pressAndHoldTimer.setSingleShot(true);
- m_pressAndHoldTimer.setInterval(PressAndHoldTimeout);
- connect(&m_pressAndHoldTimer, SIGNAL(timeout()), SLOT(zoomTo100()));
//Timer to display selected item's name
m_nameDisplayTimer.setSingleShot(true);
m_nameDisplayTimer.setInterval(QGuiApplication::styleHints()->mouseDoubleClickInterval());
- connect(&m_nameDisplayTimer, SIGNAL(timeout()), SLOT(showSelectedItemName()));
- enable(true);
+ connect(&m_nameDisplayTimer, &QTimer::timeout, this, &InspectTool::showItemName);
}
-InspectTool::~InspectTool()
+void InspectTool::enterEvent(QEvent *)
{
- enable(false);
-}
-
-void InspectTool::enable(bool enable)
-{
- if (!enable) {
- inspector()->setSelectedItems(QList<QQuickItem*>());
- // restoring the original states.
- if (m_contentItem) {
- m_contentItem->setScale(m_originalScale);
- m_contentItem->setPosition(m_originalPosition);
- m_contentItem->setSmooth(m_originalSmooth);
- }
- } else {
- if (m_contentItem) {
- m_originalSmooth = m_contentItem->smooth();
- m_originalScale = m_contentItem->scale();
- m_originalPosition = m_contentItem->position();
- m_contentItem->setSmooth(true);
- }
- }
+ m_hoverHighlight->setVisible(true);
}
void InspectTool::leaveEvent(QEvent *)
@@ -118,16 +79,6 @@ void InspectTool::mousePressEvent(QMouseEvent *event)
{
m_mousePosition = event->localPos();
if (event->button() == Qt::LeftButton) {
- m_pressAndHoldTimer.start();
- initializeDrag(event->localPos());
- }
-}
-
-void InspectTool::mouseReleaseEvent(QMouseEvent *event)
-{
- m_mousePosition = event->localPos();
- m_pressAndHoldTimer.stop();
- if (event->button() == Qt::LeftButton && !m_dragStarted) {
selectItem();
m_hoverHighlight->setVisible(false);
}
@@ -136,7 +87,6 @@ void InspectTool::mouseReleaseEvent(QMouseEvent *event)
void InspectTool::mouseDoubleClickEvent(QMouseEvent *event)
{
m_mousePosition = event->localPos();
- m_pressAndHoldTimer.stop();
if (event->button() == Qt::LeftButton) {
selectNextItem();
m_hoverHighlight->setVisible(false);
@@ -145,14 +95,12 @@ void InspectTool::mouseDoubleClickEvent(QMouseEvent *event)
void InspectTool::mouseMoveEvent(QMouseEvent *event)
{
- m_mousePosition = event->localPos();
- moveItem(event->buttons() & Qt::LeftButton);
+ hoverMoveEvent(event);
}
void InspectTool::hoverMoveEvent(QMouseEvent *event)
{
m_mousePosition = event->localPos();
- m_pressAndHoldTimer.stop();
QQuickItem *item = inspector()->topVisibleItemAt(event->pos());
if (!item || item == m_lastClickedItem) {
m_hoverHighlight->setVisible(false);
@@ -162,54 +110,6 @@ void InspectTool::hoverMoveEvent(QMouseEvent *event)
}
}
-#ifndef QT_NO_WHEELEVENT
-void InspectTool::wheelEvent(QWheelEvent *event)
-{
- if (event->orientation() != Qt::Vertical)
- return;
-
- Qt::KeyboardModifier smoothZoomModifier = Qt::ControlModifier;
- if (event->modifiers() & smoothZoomModifier) {
- int numDegrees = event->delta() / 8;
- qreal newScale = m_contentItem->scale() + m_smoothScaleFactor * (numDegrees / 15.0f);
- scaleView(newScale / m_contentItem->scale(), m_mousePosition, m_mousePosition);
- } else if (!event->modifiers()) {
- if (event->delta() > 0) {
- zoomIn();
- } else if (event->delta() < 0) {
- zoomOut();
- }
- }
-}
-#endif
-
-void InspectTool::keyReleaseEvent(QKeyEvent *event)
-{
- switch (event->key()) {
- case Qt::Key_Plus:
- zoomIn();
- break;
- case Qt::Key_Minus:
- zoomOut();
- break;
- case Qt::Key_1:
- case Qt::Key_2:
- case Qt::Key_3:
- case Qt::Key_4:
- case Qt::Key_5:
- case Qt::Key_6:
- case Qt::Key_7:
- case Qt::Key_8:
- case Qt::Key_9: {
- qreal newScale = ((event->key() - Qt::Key_0) * 1.0f);
- scaleView(newScale / m_contentItem->scale(), m_mousePosition, m_mousePosition);
- break;
- }
- default:
- break;
- }
-}
-
void InspectTool::touchEvent(QTouchEvent *event)
{
QList<QTouchEvent::TouchPoint> touchPoints = event->touchPoints();
@@ -217,10 +117,7 @@ void InspectTool::touchEvent(QTouchEvent *event)
switch (event->type()) {
case QEvent::TouchBegin:
if (touchPoints.count() == 1 && (event->touchPointStates() & Qt::TouchPointPressed)) {
- if (!m_pressAndHoldTimer.isActive())
- m_pressAndHoldTimer.start();
m_mousePosition = touchPoints.first().pos();
- initializeDrag(touchPoints.first().pos());
m_tapEvent = true;
} else {
m_tapEvent = false;
@@ -229,48 +126,23 @@ void InspectTool::touchEvent(QTouchEvent *event)
case QEvent::TouchUpdate: {
if (touchPoints.count() > 1)
m_tapEvent = false;
- if ((touchPoints.count() == 1)
- && (event->touchPointStates() & Qt::TouchPointMoved)) {
+ else if ((touchPoints.count() == 1) && (event->touchPointStates() & Qt::TouchPointMoved))
m_mousePosition = touchPoints.first().pos();
- moveItem(true);
- } else if ((touchPoints.count() == 2)
- && (!(event->touchPointStates() & Qt::TouchPointReleased))) {
- // determine scale factor
- const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.first();
- const QTouchEvent::TouchPoint &touchPoint1 = touchPoints.last();
-
- qreal touchScaleFactor =
- QLineF(touchPoint0.pos(), touchPoint1.pos()).length()
- / QLineF(touchPoint0.lastPos(), touchPoint1.lastPos()).length();
-
- QPointF oldcenter = (touchPoint0.lastPos() + touchPoint1.lastPos()) / 2;
- QPointF newcenter = (touchPoint0.pos() + touchPoint1.pos()) / 2;
-
- m_pinchStarted = true;
- scaleView(touchScaleFactor, newcenter, oldcenter);
- }
break;
}
case QEvent::TouchEnd: {
- m_pressAndHoldTimer.stop();
- if (m_pinchStarted) {
- m_pinchStarted = false;
- }
- if (touchPoints.count() == 1 && !m_dragStarted &&
- !m_didPressAndHold && m_tapEvent) {
+ if (touchPoints.count() == 1 && m_tapEvent) {
m_tapEvent = false;
bool doubleTap = event->timestamp() - m_touchTimestamp
< static_cast<ulong>(QGuiApplication::styleHints()->mouseDoubleClickInterval());
if (doubleTap) {
m_nameDisplayTimer.stop();
selectNextItem();
- }
- else {
+ } else {
selectItem();
}
m_touchTimestamp = event->timestamp();
}
- m_didPressAndHold = false;
break;
}
default:
@@ -278,106 +150,6 @@ void InspectTool::touchEvent(QTouchEvent *event)
}
}
-void InspectTool::scaleView(const qreal &factor, const QPointF &newcenter, const QPointF &oldcenter)
-{
- m_pressAndHoldTimer.stop();
- if (((m_contentItem->scale() * factor) > m_maxScale)
- || ((m_contentItem->scale() * factor) < m_minScale)) {
- return;
- }
- //New position = new center + scalefactor * (oldposition - oldcenter)
- QPointF newPosition = newcenter + (factor * (m_contentItem->position() - oldcenter));
- m_contentItem->setScale(m_contentItem->scale() * factor);
- m_contentItem->setPosition(newPosition);
-}
-
-void InspectTool::zoomIn()
-{
- qreal newScale = nextZoomScale(ZoomIn);
- scaleView(newScale / m_contentItem->scale(), m_mousePosition, m_mousePosition);
-}
-
-void InspectTool::zoomOut()
-{
- qreal newScale = nextZoomScale(ZoomOut);
- scaleView(newScale / m_contentItem->scale(), m_mousePosition, m_mousePosition);
-}
-
-void InspectTool::zoomTo100()
-{
- m_didPressAndHold = true;
-
- m_contentItem->setPosition(QPointF(0, 0));
- m_contentItem->setScale(1.0);
-}
-
-qreal InspectTool::nextZoomScale(ZoomDirection direction)
-{
- static QList<qreal> zoomScales =
- QList<qreal>()
- << 0.125f
- << 1.0f / 6.0f
- << 0.25f
- << 1.0f / 3.0f
- << 0.5f
- << 2.0f / 3.0f
- << 1.0f
- << 2.0f
- << 3.0f
- << 4.0f
- << 5.0f
- << 6.0f
- << 7.0f
- << 8.0f
- << 12.0f
- << 16.0f
- << 32.0f
- << 48.0f;
-
- if (direction == ZoomIn) {
- for (int i = 0; i < zoomScales.length(); ++i) {
- if (zoomScales[i] > m_contentItem->scale())
- return zoomScales[i];
- }
- return zoomScales.last();
- } else {
- for (int i = zoomScales.length() - 1; i >= 0; --i) {
- if (zoomScales[i] < m_contentItem->scale())
- return zoomScales[i];
- }
- return zoomScales.first();
- }
-}
-
-void InspectTool::initializeDrag(const QPointF &pos)
-{
- m_dragStartPosition = pos;
- m_dragStarted = false;
-}
-
-void InspectTool::dragItemToPosition()
-{
- QPointF newPosition = m_contentItem->position() + m_mousePosition - m_dragStartPosition;
- m_dragStartPosition = m_mousePosition;
- m_contentItem->setPosition(newPosition);
-}
-
-void InspectTool::moveItem(bool valid)
-{
- if (m_pinchStarted)
- return;
-
- if (!m_dragStarted
- && valid
- && ((m_dragStartPosition - m_mousePosition).manhattanLength()
- > QGuiApplication::styleHints()->startDragDistance())) {
- m_pressAndHoldTimer.stop();
- m_dragStarted = true;
- }
- if (m_dragStarted)
- dragItemToPosition();
-}
-
void InspectTool::selectNextItem()
{
if (m_lastClickedItem != inspector()->topVisibleItemAt(m_mousePosition))
@@ -389,8 +161,8 @@ void InspectTool::selectNextItem()
m_lastItem = items[i+1];
else
m_lastItem = items[0];
- inspector()->setSelectedItems(QList<QQuickItem*>() << m_lastItem);
- showSelectedItemName();
+ globalInspector()->setSelectedItems(QList<QQuickItem*>() << m_lastItem);
+ showItemName();
break;
}
}
@@ -400,24 +172,29 @@ void InspectTool::selectItem()
{
if (!inspector()->topVisibleItemAt(m_mousePosition))
return;
+ m_lastClickedItem = inspector()->topVisibleItemAt(m_mousePosition);
+ m_lastItem = m_lastClickedItem;
+ globalInspector()->setSelectedItems(QList<QQuickItem*>() << m_lastClickedItem);
if (m_lastClickedItem == inspector()->topVisibleItemAt(m_mousePosition)) {
m_nameDisplayTimer.start();
- return;
+ } else {
+ showItemName();
}
- m_lastClickedItem = inspector()->topVisibleItemAt(m_mousePosition);
- m_lastItem = m_lastClickedItem;
- inspector()->setSelectedItems(QList<QQuickItem*>() << m_lastClickedItem);
- showSelectedItemName();
}
-QQuickViewInspector *InspectTool::inspector() const
+void InspectTool::showItemName()
+{
+ globalInspector()->showSelectedItemName(m_lastItem, m_mousePosition);
+}
+
+QQuickWindowInspector *InspectTool::inspector() const
{
- return static_cast<QQuickViewInspector*>(AbstractTool::inspector());
+ return static_cast<QQuickWindowInspector *>(parent());
}
-void InspectTool::showSelectedItemName()
+GlobalInspector *InspectTool::globalInspector() const
{
- inspector()->showSelectedItemName(m_lastItem, m_mousePosition);
+ return static_cast<GlobalInspector *>(parent()->parent());
}
} // namespace QmlJSDebugger
diff --git a/src/plugins/qmltooling/qmldbg_inspector/inspecttool.h b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.h
index fdb763d4b3..01392185db 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/inspecttool.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.h
@@ -34,85 +34,52 @@
#ifndef INSPECTTOOL_H
#define INSPECTTOOL_H
-#include "abstracttool.h"
-
#include <QtCore/QPointF>
#include <QtCore/QPointer>
#include <QtCore/QTimer>
QT_BEGIN_NAMESPACE
-class QQuickView;
+class QQuickWindow;
class QQuickItem;
+class QMouseEvent;
+class QKeyEvent;
+class QTouchEvent;
namespace QmlJSDebugger {
-class QQuickViewInspector;
+class GlobalInspector;
+class QQuickWindowInspector;
class HoverHighlight;
-class InspectTool : public AbstractTool
+class InspectTool : public QObject
{
Q_OBJECT
public:
- enum ZoomDirection {
- ZoomIn,
- ZoomOut
- };
-
- InspectTool(QQuickViewInspector *inspector, QQuickView *view);
- ~InspectTool();
-
- void enable(bool enable);
+ InspectTool(QQuickWindowInspector *inspector, QQuickWindow *view);
+ void enterEvent(QEvent *);
void leaveEvent(QEvent *);
-
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
- void mouseReleaseEvent(QMouseEvent *);
void mouseDoubleClickEvent(QMouseEvent *);
-
void hoverMoveEvent(QMouseEvent *);
-#ifndef QT_NO_WHEELEVENT
- void wheelEvent(QWheelEvent *);
-#endif
-
void keyPressEvent(QKeyEvent *) {}
void keyReleaseEvent(QKeyEvent *);
-
void touchEvent(QTouchEvent *event);
private:
- QQuickViewInspector *inspector() const;
- qreal nextZoomScale(ZoomDirection direction);
- void scaleView(const qreal &factor, const QPointF &newcenter, const QPointF &oldcenter);
- void zoomIn();
- void zoomOut();
- void initializeDrag(const QPointF &pos);
- void dragItemToPosition();
- void moveItem(bool valid);
void selectNextItem();
void selectItem();
+ void showItemName();
-private slots:
- void zoomTo100();
- void showSelectedItemName();
+ QQuickWindowInspector *inspector() const;
+ GlobalInspector *globalInspector() const;
-private:
- bool m_originalSmooth;
- bool m_dragStarted;
- bool m_pinchStarted;
- bool m_didPressAndHold;
bool m_tapEvent;
QPointer<QQuickItem> m_contentItem;
- QPointF m_dragStartPosition;
QPointF m_mousePosition;
- QPointF m_originalPosition;
- qreal m_smoothScaleFactor;
- qreal m_minScale;
- qreal m_maxScale;
- qreal m_originalScale;
ulong m_touchTimestamp;
- QTimer m_pressAndHoldTimer;
QTimer m_nameDisplayTimer;
HoverHighlight *m_hoverHighlight;
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro b/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro
index dd5cc8ceef..c2ee733db6 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro
+++ b/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro
@@ -8,21 +8,19 @@ load(qt_plugin)
INCLUDEPATH *= $$PWD $$PWD/../shared
SOURCES += \
+ $$PWD/globalinspector.cpp \
$$PWD/highlight.cpp \
- $$PWD/qquickviewinspector.cpp \
- $$PWD/abstracttool.cpp \
- $$PWD/abstractviewinspector.cpp \
$$PWD/inspecttool.cpp \
- $$PWD/qqmlinspectorservice.cpp
+ $$PWD/qqmlinspectorservice.cpp \
+ $$PWD/qquickwindowinspector.cpp
HEADERS += \
$$PWD/../shared/qqmldebugpacket.h \
+ $$PWD/globalinspector.h \
$$PWD/highlight.h \
- $$PWD/qquickviewinspector.h \
+ $$PWD/inspecttool.h\
$$PWD/qqmlinspectorservicefactory.h \
- $$PWD/abstracttool.h \
- $$PWD/abstractviewinspector.h \
- $$PWD/inspecttool.h
+ $$PWD/qquickwindowinspector.h
OTHER_FILES += \
qqmlinspectorservice.json
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp
index 6b786024f8..37faff9c8c 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp
@@ -32,89 +32,98 @@
****************************************************************************/
#include "qqmlinspectorservicefactory.h"
-#include "qquickviewinspector.h"
+#include "globalinspector.h"
+#include "qquickwindowinspector.h"
-#include <private/qqmlglobal_p.h>
-
-#include <QtCore/QCoreApplication>
-#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtCore/QPluginLoader>
+#include <QtGui/QWindow>
QT_BEGIN_NAMESPACE
class QQmlInspectorServiceImpl : public QQmlInspectorService
{
Q_OBJECT
-
public:
QQmlInspectorServiceImpl(QObject *parent = 0);
- void addView(QObject *) Q_DECL_OVERRIDE;
- void removeView(QObject *) Q_DECL_OVERRIDE;
+ void addWindow(QQuickWindow *window) Q_DECL_OVERRIDE;
+ void setParentWindow(QQuickWindow *window, QWindow *parent) Q_DECL_OVERRIDE;
+ void removeWindow(QQuickWindow *window) Q_DECL_OVERRIDE;
protected:
- virtual void stateChanged(State state) Q_DECL_OVERRIDE;
virtual void messageReceived(const QByteArray &) Q_DECL_OVERRIDE;
-private Q_SLOTS:
- void processMessage(const QByteArray &message);
- void updateState();
+private slots:
+ void messageFromClient(const QByteArray &message);
private:
friend class QQmlInspectorServiceFactory;
- QList<QObject*> m_views;
- QmlJSDebugger::AbstractViewInspector *m_currentInspector;
+ QmlJSDebugger::GlobalInspector *checkInspector();
+ QmlJSDebugger::GlobalInspector *m_globalInspector;
+ QHash<QQuickWindow *, QWindow *> m_waitingWindows;
};
QQmlInspectorServiceImpl::QQmlInspectorServiceImpl(QObject *parent):
- QQmlInspectorService(1, parent), m_currentInspector(0)
+ QQmlInspectorService(1, parent), m_globalInspector(0)
{
}
-void QQmlInspectorServiceImpl::addView(QObject *view)
+QmlJSDebugger::GlobalInspector *QQmlInspectorServiceImpl::checkInspector()
{
- m_views.append(view);
- updateState();
+ if (state() == Enabled) {
+ if (!m_globalInspector) {
+ m_globalInspector = new QmlJSDebugger::GlobalInspector(this);
+ connect(m_globalInspector, &QmlJSDebugger::GlobalInspector::messageToClient,
+ this, &QQmlDebugService::messageToClient);
+ for (QHash<QQuickWindow *, QWindow *>::ConstIterator i = m_waitingWindows.constBegin();
+ i != m_waitingWindows.constEnd(); ++i) {
+ m_globalInspector->addWindow(i.key());
+ if (i.value() != 0)
+ m_globalInspector->setParentWindow(i.key(), i.value());
+ }
+ m_waitingWindows.clear();
+ }
+ } else if (m_globalInspector) {
+ delete m_globalInspector;
+ m_globalInspector = 0;
+ }
+ return m_globalInspector;
}
-void QQmlInspectorServiceImpl::removeView(QObject *view)
+void QQmlInspectorServiceImpl::addWindow(QQuickWindow *window)
{
- m_views.removeAll(view);
- updateState();
+ if (QmlJSDebugger::GlobalInspector *inspector = checkInspector())
+ inspector->addWindow(window);
+ else
+ m_waitingWindows.insert(window, 0);
}
-void QQmlInspectorServiceImpl::stateChanged(State /*state*/)
+void QQmlInspectorServiceImpl::removeWindow(QQuickWindow *window)
{
- QMetaObject::invokeMethod(this, "updateState", Qt::QueuedConnection);
+ if (QmlJSDebugger::GlobalInspector *inspector = checkInspector())
+ inspector->removeWindow(window);
+ else
+ m_waitingWindows.remove(window);
}
-void QQmlInspectorServiceImpl::updateState()
+void QQmlInspectorServiceImpl::setParentWindow(QQuickWindow *window, QWindow *parent)
{
- delete m_currentInspector;
- m_currentInspector = 0;
-
- if (m_views.isEmpty() || state() != Enabled)
- return;
-
- QQuickView *qtQuickView = qobject_cast<QQuickView*>(m_views.first());
- if (qtQuickView)
- m_currentInspector = new QmlJSDebugger::QQuickViewInspector(this, qtQuickView, this);
+ if (QmlJSDebugger::GlobalInspector *inspector = checkInspector())
+ inspector->setParentWindow(window, parent);
else
- qWarning() << "QQmlInspector: No inspector available for view '"
- << m_views.first()->metaObject()->className() << "'.";
+ m_waitingWindows[window] = parent;
}
void QQmlInspectorServiceImpl::messageReceived(const QByteArray &message)
{
- QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection, Q_ARG(QByteArray, message));
+ QMetaObject::invokeMethod(this, "messageFromClient", Qt::QueuedConnection,
+ Q_ARG(QByteArray, message));
}
-void QQmlInspectorServiceImpl::processMessage(const QByteArray &message)
+void QQmlInspectorServiceImpl::messageFromClient(const QByteArray &message)
{
- if (m_currentInspector)
- m_currentInspector->handleMessage(message);
+ if (QmlJSDebugger::GlobalInspector *inspector = checkInspector())
+ inspector->processMessage(message);
}
QQmlDebugService *QQmlInspectorServiceFactory::create(const QString &key)
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.cpp
deleted file mode 100644
index de9d5617b5..0000000000
--- a/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickviewinspector.h"
-
-#include "highlight.h"
-#include "inspecttool.h"
-
-#include <QtQml/private/qqmlengine_p.h>
-#include <QtQuick/private/qquickitem_p.h>
-
-#include <QtQuick/QQuickView>
-#include <QtQuick/QQuickItem>
-
-#include <cfloat>
-
-QT_BEGIN_NAMESPACE
-namespace QmlJSDebugger {
-
-/*
- * Collects all the items at the given position, from top to bottom.
- */
-static void collectItemsAt(QQuickItem *item, const QPointF &pos,
- QQuickItem *overlay, QList<QQuickItem *> &resultList)
-{
- if (item == overlay)
- return;
-
- if (item->flags() & QQuickItem::ItemClipsChildrenToShape) {
- if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
- return;
- }
-
- QList<QQuickItem *> children = QQuickItemPrivate::get(item)->paintOrderChildItems();
- for (int i = children.count() - 1; i >= 0; --i) {
- QQuickItem *child = children.at(i);
- collectItemsAt(child, item->mapToItem(child, pos), overlay, resultList);
- }
-
- if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
- return;
-
- resultList.append(item);
-}
-
-/*
- * Returns the first visible item at the given position, or 0 when no such
- * child exists.
- */
-static QQuickItem *itemAt(QQuickItem *item, const QPointF &pos,
- QQuickItem *overlay)
-{
- if (item == overlay)
- return 0;
-
- if (!item->isVisible() || item->opacity() == 0.0)
- return 0;
-
- if (item->flags() & QQuickItem::ItemClipsChildrenToShape) {
- if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
- return 0;
- }
-
- QList<QQuickItem *> children = QQuickItemPrivate::get(item)->paintOrderChildItems();
- for (int i = children.count() - 1; i >= 0; --i) {
- QQuickItem *child = children.at(i);
- if (QQuickItem *betterCandidate = itemAt(child, item->mapToItem(child, pos),
- overlay))
- return betterCandidate;
- }
-
- if (!(item->flags() & QQuickItem::ItemHasContents))
- return 0;
-
- if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
- return 0;
-
- return item;
-}
-
-
-QQuickViewInspector::QQuickViewInspector(QQmlDebugService *service, QQuickView *view,
- QObject *parent) :
- AbstractViewInspector(service, parent),
- m_view(view),
- m_overlay(new QQuickItem),
- m_inspectTool(new InspectTool(this, view)),
- m_sendQmlReloadedMessage(false)
-{
- // Try to make sure the overlay is always on top
- m_overlay->setZ(FLT_MAX);
-
- if (QQuickItem *root = view->contentItem())
- m_overlay->setParentItem(root);
-
- view->installEventFilter(this);
- appendTool(m_inspectTool);
- connect(view, SIGNAL(statusChanged(QQuickView::Status)),
- this, SLOT(onViewStatus(QQuickView::Status)));
-}
-
-void QQuickViewInspector::changeCurrentObjects(const QList<QObject*> &objects)
-{
- QList<QQuickItem*> items;
- foreach (QObject *obj, objects)
- if (QQuickItem *item = qobject_cast<QQuickItem*>(obj))
- items << item;
-
- syncSelectedItems(items);
-}
-
-void QQuickViewInspector::reparentQmlObject(QObject *object, QObject *newParent)
-{
- if (!newParent)
- return;
-
- object->setParent(newParent);
- QQuickItem *newParentItem = qobject_cast<QQuickItem*>(newParent);
- QQuickItem *item = qobject_cast<QQuickItem*>(object);
- if (newParentItem && item)
- item->setParentItem(newParentItem);
-}
-
-QWindow *getMasterWindow(QWindow *w)
-{
- QWindow *p = w->parent();
- while (p) {
- w = p;
- p = p->parent();
- }
- return w;
-}
-
-Qt::WindowFlags QQuickViewInspector::windowFlags() const
-{
- return getMasterWindow(m_view)->flags();
-}
-
-void QQuickViewInspector::setWindowFlags(Qt::WindowFlags flags)
-{
- QWindow *w = getMasterWindow(m_view);
- w->setFlags(flags);
- // make flags are applied
- w->setVisible(false);
- w->setVisible(true);
-}
-
-QQmlEngine *QQuickViewInspector::declarativeEngine() const
-{
- return m_view->engine();
-}
-
-QQuickItem *QQuickViewInspector::topVisibleItemAt(const QPointF &pos) const
-{
- QQuickItem *root = m_view->contentItem();
- return itemAt(root, root->mapFromScene(pos), m_overlay);
-}
-
-QList<QQuickItem *> QQuickViewInspector::itemsAt(const QPointF &pos) const
-{
- QQuickItem *root = m_view->contentItem();
- QList<QQuickItem *> resultList;
- collectItemsAt(root, root->mapFromScene(pos), m_overlay,
- resultList);
- return resultList;
-}
-
-QList<QQuickItem*> QQuickViewInspector::selectedItems() const
-{
- QList<QQuickItem *> selection;
- foreach (const QPointer<QQuickItem> &selectedItem, m_selectedItems) {
- if (selectedItem)
- selection << selectedItem;
- }
- return selection;
-}
-
-void QQuickViewInspector::setSelectedItems(const QList<QQuickItem *> &items)
-{
- if (!syncSelectedItems(items))
- return;
-
- QList<QObject*> objectList;
- objectList.reserve(items.count());
- foreach (QQuickItem *item, items)
- objectList << item;
-
- sendCurrentObjects(objectList);
-}
-
-bool QQuickViewInspector::syncSelectedItems(const QList<QQuickItem *> &items)
-{
- bool selectionChanged = false;
-
- // Disconnect and remove items that are no longer selected
- foreach (const QPointer<QQuickItem> &item, m_selectedItems) {
- if (!item) // Don't see how this can happen due to handling of destroyed()
- continue;
- if (items.contains(item))
- continue;
-
- selectionChanged = true;
- item->disconnect(this);
- m_selectedItems.removeOne(item);
- delete m_highlightItems.take(item);
- }
-
- // Connect and add newly selected items
- foreach (QQuickItem *item, items) {
- if (m_selectedItems.contains(item))
- continue;
-
- selectionChanged = true;
- connect(item, SIGNAL(destroyed(QObject*)), this, SLOT(removeFromSelectedItems(QObject*)));
- m_selectedItems.append(item);
- SelectionHighlight *selectionHighlightItem;
- selectionHighlightItem = new SelectionHighlight(titleForItem(item), item, m_overlay);
- m_highlightItems.insert(item, selectionHighlightItem);
- }
-
- return selectionChanged;
-}
-
-void QQuickViewInspector::showSelectedItemName(QQuickItem *item, const QPointF &point)
-{
- SelectionHighlight *highlightItem = m_highlightItems.value(item, 0);
- if (highlightItem)
- highlightItem->showName(point);
-}
-
-void QQuickViewInspector::removeFromSelectedItems(QObject *object)
-{
- if (QQuickItem *item = qobject_cast<QQuickItem*>(object)) {
- if (m_selectedItems.removeOne(item))
- delete m_highlightItems.take(item);
- }
-}
-
-bool QQuickViewInspector::eventFilter(QObject *obj, QEvent *event)
-{
- if (obj != m_view)
- return QObject::eventFilter(obj, event);
-
- return AbstractViewInspector::eventFilter(obj, event);
-}
-
-bool QQuickViewInspector::mouseMoveEvent(QMouseEvent *event)
-{
- // TODO
-// if (QQuickItem *item = topVisibleItemAt(event->pos()))
-// m_view->setToolTip(titleForItem(item));
-// else
-// m_view->setToolTip(QString());
-
- return AbstractViewInspector::mouseMoveEvent(event);
-}
-
-QString QQuickViewInspector::titleForItem(QQuickItem *item) const
-{
- QString className = QLatin1String(item->metaObject()->className());
- QString objectStringId = idStringForObject(item);
-
- className.remove(QRegExp(QLatin1String("_QMLTYPE_\\d+")));
- className.remove(QRegExp(QLatin1String("_QML_\\d+")));
- if (className.startsWith(QLatin1String("QQuick")))
- className = className.mid(6);
-
- QString constructedName;
-
- if (!objectStringId.isEmpty()) {
- constructedName = objectStringId + QLatin1String(" (") + className + QLatin1Char(')');
- } else if (!item->objectName().isEmpty()) {
- constructedName = item->objectName() + QLatin1String(" (") + className + QLatin1Char(')');
- } else {
- constructedName = className;
- }
-
- return constructedName;
-}
-
-void QQuickViewInspector::reloadQmlFile(const QHash<QString, QByteArray> &changesHash)
-{
- clearComponentCache();
-
- // Reset the selection since we are reloading the main qml
- setSelectedItems(QList<QQuickItem *>());
-
- QHash<QUrl, QByteArray> debugCache;
-
- foreach (const QString &str, changesHash.keys())
- debugCache.insert(QUrl(str), changesHash.value(str, QByteArray()));
-
- // Updating the cache in engine private such that the QML Data loader
- // gets the changes from the cache.
- QQmlEnginePrivate::get(declarativeEngine())->setDebugChangesCache(debugCache);
-
- m_sendQmlReloadedMessage = true;
- // reloading the view such that the changes done for the files are
- // reflected in view
- view()->setSource(view()->source());
-}
-
-void QQuickViewInspector::setShowAppOnTop(bool appOnTop)
-{
- m_appOnTop = appOnTop;
- // Hack for QTCREATORBUG-6295.
- // TODO: The root cause to be identified and fixed later.
- QTimer::singleShot(100, this, SLOT(applyAppOnTop()));
-}
-
-void QQuickViewInspector::onViewStatus(QQuickView::Status status)
-{
- bool success = false;
- switch (status) {
- case QQuickView::Loading:
- return;
- case QQuickView::Ready:
- if (view()->errors().count())
- break;
- success = true;
- break;
- case QQuickView::Null:
- case QQuickView::Error:
- break;
- default:
- break;
- }
- if (m_sendQmlReloadedMessage) {
- m_sendQmlReloadedMessage = false;
- sendQmlFileReloaded(success);
- }
-}
-
-void QQuickViewInspector::applyAppOnTop()
-{
- Qt::WindowFlags flags = windowFlags();
- if (m_appOnTop)
- flags |= Qt::WindowStaysOnTopHint;
- else
- flags &= ~Qt::WindowStaysOnTopHint;
-
- setWindowFlags(flags);
-}
-
-} // namespace QmlJSDebugger
-
-QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.cpp
new file mode 100644
index 0000000000..efb9a6f812
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickwindowinspector.h"
+#include "inspecttool.h"
+
+#include <private/qquickitem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QmlJSDebugger {
+
+/*
+ * Returns the first visible item at the given position, or 0 when no such
+ * child exists.
+ */
+static QQuickItem *itemAt(QQuickItem *item, const QPointF &pos,
+ QQuickItem *overlay)
+{
+ if (item == overlay)
+ return 0;
+
+ if (!item->isVisible() || item->opacity() == 0.0)
+ return 0;
+
+ if (item->flags() & QQuickItem::ItemClipsChildrenToShape) {
+ if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
+ return 0;
+ }
+
+ QList<QQuickItem *> children = QQuickItemPrivate::get(item)->paintOrderChildItems();
+ for (int i = children.count() - 1; i >= 0; --i) {
+ QQuickItem *child = children.at(i);
+ if (QQuickItem *betterCandidate = itemAt(child, item->mapToItem(child, pos),
+ overlay))
+ return betterCandidate;
+ }
+
+ if (!(item->flags() & QQuickItem::ItemHasContents))
+ return 0;
+
+ if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
+ return 0;
+
+ return item;
+}
+
+/*
+ * Collects all the items at the given position, from top to bottom.
+ */
+static void collectItemsAt(QQuickItem *item, const QPointF &pos,
+ QQuickItem *overlay, QList<QQuickItem *> &resultList)
+{
+ if (item == overlay)
+ return;
+
+ if (item->flags() & QQuickItem::ItemClipsChildrenToShape) {
+ if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
+ return;
+ }
+
+ QList<QQuickItem *> children = QQuickItemPrivate::get(item)->paintOrderChildItems();
+ for (int i = children.count() - 1; i >= 0; --i) {
+ QQuickItem *child = children.at(i);
+ collectItemsAt(child, item->mapToItem(child, pos), overlay, resultList);
+ }
+
+ if (!QRectF(0, 0, item->width(), item->height()).contains(pos))
+ return;
+
+ resultList.append(item);
+}
+
+QQuickWindowInspector::QQuickWindowInspector(QQuickWindow *quickWindow, QObject *parent) :
+ QObject(parent),
+ m_overlay(new QQuickItem),
+ m_window(quickWindow),
+ m_parentWindow(0),
+ m_tool(0)
+{
+ setParentWindow(quickWindow);
+
+ // Try to make sure the overlay is always on top
+ m_overlay->setZ(FLT_MAX);
+
+ if (QQuickItem *root = m_window->contentItem())
+ m_overlay->setParentItem(root);
+
+ m_window->installEventFilter(this);
+}
+
+bool QQuickWindowInspector::eventFilter(QObject *obj, QEvent *event)
+{
+ if (!m_tool || obj != m_window)
+ return QObject::eventFilter(obj, event);
+
+ switch (event->type()) {
+ case QEvent::Enter:
+ m_tool->enterEvent(event);
+ return true;
+ case QEvent::Leave:
+ m_tool->leaveEvent(event);
+ return true;
+ case QEvent::MouseButtonPress:
+ m_tool->mousePressEvent(static_cast<QMouseEvent*>(event));
+ return true;
+ case QEvent::MouseMove:
+ m_tool->mouseMoveEvent(static_cast<QMouseEvent*>(event));
+ return true;
+ case QEvent::MouseButtonRelease:
+ return true;
+ case QEvent::KeyPress:
+ m_tool->keyPressEvent(static_cast<QKeyEvent*>(event));
+ return true;
+ case QEvent::KeyRelease:
+ return true;
+ case QEvent::MouseButtonDblClick:
+ m_tool->mouseDoubleClickEvent(static_cast<QMouseEvent*>(event));
+ return true;
+#ifndef QT_NO_WHEELEVENT
+ case QEvent::Wheel:
+ return true;
+#endif
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ m_tool->touchEvent(static_cast<QTouchEvent*>(event));
+ return true;
+ default:
+ break;
+ }
+
+ return QObject::eventFilter(obj, event);
+}
+
+void QQuickWindowInspector::setShowAppOnTop(bool appOnTop)
+{
+ if (!m_parentWindow)
+ return;
+
+ Qt::WindowFlags flags = m_parentWindow->flags();
+ Qt::WindowFlags newFlags = appOnTop ? (flags | Qt::WindowStaysOnTopHint) :
+ (flags & ~Qt::WindowStaysOnTopHint);
+ if (newFlags != flags)
+ m_parentWindow->setFlags(newFlags);
+}
+
+bool QQuickWindowInspector::isEnabled() const
+{
+ return m_tool != 0;
+}
+
+void QQuickWindowInspector::setEnabled(bool enabled)
+{
+ if (enabled) {
+ m_tool = new InspectTool(this, m_window);
+ } else {
+ delete m_tool;
+ m_tool = 0;
+ }
+}
+
+QQuickWindow *QQuickWindowInspector::quickWindow() const
+{
+ return m_window;
+}
+
+void QQuickWindowInspector::setParentWindow(QWindow *parentWindow)
+{
+ if (parentWindow) {
+ while (QWindow *w = parentWindow->parent())
+ parentWindow = w;
+ }
+
+ m_parentWindow = parentWindow;
+}
+
+QList<QQuickItem *> QQuickWindowInspector::itemsAt(const QPointF &pos) const
+{
+ QList<QQuickItem *> resultList;
+ QQuickItem *root = m_window->contentItem();
+ collectItemsAt(root, root->mapFromScene(pos), m_overlay,
+ resultList);
+ return resultList;
+}
+
+QQuickItem *QQuickWindowInspector::topVisibleItemAt(const QPointF &pos) const
+{
+ QQuickItem *root = m_window->contentItem();
+ return itemAt(root, root->mapFromScene(pos), m_overlay);
+}
+
+
+} // namespace QmlJSDebugger
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_inspector/abstracttool.h b/src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.h
index c796925866..e98cdec9f6 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/abstracttool.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.h
@@ -31,55 +31,58 @@
**
****************************************************************************/
-#ifndef ABSTRACTTOOL_H
-#define ABSTRACTTOOL_H
+#ifndef QQUICKWINDOWINSPECTOR_H
+#define QQUICKWINDOWINSPECTOR_H
#include <QtCore/QObject>
QT_BEGIN_NAMESPACE
-class QMouseEvent;
-class QKeyEvent;
-class QWheelEvent;
-class QTouchEvent;
+
+class QQmlDebugService;
+class QQuickWindow;
+class QQmlEngine;
+class QWindow;
+class QQuickItem;
namespace QmlJSDebugger {
-class AbstractViewInspector;
+class InspectTool;
+class GlobalInspector;
-class AbstractTool : public QObject
+/*
+ * The common code between QQuickView and QQuickView inspectors lives here,
+ */
+class QQuickWindowInspector : public QObject
{
Q_OBJECT
public:
- explicit AbstractTool(AbstractViewInspector *inspector);
-
- AbstractViewInspector *inspector() const { return m_inspector; }
-
- virtual void enable(bool enable) = 0;
+ explicit QQuickWindowInspector(QQuickWindow *quickWindow, QObject *parent = 0);
- virtual void leaveEvent(QEvent *event) = 0;
+ QQuickItem *overlay() const { return m_overlay; }
+ QQuickItem *topVisibleItemAt(const QPointF &pos) const;
+ QList<QQuickItem *> itemsAt(const QPointF &pos) const;
- virtual void mousePressEvent(QMouseEvent *event) = 0;
- virtual void mouseMoveEvent(QMouseEvent *event) = 0;
- virtual void mouseReleaseEvent(QMouseEvent *event) = 0;
- virtual void mouseDoubleClickEvent(QMouseEvent *event) = 0;
+ QQuickWindow *quickWindow() const;
- virtual void hoverMoveEvent(QMouseEvent *event) = 0;
-#ifndef QT_NO_WHEELEVENT
- virtual void wheelEvent(QWheelEvent *event) = 0;
-#endif
+ void setParentWindow(QWindow *parentWindow);
+ void setShowAppOnTop(bool appOnTop);
- virtual void keyPressEvent(QKeyEvent *event) = 0;
- virtual void keyReleaseEvent(QKeyEvent *keyEvent) = 0;
+ bool isEnabled() const;
+ void setEnabled(bool enabled);
- virtual void touchEvent(QTouchEvent *) {}
+protected:
+ bool eventFilter(QObject *, QEvent *);
private:
- AbstractViewInspector *m_inspector;
+ QQuickItem *m_overlay;
+ QQuickWindow *m_window;
+ QWindow *m_parentWindow;
+ InspectTool *m_tool;
};
} // namespace QmlJSDebugger
QT_END_NAMESPACE
-#endif // ABSTRACTTOOL_H
+#endif // QQUICKWINDOWINSPECTOR_H