diff options
Diffstat (limited to 'src/plugins/qmltooling/qmldbg_inspector')
17 files changed, 1049 insertions, 1598 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/abstracttool.h b/src/plugins/qmltooling/qmldbg_inspector/abstracttool.h deleted file mode 100644 index c796925866..0000000000 --- a/src/plugins/qmltooling/qmldbg_inspector/abstracttool.h +++ /dev/null @@ -1,85 +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 ABSTRACTTOOL_H -#define ABSTRACTTOOL_H - -#include <QtCore/QObject> - -QT_BEGIN_NAMESPACE -class QMouseEvent; -class QKeyEvent; -class QWheelEvent; -class QTouchEvent; - -namespace QmlJSDebugger { - -class AbstractViewInspector; - -class AbstractTool : public QObject -{ - Q_OBJECT - -public: - explicit AbstractTool(AbstractViewInspector *inspector); - - AbstractViewInspector *inspector() const { return m_inspector; } - - virtual void enable(bool enable) = 0; - - virtual void leaveEvent(QEvent *event) = 0; - - virtual void mousePressEvent(QMouseEvent *event) = 0; - virtual void mouseMoveEvent(QMouseEvent *event) = 0; - virtual void mouseReleaseEvent(QMouseEvent *event) = 0; - virtual void mouseDoubleClickEvent(QMouseEvent *event) = 0; - - virtual void hoverMoveEvent(QMouseEvent *event) = 0; -#ifndef QT_NO_WHEELEVENT - virtual void wheelEvent(QWheelEvent *event) = 0; -#endif - - virtual void keyPressEvent(QKeyEvent *event) = 0; - virtual void keyReleaseEvent(QKeyEvent *keyEvent) = 0; - - virtual void touchEvent(QTouchEvent *) {} - -private: - AbstractViewInspector *m_inspector; -}; - -} // namespace QmlJSDebugger - -QT_END_NAMESPACE - -#endif // ABSTRACTTOOL_H diff --git a/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp deleted file mode 100644 index fa6dca7aca..0000000000 --- a/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp +++ /dev/null @@ -1,419 +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 <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); - - QByteArray response; - - QQmlDebugStream rs(&response, QIODevice::WriteOnly); - rs << QByteArray(RESPONSE) << ids.first << true << ids.second; - - emit m_debugService->messageToClient(m_debugService->name(), response); -} - -void AbstractViewInspector::handleMessage(const QByteArray &message) -{ - bool success = true; - QQmlDebugStream 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; - - } - - QByteArray response; - QQmlDebugStream rs(&response, QIODevice::WriteOnly); - rs << QByteArray(RESPONSE) << requestId << success; - emit m_debugService->messageToClient(m_debugService->name(), response); -} - -void AbstractViewInspector::sendCurrentObjects(const QList<QObject*> &objects) -{ - QByteArray message; - QQmlDebugStream ds(&message, QIODevice::WriteOnly); - - 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(), message); -} - -void AbstractViewInspector::sendQmlFileReloaded(bool success) -{ - if (m_reloadEventId == -1) - return; - - QByteArray response; - - QQmlDebugStream rs(&response, QIODevice::WriteOnly); - rs << QByteArray(RESPONSE) << m_reloadEventId << success; - - emit m_debugService->messageToClient(m_debugService->name(), response); -} - -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..2150b68f32 --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp @@ -0,0 +1,406 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $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/globalinspector.h b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.h new file mode 100644 index 0000000000..7bbe6d6aa2 --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GLOBALINSPECTOR_H +#define GLOBALINSPECTOR_H + +#include "qquickwindowinspector.h" + +#include <QtCore/QObject> +#include <QtCore/QPointer> +#include <QtCore/QHash> +#include <QtQuick/QQuickItem> + +QT_BEGIN_NAMESPACE + +namespace QmlJSDebugger { + +class SelectionHighlight; + +class GlobalInspector : public QObject +{ + Q_OBJECT +public: + GlobalInspector(QObject *parent = 0) : QObject(parent), m_eventId(0) {} + ~GlobalInspector(); + + void setSelectedItems(const QList<QQuickItem *> &items); + void showSelectedItemName(QQuickItem *item, const QPointF &point); + + 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); + +signals: + void messageToClient(const QString &name, const QByteArray &data); + +private slots: + void sendResult(int requestId, bool success); + +private: + 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; + QList<QQuickWindowInspector *> m_windowInspectors; + int m_eventId; +}; + +} // QmlJSDebugger + +QT_END_NAMESPACE + +#endif // GLOBALINSPECTOR_H diff --git a/src/plugins/qmltooling/qmldbg_inspector/highlight.cpp b/src/plugins/qmltooling/qmldbg_inspector/highlight.cpp index 4d4e3aa720..26eb0f8ed8 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/highlight.cpp +++ b/src/plugins/qmltooling/qmldbg_inspector/highlight.cpp @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** 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. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.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. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/qmltooling/qmldbg_inspector/highlight.h b/src/plugins/qmltooling/qmldbg_inspector/highlight.h index 05f6382353..4a85cb4d50 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/highlight.h +++ b/src/plugins/qmltooling/qmldbg_inspector/highlight.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** 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. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.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. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp index cc6b4ffb8c..7527bc41c7 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp +++ b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp @@ -1,45 +1,50 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** 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. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.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. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #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 +57,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 +85,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 +93,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 +101,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 +116,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 +123,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 +132,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,108 +156,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(); - } - - return 1.0f; -} - -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)) @@ -391,8 +167,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; } } @@ -402,24 +178,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..933c162dad 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/inspecttool.h +++ b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** 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. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.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. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,85 +40,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 03446768a6..a8844944e0 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro +++ b/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro @@ -1,23 +1,22 @@ TARGET = qmldbg_inspector -QT += qml-private quick-private core-private gui-private +QT += qml-private quick-private core-private gui-private packetprotocol-private 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 1707091df3..48a3f656b0 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp +++ b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp @@ -1,120 +1,135 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** 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. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.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. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #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 *); - void removeView(QObject *); + 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); - virtual void messageReceived(const QByteArray &); + 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/qqmlinspectorservicefactory.h b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservicefactory.h index 52f84a362d..09e6a01f96 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservicefactory.h +++ b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservicefactory.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** 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. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.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. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** 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/qquickviewinspector.h b/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.h deleted file mode 100644 index e823e5a03d..0000000000 --- a/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.h +++ /dev/null @@ -1,109 +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 QQUICKVIEWINSPECTOR_H -#define QQUICKVIEWINSPECTOR_H - -#include "abstractviewinspector.h" - -#include <QtCore/QPointer> -#include <QtCore/QHash> -#include <QtQuick/QQuickView> - -QT_BEGIN_NAMESPACE -class QQuickView; -class QQuickItem; - -namespace QmlJSDebugger { - -class InspectTool; -class SelectionHighlight; - -class QQuickViewInspector : public AbstractViewInspector -{ - Q_OBJECT -public: - explicit QQuickViewInspector(QQmlDebugService *service, QQuickView *view, QObject *parent = 0); - - // 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 showSelectedItemName(QQuickItem *item, const QPointF &point); - - void reloadQmlFile(const QHash<QString, QByteArray> &changesHash); - -protected: - bool eventFilter(QObject *obj, QEvent *event); - - bool mouseMoveEvent(QMouseEvent *); - - void setShowAppOnTop(bool appOnTop); - -private slots: - void removeFromSelectedItems(QObject *); - void onViewStatus(QQuickView::Status status); - void applyAppOnTop(); - -private: - bool syncSelectedItems(const QList<QQuickItem*> &items); - - QQuickView *m_view; - QQuickItem *m_overlay; - - InspectTool *m_inspectTool; - - QList<QPointer<QQuickItem> > m_selectedItems; - QHash<QQuickItem*, SelectionHighlight*> m_highlightItems; - bool m_sendQmlReloadedMessage; - bool m_appOnTop; -}; - -} // namespace QmlJSDebugger - -QT_END_NAMESPACE - -#endif // QQUICKVIEWINSPECTOR_H diff --git a/src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.cpp new file mode 100644 index 0000000000..2525500e65 --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.cpp @@ -0,0 +1,232 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $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/qquickwindowinspector.h b/src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.h new file mode 100644 index 0000000000..b37a9face1 --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKWINDOWINSPECTOR_H +#define QQUICKWINDOWINSPECTOR_H + +#include <QtCore/QObject> + +QT_BEGIN_NAMESPACE + +class QQmlDebugService; +class QQuickWindow; +class QQmlEngine; +class QWindow; +class QQuickItem; + +namespace QmlJSDebugger { + +class InspectTool; +class GlobalInspector; + +/* + * The common code between QQuickView and QQuickView inspectors lives here, + */ +class QQuickWindowInspector : public QObject +{ + Q_OBJECT + +public: + explicit QQuickWindowInspector(QQuickWindow *quickWindow, QObject *parent = 0); + + QQuickItem *overlay() const { return m_overlay; } + QQuickItem *topVisibleItemAt(const QPointF &pos) const; + QList<QQuickItem *> itemsAt(const QPointF &pos) const; + + QQuickWindow *quickWindow() const; + + void setParentWindow(QWindow *parentWindow); + void setShowAppOnTop(bool appOnTop); + + bool isEnabled() const; + void setEnabled(bool enabled); + +protected: + bool eventFilter(QObject *, QEvent *); + +private: + QQuickItem *m_overlay; + QQuickWindow *m_window; + QWindow *m_parentWindow; + InspectTool *m_tool; +}; + +} // namespace QmlJSDebugger + +QT_END_NAMESPACE + +#endif // QQUICKWINDOWINSPECTOR_H |