aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/imports/folderlistmodel/fileinfothread.cpp14
-rw-r--r--src/imports/folderlistmodel/fileinfothread_p.h2
-rw-r--r--src/imports/folderlistmodel/plugin.cpp1
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.cpp27
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.h3
-rw-r--r--src/plugins/qmltooling/packetprotocol/packetprotocol.pro13
-rw-r--r--src/plugins/qmltooling/packetprotocol/qpacket.cpp112
-rw-r--r--src/plugins/qmltooling/packetprotocol/qpacket_p.h67
-rw-r--r--src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp293
-rw-r--r--src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h (renamed from src/plugins/qmltooling/shared/qpacketprotocol.h)76
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp31
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h15
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro6
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp4
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp31
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h8
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp15
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.h10
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp19
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h23
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp358
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h183
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp87
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h17
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp98
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h21
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp23
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro3
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp8
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp1
-rw-r--r--src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro9
-rw-r--r--src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp65
-rw-r--r--src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.h81
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro3
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp38
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.h28
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp14
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h2
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp88
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h33
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.cpp4
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp115
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h20
-rw-r--r--src/plugins/qmltooling/qmldbg_quickprofiler/qmldbg_quickprofiler.pro20
-rw-r--r--src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp169
-rw-r--r--src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h70
-rw-r--r--src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapterfactory.cpp48
-rw-r--r--src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapterfactory.h63
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro9
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp132
-rw-r--r--src/plugins/qmltooling/qmltooling.pro17
-rw-r--r--src/plugins/qmltooling/shared/qpacketprotocol.cpp531
-rw-r--r--src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h8
-rw-r--r--src/plugins/qmltooling/shared/qqmldebugpacket.h64
-rw-r--r--src/plugins/qmltooling/shared/qqmldebugserver.h2
-rw-r--r--src/qml/debugger/qqmlabstractprofileradapter_p.h14
-rw-r--r--src/qml/debugger/qqmldebug.cpp81
-rw-r--r--src/qml/debugger/qqmldebug.h7
-rw-r--r--src/qml/debugger/qqmldebugconnector.cpp3
-rw-r--r--src/qml/debugger/qqmldebugconnector_p.h10
-rw-r--r--src/qml/debugger/qqmldebugservice.cpp34
-rw-r--r--src/qml/debugger/qqmldebugservice_p.h26
-rw-r--r--src/qml/debugger/qqmldebugserviceinterfaces.cpp2
-rw-r--r--src/qml/debugger/qqmldebugserviceinterfaces_p.h47
-rw-r--r--src/qml/debugger/qqmlprofilerdefinitions_p.h23
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp286
-rw-r--r--src/qml/jsruntime/qv4debugging_p.h159
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp3
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp25
-rw-r--r--src/qml/qml/qqmlboundsignal_p.h4
-rw-r--r--src/qml/qml/qqmlengine.cpp1
-rw-r--r--src/qml/qml/qqmlimport.cpp14
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp7
-rw-r--r--src/qml/qml/qqmlstringconverters.cpp16
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp6
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp12
-rw-r--r--src/qml/types/qqmlconnections.cpp31
-rw-r--r--src/qml/types/qqmlconnections_p.h5
-rw-r--r--src/qmldebug/qmldebug.pro21
-rw-r--r--src/qmldebug/qqmldebugclient.cpp124
-rw-r--r--src/qmldebug/qqmldebugclient_p.h85
-rw-r--r--src/qmldebug/qqmldebugclient_p_p.h66
-rw-r--r--src/qmldebug/qqmldebugconnection.cpp458
-rw-r--r--src/qmldebug/qqmldebugconnection_p.h99
-rw-r--r--src/qmldebug/qqmlenginecontrolclient.cpp147
-rw-r--r--src/qmldebug/qqmlenginecontrolclient_p.h80
-rw-r--r--src/qmldebug/qqmlenginecontrolclient_p_p.h85
-rw-r--r--src/qmldebug/qqmleventlocation_p.h67
-rw-r--r--src/qmldebug/qqmlprofilerclient.cpp354
-rw-r--r--src/qmldebug/qqmlprofilerclient_p.h108
-rw-r--r--src/qmldebug/qqmlprofilerclient_p_p.h64
-rw-r--r--src/quick/items/qquickitem.cpp4
-rw-r--r--src/quick/items/qquicklistview.cpp47
-rw-r--r--src/quick/items/qquickloader.cpp18
-rw-r--r--src/quick/items/qquicktext.cpp4
-rw-r--r--src/quick/items/qquicktextcontrol.cpp2
-rw-r--r--src/quick/items/qquicktextedit_p_p.h4
-rw-r--r--src/quick/items/qquicktextinput.cpp6
-rw-r--r--src/quick/items/qquicktextinput_p_p.h4
-rw-r--r--src/quick/items/qquicktextnode_p.h2
-rw-r--r--src/quick/items/qquickview.cpp10
-rw-r--r--src/quick/items/qquickwindow.cpp16
-rw-r--r--src/quick/qtquick2.cpp4
-rw-r--r--src/quick/scenegraph/util/qsgdistancefieldutil.cpp2
-rw-r--r--src/quick/util/qquickanimatorjob.cpp3
-rw-r--r--src/quick/util/qquickglobal.cpp10
-rw-r--r--src/quick/util/qquickprofiler.cpp117
-rw-r--r--src/quick/util/qquickprofiler_p.h52
-rw-r--r--src/quickwidgets/qquickwidget.cpp21
-rw-r--r--src/src.pro1
112 files changed, 4289 insertions, 1819 deletions
diff --git a/src/imports/folderlistmodel/fileinfothread.cpp b/src/imports/folderlistmodel/fileinfothread.cpp
index ebdfba42a8..731eb45460 100644
--- a/src/imports/folderlistmodel/fileinfothread.cpp
+++ b/src/imports/folderlistmodel/fileinfothread.cpp
@@ -52,7 +52,8 @@ FileInfoThread::FileInfoThread(QObject *parent)
showDirsFirst(false),
showDotAndDotDot(false),
showHidden(false),
- showOnlyReadable(false)
+ showOnlyReadable(false),
+ caseSensitive(true)
{
#ifndef QT_NO_FILESYSTEMWATCHER
watcher = new QFileSystemWatcher(this);
@@ -190,6 +191,14 @@ void FileInfoThread::setShowOnlyReadable(bool on)
condition.wakeAll();
}
+void FileInfoThread::setCaseSensitive(bool on)
+{
+ QMutexLocker locker(&mutex);
+ caseSensitive = on;
+ folderUpdate = true;
+ condition.wakeAll();
+}
+
#ifndef QT_NO_FILESYSTEMWATCHER
void FileInfoThread::updateFile(const QString &path)
{
@@ -228,7 +237,8 @@ void FileInfoThread::run()
void FileInfoThread::getFileInfos(const QString &path)
{
QDir::Filters filter;
- filter = QDir::CaseSensitive;
+ if (caseSensitive)
+ filter = QDir::CaseSensitive;
if (showFiles)
filter = filter | QDir::Files;
if (showDirs)
diff --git a/src/imports/folderlistmodel/fileinfothread_p.h b/src/imports/folderlistmodel/fileinfothread_p.h
index b375584ff8..5f62f39a20 100644
--- a/src/imports/folderlistmodel/fileinfothread_p.h
+++ b/src/imports/folderlistmodel/fileinfothread_p.h
@@ -79,6 +79,7 @@ public:
void setShowDotAndDotDot(bool on);
void setShowHidden(bool on);
void setShowOnlyReadable(bool on);
+ void setCaseSensitive(bool on);
public Q_SLOTS:
#ifndef QT_NO_FILESYSTEMWATCHER
@@ -113,6 +114,7 @@ private:
bool showDotAndDotDot;
bool showHidden;
bool showOnlyReadable;
+ bool caseSensitive;
};
#endif // FILEINFOTHREAD_P_H
diff --git a/src/imports/folderlistmodel/plugin.cpp b/src/imports/folderlistmodel/plugin.cpp
index a2536bdc7d..7280fcd1dc 100644
--- a/src/imports/folderlistmodel/plugin.cpp
+++ b/src/imports/folderlistmodel/plugin.cpp
@@ -52,6 +52,7 @@ public:
qmlRegisterType<QQuickFolderListModel>(uri,1,0,"FolderListModel");
qmlRegisterType<QQuickFolderListModel>(uri,2,0,"FolderListModel");
qmlRegisterType<QQuickFolderListModel,1>(uri,2,1,"FolderListModel");
+ qmlRegisterType<QQuickFolderListModel,2>(uri,2,2,"FolderListModel");
#endif
}
};
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
index 8bfbf09769..839e0f42c7 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
@@ -49,7 +49,7 @@ public:
: q_ptr(q),
sortField(QQuickFolderListModel::Name), sortReversed(false), showFiles(true),
showDirs(true), showDirsFirst(false), showDotAndDotDot(false), showOnlyReadable(false),
- showHidden(false)
+ showHidden(false), caseSensitive(true)
{
nameFilters << QLatin1String("*");
}
@@ -70,6 +70,7 @@ public:
bool showDotAndDotDot;
bool showOnlyReadable;
bool showHidden;
+ bool caseSensitive;
~QQuickFolderListModelPrivate() {}
void init();
@@ -762,6 +763,30 @@ void QQuickFolderListModel::setShowOnlyReadable(bool on)
}
/*!
+ * \qmlproperty bool FolderListModel::caseSensitive
+ * \since 5.7
+ *
+ * Use case sensitive pattern matching.
+ *
+ * By default, this property is true.
+ *
+ */
+bool QQuickFolderListModel::caseSensitive() const
+{
+ Q_D(const QQuickFolderListModel);
+ return d->caseSensitive;
+}
+
+void QQuickFolderListModel::setCaseSensitive(bool on)
+{
+ Q_D(QQuickFolderListModel);
+
+ if (on != d->caseSensitive) {
+ d->fileInfoThread.setCaseSensitive(on);
+ }
+}
+
+/*!
\qmlmethod var FolderListModel::get(int index, string property)
Get the folder property for the given index. The following properties
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.h b/src/imports/folderlistmodel/qquickfolderlistmodel.h
index fcfec56c87..4b540742b4 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.h
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.h
@@ -67,6 +67,7 @@ class QQuickFolderListModel : public QAbstractListModel, public QQmlParserStatus
Q_PROPERTY(bool showDotAndDotDot READ showDotAndDotDot WRITE setShowDotAndDotDot)
Q_PROPERTY(bool showHidden READ showHidden WRITE setShowHidden REVISION 1)
Q_PROPERTY(bool showOnlyReadable READ showOnlyReadable WRITE setShowOnlyReadable)
+ Q_PROPERTY(bool caseSensitive READ caseSensitive WRITE setCaseSensitive REVISION 2)
Q_PROPERTY(int count READ count NOTIFY countChanged)
//![class props]
@@ -128,6 +129,8 @@ public:
void setShowHidden(bool on);
bool showOnlyReadable() const;
void setShowOnlyReadable(bool on);
+ bool caseSensitive() const;
+ void setCaseSensitive(bool on);
//![prop funcs]
Q_INVOKABLE bool isFolder(int index) const;
diff --git a/src/plugins/qmltooling/packetprotocol/packetprotocol.pro b/src/plugins/qmltooling/packetprotocol/packetprotocol.pro
new file mode 100644
index 0000000000..383e32b54e
--- /dev/null
+++ b/src/plugins/qmltooling/packetprotocol/packetprotocol.pro
@@ -0,0 +1,13 @@
+TARGET = QtPacketProtocol
+QT = core-private qml-private
+CONFIG += static internal_module
+
+HEADERS = \
+ qpacketprotocol_p.h \
+ qpacket_p.h
+
+SOURCES = \
+ qpacketprotocol.cpp \
+ qpacket.cpp
+
+load(qt_module)
diff --git a/src/plugins/qmltooling/packetprotocol/qpacket.cpp b/src/plugins/qmltooling/packetprotocol/qpacket.cpp
new file mode 100644
index 0000000000..1bb611ab25
--- /dev/null
+++ b/src/plugins/qmltooling/packetprotocol/qpacket.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** 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 "qpacket_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QPacket
+ \internal
+
+ \brief The QPacket class encapsulates an unfragmentable packet of data to be
+ transmitted by QPacketProtocol.
+
+ The QPacket class works together with QPacketProtocol to make it simple to
+ send arbitrary sized data "packets" across fragmented transports such as TCP
+ and UDP.
+
+ QPacket provides a QDataStream interface to an unfragmentable packet.
+ Applications should construct a QPacket, propagate it with data and then
+ transmit it over a QPacketProtocol instance. For example:
+ \code
+ int version = QDataStream::Qt_DefaultCompiledVersion;
+ QPacketProtocol protocol(...);
+
+ QPacket myPacket(version);
+ myPacket << "Hello world!" << 123;
+ protocol.send(myPacket.data());
+ \endcode
+
+ As long as both ends of the connection are using the QPacketProtocol class
+ and the same data stream version, the data within this packet will be
+ delivered unfragmented at the other end, ready for extraction.
+
+ \code
+ QByteArray greeting;
+ int count;
+
+ QPacket myPacket(version, protocol.read());
+
+ myPacket >> greeting >> count;
+ \endcode
+
+ Only packets constructed from raw byte arrays may be read from. Empty QPacket
+ instances are for transmission only and are considered "write only". Attempting
+ to read data from them will result in undefined behavior.
+
+ \ingroup io
+ \sa QPacketProtocol
+ */
+
+
+/*!
+ Constructs an empty write-only packet.
+ */
+QPacket::QPacket(int version)
+{
+ buf.open(QIODevice::WriteOnly);
+ setDevice(&buf);
+ setVersion(version);
+}
+
+/*!
+ Constructs a read-only packet.
+ */
+QPacket::QPacket(int version, const QByteArray &data)
+{
+ buf.setData(data);
+ buf.open(QIODevice::ReadOnly);
+ setDevice(&buf);
+ setVersion(version);
+}
+
+/*!
+ Returns raw packet data.
+ */
+QByteArray QPacket::data() const
+{
+ return buf.data();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/packetprotocol/qpacket_p.h b/src/plugins/qmltooling/packetprotocol/qpacket_p.h
new file mode 100644
index 0000000000..dda152dfd1
--- /dev/null
+++ b/src/plugins/qmltooling/packetprotocol/qpacket_p.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** 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 QPACKET_H
+#define QPACKET_H
+
+#include <QtCore/qdatastream.h>
+#include <QtCore/qbuffer.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QPacket : public QDataStream
+{
+public:
+ QPacket(int version);
+ explicit QPacket(int version, const QByteArray &ba);
+ QByteArray data() const;
+
+private:
+ void init(QIODevice::OpenMode mode);
+ QBuffer buf;
+};
+
+QT_END_NAMESPACE
+
+#endif // QPACKET_H
diff --git a/src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp b/src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp
new file mode 100644
index 0000000000..d576e74e53
--- /dev/null
+++ b/src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp
@@ -0,0 +1,293 @@
+/****************************************************************************
+**
+** 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 "qpacketprotocol_p.h"
+
+#include <QtCore/QElapsedTimer>
+#include <private/qiodevice_p.h>
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const int MAX_PACKET_SIZE = 0x7FFFFFFF;
+
+/*!
+ \class QPacketProtocol
+ \internal
+
+ \brief The QPacketProtocol class encapsulates communicating discrete packets
+ across fragmented IO channels, such as TCP sockets.
+
+ QPacketProtocol makes it simple to send arbitrary sized data "packets" across
+ fragmented transports such as TCP and UDP.
+
+ As transmission boundaries are not respected, sending packets over protocols
+ like TCP frequently involves "stitching" them back together at the receiver.
+ QPacketProtocol makes this easier by performing this task for you. Packet
+ data sent using QPacketProtocol is prepended with a 4-byte size header
+ allowing the receiving QPacketProtocol to buffer the packet internally until
+ it has all been received. QPacketProtocol does not perform any sanity
+ checking on the size or on the data, so this class should only be used in
+ prototyping or trusted situations where DOS attacks are unlikely.
+
+ QPacketProtocol does not perform any communications itself. Instead it can
+ operate on any QIODevice that supports the QIODevice::readyRead() signal. A
+ logical "packet" is simply a QByteArray. The following example how to send
+ data using QPacketProtocol.
+
+ \code
+ QTcpSocket socket;
+ // ... connect socket ...
+
+ QPacketProtocol protocol(&socket);
+
+ // Send a packet
+ QDataStream packet;
+ packet << "Hello world" << 123;
+ protocol.send(packet.data());
+ \endcode
+
+ Likewise, the following shows how to read data from QPacketProtocol, assuming
+ that the QPacketProtocol::readyRead() signal has been emitted.
+
+ \code
+ // ... QPacketProtocol::readyRead() is emitted ...
+
+ int a;
+ QByteArray b;
+
+ // Receive packet
+ QDataStream packet(protocol.read());
+ p >> a >> b;
+ \endcode
+
+ \ingroup io
+*/
+
+class QPacketProtocolPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QPacketProtocol)
+public:
+ QPacketProtocolPrivate(QIODevice *dev);
+
+ QList<qint64> sendingPackets;
+ QList<QByteArray> packets;
+ QByteArray inProgress;
+ qint32 inProgressSize;
+ bool waitingForPacket;
+ QIODevice *dev;
+};
+
+/*!
+ Construct a QPacketProtocol instance that works on \a dev with the
+ specified \a parent.
+ */
+QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent)
+ : QObject(*(new QPacketProtocolPrivate(dev)), parent)
+{
+ Q_ASSERT(4 == sizeof(qint32));
+ Q_ASSERT(dev);
+
+ QObject::connect(dev, SIGNAL(readyRead()),
+ this, SLOT(readyToRead()));
+ QObject::connect(dev, SIGNAL(aboutToClose()),
+ this, SLOT(aboutToClose()));
+ QObject::connect(dev, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(bytesWritten(qint64)));
+}
+
+/*!
+ \fn void QPacketProtocol::send(const QByteArray &data)
+
+ Transmit the \a packet.
+ */
+void QPacketProtocol::send(const QByteArray &data)
+{
+ Q_D(QPacketProtocol);
+
+ if (data.isEmpty())
+ return; // We don't send empty packets
+ qint64 sendSize = data.size() + sizeof(qint32);
+
+ d->sendingPackets.append(sendSize);
+ qint32 sendSize32 = sendSize;
+ qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
+ Q_UNUSED(writeBytes);
+ Q_ASSERT(writeBytes == sizeof(qint32));
+ writeBytes = d->dev->write(data);
+ Q_ASSERT(writeBytes == data.size());
+}
+
+/*!
+ Returns the number of received packets yet to be read.
+ */
+qint64 QPacketProtocol::packetsAvailable() const
+{
+ Q_D(const QPacketProtocol);
+ return d->packets.count();
+}
+
+/*!
+ Return the next unread packet, or an empty QByteArray if no packets
+ are available. This method does NOT block.
+ */
+QByteArray QPacketProtocol::read()
+{
+ Q_D(QPacketProtocol);
+ return d->packets.isEmpty() ? QByteArray() : d->packets.takeFirst();
+}
+
+/*!
+ This function locks until a new packet is available for reading and the
+ \l{QIODevice::}{readyRead()} signal has been emitted. The function
+ will timeout after \a msecs milliseconds; the default timeout is
+ 30000 milliseconds.
+
+ The function returns true if the readyRead() signal is emitted and
+ there is new data available for reading; otherwise it returns false
+ (if an error occurred or the operation timed out).
+ */
+
+bool QPacketProtocol::waitForReadyRead(int msecs)
+{
+ Q_D(QPacketProtocol);
+ if (!d->packets.isEmpty())
+ return true;
+
+ QElapsedTimer stopWatch;
+ stopWatch.start();
+
+ d->waitingForPacket = true;
+ do {
+ if (!d->dev->waitForReadyRead(msecs))
+ return false;
+ if (!d->waitingForPacket)
+ return true;
+ msecs = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
+ } while (true);
+}
+
+/*!
+ Return the QIODevice passed to the QPacketProtocol constructor.
+*/
+void QPacketProtocol::aboutToClose()
+{
+ Q_D(QPacketProtocol);
+ d->inProgress.clear();
+ d->sendingPackets.clear();
+ d->inProgressSize = -1;
+}
+
+void QPacketProtocol::bytesWritten(qint64 bytes)
+{
+ Q_D(QPacketProtocol);
+ Q_ASSERT(!d->sendingPackets.isEmpty());
+
+ while (bytes) {
+ if (d->sendingPackets.at(0) > bytes) {
+ d->sendingPackets[0] -= bytes;
+ bytes = 0;
+ } else {
+ bytes -= d->sendingPackets.at(0);
+ d->sendingPackets.removeFirst();
+ }
+ }
+}
+
+void QPacketProtocol::readyToRead()
+{
+ Q_D(QPacketProtocol);
+ while (true) {
+ // Need to get trailing data
+ if (-1 == d->inProgressSize) {
+ // We need a size header of sizeof(qint32)
+ if (sizeof(qint32) > (uint)d->dev->bytesAvailable())
+ return;
+
+ // Read size header
+ int read = d->dev->read((char *)&d->inProgressSize, sizeof(qint32));
+ Q_ASSERT(read == sizeof(qint32));
+ Q_UNUSED(read);
+
+ // Check sizing constraints
+ if (d->inProgressSize > MAX_PACKET_SIZE) {
+ QObject::disconnect(d->dev, SIGNAL(readyRead()),
+ this, SLOT(readyToRead()));
+ QObject::disconnect(d->dev, SIGNAL(aboutToClose()),
+ this, SLOT(aboutToClose()));
+ QObject::disconnect(d->dev, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(bytesWritten(qint64)));
+ d->dev = 0;
+ emit invalidPacket();
+ return;
+ }
+
+ d->inProgressSize -= sizeof(qint32);
+ } else {
+ d->inProgress.append(d->dev->read(d->inProgressSize - d->inProgress.size()));
+
+ if (d->inProgressSize == d->inProgress.size()) {
+ // Packet has arrived!
+ d->packets.append(d->inProgress);
+ d->inProgressSize = -1;
+ d->inProgress.clear();
+
+ d->waitingForPacket = false;
+ emit readyRead();
+ } else
+ return;
+ }
+ }
+}
+
+QPacketProtocolPrivate::QPacketProtocolPrivate(QIODevice *dev) :
+ inProgressSize(-1), waitingForPacket(false), dev(dev)
+{
+}
+
+/*!
+ \fn void QPacketProtocol::readyRead()
+
+ Emitted whenever a new packet is received. Applications may use
+ QPacketProtocol::read() to retrieve this packet.
+ */
+
+/*!
+ \fn void QPacketProtocol::invalidPacket()
+
+ A packet larger than the maximum allowable packet size was received. The
+ packet will be discarded and, as it indicates corruption in the protocol, no
+ further packets will be received.
+ */
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/shared/qpacketprotocol.h b/src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h
index c571e8d2b8..20bbc66418 100644
--- a/src/plugins/qmltooling/shared/qpacketprotocol.h
+++ b/src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h
@@ -31,81 +31,49 @@
**
****************************************************************************/
-#ifndef QPACKETPROTOCOL_H
-#define QPACKETPROTOCOL_H
+#ifndef QPACKETPROTOCOL_P_H
+#define QPACKETPROTOCOL_P_H
#include <QtCore/qobject.h>
-#include <QtCore/qdatastream.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
QT_BEGIN_NAMESPACE
class QIODevice;
-class QBuffer;
-class QPacket;
-class QPacketAutoSend;
-class QPacketProtocolPrivate;
+class QPacketProtocolPrivate;
class QPacketProtocol : public QObject
{
Q_OBJECT
+ Q_DECLARE_PRIVATE(QPacketProtocol)
public:
explicit QPacketProtocol(QIODevice *dev, QObject *parent = 0);
- virtual ~QPacketProtocol();
-
- qint32 maximumPacketSize() const;
- qint32 setMaximumPacketSize(qint32);
-
- QPacketAutoSend send();
- void send(const QPacket &);
+ void send(const QByteArray &data);
qint64 packetsAvailable() const;
- QPacket read();
-
+ QByteArray read();
bool waitForReadyRead(int msecs = 3000);
- void clear();
-
- QIODevice *device();
-
Q_SIGNALS:
void readyRead();
void invalidPacket();
- void packetWritten();
-
-private:
- QPacketProtocolPrivate *d;
-};
-
-
-class QPacket : public QDataStream
-{
-public:
- QPacket();
- QPacket(const QPacket &);
- virtual ~QPacket();
-
- void clear();
- bool isEmpty() const;
- QByteArray data() const;
-
-protected:
- friend class QPacketProtocol;
- QPacket(const QByteArray &ba);
- QByteArray b;
- QBuffer *buf;
-};
-
-class QPacketAutoSend : public QPacket
-{
-public:
- virtual ~QPacketAutoSend();
-private:
- friend class QPacketProtocol;
- QPacketAutoSend(QPacketProtocol *);
- QPacketProtocol *p;
+private Q_SLOTS:
+ void aboutToClose();
+ void bytesWritten(qint64 bytes);
+ void readyToRead();
};
QT_END_NAMESPACE
-#endif
+#endif // QPACKETPROTOCOL_P_H
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
index 6bccec08b1..6880417f1d 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
@@ -32,51 +32,48 @@
****************************************************************************/
#include "qdebugmessageservice.h"
+#include "qqmldebugpacket.h"
#include <private/qqmldebugconnector_p.h>
-#include <QDataStream>
-
QT_BEGIN_NAMESPACE
-const QString QDebugMessageService::s_key = QStringLiteral("DebugMessages");
-
void DebugMessageHandler(QtMsgType type, const QMessageLogContext &ctxt,
const QString &buf)
{
- QQmlDebugConnector::service<QDebugMessageService>()->sendDebugMessage(type, ctxt, buf);
+ QQmlDebugConnector::service<QDebugMessageServiceImpl>()->sendDebugMessage(type, ctxt, buf);
}
-QDebugMessageService::QDebugMessageService(QObject *parent) :
- QQmlDebugService(s_key, 2, parent), oldMsgHandler(0),
+QDebugMessageServiceImpl::QDebugMessageServiceImpl(QObject *parent) :
+ QDebugMessageService(2, parent), oldMsgHandler(0),
prevState(QQmlDebugService::NotConnected)
{
// don't execute stateChanged() in parallel
QMutexLocker lock(&initMutex);
+ timer.start();
if (state() == Enabled) {
oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
prevState = Enabled;
}
}
-void QDebugMessageService::sendDebugMessage(QtMsgType type,
+void QDebugMessageServiceImpl::sendDebugMessage(QtMsgType type,
const QMessageLogContext &ctxt,
const QString &buf)
{
//We do not want to alter the message handling mechanism
//We just eavesdrop and forward the messages to a port
//only if a client is connected to it.
- QByteArray message;
- QQmlDebugStream ws(&message, QIODevice::WriteOnly);
+ QQmlDebugPacket ws;
ws << QByteArray("MESSAGE") << type << buf.toUtf8();
- ws << QString::fromLatin1(ctxt.file).toUtf8();
- ws << ctxt.line << QString::fromLatin1(ctxt.function).toUtf8();
+ ws << QByteArray(ctxt.file) << ctxt.line << QByteArray(ctxt.function);
+ ws << QByteArray(ctxt.category) << timer.nsecsElapsed();
- emit messageToClient(name(), message);
+ emit messageToClient(name(), ws.data());
if (oldMsgHandler)
(*oldMsgHandler)(type, ctxt, buf);
}
-void QDebugMessageService::stateChanged(State state)
+void QDebugMessageServiceImpl::stateChanged(State state)
{
QMutexLocker lock(&initMutex);
@@ -93,4 +90,10 @@ void QDebugMessageService::stateChanged(State state)
prevState = state;
}
+void QDebugMessageServiceImpl::synchronizeTime(const QElapsedTimer &otherTimer)
+{
+ QMutexLocker lock(&initMutex);
+ timer = otherTimer;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h
index c0dc41bcd0..a5ff1fc3d7 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h
@@ -45,36 +45,35 @@
// We mean it.
//
-#include <private/qqmldebugservice_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include <QtCore/qlogging.h>
#include <QtCore/qmutex.h>
+#include <QtCore/qelapsedtimer.h>
QT_BEGIN_NAMESPACE
class QDebugMessageServicePrivate;
-class QDebugMessageService : public QQmlDebugService
+class QDebugMessageServiceImpl : public QDebugMessageService
{
Q_OBJECT
public:
- QDebugMessageService(QObject *parent = 0);
+ QDebugMessageServiceImpl(QObject *parent = 0);
- void sendDebugMessage(QtMsgType type, const QMessageLogContext &ctxt,
- const QString &buf);
+ void sendDebugMessage(QtMsgType type, const QMessageLogContext &ctxt, const QString &buf);
+ void synchronizeTime(const QElapsedTimer &otherTimer);
protected:
- static const QString s_key;
-
void stateChanged(State);
private:
- friend class QQmlDebugConnector;
friend class QQmlDebuggerServiceFactory;
QtMessageHandler oldMsgHandler;
QQmlDebugService::State prevState;
QMutex initMutex;
+ QElapsedTimer timer;
};
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro b/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
index 8d1a54e9e4..9db38d2dfe 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
+++ b/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
@@ -1,5 +1,5 @@
TARGET = qmldbg_debugger
-QT = qml-private core-private
+QT = qml-private core-private packetprotocol-private
PLUGIN_TYPE = qmltooling
PLUGIN_CLASS_NAME = QQmlDebuggerServiceFactory
@@ -12,17 +12,21 @@ SOURCES += \
$$PWD/qqmlnativedebugservice.cpp \
$$PWD/qqmlwatcher.cpp \
$$PWD/qv4debugservice.cpp \
+ $$PWD/qv4debugger.cpp \
$$PWD/qv4debuggeragent.cpp \
$$PWD/qv4datacollector.cpp
+
HEADERS += \
$$PWD/../shared/qqmlconfigurabledebugservice.h \
+ $$PWD/../shared/qqmldebugpacket.h \
$$PWD/qdebugmessageservice.h \
$$PWD/qqmldebuggerservicefactory.h \
$$PWD/qqmlenginedebugservice.h \
$$PWD/qqmlnativedebugservice.h \
$$PWD/qqmlwatcher.h \
$$PWD/qv4debugservice.h \
+ $$PWD/qv4debugger.h \
$$PWD/qv4debuggeragent.h \
$$PWD/qv4datacollector.h
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp
index f379352cfa..4690da04d1 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp
@@ -42,8 +42,8 @@ QT_BEGIN_NAMESPACE
QQmlDebugService *QQmlDebuggerServiceFactory::create(const QString &key)
{
- if (key == QDebugMessageService::s_key)
- return new QDebugMessageService(this);
+ if (key == QDebugMessageServiceImpl::s_key)
+ return new QDebugMessageServiceImpl(this);
if (key == QQmlEngineDebugServiceImpl::s_key)
return new QQmlEngineDebugServiceImpl(this);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index 8f53dc6d50..3775a2c1b4 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -33,6 +33,7 @@
#include "qqmlenginedebugservice.h"
#include "qqmlwatcher.h"
+#include "qqmldebugpacket.h"
#include <private/qqmldebugstatesdelegate_p.h>
#include <private/qqmlboundsignal_p.h>
@@ -89,8 +90,7 @@ QDataStream &operator<<(QDataStream &ds,
ds << (int)data.type << data.name;
// check first whether the data can be saved
// (otherwise we assert in QVariant::operator<<)
- QByteArray buffer;
- QDataStream fakeStream(&buffer, QIODevice::WriteOnly);
+ QQmlDebugPacket fakeStream;
if (QMetaType::save(fakeStream, data.value.type(), data.value.constData()))
ds << data.value;
else
@@ -440,21 +440,20 @@ QList<QObject*> QQmlEngineDebugServiceImpl::objectForLocationInfo(const QString
void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
{
- QQmlDebugStream ds(message);
+ QQmlDebugPacket ds(message);
QByteArray type;
int queryId;
ds >> type >> queryId;
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
+ QQmlDebugPacket rs;
if (type == "LIST_ENGINES") {
rs << QByteArray("LIST_ENGINES_R");
rs << queryId << m_engines.count();
for (int ii = 0; ii < m_engines.count(); ++ii) {
- QQmlEngine *engine = m_engines.at(ii);
+ QJSEngine *engine = m_engines.at(ii);
QString engineName = engine->objectName();
int engineId = QQmlDebugService::idForObject(engine);
@@ -617,7 +616,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
rs << QByteArray("SET_METHOD_BODY_R") << queryId << ok;
}
- emit messageToClient(name(), reply);
+ emit messageToClient(name(), rs.data());
}
bool QQmlEngineDebugServiceImpl::setBinding(int objectId,
@@ -769,15 +768,12 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth
void QQmlEngineDebugServiceImpl::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
{
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
-
+ QQmlDebugPacket rs;
rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value);
-
- emit messageToClient(name(), reply);
+ emit messageToClient(name(), rs.data());
}
-void QQmlEngineDebugServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
+void QQmlEngineDebugServiceImpl::engineAboutToBeAdded(QJSEngine *engine)
{
Q_ASSERT(engine);
Q_ASSERT(!m_engines.contains(engine));
@@ -786,7 +782,7 @@ void QQmlEngineDebugServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
emit attachedToEngine(engine);
}
-void QQmlEngineDebugServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine)
+void QQmlEngineDebugServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
{
Q_ASSERT(engine);
Q_ASSERT(m_engines.contains(engine));
@@ -795,7 +791,7 @@ void QQmlEngineDebugServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine)
emit detachedFromEngine(engine);
}
-void QQmlEngineDebugServiceImpl::objectCreated(QQmlEngine *engine, QObject *object)
+void QQmlEngineDebugServiceImpl::objectCreated(QJSEngine *engine, QObject *object)
{
Q_ASSERT(engine);
Q_ASSERT(m_engines.contains(engine));
@@ -804,12 +800,11 @@ void QQmlEngineDebugServiceImpl::objectCreated(QQmlEngine *engine, QObject *obje
int objectId = QQmlDebugService::idForObject(object);
int parentId = QQmlDebugService::idForObject(object->parent());
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
+ QQmlDebugPacket rs;
//unique queryId -1
rs << QByteArray("OBJECT_CREATED") << -1 << engineId << objectId << parentId;
- emit messageToClient(name(), reply);
+ emit messageToClient(name(), rs.data());
}
void QQmlEngineDebugServiceImpl::setStatesDelegate(QQmlDebugStatesDelegate *delegate)
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
index 19a4827f89..a12aa495c3 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
@@ -89,9 +89,9 @@ public:
bool hasNotifySignal;
};
- void engineAboutToBeAdded(QQmlEngine *);
- void engineAboutToBeRemoved(QQmlEngine *);
- void objectCreated(QQmlEngine *, QObject *);
+ void engineAboutToBeAdded(QJSEngine *) Q_DECL_OVERRIDE;
+ void engineAboutToBeRemoved(QJSEngine *) Q_DECL_OVERRIDE;
+ void objectCreated(QJSEngine *, QObject *) Q_DECL_OVERRIDE;
void setStatesDelegate(QQmlDebugStatesDelegate *);
@@ -120,7 +120,7 @@ private:
QList<QObject *> objectForLocationInfo(const QString &filename, int lineNumber,
int columnNumber);
- QList<QQmlEngine *> m_engines;
+ QList<QJSEngine *> m_engines;
QQmlWatcher *m_watch;
QQmlDebugStatesDelegate *m_statesDelegate;
};
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
index f5cc78e77f..a57ef56a84 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
@@ -32,6 +32,7 @@
****************************************************************************/
#include "qqmlnativedebugservice.h"
+#include "qqmldebugpacket.h"
#include <private/qqmldebugconnector_p.h>
#include <private/qv4debugging_p.h>
@@ -46,8 +47,7 @@
#include <private/qv4isel_moth_p.h>
#include <private/qqmldebugserviceinterfaces_p.h>
-#include <qqmlengine.h>
-
+#include <QtQml/qjsengine.h>
#include <QtCore/qjsonarray.h>
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
@@ -313,16 +313,15 @@ void NativeDebugger::handleCommand(QJsonObject *response, const QString &cmd,
static QString encodeContext(QV4::ExecutionContext *executionContext)
{
- QByteArray ba;
- QDataStream ds(&ba, QIODevice::WriteOnly);
+ QQmlDebugPacket ds;
ds << quintptr(executionContext);
- return QString::fromLatin1(ba.toHex());
+ return QString::fromLatin1(ds.data().toHex());
}
static void decodeContext(const QString &context, QV4::ExecutionContext **executionContext)
{
quintptr rawContext;
- QDataStream ds(QByteArray::fromHex(context.toLatin1()));
+ QQmlDebugPacket ds(QByteArray::fromHex(context.toLatin1()));
ds >> rawContext;
*executionContext = reinterpret_cast<QV4::ExecutionContext *>(rawContext);
}
@@ -724,7 +723,7 @@ QQmlNativeDebugServiceImpl::~QQmlNativeDebugServiceImpl()
delete m_breakHandler;
}
-void QQmlNativeDebugServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
+void QQmlNativeDebugServiceImpl::engineAboutToBeAdded(QJSEngine *engine)
{
TRACE_PROTOCOL("Adding engine" << engine);
if (engine) {
@@ -741,7 +740,7 @@ void QQmlNativeDebugServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
QQmlDebugService::engineAboutToBeAdded(engine);
}
-void QQmlNativeDebugServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine)
+void QQmlNativeDebugServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
{
TRACE_PROTOCOL("Removing engine" << engine);
if (engine) {
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.h b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.h
index 9d0780a203..5ebf0a7f54 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.h
@@ -68,14 +68,14 @@ class QQmlNativeDebugServiceImpl : public QQmlNativeDebugService
public:
QQmlNativeDebugServiceImpl(QObject *parent);
- ~QQmlNativeDebugServiceImpl();
+ ~QQmlNativeDebugServiceImpl() Q_DECL_OVERRIDE;
- void engineAboutToBeAdded(QQmlEngine *engine);
- void engineAboutToBeRemoved(QQmlEngine *engine);
+ void engineAboutToBeAdded(QJSEngine *engine) Q_DECL_OVERRIDE;
+ void engineAboutToBeRemoved(QJSEngine *engine) Q_DECL_OVERRIDE;
- void stateAboutToBeChanged(State state);
+ void stateAboutToBeChanged(State state) Q_DECL_OVERRIDE;
- void messageReceived(const QByteArray &message);
+ void messageReceived(const QByteArray &message) Q_DECL_OVERRIDE;
void emitAsynchronousMessageToClient(const QJsonObject &message);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
index 4cca1900de..e3347be14c 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
@@ -40,6 +40,7 @@
#include <private/qv4runtime_p.h>
#include <QtCore/qjsonarray.h>
+#include <QtCore/qjsonobject.h>
QT_BEGIN_NAMESPACE
@@ -208,13 +209,13 @@ QV4DataCollector::Ref QV4DataCollector::addScriptRef(const QString &scriptName)
return ref;
}
-void QV4DataCollector::collectScope(QJsonObject *dict, QV4::Debugging::V4Debugger *debugger,
- int frameNr, int scopeNr)
+void QV4DataCollector::collectScope(QJsonObject *dict, QV4Debugger *debugger, int frameNr,
+ int scopeNr)
{
QStringList names;
Refs refs;
- if (debugger->state() == QV4::Debugging::V4Debugger::Paused) {
+ if (debugger->state() == QV4Debugger::Paused) {
RefHolder holder(this, &refs);
ArgumentCollectJob argumentsJob(m_engine, this, &names, frameNr, scopeNr);
debugger->runInEngine(&argumentsJob);
@@ -344,24 +345,22 @@ const QString &ExpressionEvalJob::exceptionMessage() const
return exception;
}
-GatherSourcesJob::GatherSourcesJob(QV4::ExecutionEngine *engine, int seq)
+GatherSourcesJob::GatherSourcesJob(QV4::ExecutionEngine *engine)
: engine(engine)
- , seq(seq)
{}
void GatherSourcesJob::run()
{
- QStringList sources;
-
foreach (QV4::CompiledData::CompilationUnit *unit, engine->compilationUnits) {
QString fileName = unit->fileName();
if (!fileName.isEmpty())
sources.append(fileName);
}
+}
- QV4::Debugging::V4Debugger *debugger
- = static_cast<QV4::Debugging::V4Debugger *>(engine->debugger);
- emit debugger->sourcesCollected(debugger, sources, seq);
+const QStringList &GatherSourcesJob::result() const
+{
+ return sources;
}
ArgumentCollectJob::ArgumentCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector,
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
index d0e4a4ad18..bfa3bd2fe1 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
@@ -34,8 +34,9 @@
#ifndef QV4DATACOLLECTOR_H
#define QV4DATACOLLECTOR_H
+#include "qv4debugger.h"
#include <private/qv4engine_p.h>
-#include <private/qv4debugging_p.h>
+#include <private/qv4persistent_p.h>
QT_BEGIN_NAMESPACE
@@ -60,8 +61,7 @@ public:
Ref addFunctionRef(const QString &functionName);
Ref addScriptRef(const QString &scriptName);
- void collectScope(QJsonObject *dict, QV4::Debugging::V4Debugger *debugger, int frameNr,
- int scopeNr);
+ void collectScope(QJsonObject *dict, QV4Debugger *debugger, int frameNr, int scopeNr);
QV4::ExecutionEngine *engine() const { return m_engine; }
@@ -101,7 +101,7 @@ private:
QV4DataCollector::Refs *m_previousRefs;
};
-class ExpressionEvalJob: public QV4::Debugging::V4Debugger::JavaScriptJob
+class ExpressionEvalJob: public QV4Debugger::JavaScriptJob
{
QV4DataCollector *collector;
QString exception;
@@ -113,17 +113,18 @@ public:
const QString &exceptionMessage() const;
};
-class GatherSourcesJob: public QV4::Debugging::V4Debugger::Job
+class GatherSourcesJob: public QV4Debugger::Job
{
QV4::ExecutionEngine *engine;
- const int seq;
+ QStringList sources;
public:
- GatherSourcesJob(QV4::ExecutionEngine *engine, int seq);
+ GatherSourcesJob(QV4::ExecutionEngine *engine);
void run();
+ const QStringList &result() const;
};
-class ArgumentCollectJob: public QV4::Debugging::V4Debugger::Job
+class ArgumentCollectJob: public QV4Debugger::Job
{
QV4::ExecutionEngine *engine;
QV4DataCollector *collector;
@@ -137,7 +138,7 @@ public:
void run();
};
-class LocalCollectJob: public QV4::Debugging::V4Debugger::Job
+class LocalCollectJob: public QV4Debugger::Job
{
QV4::ExecutionEngine *engine;
QV4DataCollector *collector;
@@ -151,7 +152,7 @@ public:
void run();
};
-class ThisCollectJob: public QV4::Debugging::V4Debugger::Job
+class ThisCollectJob: public QV4Debugger::Job
{
QV4::ExecutionEngine *engine;
QV4DataCollector *collector;
@@ -165,7 +166,7 @@ public:
bool myRun();
};
-class ExceptionCollectJob: public QV4::Debugging::V4Debugger::Job
+class ExceptionCollectJob: public QV4Debugger::Job
{
QV4::ExecutionEngine *engine;
QV4DataCollector *collector;
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp
new file mode 100644
index 0000000000..6198e2c039
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp
@@ -0,0 +1,358 @@
+/****************************************************************************
+**
+** 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 "qv4debugger.h"
+
+#include <private/qv4scopedvalue_p.h>
+#include <private/qv4script_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QV4Debugger::BreakPoint::BreakPoint(const QString &fileName, int line)
+ : fileName(fileName), lineNumber(line)
+{}
+
+inline uint qHash(const QV4Debugger::BreakPoint &b, uint seed = 0) Q_DECL_NOTHROW
+{
+ return qHash(b.fileName, seed) ^ b.lineNumber;
+}
+
+inline bool operator==(const QV4Debugger::BreakPoint &a,
+ const QV4Debugger::BreakPoint &b)
+{
+ return a.lineNumber == b.lineNumber && a.fileName == b.fileName;
+}
+
+QV4Debugger::JavaScriptJob::JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr,
+ const QString &script)
+ : engine(engine)
+ , frameNr(frameNr)
+ , script(script)
+ , resultIsException(false)
+{}
+
+void QV4Debugger::JavaScriptJob::run()
+{
+ QV4::Scope scope(engine);
+
+ QV4::ExecutionContextSaver saver(scope);
+
+ QV4::ExecutionContext *ctx = engine->currentContext;
+ if (frameNr > 0) {
+ for (int i = 0; i < frameNr; ++i) {
+ ctx = engine->parentContext(ctx);
+ }
+ engine->pushContext(ctx);
+ }
+
+ QV4::Script script(ctx, this->script);
+ script.strictMode = ctx->d()->strictMode;
+ // In order for property lookups in QML to work, we need to disable fast v4 lookups. That
+ // is a side-effect of inheritContext.
+ script.inheritContext = true;
+ script.parse();
+ QV4::ScopedValue result(scope);
+ if (!scope.engine->hasException)
+ result = script.run();
+ if (scope.engine->hasException) {
+ result = scope.engine->catchException();
+ resultIsException = true;
+ }
+ handleResult(result);
+}
+
+bool QV4Debugger::JavaScriptJob::hasExeption() const
+{
+ return resultIsException;
+}
+
+class EvalJob: public QV4Debugger::JavaScriptJob
+{
+ bool result;
+
+public:
+ EvalJob(QV4::ExecutionEngine *engine, const QString &script)
+ : QV4Debugger::JavaScriptJob(engine, /*frameNr*/-1, script)
+ , result(false)
+ {}
+
+ virtual void handleResult(QV4::ScopedValue &result)
+ {
+ this->result = result->toBoolean();
+ }
+
+ bool resultAsBoolean() const
+ {
+ return result;
+ }
+};
+
+QV4Debugger::QV4Debugger(QV4::ExecutionEngine *engine)
+ : m_engine(engine)
+ , m_state(Running)
+ , m_stepping(NotStepping)
+ , m_pauseRequested(false)
+ , m_haveBreakPoints(false)
+ , m_breakOnThrow(false)
+ , m_returnedValue(engine, QV4::Primitive::undefinedValue())
+ , m_gatherSources(0)
+ , m_runningJob(0)
+{
+ static int debuggerId = qRegisterMetaType<QV4Debugger*>();
+ static int pauseReasonId = qRegisterMetaType<QV4Debugger::PauseReason>();
+ Q_UNUSED(debuggerId);
+ Q_UNUSED(pauseReasonId);
+}
+
+QV4::ExecutionEngine *QV4Debugger::engine() const
+{
+ return m_engine;
+}
+
+void QV4Debugger::pause()
+{
+ QMutexLocker locker(&m_lock);
+ if (m_state == Paused)
+ return;
+ m_pauseRequested = true;
+}
+
+void QV4Debugger::resume(Speed speed)
+{
+ QMutexLocker locker(&m_lock);
+ if (m_state != Paused)
+ return;
+
+ if (!m_returnedValue.isUndefined())
+ m_returnedValue.set(m_engine, QV4::Encode::undefined());
+
+ m_currentContext.set(m_engine, *m_engine->currentContext);
+ m_stepping = speed;
+ m_runningCondition.wakeAll();
+}
+
+QV4Debugger::State QV4Debugger::state() const
+{
+ return m_state;
+}
+
+void QV4Debugger::addBreakPoint(const QString &fileName, int lineNumber, const QString &condition)
+{
+ QMutexLocker locker(&m_lock);
+ m_breakPoints.insert(BreakPoint(fileName.mid(fileName.lastIndexOf('/') + 1),
+ lineNumber), condition);
+ m_haveBreakPoints = true;
+}
+
+void QV4Debugger::removeBreakPoint(const QString &fileName, int lineNumber)
+{
+ QMutexLocker locker(&m_lock);
+ m_breakPoints.remove(BreakPoint(fileName.mid(fileName.lastIndexOf('/') + 1),
+ lineNumber));
+ m_haveBreakPoints = !m_breakPoints.isEmpty();
+}
+
+void QV4Debugger::setBreakOnThrow(bool onoff)
+{
+ QMutexLocker locker(&m_lock);
+
+ m_breakOnThrow = onoff;
+}
+
+QV4Debugger::ExecutionState QV4Debugger::currentExecutionState() const
+{
+ ExecutionState state;
+ state.fileName = getFunction()->sourceFile();
+ state.lineNumber = engine()->current->lineNumber;
+
+ return state;
+}
+
+bool QV4Debugger::pauseAtNextOpportunity() const {
+ return m_pauseRequested || m_haveBreakPoints || m_gatherSources || m_stepping >= StepOver;
+}
+
+QVector<QV4::StackFrame> QV4Debugger::stackTrace(int frameLimit) const
+{
+ return m_engine->stackTrace(frameLimit);
+}
+
+void QV4Debugger::maybeBreakAtInstruction()
+{
+ if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
+ return;
+
+ QMutexLocker locker(&m_lock);
+
+ if (m_gatherSources) {
+ m_gatherSources->run();
+ delete m_gatherSources;
+ m_gatherSources = 0;
+ }
+
+ switch (m_stepping) {
+ case StepOver:
+ if (m_currentContext.asManaged()->d() != m_engine->current)
+ break;
+ // fall through
+ case StepIn:
+ pauseAndWait(Step);
+ return;
+ case StepOut:
+ case NotStepping:
+ break;
+ }
+
+ if (m_pauseRequested) { // Serve debugging requests from the agent
+ m_pauseRequested = false;
+ pauseAndWait(PauseRequest);
+ } else if (m_haveBreakPoints) {
+ if (QV4::Function *f = getFunction()) {
+ const int lineNumber = engine()->current->lineNumber;
+ if (reallyHitTheBreakPoint(f->sourceFile(), lineNumber))
+ pauseAndWait(BreakPointHit);
+ }
+ }
+}
+
+void QV4Debugger::enteringFunction()
+{
+ if (m_runningJob)
+ return;
+ QMutexLocker locker(&m_lock);
+
+ if (m_stepping == StepIn) {
+ m_currentContext.set(m_engine, *m_engine->currentContext);
+ }
+}
+
+void QV4Debugger::leavingFunction(const QV4::ReturnedValue &retVal)
+{
+ if (m_runningJob)
+ return;
+ Q_UNUSED(retVal); // TODO
+
+ QMutexLocker locker(&m_lock);
+
+ if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->current) {
+ m_currentContext.set(m_engine, *m_engine->parentContext(m_engine->currentContext));
+ m_stepping = StepOver;
+ m_returnedValue.set(m_engine, retVal);
+ }
+}
+
+void QV4Debugger::aboutToThrow()
+{
+ if (!m_breakOnThrow)
+ return;
+
+ if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
+ return;
+
+ QMutexLocker locker(&m_lock);
+ pauseAndWait(Throwing);
+}
+
+QV4::Function *QV4Debugger::getFunction() const
+{
+ QV4::Scope scope(m_engine);
+ QV4::ExecutionContext *context = m_engine->currentContext;
+ QV4::ScopedFunctionObject function(scope, context->getFunctionObject());
+ if (function)
+ return function->function();
+ else
+ return context->d()->engine->globalCode;
+}
+
+void QV4Debugger::pauseAndWait(PauseReason reason)
+{
+ if (m_runningJob)
+ return;
+
+ m_state = Paused;
+ emit debuggerPaused(this, reason);
+
+ while (true) {
+ m_runningCondition.wait(&m_lock);
+ if (m_runningJob) {
+ m_runningJob->run();
+ m_jobIsRunning.wakeAll();
+ } else {
+ break;
+ }
+ }
+
+ m_state = Running;
+}
+
+bool QV4Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr)
+{
+ QHash<BreakPoint, QString>::iterator it = m_breakPoints.find(
+ BreakPoint(filename.mid(filename.lastIndexOf('/') + 1), linenr));
+ if (it == m_breakPoints.end())
+ return false;
+ QString condition = it.value();
+ if (condition.isEmpty())
+ return true;
+
+ Q_ASSERT(m_runningJob == 0);
+ EvalJob evilJob(m_engine, condition);
+ m_runningJob = &evilJob;
+ m_runningJob->run();
+ m_runningJob = 0;
+
+ return evilJob.resultAsBoolean();
+}
+
+void QV4Debugger::runInEngine(QV4Debugger::Job *job)
+{
+ QMutexLocker locker(&m_lock);
+ runInEngine_havingLock(job);
+}
+
+void QV4Debugger::runInEngine_havingLock(QV4Debugger::Job *job)
+{
+ Q_ASSERT(job);
+ Q_ASSERT(m_runningJob == 0);
+
+ m_runningJob = job;
+ m_runningCondition.wakeAll();
+ m_jobIsRunning.wait(&m_lock);
+ m_runningJob = 0;
+}
+
+QV4Debugger::Job::~Job()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h
new file mode 100644
index 0000000000..adc58141d0
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** 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 QV4DEBUGGER_H
+#define QV4DEBUGGER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qv4debugging_p.h>
+#include <private/qv4function_p.h>
+#include <private/qv4context_p.h>
+#include <private/qv4persistent_p.h>
+
+#include <QtCore/qmutex.h>
+#include <QtCore/qwaitcondition.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV4Debugger : public QV4::Debugging::Debugger
+{
+ Q_OBJECT
+public:
+ struct BreakPoint {
+ BreakPoint(const QString &fileName, int line);
+ QString fileName;
+ int lineNumber;
+ };
+
+ class Job
+ {
+ public:
+ virtual ~Job();
+ virtual void run() = 0;
+ };
+
+ class JavaScriptJob: public Job
+ {
+ QV4::ExecutionEngine *engine;
+ int frameNr;
+ const QString &script;
+ bool resultIsException;
+
+ public:
+ JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, const QString &script);
+ void run();
+ bool hasExeption() const;
+
+ protected:
+ virtual void handleResult(QV4::ScopedValue &result) = 0;
+ };
+
+ enum State {
+ Running,
+ Paused
+ };
+
+ enum Speed {
+ FullThrottle = 0,
+ StepOut,
+ StepOver,
+ StepIn,
+
+ NotStepping = FullThrottle
+ };
+
+ enum PauseReason {
+ PauseRequest,
+ BreakPointHit,
+ Throwing,
+ Step
+ };
+
+ QV4Debugger(QV4::ExecutionEngine *engine);
+
+ QV4::ExecutionEngine *engine() const;
+
+ void pause();
+ void resume(Speed speed);
+
+ State state() const;
+
+ void addBreakPoint(const QString &fileName, int lineNumber,
+ const QString &condition = QString());
+ void removeBreakPoint(const QString &fileName, int lineNumber);
+
+ void setBreakOnThrow(bool onoff);
+
+ // used for testing
+ struct ExecutionState
+ {
+ QString fileName;
+ int lineNumber;
+ };
+ ExecutionState currentExecutionState() const;
+
+ QVector<QV4::StackFrame> stackTrace(int frameLimit = -1) const;
+ QVector<QV4::Heap::ExecutionContext::ContextType> getScopeTypes(int frame = 0) const;
+
+ QV4::Function *getFunction() const;
+ void runInEngine(Job *job);
+
+ // compile-time interface
+ void maybeBreakAtInstruction() Q_DECL_OVERRIDE;
+
+ // execution hooks
+ void enteringFunction() Q_DECL_OVERRIDE;
+ void leavingFunction(const QV4::ReturnedValue &retVal) Q_DECL_OVERRIDE;
+ void aboutToThrow() Q_DECL_OVERRIDE;
+
+ bool pauseAtNextOpportunity() const Q_DECL_OVERRIDE;
+
+signals:
+ void debuggerPaused(QV4Debugger *self, QV4Debugger::PauseReason reason);
+
+private:
+ // requires lock to be held
+ void pauseAndWait(PauseReason reason);
+ bool reallyHitTheBreakPoint(const QString &filename, int linenr);
+ void runInEngine_havingLock(QV4Debugger::Job *job);
+
+ QV4::ExecutionEngine *m_engine;
+ QV4::PersistentValue m_currentContext;
+ QMutex m_lock;
+ QWaitCondition m_runningCondition;
+ State m_state;
+ Speed m_stepping;
+ bool m_pauseRequested;
+ bool m_haveBreakPoints;
+ bool m_breakOnThrow;
+
+ QHash<BreakPoint, QString> m_breakPoints;
+ QV4::PersistentValue m_returnedValue;
+
+ Job *m_gatherSources;
+ Job *m_runningJob;
+ QWaitCondition m_jobIsRunning;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QV4Debugger::PauseReason)
+Q_DECLARE_METATYPE(QV4Debugger*)
+
+#endif // QV4DEBUGGER_H
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
index e33595c629..da43257b24 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
@@ -44,7 +44,7 @@ QV4DebuggerAgent::QV4DebuggerAgent(QV4DebugServiceImpl *debugService)
: m_breakOnThrow(false), m_debugService(debugService)
{}
-QV4::Debugging::V4Debugger *QV4DebuggerAgent::firstDebugger() const
+QV4Debugger *QV4DebuggerAgent::firstDebugger() const
{
// Currently only 1 single engine is supported, so:
if (m_debuggers.isEmpty())
@@ -56,14 +56,13 @@ QV4::Debugging::V4Debugger *QV4DebuggerAgent::firstDebugger() const
bool QV4DebuggerAgent::isRunning() const
{
// Currently only 1 single engine is supported, so:
- if (QV4::Debugging::V4Debugger *debugger = firstDebugger())
- return debugger->state() == QV4::Debugging::V4Debugger::Running;
+ if (QV4Debugger *debugger = firstDebugger())
+ return debugger->state() == QV4Debugger::Running;
else
return false;
}
-void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::V4Debugger *debugger,
- QV4::Debugging::PauseReason reason)
+void QV4DebuggerAgent::debuggerPaused(QV4Debugger *debugger, QV4Debugger::PauseReason reason)
{
Q_UNUSED(reason);
@@ -73,9 +72,9 @@ void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::V4Debugger *debugger,
event.insert(QStringLiteral("type"), QStringLiteral("event"));
switch (reason) {
- case QV4::Debugging::Step:
- case QV4::Debugging::PauseRequest:
- case QV4::Debugging::BreakPoint: {
+ case QV4Debugger::Step:
+ case QV4Debugger::PauseRequest:
+ case QV4Debugger::BreakPointHit: {
event.insert(QStringLiteral("event"), QStringLiteral("break"));
QVector<QV4::StackFrame> frames = debugger->stackTrace(1);
if (frames.isEmpty())
@@ -92,7 +91,7 @@ void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::V4Debugger *debugger,
body.insert(QStringLiteral("breakpoints"), breakPoints);
script.insert(QStringLiteral("name"), topFrame.source);
} break;
- case QV4::Debugging::Throwing:
+ case QV4Debugger::Throwing:
// TODO: complete this!
event.insert(QStringLiteral("event"), QStringLiteral("exception"));
break;
@@ -105,28 +104,7 @@ void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::V4Debugger *debugger,
m_debugService->send(event);
}
-void QV4DebuggerAgent::sourcesCollected(QV4::Debugging::V4Debugger *debugger,
- const QStringList &sources, int requestSequenceNr)
-{
- QJsonArray body;
- foreach (const QString &source, sources) {
- QJsonObject src;
- src[QLatin1String("name")] = source;
- src[QLatin1String("scriptType")] = 4;
- body.append(src);
- }
-
- QJsonObject response;
- response[QLatin1String("success")] = true;
- response[QLatin1String("running")] = debugger->state() == QV4::Debugging::V4Debugger::Running;
- response[QLatin1String("body")] = body;
- response[QLatin1String("command")] = QStringLiteral("scripts");
- response[QLatin1String("request_seq")] = requestSequenceNr;
- response[QLatin1String("type")] = QStringLiteral("response");
- m_debugService->send(response);
-}
-
-void QV4DebuggerAgent::addDebugger(QV4::Debugging::V4Debugger *debugger)
+void QV4DebuggerAgent::addDebugger(QV4Debugger *debugger)
{
Q_ASSERT(!m_debuggers.contains(debugger));
m_debuggers << debugger;
@@ -137,57 +115,50 @@ void QV4DebuggerAgent::addDebugger(QV4::Debugging::V4Debugger *debugger)
if (breakPoint.enabled)
debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
- connect(debugger, SIGNAL(destroyed(QObject*)),
- this, SLOT(handleDebuggerDeleted(QObject*)));
- connect(debugger, SIGNAL(sourcesCollected(QV4::Debugging::V4Debugger*,QStringList,int)),
- this, SLOT(sourcesCollected(QV4::Debugging::V4Debugger*,QStringList,int)),
- Qt::QueuedConnection);
- connect(debugger,
- SIGNAL(debuggerPaused(QV4::Debugging::V4Debugger*,QV4::Debugging::PauseReason)),
- this, SLOT(debuggerPaused(QV4::Debugging::V4Debugger*,QV4::Debugging::PauseReason)),
+ connect(debugger, &QObject::destroyed, this, &QV4DebuggerAgent::handleDebuggerDeleted);
+ connect(debugger, &QV4Debugger::debuggerPaused, this, &QV4DebuggerAgent::debuggerPaused,
Qt::QueuedConnection);
}
-void QV4DebuggerAgent::removeDebugger(QV4::Debugging::V4Debugger *debugger)
+void QV4DebuggerAgent::removeDebugger(QV4Debugger *debugger)
{
m_debuggers.removeAll(debugger);
- disconnect(debugger, SIGNAL(destroyed(QObject*)),
- this, SLOT(handleDebuggerDeleted(QObject*)));
- disconnect(debugger, SIGNAL(sourcesCollected(QV4::Debugging::V4Debugger*,QStringList,int)),
- this, SLOT(sourcesCollected(QV4::Debugging::V4Debugger*,QStringList,int)));
- disconnect(debugger,
- SIGNAL(debuggerPaused(QV4::Debugging::V4Debugger*,QV4::Debugging::PauseReason)),
- this,
- SLOT(debuggerPaused(QV4::Debugging::V4Debugger*,QV4::Debugging::PauseReason)));
+ disconnect(debugger, &QObject::destroyed, this, &QV4DebuggerAgent::handleDebuggerDeleted);
+ disconnect(debugger, &QV4Debugger::debuggerPaused, this, &QV4DebuggerAgent::debuggerPaused);
+}
+
+const QList<QV4Debugger *> &QV4DebuggerAgent::debuggers()
+{
+ return m_debuggers;
}
void QV4DebuggerAgent::handleDebuggerDeleted(QObject *debugger)
{
- m_debuggers.removeAll(static_cast<QV4::Debugging::V4Debugger *>(debugger));
+ m_debuggers.removeAll(static_cast<QV4Debugger *>(debugger));
}
-void QV4DebuggerAgent::pause(QV4::Debugging::V4Debugger *debugger) const
+void QV4DebuggerAgent::pause(QV4Debugger *debugger) const
{
debugger->pause();
}
void QV4DebuggerAgent::pauseAll() const
{
- foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers)
+ foreach (QV4Debugger *debugger, m_debuggers)
pause(debugger);
}
void QV4DebuggerAgent::resumeAll() const
{
- foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers)
- if (debugger->state() == QV4::Debugging::V4Debugger::Paused)
- debugger->resume(QV4::Debugging::V4Debugger::FullThrottle);
+ foreach (QV4Debugger *debugger, m_debuggers)
+ if (debugger->state() == QV4Debugger::Paused)
+ debugger->resume(QV4Debugger::FullThrottle);
}
int QV4DebuggerAgent::addBreakPoint(const QString &fileName, int lineNumber, bool enabled, const QString &condition)
{
if (enabled)
- foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers)
+ foreach (QV4Debugger *debugger, m_debuggers)
debugger->addBreakPoint(fileName, lineNumber, condition);
int id = m_breakPoints.size();
@@ -204,7 +175,7 @@ void QV4DebuggerAgent::removeBreakPoint(int id)
m_breakPoints.remove(id);
if (breakPoint.enabled)
- foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers)
+ foreach (QV4Debugger *debugger, m_debuggers)
debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr);
}
@@ -222,7 +193,7 @@ void QV4DebuggerAgent::enableBreakPoint(int id, bool onoff)
return;
breakPoint.enabled = onoff;
- foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers) {
+ foreach (QV4Debugger *debugger, m_debuggers) {
if (onoff)
debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
else
@@ -245,7 +216,7 @@ void QV4DebuggerAgent::setBreakOnThrow(bool onoff)
{
if (onoff != m_breakOnThrow) {
m_breakOnThrow = onoff;
- foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers)
+ foreach (QV4Debugger *debugger, m_debuggers)
debugger->setBreakOnThrow(onoff);
}
}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h
index eafb408e7a..d133c6954b 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h
@@ -34,7 +34,7 @@
#ifndef QV4DEBUGGERAGENT_H
#define QV4DEBUGGERAGENT_H
-#include <private/qv4debugging_p.h>
+#include "qv4debugger.h"
QT_BEGIN_NAMESPACE
@@ -46,13 +46,14 @@ class QV4DebuggerAgent : public QObject
public:
QV4DebuggerAgent(QV4DebugServiceImpl *m_debugService);
- QV4::Debugging::V4Debugger *firstDebugger() const;
+ QV4Debugger *firstDebugger() const;
bool isRunning() const;
- void addDebugger(QV4::Debugging::V4Debugger *debugger);
- void removeDebugger(QV4::Debugging::V4Debugger *debugger);
+ void addDebugger(QV4Debugger *debugger);
+ void removeDebugger(QV4Debugger *debugger);
+ const QList<QV4Debugger *> &debuggers();
- void pause(QV4::Debugging::V4Debugger *debugger) const;
+ void pause(QV4Debugger *debugger) const;
void pauseAll() const;
void resumeAll() const;
int addBreakPoint(const QString &fileName, int lineNumber, bool enabled = true, const QString &condition = QString());
@@ -65,13 +66,11 @@ public:
void setBreakOnThrow(bool onoff);
public slots:
- void debuggerPaused(QV4::Debugging::V4Debugger *debugger, QV4::Debugging::PauseReason reason);
- void sourcesCollected(QV4::Debugging::V4Debugger *debugger, const QStringList &sources,
- int requestSequenceNr);
+ void debuggerPaused(QV4Debugger *debugger, QV4Debugger::PauseReason reason);
void handleDebuggerDeleted(QObject *debugger);
private:
- QList<QV4::Debugging::V4Debugger *> m_debuggers;
+ QList<QV4Debugger *> m_debuggers;
struct BreakPoint {
QString fileName;
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
index 5233a09992..dbfbcb25bb 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
@@ -33,11 +33,12 @@
#include "qv4debugservice.h"
#include "qqmlengine.h"
+#include "qqmldebugpacket.h"
+
#include <private/qv4engine_p.h>
#include <private/qv4isel_moth_p.h>
#include <private/qv4function_p.h>
#include <private/qqmldebugconnector_p.h>
-
#include <private/qv8engine_p.h>
#include <QtCore/QJsonArray>
@@ -63,7 +64,6 @@ QT_BEGIN_NAMESPACE
class V8CommandHandler;
class UnknownV8CommandHandler;
-int QV4DebugServiceImpl::debuggerIndex = 0;
int QV4DebugServiceImpl::sequence = 0;
class V8CommandHandler
@@ -104,7 +104,7 @@ protected:
void addCommand() { response.insert(QStringLiteral("command"), cmd); }
void addRequestSequence() { response.insert(QStringLiteral("request_seq"), seq); }
void addSuccess(bool success) { response.insert(QStringLiteral("success"), success); }
- void addBody(const QJsonObject &body)
+ void addBody(const QJsonValue &body)
{
response.insert(QStringLiteral("body"), body);
}
@@ -271,7 +271,7 @@ public:
int toFrame = arguments.value(QStringLiteral("toFrame")).toInt(fromFrame + 10);
// no idea what the bottom property is for, so we'll ignore it.
- QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+ QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
QJsonArray frameArray;
QVector<QV4::StackFrame> frames = debugger->stackTrace(toFrame);
@@ -308,7 +308,7 @@ public:
const int frameNr = arguments.value(QStringLiteral("number")).toInt(
debugService->selectedFrame());
- QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+ QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
if (frameNr < 0 || frameNr >= frames.size()) {
createErrorResponse(QStringLiteral("frame command has invalid frame number"));
@@ -341,7 +341,7 @@ public:
debugService->selectedFrame());
const int scopeNr = arguments.value(QStringLiteral("number")).toInt(0);
- QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+ QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
if (frameNr < 0 || frameNr >= frames.size()) {
createErrorResponse(QStringLiteral("scope command has invalid frame number"));
@@ -399,10 +399,10 @@ public:
// decypher the payload:
QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+ QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
if (arguments.empty()) {
- debugger->resume(QV4::Debugging::V4Debugger::FullThrottle);
+ debugger->resume(QV4Debugger::FullThrottle);
} else {
QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
QString stepAction = arguments.value(QStringLiteral("stepaction")).toString();
@@ -411,11 +411,11 @@ public:
qWarning() << "Step count other than 1 is not supported.";
if (stepAction == QStringLiteral("in")) {
- debugger->resume(QV4::Debugging::V4Debugger::StepIn);
+ debugger->resume(QV4Debugger::StepIn);
} else if (stepAction == QStringLiteral("out")) {
- debugger->resume(QV4::Debugging::V4Debugger::StepOut);
+ debugger->resume(QV4Debugger::StepOut);
} else if (stepAction == QStringLiteral("next")) {
- debugger->resume(QV4::Debugging::V4Debugger::StepOver);
+ debugger->resume(QV4Debugger::StepOver);
} else {
createErrorResponse(QStringLiteral("continue command has invalid stepaction"));
return;
@@ -507,11 +507,23 @@ public:
}
// do it:
- QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
- GatherSourcesJob job(debugger->engine(), requestSequenceNr());
+ QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+ GatherSourcesJob job(debugger->engine());
debugger->runInEngine(&job);
- // response will be send by
+ QJsonArray body;
+ foreach (const QString &source, job.result()) {
+ QJsonObject src;
+ src[QLatin1String("name")] = source;
+ src[QLatin1String("scriptType")] = 4;
+ body.append(src);
+ }
+
+ addSuccess(true);
+ addRunning();
+ addBody(body);
+ addCommand();
+ addRequestSequence();
}
};
@@ -550,8 +562,8 @@ public:
virtual void handleRequest()
{
- QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
- if (debugger->state() == QV4::Debugging::V4Debugger::Paused) {
+ QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+ if (debugger->state() == QV4Debugger::Paused) {
QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
QString expression = arguments.value(QStringLiteral("expression")).toString();
const int frame = arguments.value(QStringLiteral("frame")).toInt(0);
@@ -593,7 +605,7 @@ V8CommandHandler *QV4DebugServiceImpl::v8CommandHandler(const QString &command)
QV4DebugServiceImpl::QV4DebugServiceImpl(QObject *parent) :
QQmlConfigurableDebugService<QV4DebugService>(1, parent),
- debuggerAgent(this), version(1), theSelectedFrame(0),
+ debuggerAgent(this), theSelectedFrame(0),
unknownV8CommandHandler(new UnknownV8CommandHandler)
{
addHandler(new V8VersionRequest);
@@ -615,7 +627,7 @@ QV4DebugServiceImpl::~QV4DebugServiceImpl()
qDeleteAll(handlers);
}
-void QV4DebugServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
+void QV4DebugServiceImpl::engineAboutToBeAdded(QJSEngine *engine)
{
QMutexLocker lock(&m_configMutex);
if (engine) {
@@ -623,10 +635,9 @@ void QV4DebugServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
if (QQmlDebugConnector *server = QQmlDebugConnector::instance()) {
if (ee) {
ee->iselFactory.reset(new QV4::Moth::ISelFactory);
- QV4::Debugging::V4Debugger *debugger = new QV4::Debugging::V4Debugger(ee);
+ QV4Debugger *debugger = new QV4Debugger(ee);
if (state() == Enabled)
ee->setDebugger(debugger);
- debuggerMap.insert(debuggerIndex++, debugger);
debuggerAgent.addDebugger(debugger);
debuggerAgent.moveToThread(server->thread());
}
@@ -635,25 +646,15 @@ void QV4DebugServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
QQmlConfigurableDebugService<QV4DebugService>::engineAboutToBeAdded(engine);
}
-void QV4DebugServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine)
+void QV4DebugServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
{
QMutexLocker lock(&m_configMutex);
if (engine){
const QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
if (ee) {
- QV4::Debugging::V4Debugger *debugger
- = qobject_cast<QV4::Debugging::V4Debugger *>(ee->debugger);
- if (debugger) {
- typedef QMap<int, QV4::Debugging::V4Debugger *>::const_iterator DebuggerMapIterator;
- const DebuggerMapIterator end = debuggerMap.constEnd();
- for (DebuggerMapIterator i = debuggerMap.constBegin(); i != end; ++i) {
- if (i.value() == debugger) {
- debuggerMap.remove(i.key());
- break;
- }
- }
+ QV4Debugger *debugger = qobject_cast<QV4Debugger *>(ee->debugger);
+ if (debugger)
debuggerAgent.removeDebugger(debugger);
- }
}
}
QQmlConfigurableDebugService<QV4DebugService>::engineAboutToBeRemoved(engine);
@@ -663,12 +664,10 @@ void QV4DebugServiceImpl::stateAboutToBeChanged(State state)
{
QMutexLocker lock(&m_configMutex);
if (state == Enabled) {
- typedef QMap<int, QV4::Debugging::V4Debugger *>::const_iterator DebuggerMapIterator;
- const DebuggerMapIterator end = debuggerMap.constEnd();
- for (DebuggerMapIterator i = debuggerMap.constBegin(); i != end; ++i) {
- QV4::ExecutionEngine *ee = i.value()->engine();
+ foreach (QV4Debugger *debugger, debuggerAgent.debuggers()) {
+ QV4::ExecutionEngine *ee = debugger->engine();
if (!ee->debugger)
- ee->setDebugger(i.value());
+ ee->setDebugger(debugger);
}
}
QQmlConfigurableDebugService<QV4DebugService>::stateAboutToBeChanged(state);
@@ -696,7 +695,7 @@ void QV4DebugServiceImpl::messageReceived(const QByteArray &message)
{
QMutexLocker lock(&m_configMutex);
- QQmlDebugStream ms(message);
+ QQmlDebugPacket ms(message);
QByteArray header;
ms >> header;
@@ -737,11 +736,10 @@ void QV4DebugServiceImpl::messageReceived(const QByteArray &message)
void QV4DebugServiceImpl::sendSomethingToSomebody(const char *type, int magicNumber)
{
- QByteArray response;
- QQmlDebugStream rs(&response, QIODevice::WriteOnly);
+ QQmlDebugPacket rs;
rs << QByteArray(type)
- << QByteArray::number(version) << QByteArray::number(magicNumber);
- emit messageToClient(name(), packMessage(type, response));
+ << QByteArray::number(int(version())) << QByteArray::number(magicNumber);
+ emit messageToClient(name(), packMessage(type, rs.data()));
}
void QV4DebugServiceImpl::handleV8Request(const QByteArray &payload)
@@ -761,11 +759,10 @@ void QV4DebugServiceImpl::handleV8Request(const QByteArray &payload)
QByteArray QV4DebugServiceImpl::packMessage(const QByteArray &command, const QByteArray &message)
{
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
+ QQmlDebugPacket rs;
static const QByteArray cmd("V8DEBUG");
rs << cmd << command << message;
- return reply;
+ return rs.data();
}
void QV4DebugServiceImpl::send(QJsonObject v8Payload)
@@ -790,7 +787,7 @@ void QV4DebugServiceImpl::clearHandles(QV4::ExecutionEngine *engine)
}
QJsonObject QV4DebugServiceImpl::buildFrame(const QV4::StackFrame &stackFrame, int frameNr,
- QV4::Debugging::V4Debugger *debugger)
+ QV4Debugger *debugger)
{
QV4DataCollector::Ref ref;
@@ -808,7 +805,7 @@ QJsonObject QV4DebugServiceImpl::buildFrame(const QV4::StackFrame &stackFrame, i
frame[QLatin1String("column")] = stackFrame.column;
QJsonArray scopes;
- if (debugger->state() == QV4::Debugging::V4Debugger::Paused) {
+ if (debugger->state() == QV4Debugger::Paused) {
RefHolder holder(theCollector.data(), &collectedRefs);
bool foundThis = false;
ThisCollectJob job(debugger->engine(), theCollector.data(), frameNr, &foundThis);
@@ -857,8 +854,7 @@ int QV4DebugServiceImpl::encodeScopeType(QV4::Heap::ExecutionContext::ContextTyp
}
}
-QJsonObject QV4DebugServiceImpl::buildScope(int frameNr, int scopeNr,
- QV4::Debugging::V4Debugger *debugger)
+QJsonObject QV4DebugServiceImpl::buildScope(int frameNr, int scopeNr, QV4Debugger *debugger)
{
QJsonObject scope;
@@ -866,7 +862,7 @@ QJsonObject QV4DebugServiceImpl::buildScope(int frameNr, int scopeNr,
RefHolder holder(theCollector.data(), &collectedRefs);
theCollector->collectScope(&object, debugger, frameNr, scopeNr);
- if (debugger->state() == QV4::Debugging::V4Debugger::Paused) {
+ if (debugger->state() == QV4Debugger::Paused) {
QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes =
QV4DataCollector::getScopeTypes(debugger->engine(), frameNr);
scope[QLatin1String("type")] = encodeScopeType(scopeTypes[scopeNr]);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h
index 273e5ffd62..5e6f466ecf 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h
@@ -57,7 +57,6 @@ QT_BEGIN_NAMESPACE
namespace QV4 { struct ExecutionEngine; }
-class QQmlEngine;
class VariableCollector;
class V8CommandHandler;
class UnknownV8CommandHandler;
@@ -68,23 +67,22 @@ class QV4DebugServiceImpl : public QQmlConfigurableDebugService<QV4DebugService>
Q_OBJECT
public:
explicit QV4DebugServiceImpl(QObject *parent = 0);
- ~QV4DebugServiceImpl();
+ ~QV4DebugServiceImpl() Q_DECL_OVERRIDE;
- void engineAboutToBeAdded(QQmlEngine *engine);
- void engineAboutToBeRemoved(QQmlEngine *engine);
+ void engineAboutToBeAdded(QJSEngine *engine) Q_DECL_OVERRIDE;
+ void engineAboutToBeRemoved(QJSEngine *engine) Q_DECL_OVERRIDE;
- void stateAboutToBeChanged(State state);
+ void stateAboutToBeChanged(State state) Q_DECL_OVERRIDE;
- void signalEmitted(const QString &signal);
+ void signalEmitted(const QString &signal) Q_DECL_OVERRIDE;
void send(QJsonObject v8Payload);
- QJsonObject buildScope(int frameNr, int scopeNr, QV4::Debugging::V4Debugger *debugger);
+ QJsonObject buildScope(int frameNr, int scopeNr, QV4Debugger *debugger);
QJsonArray buildRefs();
QJsonValue lookup(QV4DataCollector::Ref refId);
QJsonValue toRef(QV4DataCollector::Ref ref);
- QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr,
- QV4::Debugging::V4Debugger *debugger);
+ QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr, QV4Debugger *debugger);
int selectedFrame() const;
void selectFrame(int frameNr);
@@ -95,7 +93,7 @@ public:
QV4DataCollector::Refs *refs();
protected:
- void messageReceived(const QByteArray &);
+ void messageReceived(const QByteArray &) Q_DECL_OVERRIDE;
void sendSomethingToSomebody(const char *type, int magicNumber = 1);
private:
@@ -109,10 +107,7 @@ private:
int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType);
QStringList breakOnSignals;
- QMap<int, QV4::Debugging::V4Debugger *> debuggerMap;
- static int debuggerIndex;
static int sequence;
- const int version;
QV4DataCollector::Refs collectedRefs;
QScopedPointer<QV4DataCollector> theCollector;
diff --git a/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp
index fa6dca7aca..daf620805f 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp
@@ -33,6 +33,7 @@
#include "abstractviewinspector.h"
#include "abstracttool.h"
+#include "qqmldebugpacket.h"
#include <QtCore/QDebug>
#include <QtQml/QQmlEngine>
@@ -262,18 +263,16 @@ void AbstractViewInspector::onQmlObjectDestroyed(QObject *object)
QPair<int, int> ids = m_hashObjectsTobeDestroyed.take(object);
- QByteArray response;
-
- QQmlDebugStream rs(&response, QIODevice::WriteOnly);
+ QQmlDebugPacket rs;
rs << QByteArray(RESPONSE) << ids.first << true << ids.second;
- emit m_debugService->messageToClient(m_debugService->name(), response);
+ emit m_debugService->messageToClient(m_debugService->name(), rs.data());
}
void AbstractViewInspector::handleMessage(const QByteArray &message)
{
bool success = true;
- QQmlDebugStream ds(message);
+ QQmlDebugPacket ds(message);
QByteArray type;
ds >> type;
@@ -358,16 +357,14 @@ void AbstractViewInspector::handleMessage(const QByteArray &message)
}
- QByteArray response;
- QQmlDebugStream rs(&response, QIODevice::WriteOnly);
+ QQmlDebugPacket rs;
rs << QByteArray(RESPONSE) << requestId << success;
- emit m_debugService->messageToClient(m_debugService->name(), response);
+ emit m_debugService->messageToClient(m_debugService->name(), rs.data());
}
void AbstractViewInspector::sendCurrentObjects(const QList<QObject*> &objects)
{
- QByteArray message;
- QQmlDebugStream ds(&message, QIODevice::WriteOnly);
+ QQmlDebugPacket ds;
ds << QByteArray(EVENT) << m_eventId++ << QByteArray(SELECT);
@@ -377,7 +374,7 @@ void AbstractViewInspector::sendCurrentObjects(const QList<QObject*> &objects)
debugIds << QQmlDebugService::idForObject(object);
ds << debugIds;
- emit m_debugService->messageToClient(m_debugService->name(), message);
+ emit m_debugService->messageToClient(m_debugService->name(), ds.data());
}
void AbstractViewInspector::sendQmlFileReloaded(bool success)
@@ -387,10 +384,10 @@ void AbstractViewInspector::sendQmlFileReloaded(bool success)
QByteArray response;
- QQmlDebugStream rs(&response, QIODevice::WriteOnly);
+ QQmlDebugPacket rs;
rs << QByteArray(RESPONSE) << m_reloadEventId << success;
- emit m_debugService->messageToClient(m_debugService->name(), response);
+ emit m_debugService->messageToClient(m_debugService->name(), rs.data());
}
QString AbstractViewInspector::idStringForObject(QObject *obj) const
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro b/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro
index 1c3e5f387b..dd5cc8ceef 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro
+++ b/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro
@@ -1,5 +1,5 @@
TARGET = qmldbg_inspector
-QT += qml-private quick-private core-private gui-private
+QT += qml-private quick-private core-private gui-private packetprotocol-private
PLUGIN_TYPE = qmltooling
PLUGIN_CLASS_NAME = QQmlInspectorServiceFactory
@@ -16,6 +16,7 @@ SOURCES += \
$$PWD/qqmlinspectorservice.cpp
HEADERS += \
+ $$PWD/../shared/qqmldebugpacket.h \
$$PWD/highlight.h \
$$PWD/qquickviewinspector.h \
$$PWD/qqmlinspectorservicefactory.h \
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp
index 1707091df3..6b786024f8 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp
@@ -50,12 +50,12 @@ class QQmlInspectorServiceImpl : public QQmlInspectorService
public:
QQmlInspectorServiceImpl(QObject *parent = 0);
- void addView(QObject *);
- void removeView(QObject *);
+ void addView(QObject *) Q_DECL_OVERRIDE;
+ void removeView(QObject *) Q_DECL_OVERRIDE;
protected:
- virtual void stateChanged(State state);
- virtual void messageReceived(const QByteArray &);
+ virtual void stateChanged(State state) Q_DECL_OVERRIDE;
+ virtual void messageReceived(const QByteArray &) Q_DECL_OVERRIDE;
private Q_SLOTS:
void processMessage(const QByteArray &message);
diff --git a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
index 057bf9523e..478cbf5514 100644
--- a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
+++ b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
@@ -32,7 +32,6 @@
****************************************************************************/
#include "qlocalclientconnectionfactory.h"
-#include "qpacketprotocol.h"
#include "qqmldebugserver.h"
#include <QtCore/qplugin.h>
diff --git a/src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro b/src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro
index 7dc16b8c44..d490d77e50 100644
--- a/src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro
+++ b/src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro
@@ -1,12 +1,19 @@
TARGET = qmldbg_native
-QT += qml-private core-private
+QT += qml-private core-private packetprotocol-private
PLUGIN_TYPE = qmltooling
PLUGIN_CLASS_NAME = QQmlNativeDebugConnectorFactory
load(qt_plugin)
+HEADERS += \
+ $$PWD/../shared/qqmldebugpacket.h \
+ $$PWD/qqmlnativedebugconnector.h
+
SOURCES += \
$$PWD/qqmlnativedebugconnector.cpp
+INCLUDEPATH += $$PWD \
+ $$PWD/../shared
+
OTHER_FILES += \
$$PWD/qqmlnativedebugconnector.json
diff --git a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp
index 6621eafb27..e4054e100d 100644
--- a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp
+++ b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp
@@ -31,18 +31,18 @@
**
****************************************************************************/
-#include <private/qqmldebugconnector_p.h>
-#include <private/qhooks_p.h>
+#include "qqmlnativedebugconnector.h"
+#include "qqmldebugpacket.h"
-#include <qqmlengine.h>
+#include <private/qhooks_p.h>
+#include <QtQml/qjsengine.h>
#include <QtCore/qdebug.h>
#include <QtCore/qjsonarray.h>
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
#include <QtCore/qjsonvalue.h>
#include <QtCore/qpointer.h>
-#include <QtCore/qvector.h>
//#define TRACE_PROTOCOL(s) qDebug() << s
#define TRACE_PROTOCOL(s)
@@ -65,7 +65,7 @@ Q_DECL_EXPORT void qt_qmlDebugConnectorOpen();
// member to some other place.
Q_DECL_EXPORT void qt_qmlDebugSetStreamVersion(int version)
{
- QQmlDebugStream::s_dataStreamVersion = version;
+ QQmlNativeDebugConnector::setDataStreamVersion(version);
}
@@ -172,33 +172,6 @@ Q_DECL_EXPORT void qt_qmlDebugConnectorOpen()
QT_BEGIN_NAMESPACE
-class QQmlNativeDebugConnector : public QQmlDebugConnector
-{
- Q_OBJECT
-
-public:
- QQmlNativeDebugConnector();
- ~QQmlNativeDebugConnector();
-
- bool blockingMode() const;
- QQmlDebugService *service(const QString &name) const;
- void addEngine(QQmlEngine *engine);
- void removeEngine(QQmlEngine *engine);
- bool addService(const QString &name, QQmlDebugService *service);
- bool removeService(const QString &name);
- bool open(const QVariantHash &configuration);
-
-private slots:
- void sendMessage(const QString &name, const QByteArray &message);
- void sendMessages(const QString &name, const QList<QByteArray> &messages);
-
-private:
- void announceObjectAvailability(const QString &objectType, QObject *object, bool available);
-
- QVector<QQmlDebugService *> m_services;
- bool m_blockingMode;
-};
-
QQmlNativeDebugConnector::QQmlNativeDebugConnector()
: m_blockingMode(false)
{
@@ -250,7 +223,7 @@ QQmlDebugService *QQmlNativeDebugConnector::service(const QString &name) const
return 0;
}
-void QQmlNativeDebugConnector::addEngine(QQmlEngine *engine)
+void QQmlNativeDebugConnector::addEngine(QJSEngine *engine)
{
TRACE_PROTOCOL("Add engine to connector:" << engine);
foreach (QQmlDebugService *service, m_services)
@@ -262,7 +235,7 @@ void QQmlNativeDebugConnector::addEngine(QQmlEngine *engine)
service->engineAdded(engine);
}
-void QQmlNativeDebugConnector::removeEngine(QQmlEngine *engine)
+void QQmlNativeDebugConnector::removeEngine(QJSEngine *engine)
{
TRACE_PROTOCOL("Remove engine from connector:" << engine);
foreach (QQmlDebugService *service, m_services)
@@ -338,6 +311,12 @@ bool QQmlNativeDebugConnector::open(const QVariantHash &configuration)
return true;
}
+void QQmlNativeDebugConnector::setDataStreamVersion(int version)
+{
+ Q_ASSERT(version <= QDataStream::Qt_DefaultCompiledVersion);
+ s_dataStreamVersion = version;
+}
+
void QQmlNativeDebugConnector::sendMessage(const QString &name, const QByteArray &message)
{
(*responseBuffer) += name.toUtf8() + ' ' + QByteArray::number(message.size()) + ' ' + message;
@@ -363,21 +342,9 @@ void QQmlNativeDebugConnector::sendMessages(const QString &name, const QList<QBy
sendMessage(name, messages.at(i));
}
-class QQmlNativeDebugConnectorFactory : public QQmlDebugConnectorFactory
+QQmlDebugConnector *QQmlNativeDebugConnectorFactory::create(const QString &key)
{
- Q_OBJECT
-
- Q_PLUGIN_METADATA(IID QQmlDebugConnectorFactory_iid FILE "qqmlnativedebugconnector.json")
-
-public:
- QQmlNativeDebugConnectorFactory() {}
-
- QQmlDebugConnector *create(const QString &key)
- {
- return key == QLatin1String("QQmlNativeDebugConnector") ? new QQmlNativeDebugConnector : 0;
- }
-};
+ return key == QLatin1String("QQmlNativeDebugConnector") ? new QQmlNativeDebugConnector : 0;
+}
QT_END_NAMESPACE
-
-#include "qqmlnativedebugconnector.moc"
diff --git a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.h b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.h
new file mode 100644
index 0000000000..a883608fd4
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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 QQMLNATIVEDEBUGCONNECTOR_H
+#define QQMLNATIVEDEBUGCONNECTOR_H
+
+#include <private/qqmldebugconnector_p.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlNativeDebugConnector : public QQmlDebugConnector
+{
+ Q_OBJECT
+
+public:
+ QQmlNativeDebugConnector();
+ ~QQmlNativeDebugConnector() Q_DECL_OVERRIDE;
+
+ bool blockingMode() const Q_DECL_OVERRIDE;
+ QQmlDebugService *service(const QString &name) const Q_DECL_OVERRIDE;
+ void addEngine(QJSEngine *engine) Q_DECL_OVERRIDE;
+ void removeEngine(QJSEngine *engine) Q_DECL_OVERRIDE;
+ bool addService(const QString &name, QQmlDebugService *service) Q_DECL_OVERRIDE;
+ bool removeService(const QString &name) Q_DECL_OVERRIDE;
+ bool open(const QVariantHash &configuration) Q_DECL_OVERRIDE;
+ static void setDataStreamVersion(int version);
+
+private slots:
+ void sendMessage(const QString &name, const QByteArray &message);
+ void sendMessages(const QString &name, const QList<QByteArray> &messages);
+
+private:
+ void announceObjectAvailability(const QString &objectType, QObject *object, bool available);
+
+ QVector<QQmlDebugService *> m_services;
+ bool m_blockingMode;
+};
+
+class QQmlNativeDebugConnectorFactory : public QQmlDebugConnectorFactory
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlDebugConnectorFactory_iid FILE "qqmlnativedebugconnector.json")
+public:
+ QQmlDebugConnector *create(const QString &key);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLNATIVEDEBUGCONNECTOR_H
+
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro b/src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro
index e1c4095d88..6efe9eacad 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro
+++ b/src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro
@@ -1,5 +1,5 @@
TARGET = qmldbg_profiler
-QT = qml-private core-private
+QT = qml-private core-private packetprotocol-private
PLUGIN_TYPE = qmltooling
PLUGIN_CLASS_NAME = QQmlProfilerServiceFactory
@@ -14,6 +14,7 @@ SOURCES += \
HEADERS += \
$$PWD/../shared/qqmlconfigurabledebugservice.h \
+ $$PWD/../shared/qqmldebugpacket.h \
$$PWD/qqmlenginecontrolservice.h \
$$PWD/qqmlprofileradapter.h \
$$PWD/qqmlprofilerservice.h \
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp
index 4f131ac481..4da279bb42 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp
@@ -32,25 +32,24 @@
****************************************************************************/
#include "qqmlenginecontrolservice.h"
-#include <QQmlEngine>
+#include "qqmldebugpacket.h"
+#include <QJSEngine>
QT_BEGIN_NAMESPACE
-const QString QQmlEngineControlService::s_key = QStringLiteral("EngineControl");
-
-QQmlEngineControlService::QQmlEngineControlService(QObject *parent) :
- QQmlDebugService(s_key, 1, parent)
+QQmlEngineControlServiceImpl::QQmlEngineControlServiceImpl(QObject *parent) :
+ QQmlEngineControlService(1, parent)
{
}
-void QQmlEngineControlService::messageReceived(const QByteArray &message)
+void QQmlEngineControlServiceImpl::messageReceived(const QByteArray &message)
{
QMutexLocker lock(&dataMutex);
- QQmlDebugStream d(message);
+ QQmlDebugPacket d(message);
int command;
int engineId;
d >> command >> engineId;
- QQmlEngine *engine = qobject_cast<QQmlEngine *>(objectForId(engineId));
+ QJSEngine *engine = qobject_cast<QJSEngine *>(objectForId(engineId));
if (command == StartWaitingEngine && startingEngines.contains(engine)) {
startingEngines.removeOne(engine);
emit attachedToEngine(engine);
@@ -60,7 +59,7 @@ void QQmlEngineControlService::messageReceived(const QByteArray &message)
}
}
-void QQmlEngineControlService::engineAboutToBeAdded(QQmlEngine *engine)
+void QQmlEngineControlServiceImpl::engineAboutToBeAdded(QJSEngine *engine)
{
QMutexLocker lock(&dataMutex);
if (state() == Enabled) {
@@ -73,7 +72,7 @@ void QQmlEngineControlService::engineAboutToBeAdded(QQmlEngine *engine)
}
}
-void QQmlEngineControlService::engineAboutToBeRemoved(QQmlEngine *engine)
+void QQmlEngineControlServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
{
QMutexLocker lock(&dataMutex);
if (state() == Enabled) {
@@ -86,7 +85,7 @@ void QQmlEngineControlService::engineAboutToBeRemoved(QQmlEngine *engine)
}
}
-void QQmlEngineControlService::engineAdded(QQmlEngine *engine)
+void QQmlEngineControlServiceImpl::engineAdded(QJSEngine *engine)
{
if (state() == Enabled) {
QMutexLocker lock(&dataMutex);
@@ -96,7 +95,7 @@ void QQmlEngineControlService::engineAdded(QQmlEngine *engine)
}
}
-void QQmlEngineControlService::engineRemoved(QQmlEngine *engine)
+void QQmlEngineControlServiceImpl::engineRemoved(QJSEngine *engine)
{
if (state() == Enabled) {
QMutexLocker lock(&dataMutex);
@@ -106,22 +105,21 @@ void QQmlEngineControlService::engineRemoved(QQmlEngine *engine)
}
}
-void QQmlEngineControlService::sendMessage(QQmlEngineControlService::MessageType type, QQmlEngine *engine)
+void QQmlEngineControlServiceImpl::sendMessage(QQmlEngineControlServiceImpl::MessageType type, QJSEngine *engine)
{
- QByteArray message;
- QQmlDebugStream d(&message, QIODevice::WriteOnly);
- d << type << idForObject(engine);
- emit messageToClient(name(), message);
+ QQmlDebugPacket d;
+ d << int(type) << idForObject(engine);
+ emit messageToClient(name(), d.data());
}
-void QQmlEngineControlService::stateChanged(State)
+void QQmlEngineControlServiceImpl::stateChanged(State)
{
// We flush everything for any kind of state change, to avoid complicated timing issues.
QMutexLocker lock(&dataMutex);
- foreach (QQmlEngine *engine, startingEngines)
+ foreach (QJSEngine *engine, startingEngines)
emit attachedToEngine(engine);
startingEngines.clear();
- foreach (QQmlEngine *engine, stoppingEngines)
+ foreach (QJSEngine *engine, stoppingEngines)
emit detachedFromEngine(engine);
stoppingEngines.clear();
}
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.h
index e2a93e562a..028852e964 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.h
@@ -35,7 +35,7 @@
#define QQMLENGINECONTROLSERVICE_H
#include <QMutex>
-#include <private/qqmldebugservice_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
//
// W A R N I N G
@@ -50,11 +50,9 @@
QT_BEGIN_NAMESPACE
-class QQmlEngineControlService : public QQmlDebugService
+class QQmlEngineControlServiceImpl : public QQmlEngineControlService
{
public:
- static const QString s_key;
-
enum MessageType {
EngineAboutToBeAdded,
EngineAdded,
@@ -67,22 +65,24 @@ public:
StopWaitingEngine
};
- QQmlEngineControlService(QObject *parent = 0);
+ QQmlEngineControlServiceImpl(QObject *parent = 0);
protected:
+ friend class QQmlProfilerServiceFactory;
+
QMutex dataMutex;
- QList<QQmlEngine *> startingEngines;
- QList<QQmlEngine *> stoppingEngines;
+ QList<QJSEngine *> startingEngines;
+ QList<QJSEngine *> stoppingEngines;
- void messageReceived(const QByteArray &);
- void engineAboutToBeAdded(QQmlEngine *);
- void engineAboutToBeRemoved(QQmlEngine *);
- void engineAdded(QQmlEngine *);
- void engineRemoved(QQmlEngine *);
+ void messageReceived(const QByteArray &) Q_DECL_OVERRIDE;
+ void engineAboutToBeAdded(QJSEngine *) Q_DECL_OVERRIDE;
+ void engineAboutToBeRemoved(QJSEngine *) Q_DECL_OVERRIDE;
+ void engineAdded(QJSEngine *) Q_DECL_OVERRIDE;
+ void engineRemoved(QJSEngine *) Q_DECL_OVERRIDE;
- void sendMessage(MessageType type, QQmlEngine *engine);
+ void sendMessage(MessageType type, QJSEngine *engine);
- void stateChanged(State);
+ void stateChanged(State) Q_DECL_OVERRIDE;
};
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
index 245900abae..faa1726637 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
@@ -32,13 +32,16 @@
****************************************************************************/
#include "qqmlprofileradapter.h"
+#include "qqmldebugpacket.h"
+
#include <private/qqmldebugserviceinterfaces_p.h>
QT_BEGIN_NAMESPACE
QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine) :
- QQmlAbstractProfilerAdapter(service), next(0)
+ next(0)
{
+ setService(service);
engine->enableProfiler();
connect(this, SIGNAL(profilingEnabled(quint64)), engine->profiler, SLOT(startProfiling(quint64)));
connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
@@ -72,13 +75,12 @@ static void qQmlProfilerDataToByteArrays(const QQmlProfilerData *d, QList<QByteA
continue;
//### using QDataStream is relatively expensive
- QQmlDebugStream ds(&data, QIODevice::WriteOnly);
+ QQmlDebugPacket ds;
ds << d->time << decodedMessageType << decodedDetailType;
switch (decodedMessageType) {
case QQmlProfilerDefinitions::RangeStart:
- if (decodedDetailType == (int)QQmlProfilerDefinitions::Binding)
- ds << QQmlProfilerDefinitions::QmlBinding;
+ case QQmlProfilerDefinitions::RangeEnd:
break;
case QQmlProfilerDefinitions::RangeData:
ds << (d->detailString.isEmpty() ? d->detailUrl.toString() : d->detailString);
@@ -87,13 +89,11 @@ static void qQmlProfilerDataToByteArrays(const QQmlProfilerData *d, QList<QByteA
ds << (d->detailUrl.isEmpty() ? d->detailString : d->detailUrl.toString()) << d->x
<< d->y;
break;
- case QQmlProfilerDefinitions::RangeEnd: break;
default:
Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
break;
}
- messages << data;
- data.clear();
+ messages << ds.data();
}
}
}
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
index eceb58ce3a..b15c2febda 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
@@ -54,7 +54,7 @@ class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter {
Q_OBJECT
public:
QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine);
- qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
+ qint64 sendMessages(qint64 until, QList<QByteArray> &messages) Q_DECL_OVERRIDE;
public slots:
void receiveData(const QVector<QQmlProfilerData> &new_data);
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
index 65b99ef7ca..462bd5e394 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
@@ -35,9 +35,11 @@
#include "qv4profileradapter.h"
#include "qqmlprofileradapter.h"
#include "qqmlprofilerservicefactory.h"
-#include <private/qqmlengine_p.h>
+#include "qqmldebugpacket.h"
+
+#include <private/qjsengine_p.h>
+#include <private/qqmldebugpluginmanager_p.h>
-#include <QtCore/qdatastream.h>
#include <QtCore/qurl.h>
#include <QtCore/qtimer.h>
#include <QtCore/qthread.h>
@@ -45,18 +47,27 @@
QT_BEGIN_NAMESPACE
+Q_QML_DEBUG_PLUGIN_LOADER(QQmlAbstractProfilerAdapter)
+Q_QML_IMPORT_DEBUG_PLUGIN(QQuickProfilerAdapterFactory)
+
QQmlProfilerServiceImpl::QQmlProfilerServiceImpl(QObject *parent) :
QQmlConfigurableDebugService<QQmlProfilerService>(1, parent),
m_waitingForStop(false)
{
m_timer.start();
+ QQmlAbstractProfilerAdapter *quickAdapter =
+ loadQQmlAbstractProfilerAdapter(QLatin1String("QQuickProfilerAdapter"));
+ if (quickAdapter) {
+ addGlobalProfiler(quickAdapter);
+ quickAdapter->setService(this);
+ }
}
QQmlProfilerServiceImpl::~QQmlProfilerServiceImpl()
{
// No need to lock here. If any engine or global profiler is still trying to register at this
// point we have a nasty bug anyway.
- qDeleteAll(m_engineProfilers.values());
+ qDeleteAll(m_engineProfilers);
qDeleteAll(m_globalProfilers);
}
@@ -75,8 +86,8 @@ void QQmlProfilerServiceImpl::dataReady(QQmlAbstractProfilerAdapter *profiler)
}
m_startTimes.insert(0, profiler);
if (dataComplete) {
- QList<QQmlEngine *> enginesToRelease;
- foreach (QQmlEngine *engine, m_stoppingEngines) {
+ QList<QJSEngine *> enginesToRelease;
+ foreach (QJSEngine *engine, m_stoppingEngines) {
foreach (QQmlAbstractProfilerAdapter *engineProfiler, m_engineProfilers.values(engine)) {
if (m_startTimes.values().contains(engineProfiler)) {
enginesToRelease.append(engine);
@@ -85,27 +96,30 @@ void QQmlProfilerServiceImpl::dataReady(QQmlAbstractProfilerAdapter *profiler)
}
}
sendMessages();
- foreach (QQmlEngine *engine, enginesToRelease) {
+ foreach (QJSEngine *engine, enginesToRelease) {
m_stoppingEngines.removeOne(engine);
emit detachedFromEngine(engine);
}
}
}
-void QQmlProfilerServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::engineAboutToBeAdded(QJSEngine *engine)
{
Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO,
"QML profilers have to be added from the engine thread");
QMutexLocker lock(&m_configMutex);
- QQmlProfilerAdapter *qmlAdapter = new QQmlProfilerAdapter(this, QQmlEnginePrivate::get(engine));
+ if (QQmlEngine *qmlEngine = qobject_cast<QQmlEngine *>(engine)) {
+ QQmlProfilerAdapter *qmlAdapter =
+ new QQmlProfilerAdapter(this, QQmlEnginePrivate::get(qmlEngine));
+ addEngineProfiler(qmlAdapter, engine);
+ }
QV4ProfilerAdapter *v4Adapter = new QV4ProfilerAdapter(this, QV8Engine::getV4(engine->handle()));
- addEngineProfiler(qmlAdapter, engine);
addEngineProfiler(v4Adapter, engine);
QQmlConfigurableDebugService<QQmlProfilerService>::engineAboutToBeAdded(engine);
}
-void QQmlProfilerServiceImpl::engineAdded(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::engineAdded(QJSEngine *engine)
{
Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO,
"QML profilers have to be added from the engine thread");
@@ -115,7 +129,7 @@ void QQmlProfilerServiceImpl::engineAdded(QQmlEngine *engine)
profiler->stopWaiting();
}
-void QQmlProfilerServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
{
Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO,
"QML profilers have to be removed from the engine thread");
@@ -135,7 +149,7 @@ void QQmlProfilerServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine)
}
}
-void QQmlProfilerServiceImpl::engineRemoved(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::engineRemoved(QJSEngine *engine)
{
Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO,
"QML profilers have to be removed from the engine thread");
@@ -148,7 +162,7 @@ void QQmlProfilerServiceImpl::engineRemoved(QQmlEngine *engine)
m_engineProfilers.remove(engine);
}
-void QQmlProfilerServiceImpl::addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine)
+void QQmlProfilerServiceImpl::addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QJSEngine *engine)
{
profiler->moveToThread(thread());
profiler->synchronize(m_timer);
@@ -176,7 +190,6 @@ void QQmlProfilerServiceImpl::removeGlobalProfiler(QQmlAbstractProfilerAdapter *
QMutexLocker lock(&m_configMutex);
removeProfilerFromStartTimes(profiler);
m_globalProfilers.removeOne(profiler);
- delete profiler;
}
void QQmlProfilerServiceImpl::removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler)
@@ -198,12 +211,17 @@ void QQmlProfilerServiceImpl::removeProfilerFromStartTimes(const QQmlAbstractPro
*
* If any engine profiler is started like that also start all global profilers.
*/
-void QQmlProfilerServiceImpl::startProfiling(QQmlEngine *engine, quint64 features)
+void QQmlProfilerServiceImpl::startProfiling(QJSEngine *engine, quint64 features)
{
QMutexLocker lock(&m_configMutex);
- QByteArray message;
- QQmlDebugStream d(&message, QIODevice::WriteOnly);
+ if (features & static_cast<quint64>(1) << ProfileDebugMessages) {
+ if (QDebugMessageService *messageService =
+ QQmlDebugConnector::instance()->service<QDebugMessageService>())
+ messageService->synchronizeTime(m_timer);
+ }
+
+ QQmlDebugPacket d;
d << m_timer.nsecsElapsed() << (int)Event << (int)StartTrace;
bool startedAny = false;
@@ -217,8 +235,8 @@ void QQmlProfilerServiceImpl::startProfiling(QQmlEngine *engine, quint64 feature
if (startedAny)
d << idForObject(engine);
} else {
- QSet<QQmlEngine *> engines;
- for (QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
+ QSet<QJSEngine *> engines;
+ for (QMultiHash<QJSEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
i != m_engineProfilers.end(); ++i) {
if (!i.value()->isRunning()) {
engines << i.key();
@@ -226,7 +244,7 @@ void QQmlProfilerServiceImpl::startProfiling(QQmlEngine *engine, quint64 feature
startedAny = true;
}
}
- foreach (QQmlEngine *profiledEngine, engines)
+ foreach (QJSEngine *profiledEngine, engines)
d << idForObject(profiledEngine);
}
@@ -239,7 +257,7 @@ void QQmlProfilerServiceImpl::startProfiling(QQmlEngine *engine, quint64 feature
emit startFlushTimer();
}
- emit messageToClient(name(), message);
+ emit messageToClient(name(), d.data());
}
/*!
@@ -249,14 +267,14 @@ void QQmlProfilerServiceImpl::startProfiling(QQmlEngine *engine, quint64 feature
* If afterwards no more engine profilers are running, also stop all global profilers. Otherwise
* only make them report their data.
*/
-void QQmlProfilerServiceImpl::stopProfiling(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::stopProfiling(QJSEngine *engine)
{
QMutexLocker lock(&m_configMutex);
QList<QQmlAbstractProfilerAdapter *> stopping;
QList<QQmlAbstractProfilerAdapter *> reporting;
bool stillRunning = false;
- for (QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
+ for (QMultiHash<QJSEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
i != m_engineProfilers.end(); ++i) {
if (i.value()->isRunning()) {
if (engine == 0 || i.key() == engine) {
@@ -299,15 +317,13 @@ void QQmlProfilerServiceImpl::sendMessages()
{
QList<QByteArray> messages;
- QByteArray data;
-
+ QQmlDebugPacket traceEnd;
if (m_waitingForStop) {
- QQmlDebugStream traceEnd(&data, QIODevice::WriteOnly);
traceEnd << m_timer.nsecsElapsed() << (int)Event << (int)EndTrace;
- QSet<QQmlEngine *> seen;
+ QSet<QJSEngine *> seen;
foreach (QQmlAbstractProfilerAdapter *profiler, m_startTimes) {
- for (QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
+ for (QMultiHash<QJSEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
i != m_engineProfilers.end(); ++i) {
if (i.value() == profiler && !seen.contains(i.key())) {
seen << i.key();
@@ -331,12 +347,11 @@ void QQmlProfilerServiceImpl::sendMessages()
if (m_waitingForStop) {
//indicate completion
- messages << data;
- data.clear();
+ messages << traceEnd.data();
- QQmlDebugStream ds(&data, QIODevice::WriteOnly);
+ QQmlDebugPacket ds;
ds << (qint64)-1 << (int)Complete;
- messages << data;
+ messages << ds.data();
m_waitingForStop = false;
}
@@ -360,7 +375,7 @@ void QQmlProfilerServiceImpl::stateAboutToBeChanged(QQmlDebugService::State newS
// Stop all profiling and send the data before we get disabled.
if (newState != Enabled) {
- foreach (QQmlEngine *engine, m_engineProfilers.keys())
+ foreach (QJSEngine *engine, m_engineProfilers.keys())
stopProfiling(engine);
}
}
@@ -369,8 +384,7 @@ void QQmlProfilerServiceImpl::messageReceived(const QByteArray &message)
{
QMutexLocker lock(&m_configMutex);
- QByteArray rwData = message;
- QQmlDebugStream stream(&rwData, QIODevice::ReadOnly);
+ QQmlDebugPacket stream(message);
int engineId = -1;
quint64 features = std::numeric_limits<quint64>::max();
@@ -397,9 +411,9 @@ void QQmlProfilerServiceImpl::messageReceived(const QByteArray &message)
// If engineId == -1 objectForId() and then the cast will return 0.
if (enabled)
- startProfiling(qobject_cast<QQmlEngine *>(objectForId(engineId)), features);
+ startProfiling(qobject_cast<QJSEngine *>(objectForId(engineId)), features);
else
- stopProfiling(qobject_cast<QQmlEngine *>(objectForId(engineId)));
+ stopProfiling(qobject_cast<QJSEngine *>(objectForId(engineId)));
stopWaiting();
}
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
index 9b139ffabb..299d170339 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
@@ -64,8 +64,6 @@
QT_BEGIN_NAMESPACE
class QUrl;
-class QQmlEngine;
-
class QQmlProfilerServiceImpl :
public QQmlConfigurableDebugService<QQmlProfilerService>,
@@ -74,21 +72,22 @@ class QQmlProfilerServiceImpl :
Q_OBJECT
public:
- void engineAboutToBeAdded(QQmlEngine *engine);
- void engineAboutToBeRemoved(QQmlEngine *engine);
- void engineAdded(QQmlEngine *engine);
- void engineRemoved(QQmlEngine *engine);
+ void engineAboutToBeAdded(QJSEngine *engine) Q_DECL_OVERRIDE;
+ void engineAboutToBeRemoved(QJSEngine *engine) Q_DECL_OVERRIDE;
+ void engineAdded(QJSEngine *engine) Q_DECL_OVERRIDE;
+ void engineRemoved(QJSEngine *engine) Q_DECL_OVERRIDE;
- void addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler);
- void removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler);
+ void addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler) Q_DECL_OVERRIDE;
+ void removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler) Q_DECL_OVERRIDE;
- void startProfiling(QQmlEngine *engine, quint64 features = std::numeric_limits<quint64>::max());
- void stopProfiling(QQmlEngine *engine);
+ void startProfiling(QJSEngine *engine,
+ quint64 features = std::numeric_limits<quint64>::max()) Q_DECL_OVERRIDE;
+ void stopProfiling(QJSEngine *engine) Q_DECL_OVERRIDE;
QQmlProfilerServiceImpl(QObject *parent = 0);
- ~QQmlProfilerServiceImpl();
+ ~QQmlProfilerServiceImpl() Q_DECL_OVERRIDE;
- void dataReady(QQmlAbstractProfilerAdapter *profiler);
+ void dataReady(QQmlAbstractProfilerAdapter *profiler) Q_DECL_OVERRIDE;
signals:
void startFlushTimer();
@@ -98,14 +97,14 @@ private slots:
void flush();
protected:
- virtual void stateAboutToBeChanged(State state);
- virtual void messageReceived(const QByteArray &);
+ virtual void stateAboutToBeChanged(State state) Q_DECL_OVERRIDE;
+ virtual void messageReceived(const QByteArray &) Q_DECL_OVERRIDE;
private:
friend class QQmlProfilerServiceFactory;
void sendMessages();
- void addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine);
+ void addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QJSEngine *engine);
void removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler);
QElapsedTimer m_timer;
@@ -113,8 +112,8 @@ private:
bool m_waitingForStop;
QList<QQmlAbstractProfilerAdapter *> m_globalProfilers;
- QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *> m_engineProfilers;
- QList<QQmlEngine *> m_stoppingEngines;
+ QMultiHash<QJSEngine *, QQmlAbstractProfilerAdapter *> m_engineProfilers;
+ QList<QJSEngine *> m_stoppingEngines;
QMultiMap<qint64, QQmlAbstractProfilerAdapter *> m_startTimes;
};
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.cpp
index 83c2075246..c1b8e6a817 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.cpp
@@ -42,8 +42,8 @@ QQmlDebugService *QQmlProfilerServiceFactory::create(const QString &key)
if (key == QQmlProfilerServiceImpl::s_key)
return new QQmlProfilerServiceImpl(this);
- if (key == QQmlEngineControlService::s_key)
- return new QQmlEngineControlService(this);
+ if (key == QQmlEngineControlServiceImpl::s_key)
+ return new QQmlEngineControlServiceImpl(this);
return 0;
}
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
index 24e01f4c68..2e7051b912 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
@@ -33,16 +33,22 @@
#include "qv4profileradapter.h"
#include "qqmlprofilerservice.h"
+#include "qqmldebugpacket.h"
QT_BEGIN_NAMESPACE
QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine) :
- QQmlAbstractProfilerAdapter(service), dataPos(0), memoryPos(0)
+ m_functionCallPos(0), m_memoryPos(0)
{
+ setService(service);
engine->enableProfiler();
connect(this, SIGNAL(profilingEnabled(quint64)),
- engine->profiler, SLOT(startProfiling(quint64)));
+ this, SLOT(forwardEnabled(quint64)));
connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
+ this, SLOT(forwardEnabledWhileWaiting(quint64)), Qt::DirectConnection);
+ connect(this, SIGNAL(v4ProfilingEnabled(quint64)),
+ engine->profiler, SLOT(startProfiling(quint64)));
+ connect(this, SIGNAL(v4ProfilingEnabledWhileWaiting(quint64)),
engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection);
connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
connect(this, SIGNAL(profilingDisabledWhileWaiting()), engine->profiler, SLOT(stopProfiling()),
@@ -58,30 +64,29 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut
qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &messages)
{
- QByteArray message;
- while (memory_data.length() > memoryPos && memory_data[memoryPos].timestamp <= until) {
- QQmlDebugStream d(&message, QIODevice::WriteOnly);
- QV4::Profiling::MemoryAllocationProperties &props = memory_data[memoryPos];
+ while (m_memoryData.length() > m_memoryPos && m_memoryData[m_memoryPos].timestamp <= until) {
+ QQmlDebugPacket d;
+ QV4::Profiling::MemoryAllocationProperties &props = m_memoryData[m_memoryPos];
d << props.timestamp << MemoryAllocation << props.type << props.size;
- ++memoryPos;
- messages.append(message);
+ ++m_memoryPos;
+ messages.append(d.data());
}
- return memory_data.length() == memoryPos ? -1 : memory_data[memoryPos].timestamp;
+ return m_memoryData.length() == m_memoryPos ? -1 : m_memoryData[m_memoryPos].timestamp;
}
qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &messages,
qint64 callNext)
{
if (callNext == -1) {
- data.clear();
- dataPos = 0;
+ m_functionCallData.clear();
+ m_functionCallPos = 0;
}
qint64 memoryNext = appendMemoryEvents(until, messages);
if (memoryNext == -1) {
- memory_data.clear();
- memoryPos = 0;
+ m_memoryData.clear();
+ m_memoryPos = 0;
return callNext;
}
@@ -90,64 +95,84 @@ qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &mes
qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
{
- QByteArray message;
while (true) {
- while (!stack.isEmpty() && (dataPos == data.length() ||
- stack.top() <= data[dataPos].start)) {
- if (stack.top() > until)
- return finalizeMessages(until, messages, stack.top());
-
- appendMemoryEvents(stack.top(), messages);
- QQmlDebugStream d(&message, QIODevice::WriteOnly);
- d << stack.pop() << RangeEnd << Javascript;
- messages.append(message);
+ while (!m_stack.isEmpty() &&
+ (m_functionCallPos == m_functionCallData.length() ||
+ m_stack.top() <= m_functionCallData[m_functionCallPos].start)) {
+ if (m_stack.top() > until)
+ return finalizeMessages(until, messages, m_stack.top());
+
+ appendMemoryEvents(m_stack.top(), messages);
+ QQmlDebugPacket d;
+ d << m_stack.pop() << RangeEnd << Javascript;
+ messages.append(d.data());
}
- while (dataPos != data.length() && (stack.empty() || data[dataPos].start < stack.top())) {
- const QV4::Profiling::FunctionCallProperties &props = data[dataPos];
+ while (m_functionCallPos != m_functionCallData.length() &&
+ (m_stack.empty() || m_functionCallData[m_functionCallPos].start < m_stack.top())) {
+ const QV4::Profiling::FunctionCallProperties &props =
+ m_functionCallData[m_functionCallPos];
if (props.start > until)
return finalizeMessages(until, messages, props.start);
appendMemoryEvents(props.start, messages);
- QQmlDebugStream d_start(&message, QIODevice::WriteOnly);
+ QQmlDebugPacket d_start;
d_start << props.start << RangeStart << Javascript;
- messages.push_back(message);
- message.clear();
- QQmlDebugStream d_location(&message, QIODevice::WriteOnly);
+ messages.push_back(d_start.data());
+ QQmlDebugPacket d_location;
d_location << props.start << RangeLocation << Javascript << props.file << props.line
<< props.column;
- messages.push_back(message);
- message.clear();
- QQmlDebugStream d_data(&message, QIODevice::WriteOnly);
+ messages.push_back(d_location.data());
+ QQmlDebugPacket d_data;
d_data << props.start << RangeData << Javascript << props.name;
- messages.push_back(message);
- message.clear();
- stack.push(props.end);
- ++dataPos;
+ messages.push_back(d_data.data());
+ m_stack.push(props.end);
+ ++m_functionCallPos;
}
- if (stack.empty() && dataPos == data.length())
+ if (m_stack.empty() && m_functionCallPos == m_functionCallData.length())
return finalizeMessages(until, messages, -1);
}
}
void QV4ProfilerAdapter::receiveData(
- const QVector<QV4::Profiling::FunctionCallProperties> &new_data,
- const QVector<QV4::Profiling::MemoryAllocationProperties> &new_memory_data)
+ const QVector<QV4::Profiling::FunctionCallProperties> &functionCallData,
+ const QVector<QV4::Profiling::MemoryAllocationProperties> &memoryData)
{
// In rare cases it could be that another flush or stop event is processed while data from
// the previous one is still pending. In that case we just append the data.
- if (data.isEmpty())
- data = new_data;
+ if (m_functionCallData.isEmpty())
+ m_functionCallData = functionCallData;
else
- data.append(new_data);
+ m_functionCallData.append(functionCallData);
- if (memory_data.isEmpty())
- memory_data = new_memory_data;
+ if (m_memoryData.isEmpty())
+ m_memoryData = memoryData;
else
- memory_data.append(new_memory_data);
+ m_memoryData.append(memoryData);
service->dataReady(this);
}
+quint64 QV4ProfilerAdapter::translateFeatures(quint64 qmlFeatures)
+{
+ quint64 v4Features = 0;
+ const quint64 one = 1;
+ if (qmlFeatures & (one << ProfileJavaScript))
+ v4Features |= (one << QV4::Profiling::FeatureFunctionCall);
+ if (qmlFeatures & (one << ProfileMemory))
+ v4Features |= (one << QV4::Profiling::FeatureMemoryAllocation);
+ return v4Features;
+}
+
+void QV4ProfilerAdapter::forwardEnabled(quint64 features)
+{
+ emit v4ProfilingEnabled(translateFeatures(features));
+}
+
+void QV4ProfilerAdapter::forwardEnabledWhileWaiting(quint64 features)
+{
+ emit v4ProfilingEnabledWhileWaiting(translateFeatures(features));
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
index cea3da72e3..c07fc4dc96 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
@@ -62,18 +62,28 @@ public:
virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
+signals:
+ void v4ProfilingEnabled(quint64 v4Features);
+ void v4ProfilingEnabledWhileWaiting(quint64 v4Features);
+
public slots:
void receiveData(const QVector<QV4::Profiling::FunctionCallProperties> &,
const QVector<QV4::Profiling::MemoryAllocationProperties> &);
+private slots:
+ void forwardEnabled(quint64 features);
+ void forwardEnabledWhileWaiting(quint64 features);
+
private:
- QVector<QV4::Profiling::FunctionCallProperties> data;
- QVector<QV4::Profiling::MemoryAllocationProperties> memory_data;
- int dataPos;
- int memoryPos;
- QStack<qint64> stack;
+ QVector<QV4::Profiling::FunctionCallProperties> m_functionCallData;
+ QVector<QV4::Profiling::MemoryAllocationProperties> m_memoryData;
+ int m_functionCallPos;
+ int m_memoryPos;
+ QStack<qint64> m_stack;
qint64 appendMemoryEvents(qint64 until, QList<QByteArray> &messages);
qint64 finalizeMessages(qint64 until, QList<QByteArray> &messages, qint64 callNext);
+
+ static quint64 translateFeatures(quint64 qmlFeatures);
};
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qmldbg_quickprofiler.pro b/src/plugins/qmltooling/qmldbg_quickprofiler/qmldbg_quickprofiler.pro
new file mode 100644
index 0000000000..6ca0a184ca
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qmldbg_quickprofiler.pro
@@ -0,0 +1,20 @@
+TARGET = qmldbg_quickprofiler
+QT += qml-private quick-private core-private packetprotocol-private
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQuickProfilerAdapterFactory
+load(qt_plugin)
+
+INCLUDEPATH += $$PWD/../shared
+
+SOURCES += \
+ $$PWD/qquickprofileradapter.cpp \
+ $$PWD/qquickprofileradapterfactory.cpp
+
+HEADERS += \
+ $$PWD/qquickprofileradapter.h \
+ $$PWD/qquickprofileradapterfactory.h \
+ $$PWD/../shared/qqmldebugpacket.h
+
+OTHER_FILES += \
+ qquickprofileradapter.json
diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp
new file mode 100644
index 0000000000..8438a6fb3a
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** 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 "qquickprofileradapter.h"
+#include "qqmldebugpacket.h"
+#include <QCoreApplication>
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qquickprofiler_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQuickProfilerAdapter::QQuickProfilerAdapter(QObject *parent) :
+ QQmlAbstractProfilerAdapter(parent), next(0)
+{
+ QQuickProfiler::initialize(this);
+
+ // We can always do DirectConnection here as all methods are protected by mutexes
+ connect(this, SIGNAL(profilingEnabled(quint64)),
+ QQuickProfiler::s_instance, SLOT(startProfilingImpl(quint64)), Qt::DirectConnection);
+ connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
+ QQuickProfiler::s_instance, SLOT(startProfilingImpl(quint64)), Qt::DirectConnection);
+ connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
+ QQuickProfiler::s_instance, SLOT(setTimer(QElapsedTimer)), Qt::DirectConnection);
+ connect(this, SIGNAL(profilingDisabled()),
+ QQuickProfiler::s_instance, SLOT(stopProfilingImpl()), Qt::DirectConnection);
+ connect(this, SIGNAL(profilingDisabledWhileWaiting()),
+ QQuickProfiler::s_instance, SLOT(stopProfilingImpl()), Qt::DirectConnection);
+ connect(this, SIGNAL(dataRequested()),
+ QQuickProfiler::s_instance, SLOT(reportDataImpl()), Qt::DirectConnection);
+ connect(QQuickProfiler::s_instance, SIGNAL(dataReady(QVector<QQuickProfilerData>)),
+ this, SLOT(receiveData(QVector<QQuickProfilerData>)), Qt::DirectConnection);
+}
+
+QQuickProfilerAdapter::~QQuickProfilerAdapter()
+{
+ if (service)
+ service->removeGlobalProfiler(this);
+}
+
+// convert to QByteArrays that can be sent to the debug client
+// use of QDataStream can skew results
+// (see tst_qqmldebugtrace::trace() benchmark)
+static void qQuickProfilerDataToByteArrays(const QQuickProfilerData &data,
+ QList<QByteArray> &messages)
+{
+ Q_ASSERT_X(((data.messageType | data.detailType) & (1 << 31)) == 0, Q_FUNC_INFO,
+ "You can use at most 31 message types and 31 detail types.");
+ for (uint decodedMessageType = 0; (data.messageType >> decodedMessageType) != 0;
+ ++decodedMessageType) {
+ if ((data.messageType & (1 << decodedMessageType)) == 0)
+ continue;
+
+ for (uint decodedDetailType = 0; (data.detailType >> decodedDetailType) != 0;
+ ++decodedDetailType) {
+ if ((data.detailType & (1 << decodedDetailType)) == 0)
+ continue;
+
+ //### using QDataStream is relatively expensive
+ QQmlDebugPacket ds;
+ ds << data.time << decodedMessageType << decodedDetailType;
+
+ switch (decodedMessageType) {
+ case QQuickProfiler::Event:
+ switch (decodedDetailType) {
+ case QQuickProfiler::AnimationFrame:
+ ds << data.framerate << data.count << data.threadId;
+ break;
+ case QQuickProfiler::Key:
+ case QQuickProfiler::Mouse:
+ ds << data.inputType << data.inputA << data.inputB;
+ break;
+ }
+ break;
+ case QQuickProfiler::PixmapCacheEvent:
+ ds << data.detailUrl.toString();
+ switch (decodedDetailType) {
+ case QQuickProfiler::PixmapSizeKnown: ds << data.x << data.y; break;
+ case QQuickProfiler::PixmapReferenceCountChanged: ds << data.count; break;
+ case QQuickProfiler::PixmapCacheCountChanged: ds << data.count; break;
+ default: break;
+ }
+ break;
+ case QQuickProfiler::SceneGraphFrame:
+ switch (decodedDetailType) {
+ // RendererFrame: preprocessTime, updateTime, bindingTime, renderTime
+ case QQuickProfiler::SceneGraphRendererFrame: ds << data.subtime_1 << data.subtime_2 << data.subtime_3 << data.subtime_4; break;
+ // AdaptationLayerFrame: glyphCount (which is an integer), glyphRenderTime, glyphStoreTime
+ case QQuickProfiler::SceneGraphAdaptationLayerFrame: ds << data.subtime_3 << data.subtime_1 << data.subtime_2; break;
+ // ContextFrame: compiling material time
+ case QQuickProfiler::SceneGraphContextFrame: ds << data.subtime_1; break;
+ // RenderLoop: syncTime, renderTime, swapTime
+ case QQuickProfiler::SceneGraphRenderLoopFrame: ds << data.subtime_1 << data.subtime_2 << data.subtime_3; break;
+ // TexturePrepare: bind, convert, swizzle, upload, mipmap
+ case QQuickProfiler::SceneGraphTexturePrepare: ds << data.subtime_1 << data.subtime_2 << data.subtime_3 << data.subtime_4 << data.subtime_5; break;
+ // TextureDeletion: deletionTime
+ case QQuickProfiler::SceneGraphTextureDeletion: ds << data.subtime_1; break;
+ // PolishAndSync: polishTime, waitTime, syncTime, animationsTime,
+ case QQuickProfiler::SceneGraphPolishAndSync: ds << data.subtime_1 << data.subtime_2 << data.subtime_3 << data.subtime_4; break;
+ // WindowsRenderLoop: GL time, make current time, SceneGraph time
+ case QQuickProfiler::SceneGraphWindowsRenderShow: ds << data.subtime_1 << data.subtime_2 << data.subtime_3; break;
+ // WindowsAnimations: update time
+ case QQuickProfiler::SceneGraphWindowsAnimations: ds << data.subtime_1; break;
+ // non-threaded rendering: polish time
+ case QQuickProfiler::SceneGraphPolishFrame: ds << data.subtime_1; break;
+ default:break;
+ }
+ break;
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
+ break;
+ }
+ messages << ds.data();
+ }
+ }
+}
+
+qint64 QQuickProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
+{
+ while (next < m_data.size()) {
+ if (m_data[next].time <= until)
+ qQuickProfilerDataToByteArrays(m_data[next++], messages);
+ else
+ return m_data[next].time;
+ }
+ m_data.clear();
+ next = 0;
+ return -1;
+}
+
+void QQuickProfilerAdapter::receiveData(const QVector<QQuickProfilerData> &new_data)
+{
+ if (m_data.isEmpty())
+ m_data = new_data;
+ else
+ m_data.append(new_data);
+ service->dataReady(this);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h
new file mode 100644
index 0000000000..7a3a25f049
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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 QQUICKPROFILERADAPTER_H
+#define QQUICKPROFILERADAPTER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/private/qqmlabstractprofileradapter_p.h>
+#include <QtQuick/private/qquickprofiler_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickProfilerAdapter : public QQmlAbstractProfilerAdapter {
+ Q_OBJECT
+public:
+ QQuickProfilerAdapter(QObject *parent = 0);
+ ~QQuickProfilerAdapter();
+ qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
+
+public slots:
+ void receiveData(const QVector<QQuickProfilerData> &new_data);
+
+private:
+ int next;
+ QVector<QQuickProfilerData> m_data;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKPROFILERADAPTER_H
diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.json b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.json
new file mode 100644
index 0000000000..76b08fbcab
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "QQuickProfilerAdapter" ]
+}
diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapterfactory.cpp b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapterfactory.cpp
new file mode 100644
index 0000000000..9fae5e3a4d
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapterfactory.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** 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 "qquickprofileradapterfactory.h"
+#include "qquickprofileradapter.h"
+#include <private/qqmldebugconnector_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlAbstractProfilerAdapter *QQuickProfilerAdapterFactory::create(const QString &key)
+{
+ if (key != QLatin1String("QQuickProfilerAdapter"))
+ return 0;
+ return new QQuickProfilerAdapter(this);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapterfactory.h b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapterfactory.h
new file mode 100644
index 0000000000..dee77747ef
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapterfactory.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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 QQUICKPROFILERADAPTERFACTORY_H
+#define QQUICKPROFILERADAPTERFACTORY_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/private/qqmlabstractprofileradapter_p.h>
+#include <QtQuick/private/qquickprofiler_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickProfilerAdapterFactory : public QQmlAbstractProfilerAdapterFactory
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlAbstractProfilerAdapterFactory_iid FILE "qquickprofileradapter.json")
+public:
+ QQmlAbstractProfilerAdapter *create(const QString &key);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKPROFILERADAPTERFACTORY_H
diff --git a/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro b/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro
index 5e2d0874df..923faa01f3 100644
--- a/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro
+++ b/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro
@@ -1,19 +1,18 @@
TARGET = qmldbg_server
-QT = qml-private core-private
+QT = qml-private packetprotocol-private
PLUGIN_TYPE = qmltooling
PLUGIN_CLASS_NAME = QQmlDebugServerFactory
load(qt_plugin)
SOURCES += \
- $$PWD/qqmldebugserver.cpp \
- $$PWD/../shared/qpacketprotocol.cpp
+ $$PWD/qqmldebugserver.cpp
HEADERS += \
$$PWD/qqmldebugserverfactory.h \
$$PWD/../shared/qqmldebugserver.h \
- $$PWD/../shared/qpacketprotocol.h \
- $$PWD/../shared/qqmldebugserverconnection.h
+ $$PWD/../shared/qqmldebugserverconnection.h \
+ $$PWD/../shared/qqmldebugpacket.h
INCLUDEPATH += $$PWD \
$$PWD/../shared
diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
index 69d36beaca..50c7ef3771 100644
--- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
@@ -33,13 +33,15 @@
#include "qqmldebugserver.h"
#include "qqmldebugserverfactory.h"
-#include "qpacketprotocol.h"
#include "qqmldebugserverconnection.h"
+#include "qqmldebugpacket.h"
#include <private/qqmldebugservice_p.h>
-#include <private/qqmlengine_p.h>
+#include <private/qjsengine_p.h>
#include <private/qqmlglobal_p.h>
#include <private/qqmldebugpluginmanager_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qpacketprotocol_p.h>
#include <QtCore/QAtomicInt>
#include <QtCore/QDir>
@@ -47,9 +49,6 @@
#include <QtCore/QStringList>
#include <QtCore/qwaitcondition.h>
-#include <private/qobject_p.h>
-#include <private/qcoreapplication_p.h>
-
QT_BEGIN_NAMESPACE
/*
@@ -105,6 +104,11 @@ public:
m_fileName = fileName;
}
+ const QString &pluginName() const
+ {
+ return m_pluginName;
+ }
+
void run();
private:
@@ -122,25 +126,25 @@ class QQmlDebugServerImpl : public QQmlDebugServer
public:
QQmlDebugServerImpl();
- bool blockingMode() const;
+ bool blockingMode() const Q_DECL_OVERRIDE;
- QQmlDebugService *service(const QString &name) const;
+ QQmlDebugService *service(const QString &name) const Q_DECL_OVERRIDE;
- void addEngine(QQmlEngine *engine);
- void removeEngine(QQmlEngine *engine);
+ void addEngine(QJSEngine *engine) Q_DECL_OVERRIDE;
+ void removeEngine(QJSEngine *engine) Q_DECL_OVERRIDE;
- bool addService(const QString &name, QQmlDebugService *service);
- bool removeService(const QString &name);
+ bool addService(const QString &name, QQmlDebugService *service) Q_DECL_OVERRIDE;
+ bool removeService(const QString &name) Q_DECL_OVERRIDE;
- bool open(const QVariantHash &configuration);
- void setDevice(QIODevice *socket);
+ bool open(const QVariantHash &configuration) Q_DECL_OVERRIDE;
+ void setDevice(QIODevice *socket) Q_DECL_OVERRIDE;
void parseArguments();
static void cleanup();
private slots:
- void wakeEngine(QQmlEngine *engine);
+ void wakeEngine(QJSEngine *engine);
void sendMessage(const QString &name, const QByteArray &message);
void sendMessages(const QString &name, const QList<QByteArray> &messages);
void changeServiceState(const QString &serviceName, QQmlDebugService::State state);
@@ -175,7 +179,7 @@ private:
bool m_gotHello;
bool m_blockingMode;
- QHash<QQmlEngine *, EngineCondition> m_engineConditions;
+ QHash<QJSEngine *, EngineCondition> m_engineConditions;
QMutex m_helloMutex;
QWaitCondition m_helloCondition;
@@ -304,6 +308,9 @@ bool QQmlDebugServerImpl::open(const QVariantHash &configuration = QVariantHash(
}
}
+ if (m_thread.pluginName().isEmpty())
+ return false;
+
QMutexLocker locker(&m_helloMutex);
m_thread.start();
m_helloCondition.wait(&m_helloMutex); // wait for connection
@@ -312,6 +319,7 @@ bool QQmlDebugServerImpl::open(const QVariantHash &configuration = QVariantHash(
return true;
}
+#define qUsage qWarning().noquote().nospace
void QQmlDebugServerImpl::parseArguments()
{
// format: qmljsdebugger=port:<port_from>[,port_to],host:<ip address>][,block]
@@ -334,7 +342,7 @@ void QQmlDebugServerImpl::parseArguments()
for (; argsIt != argsItEnd; ++argsIt) {
const QString strArgument = *argsIt;
if (strArgument.startsWith(QLatin1String("port:"))) {
- portFrom = strArgument.mid(5).toInt(&ok);
+ portFrom = strArgument.midRef(5).toInt(&ok);
portTo = portFrom;
QStringList::const_iterator argsNext = argsIt + 1;
if (argsNext == argsItEnd)
@@ -360,9 +368,8 @@ void QQmlDebugServerImpl::parseArguments()
} else if (!services.isEmpty()) {
services.append(strArgument);
} else {
- qWarning() << QString::fromLatin1("QML Debugger: Invalid argument '%1' "
- "detected. Ignoring the same.")
- .arg(strArgument);
+ qUsage() << tr("QML Debugger: Invalid argument \"%1\" detected. Ignoring the same.")
+ .arg(strArgument);
}
}
@@ -374,11 +381,43 @@ void QQmlDebugServerImpl::parseArguments()
else
m_thread.setPortRange(portFrom, portTo, hostAddress);
} else {
- qWarning() << QString::fromLatin1("QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
- "Format is qmljsdebugger=port:<port_from>[,port_to],host:"
- "<ip address>][,block]").arg(args);
+ qUsage() << tr("QML Debugger: Ignoring \"-qmljsdebugger=%1\".").arg(args);
+ qUsage() << tr("The format is \"-qmljsdebugger=[file:<file>|port:<port_from>][,<port_to>]"
+ "[,host:<ip address>][,block][,services:<service>][,<service>]*\"\n");
+ qUsage() << tr("\"file:\" can be used to specify the name of a file the debugger will try "
+ "to connect to using a QLocalSocket. If \"file:\" is given any \"host:\" and"
+ "\"port:\" arguments will be ignored.\n");
+ qUsage() << tr("\"host:\" and \"port:\" can be used to specify an address and a single "
+ "port or a range of ports the debugger will try to bind to with a "
+ "QTcpServer.\n");
+ qUsage() << tr("\"block\" makes the debugger and some services wait for clients to be "
+ "connected and ready before the first QML engine starts.\n");
+ qUsage() << tr("\"services:\" can be used to specify which debug services the debugger "
+ "should load. Some debug services interact badly with others. The V4 "
+ "debugger should not be loaded when using the QML profiler as it will force "
+ "any V4 engines to use the JavaScript interpreter rather than the JIT. The "
+ "following debug services are available by default:");
+ qUsage() << QQmlEngineDebugService::s_key << tr("\t- The QML debugger");
+ qUsage() << QV4DebugService::s_key << tr("\t- The V4 debugger");
+ qUsage() << QQmlInspectorService::s_key << tr("\t- The QML inspector");
+ qUsage() << QQmlProfilerService::s_key << tr("\t- The QML profiler");
+ qUsage() << QQmlEngineControlService::s_key
+ << tr("\t- Allows the client to delay the starting and stopping of\n"
+ "\t\t QML engines until other services are ready. QtCreator\n"
+ "\t\t uses this service with the QML profiler in order to\n"
+ "\t\t profile multiple QML engines at the same time.");
+ qUsage() << QDebugMessageService::s_key
+ << tr("\t- Sends qDebug() and similar messages over the QML debug\n"
+ "\t\t connection. QtCreator uses this for showing debug\n"
+ "\t\t messages in the JavaScript console.");
+ qUsage() << tr("Other services offered by qmltooling plugins that implement "
+ "QQmlDebugServiceFactory and which can be found in the standard plugin "
+ "paths will also be available and can be specified. If no \"services\" "
+ "argument is given, all services found this way, including the default "
+ "ones, are loaded.");
}
}
+#undef qUsage
void QQmlDebugServerImpl::receiveMessage()
{
@@ -390,7 +429,7 @@ void QQmlDebugServerImpl::receiveMessage()
if (!m_protocol)
return;
- QQmlDebugStream in(m_protocol->read().data());
+ QQmlDebugPacket in(m_protocol->read());
QString name;
@@ -404,16 +443,15 @@ void QQmlDebugServerImpl::receiveMessage()
//Get the supported QDataStream version
if (!in.atEnd()) {
- in >> QQmlDebugStream::s_dataStreamVersion;
- if (QQmlDebugStream::s_dataStreamVersion > QDataStream().version())
- QQmlDebugStream::s_dataStreamVersion = QDataStream().version();
+ in >> s_dataStreamVersion;
+ if (s_dataStreamVersion > QDataStream::Qt_DefaultCompiledVersion)
+ s_dataStreamVersion = QDataStream::Qt_DefaultCompiledVersion;
}
// Send the hello answer immediately, since it needs to arrive before
// the plugins below start sending messages.
- QByteArray helloAnswer;
- QQmlDebugStream out(&helloAnswer, QIODevice::WriteOnly);
+ QQmlDebugPacket out;
QStringList pluginNames;
QList<float> pluginVersions;
const int count = m_plugins.count();
@@ -426,11 +464,9 @@ void QQmlDebugServerImpl::receiveMessage()
}
out << QString(QStringLiteral("QDeclarativeDebugClient")) << 0 << protocolVersion
- << pluginNames << pluginVersions << QQmlDebugStream::s_dataStreamVersion;
+ << pluginNames << pluginVersions << dataStreamVersion();
- QPacket pack;
- pack.writeRawData(helloAnswer.data(), helloAnswer.length());
- m_protocol->send(pack);
+ m_protocol->send(out.data());
m_connection->flush();
QMutexLocker helloLock(&m_helloMutex);
@@ -523,7 +559,7 @@ QQmlDebugService *QQmlDebugServerImpl::service(const QString &name) const
return m_plugins.value(name);
}
-void QQmlDebugServerImpl::addEngine(QQmlEngine *engine)
+void QQmlDebugServerImpl::addEngine(QJSEngine *engine)
{
// to be executed outside of debugger thread
Q_ASSERT(QThread::currentThread() != &m_thread);
@@ -538,7 +574,7 @@ void QQmlDebugServerImpl::addEngine(QQmlEngine *engine)
service->engineAdded(engine);
}
-void QQmlDebugServerImpl::removeEngine(QQmlEngine *engine)
+void QQmlDebugServerImpl::removeEngine(QJSEngine *engine)
{
// to be executed outside of debugger thread
Q_ASSERT(QThread::currentThread() != &m_thread);
@@ -566,10 +602,10 @@ bool QQmlDebugServerImpl::addService(const QString &name, QQmlDebugService *serv
connect(service, SIGNAL(messagesToClient(QString,QList<QByteArray>)),
this, SLOT(sendMessages(QString,QList<QByteArray>)));
- connect(service, SIGNAL(attachedToEngine(QQmlEngine*)),
- this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection);
- connect(service, SIGNAL(detachedFromEngine(QQmlEngine*)),
- this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection);
+ connect(service, SIGNAL(attachedToEngine(QJSEngine*)),
+ this, SLOT(wakeEngine(QJSEngine*)), Qt::QueuedConnection);
+ connect(service, SIGNAL(detachedFromEngine(QJSEngine*)),
+ this, SLOT(wakeEngine(QJSEngine*)), Qt::QueuedConnection);
service->setState(QQmlDebugService::Unavailable);
m_plugins.insert(name, service);
@@ -589,18 +625,16 @@ bool QQmlDebugServerImpl::removeService(const QString &name)
m_plugins.remove(name);
service->setState(QQmlDebugService::NotConnected);
- disconnect(service, SIGNAL(detachedFromEngine(QQmlEngine*)),
- this, SLOT(wakeEngine(QQmlEngine*)));
- disconnect(service, SIGNAL(attachedToEngine(QQmlEngine*)),
- this, SLOT(wakeEngine(QQmlEngine*)));
+ disconnect(service, SIGNAL(detachedFromEngine(QJSEngine*)),
+ this, SLOT(wakeEngine(QJSEngine*)));
+ disconnect(service, SIGNAL(attachedToEngine(QJSEngine*)),
+ this, SLOT(wakeEngine(QJSEngine*)));
disconnect(service, SIGNAL(messagesToClient(QString,QList<QByteArray>)),
this, SLOT(sendMessages(QString,QList<QByteArray>)));
disconnect(service, SIGNAL(messageToClient(QString,QByteArray)),
this, SLOT(sendMessage(QString,QByteArray)));
- m_plugins.remove(service->name());
-
return true;
}
@@ -614,13 +648,9 @@ bool QQmlDebugServerImpl::canSendMessage(const QString &name)
void QQmlDebugServerImpl::doSendMessage(const QString &name, const QByteArray &message)
{
- QByteArray prefixed;
- QQmlDebugStream out(&prefixed, QIODevice::WriteOnly);
+ QQmlDebugPacket out;
out << name << message;
-
- QPacket pack;
- pack.writeRawData(prefixed.data(), prefixed.length());
- m_protocol->send(pack);
+ m_protocol->send(out.data());
}
void QQmlDebugServerImpl::sendMessage(const QString &name, const QByteArray &message)
@@ -640,7 +670,7 @@ void QQmlDebugServerImpl::sendMessages(const QString &name, const QList<QByteArr
}
}
-void QQmlDebugServerImpl::wakeEngine(QQmlEngine *engine)
+void QQmlDebugServerImpl::wakeEngine(QJSEngine *engine)
{
// to be executed in debugger thread
Q_ASSERT(QThread::currentThread() == thread());
diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro
index 263e76e016..3728126dd9 100644
--- a/src/plugins/qmltooling/qmltooling.pro
+++ b/src/plugins/qmltooling/qmltooling.pro
@@ -1,5 +1,9 @@
TEMPLATE = subdirs
+# Utilities
+SUBDIRS += \
+ packetprotocol
+
# Connectors
SUBDIRS += \
qmldbg_native \
@@ -12,4 +16,15 @@ SUBDIRS += \
qmldbg_debugger \
qmldbg_profiler
-qtHaveModule(quick): SUBDIRS += qmldbg_inspector
+qmldbg_server.depends = packetprotocol
+qmldbg_native.depends = packetprotocol
+qmldbg_debugger.depends = packetprotocol
+qmldbg_profiler.depends = packetprotocol
+
+qtHaveModule(quick) {
+ SUBDIRS += \
+ qmldbg_inspector \
+ qmldbg_quickprofiler
+ qmldbg_inspector.depends = packetprotocol
+ qmldbg_quickprofiler.depends = packetprotocol
+}
diff --git a/src/plugins/qmltooling/shared/qpacketprotocol.cpp b/src/plugins/qmltooling/shared/qpacketprotocol.cpp
deleted file mode 100644
index 9a58f803c1..0000000000
--- a/src/plugins/qmltooling/shared/qpacketprotocol.cpp
+++ /dev/null
@@ -1,531 +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 "qpacketprotocol.h"
-
-#include <QtCore/QBuffer>
-#include <QtCore/QElapsedTimer>
-#include <private/qiodevice_p.h>
-
-QT_BEGIN_NAMESPACE
-
-static const unsigned int MAX_PACKET_SIZE = 0x7FFFFFFF;
-
-/*!
- \class QPacketProtocol
- \internal
-
- \brief The QPacketProtocol class encapsulates communicating discrete packets
- across fragmented IO channels, such as TCP sockets.
-
- QPacketProtocol makes it simple to send arbitrary sized data "packets" across
- fragmented transports such as TCP and UDP.
-
- As transmission boundaries are not respected, sending packets over protocols
- like TCP frequently involves "stitching" them back together at the receiver.
- QPacketProtocol makes this easier by performing this task for you. Packet
- data sent using QPacketProtocol is prepended with a 4-byte size header
- allowing the receiving QPacketProtocol to buffer the packet internally until
- it has all been received. QPacketProtocol does not perform any sanity
- checking on the size or on the data, so this class should only be used in
- prototyping or trusted situations where DOS attacks are unlikely.
-
- QPacketProtocol does not perform any communications itself. Instead it can
- operate on any QIODevice that supports the QIODevice::readyRead() signal. A
- logical "packet" is encapsulated by the companion QPacket class. The
- following example shows two ways to send data using QPacketProtocol. The
- transmitted data is equivalent in both.
-
- \code
- QTcpSocket socket;
- // ... connect socket ...
-
- QPacketProtocol protocol(&socket);
-
- // Send packet the quick way
- protocol.send() << "Hello world" << 123;
-
- // Send packet the longer way
- QPacket packet;
- packet << "Hello world" << 123;
- protocol.send(packet);
- \endcode
-
- Likewise, the following shows how to read data from QPacketProtocol, assuming
- that the QPacketProtocol::readyRead() signal has been emitted.
-
- \code
- // ... QPacketProtocol::readyRead() is emitted ...
-
- int a;
- QByteArray b;
-
- // Receive packet the quick way
- protocol.read() >> a >> b;
-
- // Receive packet the longer way
- QPacket packet = protocol.read();
- p >> a >> b;
- \endcode
-
- \ingroup io
- \sa QPacket
-*/
-
-class QPacketProtocolPrivate : public QObject
-{
- Q_OBJECT
-public:
- QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev)
- : QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE),
- waitingForPacket(false), dev(_dev)
- {
- Q_ASSERT(4 == sizeof(qint32));
-
- QObject::connect(this, SIGNAL(readyRead()),
- parent, SIGNAL(readyRead()));
- QObject::connect(this, SIGNAL(packetWritten()),
- parent, SIGNAL(packetWritten()));
- QObject::connect(this, SIGNAL(invalidPacket()),
- parent, SIGNAL(invalidPacket()));
- QObject::connect(dev, SIGNAL(readyRead()),
- this, SLOT(readyToRead()));
- QObject::connect(dev, SIGNAL(aboutToClose()),
- this, SLOT(aboutToClose()));
- QObject::connect(dev, SIGNAL(bytesWritten(qint64)),
- this, SLOT(bytesWritten(qint64)));
- }
-
-Q_SIGNALS:
- void readyRead();
- void packetWritten();
- void invalidPacket();
-
-public Q_SLOTS:
- void aboutToClose()
- {
- inProgress.clear();
- sendingPackets.clear();
- inProgressSize = -1;
- }
-
- void bytesWritten(qint64 bytes)
- {
- Q_ASSERT(!sendingPackets.isEmpty());
-
- while (bytes) {
- if (sendingPackets.at(0) > bytes) {
- sendingPackets[0] -= bytes;
- bytes = 0;
- } else {
- bytes -= sendingPackets.at(0);
- sendingPackets.removeFirst();
- emit packetWritten();
- }
- }
- }
-
- void readyToRead()
- {
- while (true) {
- // Need to get trailing data
- if (-1 == inProgressSize) {
- // We need a size header of sizeof(qint32)
- if (sizeof(qint32) > (uint)dev->bytesAvailable())
- return;
-
- // Read size header
- int read = dev->read((char *)&inProgressSize, sizeof(qint32));
- Q_ASSERT(read == sizeof(qint32));
- Q_UNUSED(read);
-
- // Check sizing constraints
- if (inProgressSize > maxPacketSize) {
- QObject::disconnect(dev, SIGNAL(readyRead()),
- this, SLOT(readyToRead()));
- QObject::disconnect(dev, SIGNAL(aboutToClose()),
- this, SLOT(aboutToClose()));
- QObject::disconnect(dev, SIGNAL(bytesWritten(qint64)),
- this, SLOT(bytesWritten(qint64)));
- dev = 0;
- emit invalidPacket();
- return;
- }
-
- inProgressSize -= sizeof(qint32);
- } else {
- inProgress.append(dev->read(inProgressSize - inProgress.size()));
-
- if (inProgressSize == inProgress.size()) {
- // Packet has arrived!
- packets.append(inProgress);
- inProgressSize = -1;
- inProgress.clear();
-
- waitingForPacket = false;
- emit readyRead();
- } else
- return;
- }
- }
- }
-
-public:
- QList<qint64> sendingPackets;
- QList<QByteArray> packets;
- QByteArray inProgress;
- qint32 inProgressSize;
- qint32 maxPacketSize;
- bool waitingForPacket;
- QIODevice *dev;
-};
-
-/*!
- Construct a QPacketProtocol instance that works on \a dev with the
- specified \a parent.
- */
-QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent)
- : QObject(parent), d(new QPacketProtocolPrivate(this, dev))
-{
- Q_ASSERT(dev);
-}
-
-/*!
- Destroys the QPacketProtocol instance.
- */
-QPacketProtocol::~QPacketProtocol()
-{
-}
-
-/*!
- Returns the maximum packet size allowed. By default this is
- 2,147,483,647 bytes.
-
- If a packet claiming to be larger than the maximum packet size is received,
- the QPacketProtocol::invalidPacket() signal is emitted.
-
- \sa QPacketProtocol::setMaximumPacketSize()
- */
-qint32 QPacketProtocol::maximumPacketSize() const
-{
- return d->maxPacketSize;
-}
-
-/*!
- Sets the maximum allowable packet size to \a max.
-
- \sa QPacketProtocol::maximumPacketSize()
- */
-qint32 QPacketProtocol::setMaximumPacketSize(qint32 max)
-{
- if (max > (signed)sizeof(qint32))
- d->maxPacketSize = max;
- return d->maxPacketSize;
-}
-
-/*!
- Returns a streamable object that is transmitted on destruction. For example
-
- \code
- protocol.send() << "Hello world" << 123;
- \endcode
-
- will send a packet containing "Hello world" and 123. To construct more
- complex packets, explicitly construct a QPacket instance.
- */
-QPacketAutoSend QPacketProtocol::send()
-{
- return QPacketAutoSend(this);
-}
-
-/*!
- \fn void QPacketProtocol::send(const QPacket & packet)
-
- Transmit the \a packet.
- */
-void QPacketProtocol::send(const QPacket & p)
-{
- if (p.b.isEmpty())
- return; // We don't send empty packets
-
- qint64 sendSize = p.b.size() + sizeof(qint32);
-
- d->sendingPackets.append(sendSize);
- qint32 sendSize32 = sendSize;
- qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
- Q_UNUSED(writeBytes);
- Q_ASSERT(writeBytes == sizeof(qint32));
- writeBytes = d->dev->write(p.b);
- Q_ASSERT(writeBytes == p.b.size());
-}
-
-/*!
- Returns the number of received packets yet to be read.
- */
-qint64 QPacketProtocol::packetsAvailable() const
-{
- return d->packets.count();
-}
-
-/*!
- Discard any unread packets.
- */
-void QPacketProtocol::clear()
-{
- d->packets.clear();
-}
-
-/*!
- Return the next unread packet, or an invalid QPacket instance if no packets
- are available. This method does NOT block.
- */
-QPacket QPacketProtocol::read()
-{
- if (0 == d->packets.count())
- return QPacket();
-
- QPacket rv(d->packets.at(0));
- d->packets.removeFirst();
- return rv;
-}
-
-/*!
- This function locks until a new packet is available for reading and the
- \l{QIODevice::}{readyRead()} signal has been emitted. The function
- will timeout after \a msecs milliseconds; the default timeout is
- 30000 milliseconds.
-
- The function returns true if the readyRead() signal is emitted and
- there is new data available for reading; otherwise it returns false
- (if an error occurred or the operation timed out).
- */
-
-bool QPacketProtocol::waitForReadyRead(int msecs)
-{
- if (!d->packets.isEmpty())
- return true;
-
- QElapsedTimer stopWatch;
- stopWatch.start();
-
- d->waitingForPacket = true;
- do {
- if (!d->dev->waitForReadyRead(msecs))
- return false;
- if (!d->waitingForPacket)
- return true;
- msecs = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
- } while (true);
-}
-
-/*!
- Return the QIODevice passed to the QPacketProtocol constructor.
-*/
-QIODevice *QPacketProtocol::device()
-{
- return d->dev;
-}
-
-/*!
- \fn void QPacketProtocol::readyRead()
-
- Emitted whenever a new packet is received. Applications may use
- QPacketProtocol::read() to retrieve this packet.
- */
-
-/*!
- \fn void QPacketProtocol::invalidPacket()
-
- A packet larger than the maximum allowable packet size was received. The
- packet will be discarded and, as it indicates corruption in the protocol, no
- further packets will be received.
- */
-
-/*!
- \fn void QPacketProtocol::packetWritten()
-
- Emitted each time a packet is completing written to the device. This signal
- may be used for communications flow control.
- */
-
-/*!
- \class QPacket
- \internal
-
- \brief The QPacket class encapsulates an unfragmentable packet of data to be
- transmitted by QPacketProtocol.
-
- The QPacket class works together with QPacketProtocol to make it simple to
- send arbitrary sized data "packets" across fragmented transports such as TCP
- and UDP.
-
- QPacket provides a QDataStream interface to an unfragmentable packet.
- Applications should construct a QPacket, propagate it with data and then
- transmit it over a QPacketProtocol instance. For example:
- \code
- QPacketProtocol protocol(...);
-
- QPacket myPacket;
- myPacket << "Hello world!" << 123;
- protocol.send(myPacket);
- \endcode
-
- As long as both ends of the connection are using the QPacketProtocol class,
- the data within this packet will be delivered unfragmented at the other end,
- ready for extraction.
-
- \code
- QByteArray greeting;
- int count;
-
- QPacket myPacket = protocol.read();
-
- myPacket >> greeting >> count;
- \endcode
-
- Only packets returned from QPacketProtocol::read() may be read from. QPacket
- instances constructed by directly by applications are for transmission only
- and are considered "write only". Attempting to read data from them will
- result in undefined behavior.
-
- \ingroup io
- \sa QPacketProtocol
- */
-
-/*!
- Constructs an empty write-only packet.
- */
-QPacket::QPacket()
- : QDataStream(), buf(0)
-{
- buf = new QBuffer(&b);
- buf->open(QIODevice::WriteOnly);
- setDevice(buf);
- setVersion(QDataStream::Qt_4_7);
-}
-
-/*!
- Destroys the QPacket instance.
- */
-QPacket::~QPacket()
-{
- if (buf) {
- delete buf;
- buf = 0;
- }
-}
-
-/*!
- Creates a copy of \a other. The initial stream positions are shared, but the
- two packets are otherwise independent.
- */
-QPacket::QPacket(const QPacket & other)
- : QDataStream(), b(other.b), buf(0)
-{
- buf = new QBuffer(&b);
- buf->open(other.buf->openMode());
- setDevice(buf);
-}
-
-/*!
- \internal
- */
-QPacket::QPacket(const QByteArray & ba)
- : QDataStream(), b(ba), buf(0)
-{
- buf = new QBuffer(&b);
- buf->open(QIODevice::ReadOnly);
- setDevice(buf);
-}
-
-/*!
- Returns true if this packet is empty - that is, contains no data.
- */
-bool QPacket::isEmpty() const
-{
- return b.isEmpty();
-}
-
-/*!
- Returns raw packet data.
- */
-QByteArray QPacket::data() const
-{
- return b;
-}
-
-/*!
- Clears data in the packet. This is useful for reusing one writable packet.
- For example
- \code
- QPacketProtocol protocol(...);
-
- QPacket packet;
-
- packet << "Hello world!" << 123;
- protocol.send(packet);
-
- packet.clear();
- packet << "Goodbyte world!" << 789;
- protocol.send(packet);
- \endcode
- */
-void QPacket::clear()
-{
- QBuffer::OpenMode oldMode = buf->openMode();
- buf->close();
- b.clear();
- buf->setBuffer(&b); // reset QBuffer internals with new size of b.
- buf->open(oldMode);
-}
-
-/*!
- \class QPacketAutoSend
- \internal
-
- \internal
- */
-QPacketAutoSend::QPacketAutoSend(QPacketProtocol *_p)
- : QPacket(), p(_p)
-{
-}
-
-QPacketAutoSend::~QPacketAutoSend()
-{
- if (!b.isEmpty())
- p->send(*this);
-}
-
-QT_END_NAMESPACE
-
-#include <qpacketprotocol.moc>
diff --git a/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h b/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h
index 9aa4531428..52021379bc 100644
--- a/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h
+++ b/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h
@@ -66,7 +66,7 @@ protected:
{
QMutexLocker lock(&m_configMutex);
m_waitingForConfiguration = false;
- foreach (QQmlEngine *engine, m_waitingEngines)
+ foreach (QJSEngine *engine, m_waitingEngines)
emit Base::attachedToEngine(engine);
m_waitingEngines.clear();
}
@@ -79,7 +79,7 @@ protected:
QQmlDebugConnector::instance()->blockingMode());
}
- void stateChanged(QQmlDebugService::State newState)
+ void stateChanged(QQmlDebugService::State newState) Q_DECL_OVERRIDE
{
if (newState != QQmlDebugService::Enabled)
stopWaiting();
@@ -87,7 +87,7 @@ protected:
init();
}
- void engineAboutToBeAdded(QQmlEngine *engine)
+ void engineAboutToBeAdded(QJSEngine *engine) Q_DECL_OVERRIDE
{
QMutexLocker lock(&m_configMutex);
if (m_waitingForConfiguration)
@@ -97,7 +97,7 @@ protected:
}
QMutex m_configMutex;
- QList<QQmlEngine *> m_waitingEngines;
+ QList<QJSEngine *> m_waitingEngines;
bool m_waitingForConfiguration;
};
diff --git a/src/plugins/qmltooling/shared/qqmldebugpacket.h b/src/plugins/qmltooling/shared/qqmldebugpacket.h
new file mode 100644
index 0000000000..459937f411
--- /dev/null
+++ b/src/plugins/qmltooling/shared/qqmldebugpacket.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** 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 QQMLDEBUGPACKET_P_H
+#define QQMLDEBUGPACKET_P_H
+
+#include <QtCore/qbuffer.h>
+#include <QtQml/private/qqmldebugconnector_p.h>
+#include <QtPacketProtocol/private/qpacket_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+// QPacket with a fixed data stream version, centrally set by QQmlDebugServer
+class QQmlDebugPacket : public QPacket
+{
+public:
+ QQmlDebugPacket() : QPacket(QQmlDebugConnector::dataStreamVersion()) {}
+ QQmlDebugPacket(const QByteArray &ba) : QPacket(QQmlDebugConnector::dataStreamVersion(), ba) {}
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGPACKET_P_H
diff --git a/src/plugins/qmltooling/shared/qqmldebugserver.h b/src/plugins/qmltooling/shared/qqmldebugserver.h
index a7c17075d9..3807f12214 100644
--- a/src/plugins/qmltooling/shared/qqmldebugserver.h
+++ b/src/plugins/qmltooling/shared/qqmldebugserver.h
@@ -37,6 +37,8 @@
#include <private/qqmldebugconnector_p.h>
#include <private/qtqmlglobal_p.h>
+#include <QtCore/QIODevice>
+
//
// W A R N I N G
// -------------
diff --git a/src/qml/debugger/qqmlabstractprofileradapter_p.h b/src/qml/debugger/qqmlabstractprofileradapter_p.h
index bfd1561d3d..c723224985 100644
--- a/src/qml/debugger/qqmlabstractprofileradapter_p.h
+++ b/src/qml/debugger/qqmlabstractprofileradapter_p.h
@@ -58,9 +58,10 @@ class Q_QML_PRIVATE_EXPORT QQmlAbstractProfilerAdapter : public QObject, public
Q_OBJECT
public:
- QQmlAbstractProfilerAdapter(QQmlProfilerService *service) :
- service(service), waiting(true), featuresEnabled(0) {}
+ QQmlAbstractProfilerAdapter(QObject *parent = 0) :
+ QObject(parent), service(0), waiting(true), featuresEnabled(0) {}
virtual ~QQmlAbstractProfilerAdapter() {}
+ void setService(QQmlProfilerService *new_service) { service = new_service; }
virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages) = 0;
@@ -96,6 +97,15 @@ private:
quint64 featuresEnabled;
};
+class Q_QML_PRIVATE_EXPORT QQmlAbstractProfilerAdapterFactory : public QObject
+{
+ Q_OBJECT
+public:
+ virtual QQmlAbstractProfilerAdapter *create(const QString &key) = 0;
+};
+
+#define QQmlAbstractProfilerAdapterFactory_iid "org.qt-project.Qt.QQmlAbstractProfilerAdapterFactory"
+
QT_END_NAMESPACE
#endif // QQMLABSTRACTPROFILERADAPTER_P_H
diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp
index 35dc110e9a..b308f5aa29 100644
--- a/src/qml/debugger/qqmldebug.cpp
+++ b/src/qml/debugger/qqmldebug.cpp
@@ -33,6 +33,7 @@
#include "qqmldebug.h"
#include "qqmldebugconnector_p.h"
+#include "qqmldebugserviceinterfaces_p.h"
#include <private/qqmlengine_p.h>
@@ -52,10 +53,64 @@ QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
}
/*!
+ * Retrieves the plugin keys of the debugger services provided by default. The debugger services
+ * enable a debug client to use a Qml/JavaScript debugger, in order to set breakpoints, pause
+ * execution, evaluate expressions and similar debugging tasks.
+ * \return List of plugin keys of default debugger services.
+ */
+QStringList QQmlDebuggingEnabler::debuggerServices()
+{
+ return QStringList() << QV4DebugService::s_key << QQmlEngineDebugService::s_key
+ << QDebugMessageService::s_key;
+}
+
+/*!
+ * Retrieves the plugin keys of the inspector services provided by default. The inspector services
+ * enable a debug client to use a visual inspector tool for Qt Quick.
+ * \return List of plugin keys of default inspector services.
+ */
+QStringList QQmlDebuggingEnabler::inspectorServices()
+{
+ return QStringList() << QQmlInspectorService::s_key;
+}
+
+/*!
+ * Retrieves the names of the profiler services provided by default. The profiler services enable a
+ * debug client to use a profiler and track the time taken by various QML and JavaScript constructs,
+ * as well as the QtQuick SceneGraph.
+ * \return List of plugin keys of default profiler services.
+ */
+QStringList QQmlDebuggingEnabler::profilerServices()
+{
+ return QStringList() << QQmlProfilerService::s_key << QQmlEngineControlService::s_key;
+}
+
+/*!
+ * Restricts the services available from the debug connector. The connector will scan plugins in the
+ * "qmltooling" subdirectory of the default plugin path. If this function is not called before the
+ * debug connector is enabled, all services found that way will be available to any client. If this
+ * function is called, only the services with plugin keys given in \a services will be available.
+ *
+ * Use this method to disable debugger and inspector services when profiling to get better
+ * performance and more realistic profiles. The debugger service will put any JavaScript engine it
+ * connects to into interpreted mode, disabling the JIT compiler.
+ *
+ * \sa debuggerServices(), profilerServices(), inspectorServices()
+ */
+void QQmlDebuggingEnabler::setServices(const QStringList &services)
+{
+#ifndef QQML_NO_DEBUG_PROTOCOL
+ QQmlDebugConnector::setServices(services);
+#else
+ Q_UNUSED(services);
+#endif
+}
+
+/*!
* \enum QQmlDebuggingEnabler::StartMode
*
- * Defines the debug server's start behavior. You can interrupt QML engines starting while a debug
- * client is connecting, in order to set breakpoints in or profile startup code.
+ * Defines the debug connector's start behavior. You can interrupt QML engines starting while a
+ * debug client is connecting, in order to set breakpoints in or profile startup code.
*
* \value DoNotWaitForClient Run any QML engines as usual while the debug services are connecting.
* \value WaitForClient If a QML engine starts while the debug services are connecting,
@@ -63,13 +118,13 @@ QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
*/
/*!
- * Enables debugging for QML engines created after calling this function. The debug server will
+ * Enables debugging for QML engines created after calling this function. The debug connector will
* listen on \a port at \a hostName and block the QML engine until it receives a connection if
* \a mode is \c WaitForClient. If \a mode is not specified it won't block and if \a hostName is not
- * specified it will listen on all available interfaces. You can only start one debug server at a
- * time. A debug server may have already been started if the -qmljsdebugger= command line argument
- * was given. This method returns \c true if a new debug server was successfully started, or
- * \c false otherwise.
+ * specified it will listen on all available interfaces. You can only start one debug connector at a
+ * time. A debug connector may have already been started if the -qmljsdebugger= command line
+ * argument was given. This method returns \c true if a new debug connector was successfully
+ * started, or \c false otherwise.
*/
bool QQmlDebuggingEnabler::startTcpDebugServer(int port, StartMode mode, const QString &hostName)
{
@@ -85,7 +140,7 @@ bool QQmlDebuggingEnabler::startTcpDebugServer(int port, StartMode mode, const Q
}
#else
Q_UNUSED(port);
- Q_UNUSED(block);
+ Q_UNUSED(mode);
Q_UNUSED(hostName);
#endif
return false;
@@ -94,12 +149,12 @@ bool QQmlDebuggingEnabler::startTcpDebugServer(int port, StartMode mode, const Q
/*!
* \since 5.6
*
- * Enables debugging for QML engines created after calling this function. The debug server will
+ * Enables debugging for QML engines created after calling this function. The debug connector will
* connect to a debugger waiting on a local socket at the given \a socketFileName and block the QML
* engine until the connection is established if \a mode is \c WaitForClient. If \a mode is not
- * specified it will not block. You can only start one debug server at a time. A debug server may
- * have already been started if the -qmljsdebugger= command line argument was given. This method
- * returns \c true if a new debug server was successfully started, or \c false otherwise.
+ * specified it will not block. You can only start one debug connector at a time. A debug connector
+ * may have already been started if the -qmljsdebugger= command line argument was given. This method
+ * returns \c true if a new debug connector was successfully started, or \c false otherwise.
*/
bool QQmlDebuggingEnabler::connectToLocalDebugger(const QString &socketFileName, StartMode mode)
{
@@ -114,7 +169,7 @@ bool QQmlDebuggingEnabler::connectToLocalDebugger(const QString &socketFileName,
}
#else
Q_UNUSED(fileName);
- Q_UNUSED(block);
+ Q_UNUSED(mode);
#endif
return false;
}
diff --git a/src/qml/debugger/qqmldebug.h b/src/qml/debugger/qqmldebug.h
index 5d65982a49..6316ebd195 100644
--- a/src/qml/debugger/qqmldebug.h
+++ b/src/qml/debugger/qqmldebug.h
@@ -48,6 +48,13 @@ struct Q_QML_EXPORT QQmlDebuggingEnabler
};
QQmlDebuggingEnabler(bool printWarning = true);
+
+ static QStringList debuggerServices();
+ static QStringList inspectorServices();
+ static QStringList profilerServices();
+
+ static void setServices(const QStringList &services);
+
static bool startTcpDebugServer(int port, StartMode mode = DoNotWaitForClient,
const QString &hostName = QString());
static bool connectToLocalDebugger(const QString &socketFileName,
diff --git a/src/qml/debugger/qqmldebugconnector.cpp b/src/qml/debugger/qqmldebugconnector.cpp
index 64a8a49bb9..7d9f462fe2 100644
--- a/src/qml/debugger/qqmldebugconnector.cpp
+++ b/src/qml/debugger/qqmldebugconnector.cpp
@@ -39,6 +39,7 @@
#include <QtCore/QDir>
#include <QtCore/QDebug>
#include <QtCore/QJsonArray>
+#include <QtCore/QDataStream>
#include <private/qcoreapplication_p.h>
#include <private/qqmlengine_p.h>
@@ -56,6 +57,8 @@ Q_QML_IMPORT_DEBUG_PLUGIN(QQmlInspectorServiceFactory)
Q_QML_IMPORT_DEBUG_PLUGIN(QQmlProfilerServiceFactory)
Q_QML_IMPORT_DEBUG_PLUGIN(QQmlDebuggerServiceFactory)
+int QQmlDebugConnector::s_dataStreamVersion = QDataStream::Qt_4_7;
+
struct QQmlDebugConnectorParams {
QString pluginKey;
QStringList services;
diff --git a/src/qml/debugger/qqmldebugconnector_p.h b/src/qml/debugger/qqmldebugconnector_p.h
index f5f5a87b56..1e7d01e431 100644
--- a/src/qml/debugger/qqmldebugconnector_p.h
+++ b/src/qml/debugger/qqmldebugconnector_p.h
@@ -35,6 +35,7 @@
#define QQMLDEBUGCONNECTOR_H
#include <QtQml/qtqmlglobal.h>
+#include <QtQml/qjsengine.h>
#include <QtCore/QVariantList>
#include <private/qqmldebugservice_p.h>
@@ -60,13 +61,17 @@ public:
static void setPluginKey(const QString &key);
static void setServices(const QStringList &services);
static QQmlDebugConnector *instance();
+ static int dataStreamVersion()
+ {
+ return s_dataStreamVersion;
+ }
virtual bool blockingMode() const = 0;
virtual QQmlDebugService *service(const QString &name) const = 0;
- virtual void addEngine(QQmlEngine *engine) = 0;
- virtual void removeEngine(QQmlEngine *engine) = 0;
+ virtual void addEngine(QJSEngine *engine) = 0;
+ virtual void removeEngine(QJSEngine *engine) = 0;
virtual bool addService(const QString &name, QQmlDebugService *service) = 0;
virtual bool removeService(const QString &name) = 0;
@@ -82,6 +87,7 @@ public:
protected:
static QString commandLineArguments();
+ static int s_dataStreamVersion;
};
class Q_QML_PRIVATE_EXPORT QQmlDebugConnectorFactory : public QObject {
diff --git a/src/qml/debugger/qqmldebugservice.cpp b/src/qml/debugger/qqmldebugservice.cpp
index 0b07f320ec..f46a924d5e 100644
--- a/src/qml/debugger/qqmldebugservice.cpp
+++ b/src/qml/debugger/qqmldebugservice.cpp
@@ -182,50 +182,24 @@ void QQmlDebugService::messageReceived(const QByteArray &)
{
}
-void QQmlDebugService::engineAboutToBeAdded(QQmlEngine *engine)
+void QQmlDebugService::engineAboutToBeAdded(QJSEngine *engine)
{
emit attachedToEngine(engine);
}
-void QQmlDebugService::engineAboutToBeRemoved(QQmlEngine *engine)
+void QQmlDebugService::engineAboutToBeRemoved(QJSEngine *engine)
{
emit detachedFromEngine(engine);
}
-void QQmlDebugService::engineAdded(QQmlEngine *)
+void QQmlDebugService::engineAdded(QJSEngine *)
{
}
-void QQmlDebugService::engineRemoved(QQmlEngine *)
+void QQmlDebugService::engineRemoved(QJSEngine *)
{
}
-int QQmlDebugStream::s_dataStreamVersion = QDataStream::Qt_4_7;
-
-QQmlDebugStream::QQmlDebugStream()
- : QDataStream()
-{
- setVersion(s_dataStreamVersion);
-}
-
-QQmlDebugStream::QQmlDebugStream(QIODevice *d)
- : QDataStream(d)
-{
- setVersion(s_dataStreamVersion);
-}
-
-QQmlDebugStream::QQmlDebugStream(QByteArray *ba, QIODevice::OpenMode flags)
- : QDataStream(ba, flags)
-{
- setVersion(s_dataStreamVersion);
-}
-
-QQmlDebugStream::QQmlDebugStream(const QByteArray &ba)
- : QDataStream(ba)
-{
- setVersion(s_dataStreamVersion);
-}
-
QT_END_NAMESPACE
#include "qqmldebugservice.moc"
diff --git a/src/qml/debugger/qqmldebugservice_p.h b/src/qml/debugger/qqmldebugservice_p.h
index 3d692133cc..0fcf5459ef 100644
--- a/src/qml/debugger/qqmldebugservice_p.h
+++ b/src/qml/debugger/qqmldebugservice_p.h
@@ -35,7 +35,6 @@
#define QQMLDEBUGSERVICE_H
#include <QtCore/qobject.h>
-#include <QtCore/qdatastream.h>
#include <QtCore/qhash.h>
#include <private/qtqmlglobal_p.h>
@@ -53,7 +52,7 @@
QT_BEGIN_NAMESPACE
-class QQmlEngine;
+class QJSEngine;
class QQmlDebugServicePrivate;
class Q_QML_PRIVATE_EXPORT QQmlDebugService : public QObject
@@ -76,10 +75,10 @@ public:
virtual void stateChanged(State);
virtual void messageReceived(const QByteArray &);
- virtual void engineAboutToBeAdded(QQmlEngine *);
- virtual void engineAboutToBeRemoved(QQmlEngine *);
- virtual void engineAdded(QQmlEngine *);
- virtual void engineRemoved(QQmlEngine *);
+ virtual void engineAboutToBeAdded(QJSEngine *);
+ virtual void engineAboutToBeRemoved(QJSEngine *);
+ virtual void engineAdded(QJSEngine *);
+ virtual void engineRemoved(QJSEngine *);
static const QHash<int, QObject *> &objectsForIds();
static int idForObject(QObject *);
@@ -89,24 +88,13 @@ protected:
explicit QQmlDebugService(const QString &, float version, QObject *parent = 0);
signals:
- void attachedToEngine(QQmlEngine *);
- void detachedFromEngine(QQmlEngine *);
+ void attachedToEngine(QJSEngine *);
+ void detachedFromEngine(QJSEngine *);
void messageToClient(const QString &name, const QByteArray &message);
void messagesToClient(const QString &name, const QList<QByteArray> &messages);
};
-class Q_QML_PRIVATE_EXPORT QQmlDebugStream : public QDataStream
-{
-public:
- static int s_dataStreamVersion;
-
- QQmlDebugStream();
- explicit QQmlDebugStream(QIODevice *d);
- QQmlDebugStream(QByteArray *ba, QIODevice::OpenMode flags);
- QQmlDebugStream(const QByteArray &ba);
-};
-
QT_END_NAMESPACE
#endif // QQMLDEBUGSERVICE_H
diff --git a/src/qml/debugger/qqmldebugserviceinterfaces.cpp b/src/qml/debugger/qqmldebugserviceinterfaces.cpp
index 199c682748..e0968b2656 100644
--- a/src/qml/debugger/qqmldebugserviceinterfaces.cpp
+++ b/src/qml/debugger/qqmldebugserviceinterfaces.cpp
@@ -39,6 +39,8 @@ const QString QV4DebugService::s_key = QStringLiteral("V8Debugger");
const QString QQmlEngineDebugService::s_key = QStringLiteral("QmlDebugger");
const QString QQmlInspectorService::s_key = QStringLiteral("QmlInspector");
const QString QQmlProfilerService::s_key = QStringLiteral("CanvasFrameRate");
+const QString QDebugMessageService::s_key = QStringLiteral("DebugMessages");
+const QString QQmlEngineControlService::s_key = QStringLiteral("EngineControl");
const QString QQmlNativeDebugService::s_key = QStringLiteral("NativeQmlDebugger");
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmldebugserviceinterfaces_p.h b/src/qml/debugger/qqmldebugserviceinterfaces_p.h
index 6391bc6218..1b45392680 100644
--- a/src/qml/debugger/qqmldebugserviceinterfaces_p.h
+++ b/src/qml/debugger/qqmldebugserviceinterfaces_p.h
@@ -60,6 +60,8 @@ class Q_QML_PRIVATE_EXPORT QV4DebugService : protected QQmlDebugService
{
Q_OBJECT
public:
+ static const QString s_key;
+
virtual void signalEmitted(const QString &signal) = 0;
protected:
@@ -67,20 +69,20 @@ protected:
QV4DebugService(float version, QObject *parent = 0) :
QQmlDebugService(s_key, version, parent) {}
-
- static const QString s_key;
};
class Q_QML_PRIVATE_EXPORT QQmlProfilerService : protected QQmlDebugService
{
Q_OBJECT
public:
+ static const QString s_key;
+
virtual void addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler) = 0;
virtual void removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler) = 0;
- virtual void startProfiling(QQmlEngine *engine,
+ virtual void startProfiling(QJSEngine *engine,
quint64 features = std::numeric_limits<quint64>::max()) = 0;
- virtual void stopProfiling(QQmlEngine *engine) = 0;
+ virtual void stopProfiling(QJSEngine *engine) = 0;
virtual void dataReady(QQmlAbstractProfilerAdapter *profiler) = 0;
@@ -89,15 +91,15 @@ protected:
QQmlProfilerService(float version, QObject *parent = 0) :
QQmlDebugService(s_key, version, parent) {}
-
- static const QString s_key;
};
class Q_QML_PRIVATE_EXPORT QQmlEngineDebugService : protected QQmlDebugService
{
Q_OBJECT
public:
- virtual void objectCreated(QQmlEngine *engine, QObject *object) = 0;
+ static const QString s_key;
+
+ virtual void objectCreated(QJSEngine *engine, QObject *object) = 0;
virtual void setStatesDelegate(QQmlDebugStatesDelegate *) = 0;
protected:
@@ -107,14 +109,14 @@ protected:
QQmlDebugService(s_key, version, parent) {}
QQmlBoundSignal *nextSignal(QQmlBoundSignal *prev) { return prev->m_nextSignal; }
-
- static const QString s_key;
};
class Q_QML_PRIVATE_EXPORT QQmlInspectorService : protected QQmlDebugService
{
Q_OBJECT
public:
+ static const QString s_key;
+
virtual void addView(QObject *) = 0;
virtual void removeView(QObject *) = 0;
@@ -123,8 +125,35 @@ protected:
QQmlInspectorService(float version, QObject *parent = 0) :
QQmlDebugService(s_key, version, parent) {}
+};
+
+class Q_QML_PRIVATE_EXPORT QDebugMessageService : protected QQmlDebugService
+{
+ Q_OBJECT
+public:
+ static const QString s_key;
+
+ virtual void synchronizeTime(const QElapsedTimer &otherTimer) = 0;
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QDebugMessageService(float version, QObject *parent = 0) :
+ QQmlDebugService(s_key, version, parent) {}
+};
+class Q_QML_PRIVATE_EXPORT QQmlEngineControlService : protected QQmlDebugService
+{
+ Q_OBJECT
+public:
static const QString s_key;
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QQmlEngineControlService(float version, QObject *parent = 0) :
+ QQmlDebugService(s_key, version, parent) {}
+
};
class Q_QML_PRIVATE_EXPORT QQmlNativeDebugService : protected QQmlDebugService
diff --git a/src/qml/debugger/qqmlprofilerdefinitions_p.h b/src/qml/debugger/qqmlprofilerdefinitions_p.h
index 1213b67b3c..ce708132f8 100644
--- a/src/qml/debugger/qqmlprofilerdefinitions_p.h
+++ b/src/qml/debugger/qqmlprofilerdefinitions_p.h
@@ -89,9 +89,6 @@ struct QQmlProfilerDefinitions {
enum BindingType {
QmlBinding,
- V8Binding,
- V4Binding,
-
MaximumBindingType
};
@@ -126,8 +123,8 @@ struct QQmlProfilerDefinitions {
typedef QV4::Profiling::MemoryType MemoryType;
enum ProfileFeature {
- ProfileJavaScript = QV4::Profiling::FeatureFunctionCall,
- ProfileMemory = QV4::Profiling::FeatureMemoryAllocation,
+ ProfileJavaScript,
+ ProfileMemory,
ProfilePixmapCache,
ProfileSceneGraph,
ProfileAnimations,
@@ -137,9 +134,25 @@ struct QQmlProfilerDefinitions {
ProfileBinding,
ProfileHandlingSignal,
ProfileInputEvents,
+ ProfileDebugMessages,
MaximumProfileFeature
};
+
+ enum InputEventType {
+ InputKeyPress,
+ InputKeyRelease,
+ InputKeyUnknown,
+
+ InputMousePress,
+ InputMouseRelease,
+ InputMouseMove,
+ InputMouseDoubleClick,
+ InputMouseWheel,
+ InputMouseUnknown,
+
+ MaximumInputEventType
+ };
};
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 7706a40da6..b04bcd33e7 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -51,290 +51,4 @@
QT_BEGIN_NAMESPACE
-using namespace QV4;
-using namespace QV4::Debugging;
-
-V4Debugger::JavaScriptJob::JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr,
- const QString &script)
- : engine(engine)
- , frameNr(frameNr)
- , script(script)
- , resultIsException(false)
-{}
-
-void V4Debugger::JavaScriptJob::run()
-{
- Scope scope(engine);
-
- ExecutionContextSaver saver(scope);
-
- ExecutionContext *ctx = engine->currentContext;
- if (frameNr > 0) {
- for (int i = 0; i < frameNr; ++i) {
- ctx = engine->parentContext(ctx);
- }
- engine->pushContext(ctx);
- }
-
- QV4::Script script(ctx, this->script);
- script.strictMode = ctx->d()->strictMode;
- // In order for property lookups in QML to work, we need to disable fast v4 lookups. That
- // is a side-effect of inheritContext.
- script.inheritContext = true;
- script.parse();
- QV4::ScopedValue result(scope);
- if (!scope.engine->hasException)
- result = script.run();
- if (scope.engine->hasException) {
- result = scope.engine->catchException();
- resultIsException = true;
- }
- handleResult(result);
-}
-
-bool V4Debugger::JavaScriptJob::hasExeption() const
-{
- return resultIsException;
-}
-
-class EvalJob: public V4Debugger::JavaScriptJob
-{
- bool result;
-
-public:
- EvalJob(QV4::ExecutionEngine *engine, const QString &script)
- : V4Debugger::JavaScriptJob(engine, /*frameNr*/-1, script)
- , result(false)
- {}
-
- virtual void handleResult(QV4::ScopedValue &result)
- {
- this->result = result->toBoolean();
- }
-
- bool resultAsBoolean() const
- {
- return result;
- }
-};
-
-V4Debugger::V4Debugger(QV4::ExecutionEngine *engine)
- : m_engine(engine)
- , m_state(Running)
- , m_stepping(NotStepping)
- , m_pauseRequested(false)
- , m_haveBreakPoints(false)
- , m_breakOnThrow(false)
- , m_returnedValue(engine, Primitive::undefinedValue())
- , m_gatherSources(0)
- , m_runningJob(0)
-{
- qMetaTypeId<V4Debugger*>();
- qMetaTypeId<PauseReason>();
-}
-
-void V4Debugger::pause()
-{
- QMutexLocker locker(&m_lock);
- if (m_state == Paused)
- return;
- m_pauseRequested = true;
-}
-
-void V4Debugger::resume(Speed speed)
-{
- QMutexLocker locker(&m_lock);
- if (m_state != Paused)
- return;
-
- if (!m_returnedValue.isUndefined())
- m_returnedValue.set(m_engine, Encode::undefined());
-
- m_currentContext.set(m_engine, *m_engine->currentContext);
- m_stepping = speed;
- m_runningCondition.wakeAll();
-}
-
-void V4Debugger::addBreakPoint(const QString &fileName, int lineNumber, const QString &condition)
-{
- QMutexLocker locker(&m_lock);
- m_breakPoints.insert(DebuggerBreakPoint(fileName.mid(fileName.lastIndexOf('/') + 1), lineNumber), condition);
- m_haveBreakPoints = true;
-}
-
-void V4Debugger::removeBreakPoint(const QString &fileName, int lineNumber)
-{
- QMutexLocker locker(&m_lock);
- m_breakPoints.remove(DebuggerBreakPoint(fileName.mid(fileName.lastIndexOf('/') + 1), lineNumber));
- m_haveBreakPoints = !m_breakPoints.isEmpty();
-}
-
-void V4Debugger::setBreakOnThrow(bool onoff)
-{
- QMutexLocker locker(&m_lock);
-
- m_breakOnThrow = onoff;
-}
-
-V4Debugger::ExecutionState V4Debugger::currentExecutionState() const
-{
- ExecutionState state;
- state.fileName = getFunction()->sourceFile();
- state.lineNumber = engine()->current->lineNumber;
-
- return state;
-}
-
-QVector<StackFrame> V4Debugger::stackTrace(int frameLimit) const
-{
- return m_engine->stackTrace(frameLimit);
-}
-
-void V4Debugger::maybeBreakAtInstruction()
-{
- if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
- return;
-
- QMutexLocker locker(&m_lock);
-
- if (m_gatherSources) {
- m_gatherSources->run();
- delete m_gatherSources;
- m_gatherSources = 0;
- }
-
- switch (m_stepping) {
- case StepOver:
- if (m_currentContext.asManaged()->d() != m_engine->current)
- break;
- // fall through
- case StepIn:
- pauseAndWait(Step);
- return;
- case StepOut:
- case NotStepping:
- break;
- }
-
- if (m_pauseRequested) { // Serve debugging requests from the agent
- m_pauseRequested = false;
- pauseAndWait(PauseRequest);
- } else if (m_haveBreakPoints) {
- if (Function *f = getFunction()) {
- const int lineNumber = engine()->current->lineNumber;
- if (reallyHitTheBreakPoint(f->sourceFile(), lineNumber))
- pauseAndWait(BreakPoint);
- }
- }
-}
-
-void V4Debugger::enteringFunction()
-{
- if (m_runningJob)
- return;
- QMutexLocker locker(&m_lock);
-
- if (m_stepping == StepIn) {
- m_currentContext.set(m_engine, *m_engine->currentContext);
- }
-}
-
-void V4Debugger::leavingFunction(const ReturnedValue &retVal)
-{
- if (m_runningJob)
- return;
- Q_UNUSED(retVal); // TODO
-
- QMutexLocker locker(&m_lock);
-
- if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->current) {
- m_currentContext.set(m_engine, *m_engine->parentContext(m_engine->currentContext));
- m_stepping = StepOver;
- m_returnedValue.set(m_engine, retVal);
- }
-}
-
-void V4Debugger::aboutToThrow()
-{
- if (!m_breakOnThrow)
- return;
-
- if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
- return;
-
- QMutexLocker locker(&m_lock);
- pauseAndWait(Throwing);
-}
-
-Function *V4Debugger::getFunction() const
-{
- Scope scope(m_engine);
- ExecutionContext *context = m_engine->currentContext;
- ScopedFunctionObject function(scope, context->getFunctionObject());
- if (function)
- return function->function();
- else
- return context->d()->engine->globalCode;
-}
-
-void V4Debugger::pauseAndWait(PauseReason reason)
-{
- if (m_runningJob)
- return;
-
- m_state = Paused;
- emit debuggerPaused(this, reason);
-
- while (true) {
- m_runningCondition.wait(&m_lock);
- if (m_runningJob) {
- m_runningJob->run();
- m_jobIsRunning.wakeAll();
- } else {
- break;
- }
- }
-
- m_state = Running;
-}
-
-bool V4Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr)
-{
- BreakPoints::iterator it = m_breakPoints.find(DebuggerBreakPoint(filename.mid(filename.lastIndexOf('/') + 1), linenr));
- if (it == m_breakPoints.end())
- return false;
- QString condition = it.value();
- if (condition.isEmpty())
- return true;
-
- Q_ASSERT(m_runningJob == 0);
- EvalJob evilJob(m_engine, condition);
- m_runningJob = &evilJob;
- m_runningJob->run();
- m_runningJob = 0;
-
- return evilJob.resultAsBoolean();
-}
-
-void V4Debugger::runInEngine(V4Debugger::Job *job)
-{
- QMutexLocker locker(&m_lock);
- runInEngine_havingLock(job);
-}
-
-void V4Debugger::runInEngine_havingLock(V4Debugger::Job *job)
-{
- Q_ASSERT(job);
- Q_ASSERT(m_runningJob == 0);
-
- m_runningJob = job;
- m_runningCondition.wakeAll();
- m_jobIsRunning.wait(&m_lock);
- m_runningJob = 0;
-}
-
-V4Debugger::Job::~Job()
-{
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h
index fdc9cac24f..3a3ecef918 100644
--- a/src/qml/jsruntime/qv4debugging_p.h
+++ b/src/qml/jsruntime/qv4debugging_p.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef DEBUGGING_H
-#define DEBUGGING_H
+#ifndef QV4DEBUGGING_H
+#define QV4DEBUGGING_H
//
// W A R N I N G
@@ -46,50 +46,13 @@
//
#include "qv4global_p.h"
-#include "qv4engine_p.h"
-#include "qv4context_p.h"
-#include "qv4scopedvalue_p.h"
-
-#include <QHash>
-#include <QThread>
-#include <QMutex>
-#include <QWaitCondition>
-
-#include <QtCore/QJsonObject>
+#include <QtCore/qobject.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
-
-struct Function;
-
namespace Debugging {
-enum PauseReason {
- PauseRequest,
- BreakPoint,
- Throwing,
- Step
-};
-
-struct DebuggerBreakPoint {
- DebuggerBreakPoint(const QString &fileName, int line)
- : fileName(fileName), lineNumber(line)
- {}
- QString fileName;
- int lineNumber;
-};
-inline uint qHash(const DebuggerBreakPoint &b, uint seed = 0) Q_DECL_NOTHROW
-{
- return qHash(b.fileName, seed) ^ b.lineNumber;
-}
-inline bool operator==(const DebuggerBreakPoint &a, const DebuggerBreakPoint &b)
-{
- return a.lineNumber == b.lineNumber && a.fileName == b.fileName;
-}
-
-typedef QHash<DebuggerBreakPoint, QString> BreakPoints;
-
class Q_QML_EXPORT Debugger : public QObject
{
Q_OBJECT
@@ -103,123 +66,9 @@ public:
virtual void aboutToThrow() = 0;
};
-class Q_QML_EXPORT V4Debugger : public Debugger
-{
- Q_OBJECT
-public:
- class Q_QML_EXPORT Job
- {
- public:
- virtual ~Job() = 0;
- virtual void run() = 0;
- };
-
- class Q_QML_EXPORT JavaScriptJob: public Job
- {
- QV4::ExecutionEngine *engine;
- int frameNr;
- const QString &script;
- bool resultIsException;
-
- public:
- JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, const QString &script);
- void run();
- bool hasExeption() const;
-
- protected:
- virtual void handleResult(QV4::ScopedValue &result) = 0;
- };
-
- enum State {
- Running,
- Paused
- };
-
- enum Speed {
- FullThrottle = 0,
- StepOut,
- StepOver,
- StepIn,
-
- NotStepping = FullThrottle
- };
-
- V4Debugger(ExecutionEngine *engine);
-
- ExecutionEngine *engine() const
- { return m_engine; }
-
- void pause();
- void resume(Speed speed);
-
- State state() const { return m_state; }
-
- void addBreakPoint(const QString &fileName, int lineNumber, const QString &condition = QString());
- void removeBreakPoint(const QString &fileName, int lineNumber);
-
- void setBreakOnThrow(bool onoff);
-
- // used for testing
- struct ExecutionState
- {
- QString fileName;
- int lineNumber;
- };
- ExecutionState currentExecutionState() const;
-
- bool pauseAtNextOpportunity() const {
- return m_pauseRequested || m_haveBreakPoints || m_gatherSources || m_stepping >= StepOver;
- }
-
- QVector<StackFrame> stackTrace(int frameLimit = -1) const;
- QVector<Heap::ExecutionContext::ContextType> getScopeTypes(int frame = 0) const;
-
- Function *getFunction() const;
- void runInEngine(Job *job);
-
-public: // compile-time interface
- void maybeBreakAtInstruction();
-
-public: // execution hooks
- void enteringFunction();
- void leavingFunction(const ReturnedValue &retVal);
- void aboutToThrow();
-
-signals:
- void sourcesCollected(QV4::Debugging::V4Debugger *self, const QStringList &sources, int seq);
- void debuggerPaused(QV4::Debugging::V4Debugger *self, QV4::Debugging::PauseReason reason);
-
-private:
- // requires lock to be held
- void pauseAndWait(PauseReason reason);
- bool reallyHitTheBreakPoint(const QString &filename, int linenr);
- void runInEngine_havingLock(V4Debugger::Job *job);
-
-private:
- QV4::ExecutionEngine *m_engine;
- QV4::PersistentValue m_currentContext;
- QMutex m_lock;
- QWaitCondition m_runningCondition;
- State m_state;
- Speed m_stepping;
- bool m_pauseRequested;
- bool m_haveBreakPoints;
- bool m_breakOnThrow;
-
- BreakPoints m_breakPoints;
- QV4::PersistentValue m_returnedValue;
-
- Job *m_gatherSources;
- Job *m_runningJob;
- QWaitCondition m_jobIsRunning;
-};
-
} // namespace Debugging
} // namespace QV4
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QV4::Debugging::Debugger*)
-Q_DECLARE_METATYPE(QV4::Debugging::PauseReason)
-
-#endif // DEBUGGING_H
+#endif // QV4DEBUGGING_H
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 110a2c9089..b4733356ac 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -302,7 +302,7 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
++r;
}
if (*r)
- output.append(input.mid(start, i - start + 1));
+ output.append(input.midRef(start, i - start + 1));
else
output.append(QChar(b));
} else {
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 8f471132b7..ee294b3678 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1447,7 +1447,8 @@ static QV4::ReturnedValue CallOverloaded(const QQmlObjectOrGadget &object, const
const QQmlPropertyData *candidate = &data;
while (candidate) {
error += QLatin1String("\n ") +
- QString::fromUtf8(object.metaObject()->method(candidate->coreIndex).methodSignature().constData());
+ QString::fromUtf8(object.metaObject()->method(candidate->coreIndex)
+ .methodSignature());
candidate = RelatedMethod(object, candidate, dummy, propertyCache);
}
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 477a517e32..decffaf2fa 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -250,7 +250,7 @@ QQmlBoundSignal::QQmlBoundSignal(QObject *target, int signal, QObject *owner,
QQmlEngine *engine)
: QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlBoundSignal),
m_prevSignal(0), m_nextSignal(0),
- m_expression(0)
+ m_enabled(true), m_expression(0)
{
addToObject(owner);
@@ -313,18 +313,33 @@ void QQmlBoundSignal::takeExpression(QQmlBoundSignalExpression *e)
m_expression->setNotifyOnValueChanged(false);
}
+/*!
+ This property holds whether the item will emit signals.
+
+ The QQmlBoundSignal callback will only emit a signal if this property is set to true.
+
+ By default, this property is true.
+ */
+void QQmlBoundSignal::setEnabled(bool enabled)
+{
+ if (m_enabled == enabled)
+ return;
+
+ m_enabled = enabled;
+}
+
void QQmlBoundSignal_callback(QQmlNotifierEndpoint *e, void **a)
{
QQmlBoundSignal *s = static_cast<QQmlBoundSignal*>(e);
- if (!s->m_expression)
+ if (!s->m_expression || !s->m_enabled)
return;
QV4DebugService *service = QQmlDebugConnector::service<QV4DebugService>();
if (service)
- service->signalEmitted(QString::fromLatin1(QMetaObjectPrivate::signal(
- s->m_expression->target()->metaObject(),
- s->signalIndex()).methodSignature()));
+ service->signalEmitted(QString::fromUtf8(QMetaObjectPrivate::signal(
+ s->m_expression->target()->metaObject(),
+ s->signalIndex()).methodSignature()));
QQmlEngine *engine;
if (s->m_expression && (engine = s->m_expression->engine())) {
diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h
index 3742317484..ef8fdd4a1a 100644
--- a/src/qml/qml/qqmlboundsignal_p.h
+++ b/src/qml/qml/qqmlboundsignal_p.h
@@ -108,6 +108,8 @@ public:
QQmlBoundSignalExpression *expression() const;
void takeExpression(QQmlBoundSignalExpression *);
+ void setEnabled(bool enabled);
+
private:
friend void QQmlBoundSignal_callback(QQmlNotifierEndpoint *, void **);
friend class QQmlPropertyPrivate;
@@ -119,6 +121,8 @@ private:
QQmlBoundSignal **m_prevSignal;
QQmlBoundSignal *m_nextSignal;
+ bool m_enabled;
+
QQmlBoundSignalExpressionPointer m_expression;
};
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 93e66a1b12..4da19a5a5c 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -176,6 +176,7 @@ void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int
qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
qmlRegisterType<QQmlBind>(uri, versionMajor, versionMinor,"Binding");
+ qmlRegisterType<QQmlConnections,1>(uri, versionMajor, (versionMinor < 3 ? 3 : versionMinor), "Connections"); //Only available in >=2.3
qmlRegisterType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections");
qmlRegisterType<QQmlTimer>(uri, versionMajor, versionMinor,"Timer");
qmlRegisterType<QQmlInstantiator>(uri, versionMajor, (versionMinor < 1 ? 1 : versionMinor), "Instantiator"); //Only available in >=2.1
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index f6f8c6e51e..c5b5947c11 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -1000,13 +1000,21 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
}
#else
- Q_UNUSED(qmldirFilePath);
- Q_UNUSED(uri);
Q_UNUSED(vmaj);
Q_UNUSED(vmin);
Q_UNUSED(database);
Q_UNUSED(qmldir);
- Q_UNUSED(errors);
+
+ if (errors) {
+ QQmlError error;
+ error.setDescription(
+ QQmlImportDatabase::tr(
+ "plugin cannot be loaded for module \"%1\": library loading is disabled")
+ .arg(uri));
+ error.setUrl(QUrl::fromLocalFile(qmldirFilePath));
+ errors->prepend(error);
+ }
+
return false;
#endif // QT_NO_LIBRARY
return true;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index c03a463c83..f096dfeea9 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -884,9 +884,10 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
QMetaMethod signalMethod = _qobject->metaObject()->method(property->coreIndex);
if (!QMetaObject::checkConnectArgs(signalMethod, method)) {
- recordError(binding->valueLocation, tr("Cannot connect mismatched signal/slot %1 %vs. %2")
- .arg(QString::fromLatin1(method.methodSignature().constData()))
- .arg(QString::fromLatin1(signalMethod.methodSignature().constData())));
+ recordError(binding->valueLocation,
+ tr("Cannot connect mismatched signal/slot %1 %vs. %2")
+ .arg(QString::fromUtf8(method.methodSignature()))
+ .arg(QString::fromUtf8(signalMethod.methodSignature())));
return false;
}
diff --git a/src/qml/qml/qqmlstringconverters.cpp b/src/qml/qml/qqmlstringconverters.cpp
index eb0afda927..6a5c0736cf 100644
--- a/src/qml/qml/qqmlstringconverters.cpp
+++ b/src/qml/qml/qqmlstringconverters.cpp
@@ -137,8 +137,8 @@ QPointF QQmlStringConverters::pointFFromString(const QString &s, bool *ok)
bool xGood, yGood;
int index = s.indexOf(QLatin1Char(','));
- qreal xCoord = s.left(index).toDouble(&xGood);
- qreal yCoord = s.mid(index+1).toDouble(&yGood);
+ qreal xCoord = s.leftRef(index).toDouble(&xGood);
+ qreal yCoord = s.midRef(index+1).toDouble(&yGood);
if (!xGood || !yGood) {
if (ok)
*ok = false;
@@ -161,8 +161,8 @@ QSizeF QQmlStringConverters::sizeFFromString(const QString &s, bool *ok)
bool wGood, hGood;
int index = s.indexOf(QLatin1Char('x'));
- qreal width = s.left(index).toDouble(&wGood);
- qreal height = s.mid(index+1).toDouble(&hGood);
+ qreal width = s.leftRef(index).toDouble(&wGood);
+ qreal height = s.midRef(index+1).toDouble(&hGood);
if (!wGood || !hGood) {
if (ok)
*ok = false;
@@ -185,12 +185,12 @@ QRectF QQmlStringConverters::rectFFromString(const QString &s, bool *ok)
bool xGood, yGood, wGood, hGood;
int index = s.indexOf(QLatin1Char(','));
- qreal x = s.left(index).toDouble(&xGood);
+ qreal x = s.leftRef(index).toDouble(&xGood);
int index2 = s.indexOf(QLatin1Char(','), index+1);
- qreal y = s.mid(index+1, index2-index-1).toDouble(&yGood);
+ qreal y = s.midRef(index+1, index2-index-1).toDouble(&yGood);
index = s.indexOf(QLatin1Char('x'), index2+1);
- qreal width = s.mid(index2+1, index-index2-1).toDouble(&wGood);
- qreal height = s.mid(index+1).toDouble(&hGood);
+ qreal width = s.midRef(index2+1, index-index2-1).toDouble(&wGood);
+ qreal height = s.midRef(index+1).toDouble(&hGood);
if (!xGood || !yGood || !wGood || !hGood) {
if (ok)
*ok = false;
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 67c4295d95..b1f2549035 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -793,8 +793,10 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
// are not rewritten correctly but this bug is deemed out-of-scope to fix for
// performance reasons; see QTBUG-24064) and thus compilation will have failed.
QQmlError e;
- e.setDescription(QString(QLatin1String("Exception occurred during compilation of function: %1")).
- arg(QLatin1String(QMetaObject::method(_id).methodSignature().constData())));
+ e.setDescription(QString::fromLatin1("Exception occurred during compilation of "
+ "function: %1")
+ .arg(QString::fromUtf8(QMetaObject::method(_id)
+ .methodSignature())));
ep->warning(e);
return -1; // The dynamic method with that id is not available.
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index f4e980eefb..e859224aea 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -904,7 +904,7 @@ ReturnedValue QtObject::method_btoa(CallContext *ctx)
/*!
\qmlmethod string Qt::atob(data)
-ASCII to binary - this function returns a base64 decoding of \c data.
+ASCII to binary - this function decodes the base64 encoded \a data string and returns it.
*/
ReturnedValue QtObject::method_atob(CallContext *ctx)
{
@@ -1468,9 +1468,6 @@ QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->d()->engine;
- if (!v4->qmlEngine())
- return QV4::Encode::undefined(); // Not yet implemented for JavaScript.
-
QV4::StackFrame frame = v4->currentStackFrame();
const QByteArray baSource = frame.source.toUtf8();
const QByteArray baFunction = frame.function.toUtf8();
@@ -1479,7 +1476,7 @@ QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx)
if (!service) {
logger.warning("Cannot start profiling because debug service is disabled. Start with -qmljsdebugger=port:XXXXX.");
} else {
- service->startProfiling(v4->qmlEngine());
+ service->startProfiling(v4->jsEngine());
logger.debug("Profiling started.");
}
@@ -1490,9 +1487,6 @@ QV4::ReturnedValue ConsoleObject::method_profileEnd(CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->d()->engine;
- if (!v4->qmlEngine())
- return QV4::Encode::undefined(); // Not yet implemented for JavaScript.
-
QV4::StackFrame frame = v4->currentStackFrame();
const QByteArray baSource = frame.source.toUtf8();
const QByteArray baFunction = frame.function.toUtf8();
@@ -1502,7 +1496,7 @@ QV4::ReturnedValue ConsoleObject::method_profileEnd(CallContext *ctx)
if (!service) {
logger.warning("Ignoring console.profileEnd(): the debug service is disabled.");
} else {
- service->stopProfiling(v4->qmlEngine());
+ service->stopProfiling(v4->jsEngine());
logger.debug("Profiling ended.");
}
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
index 6a93410ecb..5f69bf5f94 100644
--- a/src/qml/types/qqmlconnections.cpp
+++ b/src/qml/types/qqmlconnections.cpp
@@ -51,11 +51,12 @@ QT_BEGIN_NAMESPACE
class QQmlConnectionsPrivate : public QObjectPrivate
{
public:
- QQmlConnectionsPrivate() : target(0), targetSet(false), ignoreUnknownSignals(false), componentcomplete(true) {}
+ QQmlConnectionsPrivate() : target(0), enabled(true), targetSet(false), ignoreUnknownSignals(false), componentcomplete(true) {}
QList<QQmlBoundSignal*> boundsignals;
QObject *target;
+ bool enabled;
bool targetSet;
bool ignoreUnknownSignals;
bool componentcomplete;
@@ -177,6 +178,34 @@ void QQmlConnections::setTarget(QObject *obj)
}
/*!
+ \qmlproperty bool QtQml::Connections::enabled
+ \since 5.7
+
+ This property holds whether the item accepts change events.
+
+ By default, this property is \c true.
+*/
+bool QQmlConnections::isEnabled() const
+{
+ Q_D(const QQmlConnections);
+ return d->enabled;
+}
+
+void QQmlConnections::setEnabled(bool enabled)
+{
+ Q_D(QQmlConnections);
+ if (d->enabled == enabled)
+ return;
+
+ d->enabled = enabled;
+
+ foreach (QQmlBoundSignal *s, d->boundsignals)
+ s->setEnabled(d->enabled);
+
+ emit enabledChanged();
+}
+
+/*!
\qmlproperty bool QtQml::Connections::ignoreUnknownSignals
Normally, a connection to a non-existent signal produces runtime errors.
diff --git a/src/qml/types/qqmlconnections_p.h b/src/qml/types/qqmlconnections_p.h
index 234c5061a7..d330b772cc 100644
--- a/src/qml/types/qqmlconnections_p.h
+++ b/src/qml/types/qqmlconnections_p.h
@@ -63,6 +63,7 @@ class Q_AUTOTEST_EXPORT QQmlConnections : public QObject, public QQmlParserStatu
Q_INTERFACES(QQmlParserStatus)
Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_REVISION(1) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
Q_PROPERTY(bool ignoreUnknownSignals READ ignoreUnknownSignals WRITE setIgnoreUnknownSignals)
public:
@@ -72,11 +73,15 @@ public:
QObject *target() const;
void setTarget(QObject *);
+ bool isEnabled() const;
+ void setEnabled(bool enabled);
+
bool ignoreUnknownSignals() const;
void setIgnoreUnknownSignals(bool ignore);
Q_SIGNALS:
void targetChanged();
+ Q_REVISION(1) void enabledChanged();
private:
void connectSignals();
diff --git a/src/qmldebug/qmldebug.pro b/src/qmldebug/qmldebug.pro
new file mode 100644
index 0000000000..e5f6de3314
--- /dev/null
+++ b/src/qmldebug/qmldebug.pro
@@ -0,0 +1,21 @@
+TARGET = QtQmlDebug
+QT = core-private network packetprotocol-private qml-private
+CONFIG += static internal_module
+
+load(qt_module)
+
+SOURCES += \
+ qqmldebugclient.cpp \
+ qqmldebugconnection.cpp \
+ qqmlenginecontrolclient.cpp \
+ qqmlprofilerclient.cpp
+
+HEADERS += \
+ qqmldebugclient_p.h \
+ qqmldebugclient_p_p.h \
+ qqmldebugconnection_p.h \
+ qqmlenginecontrolclient_p.h \
+ qqmlenginecontrolclient_p_p.h \
+ qqmleventlocation_p.h \
+ qqmlprofilerclient_p.h \
+ qqmlprofilerclient_p_p.h
diff --git a/src/qmldebug/qqmldebugclient.cpp b/src/qmldebug/qqmldebugclient.cpp
new file mode 100644
index 0000000000..dfa14d6667
--- /dev/null
+++ b/src/qmldebug/qqmldebugclient.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** 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 "qqmldebugclient_p_p.h"
+#include "qqmldebugconnection_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlDebugClient::QQmlDebugClient(const QString &name, QQmlDebugConnection *parent) :
+ QObject(*(new QQmlDebugClientPrivate(name, parent)), parent)
+{
+ Q_D(QQmlDebugClient);
+ d->addToConnection();
+}
+
+QQmlDebugClient::QQmlDebugClient(QQmlDebugClientPrivate &dd) :
+ QObject(dd, dd.connection.data())
+{
+ Q_D(QQmlDebugClient);
+ d->addToConnection();
+}
+
+QQmlDebugClient::~QQmlDebugClient()
+{
+ Q_D(QQmlDebugClient);
+ if (d->connection && !d->connection->removeClient(d->name))
+ qWarning() << "QQmlDebugClient: Plugin not registered" << d->name;
+}
+
+QQmlDebugClientPrivate::QQmlDebugClientPrivate(const QString &name,
+ QQmlDebugConnection *connection) :
+ name(name), connection(connection)
+{
+}
+
+void QQmlDebugClientPrivate::addToConnection()
+{
+ Q_Q(QQmlDebugClient);
+ if (connection && !connection->addClient(name, q)) {
+ qWarning() << "QQmlDebugClient: Conflicting plugin name" << name;
+ connection = 0;
+ }
+}
+
+QString QQmlDebugClient::name() const
+{
+ Q_D(const QQmlDebugClient);
+ return d->name;
+}
+
+float QQmlDebugClient::serviceVersion() const
+{
+ Q_D(const QQmlDebugClient);
+ return d->connection->serviceVersion(d->name);
+}
+
+QQmlDebugClient::State QQmlDebugClient::state() const
+{
+ Q_D(const QQmlDebugClient);
+ if (!d->connection || !d->connection->isConnected())
+ return NotConnected;
+
+ if (d->connection->serviceVersion(d->name) != -1)
+ return Enabled;
+
+ return Unavailable;
+}
+
+void QQmlDebugClient::sendMessage(const QByteArray &message)
+{
+ Q_D(QQmlDebugClient);
+ d->connection->sendMessage(d->name, message);
+}
+
+QQmlDebugConnection *QQmlDebugClient::connection() const
+{
+ Q_D(const QQmlDebugClient);
+ return d->connection;
+}
+
+void QQmlDebugClient::stateChanged(QQmlDebugClient::State state)
+{
+ Q_UNUSED(state);
+}
+
+void QQmlDebugClient::messageReceived(const QByteArray &message)
+{
+ Q_UNUSED(message);
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmldebugclient_p.h b/src/qmldebug/qqmldebugclient_p.h
new file mode 100644
index 0000000000..6d391617a9
--- /dev/null
+++ b/src/qmldebug/qqmldebugclient_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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 QQMLDEBUGCLIENT_P_H
+#define QQMLDEBUGCLIENT_P_H
+
+#include <QtCore/qobject.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlDebugConnection;
+class QQmlDebugClientPrivate;
+class QQmlDebugClient : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QQmlDebugClient)
+ Q_DECLARE_PRIVATE(QQmlDebugClient)
+
+public:
+ enum State { NotConnected, Unavailable, Enabled };
+
+ QQmlDebugClient(const QString &name, QQmlDebugConnection *parent);
+ ~QQmlDebugClient();
+
+ QString name() const;
+ float serviceVersion() const;
+ State state() const;
+ void sendMessage(const QByteArray &message);
+
+ QQmlDebugConnection *connection() const;
+
+protected:
+ QQmlDebugClient(QQmlDebugClientPrivate &dd);
+
+private:
+ friend class QQmlDebugConnection;
+
+ virtual void stateChanged(State state);
+ virtual void messageReceived(const QByteArray &message);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGCLIENT_P_H
diff --git a/src/qmldebug/qqmldebugclient_p_p.h b/src/qmldebug/qqmldebugclient_p_p.h
new file mode 100644
index 0000000000..66a4f4e0c3
--- /dev/null
+++ b/src/qmldebug/qqmldebugclient_p_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** 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 QQMLDEBUGCLIENT_P_P_H
+#define QQMLDEBUGCLIENT_P_P_H
+
+#include "qqmldebugclient_p.h"
+#include <private/qobject_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlDebugClientPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQmlDebugClient)
+public:
+ QQmlDebugClientPrivate(const QString &name, QQmlDebugConnection *connection);
+ void addToConnection();
+
+ QString name;
+ QPointer<QQmlDebugConnection> connection;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGCLIENT_P_P_H
diff --git a/src/qmldebug/qqmldebugconnection.cpp b/src/qmldebug/qqmldebugconnection.cpp
new file mode 100644
index 0000000000..3c207b7cc8
--- /dev/null
+++ b/src/qmldebug/qqmldebugconnection.cpp
@@ -0,0 +1,458 @@
+/****************************************************************************
+**
+** 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 "qqmldebugconnection_p.h"
+#include "qqmldebugclient_p.h"
+
+#include <private/qpacketprotocol_p.h>
+#include <private/qpacket_p.h>
+#include <private/qobject_p.h>
+
+#include <QtCore/qeventloop.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qdatastream.h>
+#include <QtNetwork/qlocalserver.h>
+#include <QtNetwork/qlocalsocket.h>
+#include <QtNetwork/qtcpsocket.h>
+
+QT_BEGIN_NAMESPACE
+
+static const int protocolVersion = 1;
+static const QString serverId = QLatin1String("QDeclarativeDebugServer");
+static const QString clientId = QLatin1String("QDeclarativeDebugClient");
+
+class QQmlDebugConnectionPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQmlDebugConnection)
+
+public:
+ QQmlDebugConnectionPrivate();
+ QPacketProtocol *protocol;
+ QIODevice *device;
+ QLocalServer *server;
+ QEventLoop handshakeEventLoop;
+ QTimer handshakeTimer;
+
+ bool gotHello;
+ int currentDataStreamVersion;
+ int maximumDataStreamVersion;
+ QHash <QString, float> serverPlugins;
+ QHash<QString, QQmlDebugClient *> plugins;
+ QStringList removedPlugins;
+
+ void advertisePlugins();
+ void connectDeviceSignals();
+ void flush();
+};
+
+QQmlDebugConnectionPrivate::QQmlDebugConnectionPrivate() :
+ protocol(0), device(0), server(0), gotHello(false),
+ currentDataStreamVersion(QDataStream::Qt_4_7),
+ maximumDataStreamVersion(QDataStream::Qt_DefaultCompiledVersion)
+{
+ handshakeTimer.setSingleShot(true);
+ handshakeTimer.setInterval(3000);
+}
+
+void QQmlDebugConnectionPrivate::advertisePlugins()
+{
+ Q_Q(QQmlDebugConnection);
+ if (!q->isConnected())
+ return;
+
+ QPacket pack(currentDataStreamVersion);
+ pack << serverId << 1 << plugins.keys();
+ protocol->send(pack.data());
+ flush();
+}
+
+void QQmlDebugConnection::socketConnected()
+{
+ Q_D(QQmlDebugConnection);
+ QPacket pack(d->currentDataStreamVersion);
+ pack << serverId << 0 << protocolVersion << d->plugins.keys() << d->maximumDataStreamVersion;
+ d->protocol->send(pack.data());
+ d->flush();
+}
+
+void QQmlDebugConnection::socketDisconnected()
+{
+ Q_D(QQmlDebugConnection);
+ d->gotHello = false;
+ emit disconnected();
+}
+
+void QQmlDebugConnection::protocolReadyRead()
+{
+ Q_D(QQmlDebugConnection);
+ if (!d->gotHello) {
+ QPacket pack(d->currentDataStreamVersion, d->protocol->read());
+ QString name;
+
+ pack >> name;
+
+ bool validHello = false;
+ if (name == clientId) {
+ int op = -1;
+ pack >> op;
+ if (op == 0) {
+ int version = -1;
+ pack >> version;
+ if (version == protocolVersion) {
+ QStringList pluginNames;
+ QList<float> pluginVersions;
+ pack >> pluginNames;
+ if (!pack.atEnd())
+ pack >> pluginVersions;
+
+ const int pluginNamesSize = pluginNames.size();
+ const int pluginVersionsSize = pluginVersions.size();
+ for (int i = 0; i < pluginNamesSize; ++i) {
+ float pluginVersion = 1.0;
+ if (i < pluginVersionsSize)
+ pluginVersion = pluginVersions.at(i);
+ d->serverPlugins.insert(pluginNames.at(i), pluginVersion);
+ }
+
+ pack >> d->currentDataStreamVersion;
+ validHello = true;
+ }
+ }
+ }
+
+ if (!validHello) {
+ qWarning("QQmlDebugConnection: Invalid hello message");
+ QObject::disconnect(d->protocol, SIGNAL(protocolReadyRead()), this, SLOT(protocolReadyRead()));
+ return;
+ }
+ d->gotHello = true;
+ emit connected();
+
+ QHash<QString, QQmlDebugClient *>::Iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter) {
+ QQmlDebugClient::State newState = QQmlDebugClient::Unavailable;
+ if (d->serverPlugins.contains(iter.key()))
+ newState = QQmlDebugClient::Enabled;
+ iter.value()->stateChanged(newState);
+ }
+
+ d->handshakeTimer.stop();
+ d->handshakeEventLoop.quit();
+ }
+
+ while (d->protocol->packetsAvailable()) {
+ QPacket pack(d->currentDataStreamVersion, d->protocol->read());
+ QString name;
+ pack >> name;
+
+ if (name == clientId) {
+ int op = -1;
+ pack >> op;
+
+ if (op == 1) {
+ // Service Discovery
+ QHash<QString, float> oldServerPlugins = d->serverPlugins;
+ d->serverPlugins.clear();
+
+ QStringList pluginNames;
+ QList<float> pluginVersions;
+ pack >> pluginNames;
+ if (!pack.atEnd())
+ pack >> pluginVersions;
+
+ const int pluginNamesSize = pluginNames.size();
+ const int pluginVersionsSize = pluginVersions.size();
+ for (int i = 0; i < pluginNamesSize; ++i) {
+ float pluginVersion = 1.0;
+ if (i < pluginVersionsSize)
+ pluginVersion = pluginVersions.at(i);
+ d->serverPlugins.insert(pluginNames.at(i), pluginVersion);
+ }
+
+ QHash<QString, QQmlDebugClient *>::Iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter) {
+ const QString pluginName = iter.key();
+ QQmlDebugClient::State newSate = QQmlDebugClient::Unavailable;
+ if (d->serverPlugins.contains(pluginName))
+ newSate = QQmlDebugClient::Enabled;
+
+ if (oldServerPlugins.contains(pluginName)
+ != d->serverPlugins.contains(pluginName)) {
+ iter.value()->stateChanged(newSate);
+ }
+ }
+ } else {
+ qWarning() << "QQmlDebugConnection: Unknown control message id" << op;
+ }
+ } else {
+ QByteArray message;
+ pack >> message;
+
+ QHash<QString, QQmlDebugClient *>::Iterator iter = d->plugins.find(name);
+ if (iter == d->plugins.end()) {
+ // We can get more messages for plugins we have removed because it takes time to
+ // send the advertisement message but the removal is instant locally.
+ if (!d->removedPlugins.contains(name))
+ qWarning() << "QQmlDebugConnection: Message received for missing plugin"
+ << name;
+ } else {
+ (*iter)->messageReceived(message);
+ }
+ }
+ }
+}
+
+void QQmlDebugConnection::handshakeTimeout()
+{
+ Q_D(QQmlDebugConnection);
+ if (!d->gotHello) {
+ qWarning() << "QQmlDebugConnection: Did not get handshake answer in time";
+ d->handshakeEventLoop.quit();
+ }
+}
+
+QQmlDebugConnection::QQmlDebugConnection(QObject *parent) :
+ QObject(*(new QQmlDebugConnectionPrivate), parent)
+{
+ Q_D(QQmlDebugConnection);
+ connect(&d->handshakeTimer, SIGNAL(timeout()), this, SLOT(handshakeTimeout()));
+}
+
+QQmlDebugConnection::~QQmlDebugConnection()
+{
+ Q_D(QQmlDebugConnection);
+ QHash<QString, QQmlDebugClient*>::iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter)
+ iter.value()->stateChanged(QQmlDebugClient::NotConnected);
+}
+
+int QQmlDebugConnection::currentDataStreamVersion() const
+{
+ Q_D(const QQmlDebugConnection);
+ return d->currentDataStreamVersion;
+}
+
+void QQmlDebugConnection::setMaximumDataStreamVersion(int maximumVersion)
+{
+ Q_D(QQmlDebugConnection);
+ d->maximumDataStreamVersion = maximumVersion;
+}
+
+bool QQmlDebugConnection::isConnected() const
+{
+ Q_D(const QQmlDebugConnection);
+ return d->gotHello;
+}
+
+bool QQmlDebugConnection::isConnecting() const
+{
+ Q_D(const QQmlDebugConnection);
+ return !d->gotHello && d->device;
+}
+
+void QQmlDebugConnection::close()
+{
+ Q_D(QQmlDebugConnection);
+ if (d->gotHello) {
+ d->gotHello = false;
+ d->device->close();
+
+ QHash<QString, QQmlDebugClient*>::iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter)
+ iter.value()->stateChanged(QQmlDebugClient::NotConnected);
+ }
+
+ if (d->device) {
+ d->device->deleteLater();
+ d->device = 0;
+ }
+}
+
+bool QQmlDebugConnection::waitForConnected(int msecs)
+{
+ Q_D(QQmlDebugConnection);
+ QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(d->device);
+ if (!socket) {
+ if (!d->server || (!d->server->hasPendingConnections() &&
+ !d->server->waitForNewConnection(msecs)))
+ return false;
+ } else if (!socket->waitForConnected(msecs)) {
+ return false;
+ }
+ // wait for handshake
+ d->handshakeTimer.start();
+ d->handshakeEventLoop.exec();
+ return d->gotHello;
+}
+
+QQmlDebugClient *QQmlDebugConnection::client(const QString &name) const
+{
+ Q_D(const QQmlDebugConnection);
+ return d->plugins.value(name, 0);
+}
+
+bool QQmlDebugConnection::addClient(const QString &name, QQmlDebugClient *client)
+{
+ Q_D(QQmlDebugConnection);
+ if (d->plugins.contains(name))
+ return false;
+ d->removedPlugins.removeAll(name);
+ d->plugins.insert(name, client);
+ d->advertisePlugins();
+ return true;
+}
+
+bool QQmlDebugConnection::removeClient(const QString &name)
+{
+ Q_D(QQmlDebugConnection);
+ if (!d->plugins.contains(name))
+ return false;
+ d->plugins.remove(name);
+ d->removedPlugins.append(name);
+ d->advertisePlugins();
+ return true;
+}
+
+float QQmlDebugConnection::serviceVersion(const QString &serviceName) const
+{
+ Q_D(const QQmlDebugConnection);
+ return d->serverPlugins.value(serviceName, -1);
+}
+
+bool QQmlDebugConnection::sendMessage(const QString &name, const QByteArray &message)
+{
+ Q_D(QQmlDebugConnection);
+ if (!isConnected() || !d->serverPlugins.contains(name))
+ return false;
+
+ QPacket pack(d->currentDataStreamVersion);
+ pack << name << message;
+ d->protocol->send(pack.data());
+ d->flush();
+
+ return true;
+}
+
+void QQmlDebugConnectionPrivate::flush()
+{
+ QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(device);
+ if (socket)
+ socket->flush();
+}
+
+void QQmlDebugConnection::connectToHost(const QString &hostName, quint16 port)
+{
+ Q_D(QQmlDebugConnection);
+ if (d->gotHello)
+ close();
+ QTcpSocket *socket = new QTcpSocket(this);
+ d->device = socket;
+ d->connectDeviceSignals();
+ connect(socket, SIGNAL(connected()), this, SLOT(socketConnected()));
+ connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SIGNAL(socketError(QAbstractSocket::SocketError)));
+ connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
+ this, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)));
+ socket->connectToHost(hostName, port);
+}
+
+void QQmlDebugConnection::startLocalServer(const QString &fileName)
+{
+ Q_D(QQmlDebugConnection);
+ if (d->gotHello)
+ close();
+ if (d->server)
+ d->server->deleteLater();
+ d->server = new QLocalServer(this);
+ // QueuedConnection so that waitForNewConnection() returns true.
+ connect(d->server, SIGNAL(newConnection()), this, SLOT(newConnection()), Qt::QueuedConnection);
+ d->server->listen(fileName);
+}
+
+class LocalSocketSignalTranslator : public QObject
+{
+ Q_OBJECT
+public:
+ LocalSocketSignalTranslator(QLocalSocket *parent) : QObject(parent)
+ {
+ connect(parent, SIGNAL(stateChanged(QLocalSocket::LocalSocketState)),
+ this, SLOT(onStateChanged(QLocalSocket::LocalSocketState)));
+ connect(parent, SIGNAL(error(QLocalSocket::LocalSocketError)),
+ this, SLOT(onError(QLocalSocket::LocalSocketError)));
+ }
+
+signals:
+ void socketError(QAbstractSocket::SocketError error);
+ void socketStateChanged(QAbstractSocket::SocketState state);
+
+public slots:
+ void onError(QLocalSocket::LocalSocketError error)
+ {
+ emit socketError(static_cast<QAbstractSocket::SocketError>(error));
+ }
+
+ void onStateChanged(QLocalSocket::LocalSocketState state)
+ {
+ emit socketStateChanged(static_cast<QAbstractSocket::SocketState>(state));
+ }
+};
+
+void QQmlDebugConnection::newConnection()
+{
+ Q_D(QQmlDebugConnection);
+ delete d->device;
+ QLocalSocket *socket = d->server->nextPendingConnection();
+ d->server->close();
+ d->device = socket;
+ d->connectDeviceSignals();
+ LocalSocketSignalTranslator *translator = new LocalSocketSignalTranslator(socket);
+
+ QObject::connect(translator, SIGNAL(socketError(QAbstractSocket::SocketError)),
+ this, SIGNAL(socketError(QAbstractSocket::SocketError)));
+ QObject::connect(translator, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)),
+ this, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)));
+ socketConnected();
+}
+
+void QQmlDebugConnectionPrivate::connectDeviceSignals()
+{
+ Q_Q(QQmlDebugConnection);
+ delete protocol;
+ protocol = new QPacketProtocol(device, q);
+ QObject::connect(protocol, SIGNAL(readyRead()), q, SLOT(protocolReadyRead()));
+ QObject::connect(device, SIGNAL(disconnected()), q, SLOT(socketDisconnected()));
+}
+
+QT_END_NAMESPACE
+
+#include <qqmldebugconnection.moc>
diff --git a/src/qmldebug/qqmldebugconnection_p.h b/src/qmldebug/qqmldebugconnection_p.h
new file mode 100644
index 0000000000..190ca25db2
--- /dev/null
+++ b/src/qmldebug/qqmldebugconnection_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** 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 QQMLDEBUGCONNECTION_P_H
+#define QQMLDEBUGCONNECTION_P_H
+
+#include <QtCore/qobject.h>
+#include <QtNetwork/qabstractsocket.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlDebugClient;
+class QQmlDebugConnectionPrivate;
+class QQmlDebugConnection : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QQmlDebugConnection)
+ Q_DECLARE_PRIVATE(QQmlDebugConnection)
+public:
+ QQmlDebugConnection(QObject *parent = 0);
+ ~QQmlDebugConnection();
+
+ void connectToHost(const QString &hostName, quint16 port);
+ void startLocalServer(const QString &fileName);
+
+ int currentDataStreamVersion() const;
+ void setMaximumDataStreamVersion(int maximumVersion);
+
+ bool isConnected() const;
+ bool isConnecting() const;
+
+ void close();
+ bool waitForConnected(int msecs = 30000);
+
+ QQmlDebugClient *client(const QString &name) const;
+ bool addClient(const QString &name, QQmlDebugClient *client);
+ bool removeClient(const QString &name);
+
+ float serviceVersion(const QString &serviceName) const;
+ bool sendMessage(const QString &name, const QByteArray &message);
+
+signals:
+ void connected();
+ void disconnected();
+ void socketError(QAbstractSocket::SocketError socketError);
+ void socketStateChanged(QAbstractSocket::SocketState socketState);
+
+private Q_SLOTS:
+ void newConnection();
+ void socketConnected();
+ void socketDisconnected();
+ void protocolReadyRead();
+ void handshakeTimeout();
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGCONNECTION_P_H
diff --git a/src/qmldebug/qqmlenginecontrolclient.cpp b/src/qmldebug/qqmlenginecontrolclient.cpp
new file mode 100644
index 0000000000..b45e4e1f14
--- /dev/null
+++ b/src/qmldebug/qqmlenginecontrolclient.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** 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 "qqmlenginecontrolclient_p.h"
+#include "qqmlenginecontrolclient_p_p.h"
+#include "qqmldebugconnection_p.h"
+
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qpacket_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlEngineControlClient::QQmlEngineControlClient(QQmlDebugConnection *connection) :
+ QQmlDebugClient(*(new QQmlEngineControlClientPrivate(connection)))
+{
+}
+
+QQmlEngineControlClient::QQmlEngineControlClient(QQmlEngineControlClientPrivate &dd) :
+ QQmlDebugClient(dd)
+{
+}
+
+/*!
+ * Block the starting or stopping of the engine with id \a engineId for now. By calling
+ * releaseEngine later the block can be lifted again. In the debugged application the engine control
+ * server waits until a message is received before continuing. So by not sending a message here we
+ * delay the process. Blocks add up. You have to call releaseEngine() as often as you've called
+ * blockEngine before. The intention of that is to allow different debug clients to use the same
+ * engine control and communicate with their respective counterparts before the QML engine starts or
+ * shuts down.
+ */
+void QQmlEngineControlClient::blockEngine(int engineId)
+{
+ Q_D(QQmlEngineControlClient);
+ Q_ASSERT(d->blockedEngines.contains(engineId));
+ d->blockedEngines[engineId].blockers++;
+}
+
+/*!
+ * Release the engine with id \a engineId. If no other blocks are present, depending on what the
+ * engine is waiting for, the start or stop command is sent to the process being debugged.
+ */
+void QQmlEngineControlClient::releaseEngine(int engineId)
+{
+ Q_D(QQmlEngineControlClient);
+ Q_ASSERT(d->blockedEngines.contains(engineId));
+
+ QQmlEngineControlClientPrivate::EngineState &state = d->blockedEngines[engineId];
+ if (--state.blockers == 0) {
+ Q_ASSERT(state.releaseCommand != QQmlEngineControlClientPrivate::InvalidCommand);
+ d->sendCommand(state.releaseCommand, engineId);
+ d->blockedEngines.remove(engineId);
+ }
+}
+
+QList<int> QQmlEngineControlClient::blockedEngines() const
+{
+ Q_D(const QQmlEngineControlClient);
+ return d->blockedEngines.keys();
+}
+
+void QQmlEngineControlClient::messageReceived(const QByteArray &data)
+{
+ Q_D(QQmlEngineControlClient);
+ QPacket stream(d->connection->currentDataStreamVersion(), data);
+ int message;
+ int id;
+ QString name;
+
+ stream >> message >> id;
+
+ if (!stream.atEnd())
+ stream >> name;
+
+ QQmlEngineControlClientPrivate::EngineState &state = d->blockedEngines[id];
+ Q_ASSERT(state.blockers == 0);
+ Q_ASSERT(state.releaseCommand == QQmlEngineControlClientPrivate::InvalidCommand);
+
+ switch (message) {
+ case QQmlEngineControlClientPrivate::EngineAboutToBeAdded:
+ state.releaseCommand = QQmlEngineControlClientPrivate::StartWaitingEngine;
+ emit engineAboutToBeAdded(id, name);
+ break;
+ case QQmlEngineControlClientPrivate::EngineAdded:
+ emit engineAdded(id, name);
+ break;
+ case QQmlEngineControlClientPrivate::EngineAboutToBeRemoved:
+ state.releaseCommand = QQmlEngineControlClientPrivate::StopWaitingEngine;
+ emit engineAboutToBeRemoved(id, name);
+ break;
+ case QQmlEngineControlClientPrivate::EngineRemoved:
+ emit engineRemoved(id, name);
+ break;
+ }
+
+ if (state.blockers == 0 &&
+ state.releaseCommand != QQmlEngineControlClientPrivate::InvalidCommand) {
+ d->sendCommand(state.releaseCommand, id);
+ d->blockedEngines.remove(id);
+ }
+}
+
+QQmlEngineControlClientPrivate::QQmlEngineControlClientPrivate(QQmlDebugConnection *connection) :
+ QQmlDebugClientPrivate(QQmlEngineControlService::s_key, connection)
+{
+}
+
+void QQmlEngineControlClientPrivate::sendCommand(
+ QQmlEngineControlClientPrivate::CommandType command, int engineId)
+{
+ Q_Q(QQmlEngineControlClient);
+ QPacket stream(connection->currentDataStreamVersion());
+ stream << int(command) << engineId;
+ q->sendMessage(stream.data());
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlenginecontrolclient_p.h b/src/qmldebug/qqmlenginecontrolclient_p.h
new file mode 100644
index 0000000000..601f8a871d
--- /dev/null
+++ b/src/qmldebug/qqmlenginecontrolclient_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** 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 QQMLENGINECONTROLCLIENT_P_H
+#define QQMLENGINECONTROLCLIENT_P_H
+
+#include "qqmldebugclient_p.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlEngineControlClientPrivate;
+class QQmlEngineControlClient : public QQmlDebugClient
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQmlEngineControlClient)
+public:
+ QQmlEngineControlClient(QQmlDebugConnection *connection);
+
+ void blockEngine(int engineId);
+ void releaseEngine(int engineId);
+
+ QList<int> blockedEngines() const;
+
+signals:
+ void engineAboutToBeAdded(int engineId, const QString &name);
+ void engineAdded(int engineId, const QString &name);
+ void engineAboutToBeRemoved(int engineId, const QString &name);
+ void engineRemoved(int engineId, const QString &name);
+
+protected:
+ QQmlEngineControlClient(QQmlEngineControlClientPrivate &dd);
+
+private:
+ void messageReceived(const QByteArray &);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLENGINECONTROLCLIENT_P_H
diff --git a/src/qmldebug/qqmlenginecontrolclient_p_p.h b/src/qmldebug/qqmlenginecontrolclient_p_p.h
new file mode 100644
index 0000000000..7e99c35948
--- /dev/null
+++ b/src/qmldebug/qqmlenginecontrolclient_p_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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 QQMLENGINECONTROLCLIENT_P_P_H
+#define QQMLENGINECONTROLCLIENT_P_P_H
+
+#include "qqmlenginecontrolclient_p.h"
+#include "qqmldebugclient_p_p.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlEngineControlClientPrivate : public QQmlDebugClientPrivate
+{
+ Q_DECLARE_PUBLIC(QQmlEngineControlClient)
+public:
+ enum MessageType {
+ EngineAboutToBeAdded,
+ EngineAdded,
+ EngineAboutToBeRemoved,
+ EngineRemoved
+ };
+
+ enum CommandType {
+ StartWaitingEngine,
+ StopWaitingEngine,
+ InvalidCommand
+ };
+
+ QQmlEngineControlClientPrivate(QQmlDebugConnection *connection);
+
+ void sendCommand(CommandType command, int engineId);
+
+ struct EngineState {
+ EngineState(CommandType command = InvalidCommand) : releaseCommand(command), blockers(0) {}
+ CommandType releaseCommand;
+ int blockers;
+ };
+
+ QHash<int, EngineState> blockedEngines;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLENGINECONTROLCLIENT_P_P_H
diff --git a/src/qmldebug/qqmleventlocation_p.h b/src/qmldebug/qqmleventlocation_p.h
new file mode 100644
index 0000000000..25d81a5989
--- /dev/null
+++ b/src/qmldebug/qqmleventlocation_p.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** 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 QQMLEVENTLOCATION_P_H
+#define QQMLEVENTLOCATION_P_H
+
+#include <QtCore/qstring.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+struct QQmlEventLocation
+{
+ QQmlEventLocation() : line(-1), column(-1) {}
+ QQmlEventLocation(const QString &file, int lineNumber, int columnNumber) :
+ filename(file), line(lineNumber), column(columnNumber) {}
+
+ QString filename;
+ int line;
+ int column;
+};
+
+Q_DECLARE_TYPEINFO(QQmlEventLocation, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif // QQMLEVENTLOCATION_P_H
diff --git a/src/qmldebug/qqmlprofilerclient.cpp b/src/qmldebug/qqmlprofilerclient.cpp
new file mode 100644
index 0000000000..c7ad6dae53
--- /dev/null
+++ b/src/qmldebug/qqmlprofilerclient.cpp
@@ -0,0 +1,354 @@
+/****************************************************************************
+**
+** 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 "qqmlprofilerclient_p_p.h"
+#include "qqmldebugconnection_p.h"
+#include <private/qqmldebugserviceinterfaces_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlProfilerClient::QQmlProfilerClient(QQmlDebugConnection *connection) :
+ QQmlDebugClient(*(new QQmlProfilerClientPrivate(connection)))
+{
+}
+
+QQmlProfilerClient::QQmlProfilerClient(QQmlProfilerClientPrivate &dd) :
+ QQmlDebugClient(dd)
+{
+}
+
+QQmlProfilerClientPrivate::QQmlProfilerClientPrivate(QQmlDebugConnection *connection) :
+ QQmlDebugClientPrivate(QQmlProfilerService::s_key, connection),
+ features(std::numeric_limits<quint64>::max())
+{
+}
+
+void QQmlProfilerClient::setFeatures(quint64 features)
+{
+ Q_D(QQmlProfilerClient);
+ d->features = features;
+}
+
+void QQmlProfilerClient::sendRecordingStatus(bool record, int engineId, quint32 flushInterval)
+{
+ Q_D(const QQmlProfilerClient);
+
+ QPacket stream(d->connection->currentDataStreamVersion());
+ stream << record << engineId << d->features << flushInterval;
+ sendMessage(stream.data());
+}
+
+void QQmlProfilerClient::traceStarted(qint64 time, int engineId)
+{
+ Q_UNUSED(time);
+ Q_UNUSED(engineId);
+}
+
+void QQmlProfilerClient::traceFinished(qint64 time, int engineId)
+{
+ Q_UNUSED(time);
+ Q_UNUSED(engineId);
+}
+
+void QQmlProfilerClient::rangeStart(QQmlProfilerDefinitions::RangeType type, qint64 startTime)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(startTime);
+}
+
+void QQmlProfilerClient::rangeData(QQmlProfilerDefinitions::RangeType type, qint64 time,
+ const QString &data)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(time);
+ Q_UNUSED(data);
+}
+
+void QQmlProfilerClient::rangeLocation(QQmlProfilerDefinitions::RangeType type, qint64 time,
+ const QQmlEventLocation &location)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(time);
+ Q_UNUSED(location);
+}
+
+void QQmlProfilerClient::rangeEnd(QQmlProfilerDefinitions::RangeType type, qint64 endTime)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(endTime);
+}
+
+void QQmlProfilerClient::animationFrame(qint64 time, int frameRate, int animationCount,
+ int threadId)
+{
+ Q_UNUSED(time);
+ Q_UNUSED(frameRate);
+ Q_UNUSED(animationCount);
+ Q_UNUSED(threadId);
+}
+
+void QQmlProfilerClient::sceneGraphEvent(QQmlProfilerDefinitions::SceneGraphFrameType type,
+ qint64 time, qint64 numericData1, qint64 numericData2,
+ qint64 numericData3, qint64 numericData4,
+ qint64 numericData5)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(time);
+ Q_UNUSED(numericData1);
+ Q_UNUSED(numericData2);
+ Q_UNUSED(numericData3);
+ Q_UNUSED(numericData4);
+ Q_UNUSED(numericData5);
+}
+
+void QQmlProfilerClient::pixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type,
+ qint64 time, const QString &url, int numericData1,
+ int numericData2)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(time);
+ Q_UNUSED(url);
+ Q_UNUSED(numericData1);
+ Q_UNUSED(numericData2);
+}
+
+void QQmlProfilerClient::memoryAllocation(QQmlProfilerDefinitions::MemoryType type, qint64 time,
+ qint64 amount)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(time);
+ Q_UNUSED(amount);
+}
+
+void QQmlProfilerClient::inputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time,
+ int a, int b)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(time);
+ Q_UNUSED(a);
+ Q_UNUSED(b);
+}
+
+void QQmlProfilerClient::complete()
+{
+}
+
+void QQmlProfilerClient::unknownEvent(QQmlProfilerDefinitions::Message messageType, qint64 time,
+ int detailType)
+{
+ Q_UNUSED(messageType);
+ Q_UNUSED(time);
+ Q_UNUSED(detailType);
+}
+
+void QQmlProfilerClient::unknownData(QPacket &stream)
+{
+ Q_UNUSED(stream);
+}
+
+inline QQmlProfilerDefinitions::ProfileFeature featureFromRangeType(
+ QQmlProfilerDefinitions::RangeType range)
+{
+ switch (range) {
+ case QQmlProfilerDefinitions::Painting:
+ return QQmlProfilerDefinitions::ProfilePainting;
+ case QQmlProfilerDefinitions::Compiling:
+ return QQmlProfilerDefinitions::ProfileCompiling;
+ case QQmlProfilerDefinitions::Creating:
+ return QQmlProfilerDefinitions::ProfileCreating;
+ case QQmlProfilerDefinitions::Binding:
+ return QQmlProfilerDefinitions::ProfileBinding;
+ case QQmlProfilerDefinitions::HandlingSignal:
+ return QQmlProfilerDefinitions::ProfileHandlingSignal;
+ case QQmlProfilerDefinitions::Javascript:
+ return QQmlProfilerDefinitions::ProfileJavaScript;
+ default:
+ return QQmlProfilerDefinitions::MaximumProfileFeature;
+ }
+}
+
+void QQmlProfilerClient::messageReceived(const QByteArray &data)
+{
+ Q_D(const QQmlProfilerClient);
+
+ QPacket stream(d->connection->currentDataStreamVersion(), data);
+
+ // Force all the 1 << <FLAG> expressions to be done in 64 bit, to silence some warnings
+ const quint64 one = static_cast<quint64>(1);
+
+ qint64 time;
+ int messageType;
+
+ stream >> time >> messageType;
+
+ if (messageType >= QQmlProfilerDefinitions::MaximumMessage) {
+ unknownEvent(static_cast<QQmlProfilerDefinitions::Message>(messageType), time, -1);
+ return;
+ }
+
+ if (messageType == QQmlProfilerDefinitions::Event) {
+ int type;
+ stream >> type;
+
+ QQmlProfilerDefinitions::EventType eventType =
+ static_cast<QQmlProfilerDefinitions::EventType>(type);
+
+ if (eventType == QQmlProfilerDefinitions::EndTrace) {
+ int engineId = -1;
+ if (!stream.atEnd())
+ stream >> engineId;
+ traceFinished(time, engineId);
+ } else if (eventType == QQmlProfilerDefinitions::AnimationFrame) {
+ if (!(d->features & one << QQmlProfilerDefinitions::ProfileAnimations))
+ return;
+
+ int frameRate, animationCount;
+ int threadId = 0;
+ stream >> frameRate >> animationCount;
+ if (!stream.atEnd())
+ stream >> threadId;
+
+ animationFrame(time, frameRate, animationCount, threadId);
+ } else if (type == QQmlProfilerDefinitions::StartTrace) {
+ int engineId = -1;
+ if (!stream.atEnd())
+ stream >> engineId;
+ traceStarted(time, engineId);
+ } else if (eventType == QQmlProfilerDefinitions::Key ||
+ eventType == QQmlProfilerDefinitions::Mouse) {
+
+ if (!(d->features & one << QQmlProfilerDefinitions::ProfileInputEvents))
+ return;
+
+ int type;
+ if (!stream.atEnd()) {
+ stream >> type;
+ } else {
+ type = (eventType == QQmlProfilerDefinitions::Key) ?
+ QQmlProfilerDefinitions::InputKeyUnknown :
+ QQmlProfilerDefinitions::InputMouseUnknown;
+ }
+
+ int a = 0;
+ if (!stream.atEnd())
+ stream >> a;
+
+ int b = 0;
+ if (!stream.atEnd())
+ stream >> b;
+
+ inputEvent(static_cast<QQmlProfilerDefinitions::InputEventType>(type), time, a, b);
+ } else {
+ unknownEvent(QQmlProfilerDefinitions::Event, time, type);
+ }
+ } else if (messageType == QQmlProfilerDefinitions::Complete) {
+ complete();
+ } else if (messageType == QQmlProfilerDefinitions::SceneGraphFrame) {
+ if (!(d->features & one << QQmlProfilerDefinitions::ProfileSceneGraph))
+ return;
+
+ int type;
+ int count = 0;
+ qint64 params[5];
+
+ stream >> type;
+ while (!stream.atEnd())
+ stream >> params[count++];
+
+ while (count < 5)
+ params[count++] = 0;
+
+ sceneGraphEvent(static_cast<QQmlProfilerDefinitions::SceneGraphFrameType>(type), time,
+ params[0], params[1], params[2], params[3], params[4]);
+ } else if (messageType == QQmlProfilerDefinitions::PixmapCacheEvent) {
+ if (!(d->features & one << QQmlProfilerDefinitions::ProfilePixmapCache))
+ return;
+
+ int type, param1 = 0, param2 = 0;
+ QString pixUrl;
+ stream >> type >> pixUrl;
+
+ QQmlProfilerDefinitions::PixmapEventType pixmapEventType =
+ static_cast<QQmlProfilerDefinitions::PixmapEventType>(type);
+
+ if (pixmapEventType == QQmlProfilerDefinitions::PixmapReferenceCountChanged ||
+ pixmapEventType == QQmlProfilerDefinitions::PixmapCacheCountChanged) {
+ stream >> param1;
+ } else if (pixmapEventType == QQmlProfilerDefinitions::PixmapSizeKnown) {
+ stream >> param1 >> param2;
+ }
+
+ pixmapCacheEvent(pixmapEventType, time, pixUrl, param1, param2);
+ } else if (messageType == QQmlProfilerDefinitions::MemoryAllocation) {
+ if (!(d->features & one << QQmlProfilerDefinitions::ProfileMemory))
+ return;
+ int type;
+ qint64 delta;
+ stream >> type >> delta;
+ memoryAllocation((QQmlProfilerDefinitions::MemoryType)type, time, delta);
+ } else {
+ int range;
+ stream >> range;
+
+ QQmlProfilerDefinitions::RangeType rangeType =
+ static_cast<QQmlProfilerDefinitions::RangeType>(range);
+
+ if (range >= QQmlProfilerDefinitions::MaximumRangeType ||
+ !(d->features & one << featureFromRangeType(rangeType)))
+ return;
+
+ if (messageType == QQmlProfilerDefinitions::RangeStart) {
+ rangeStart(rangeType, time);
+ } else if (messageType == QQmlProfilerDefinitions::RangeData) {
+ QString data;
+ stream >> data;
+ rangeData(rangeType, time, data);
+ } else if (messageType == QQmlProfilerDefinitions::RangeLocation) {
+ QQmlEventLocation location;
+ stream >> location.filename >> location.line;
+
+ if (!stream.atEnd())
+ stream >> location.column;
+
+ rangeLocation(rangeType, time, location);
+ } else if (messageType == QQmlProfilerDefinitions::RangeEnd) {
+ rangeEnd(rangeType, time);
+ } else {
+ unknownEvent(static_cast<QQmlProfilerDefinitions::Message>(messageType), time, range);
+ }
+ }
+
+ if (!stream.atEnd())
+ unknownData(stream);
+}
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlprofilerclient_p.h b/src/qmldebug/qqmlprofilerclient_p.h
new file mode 100644
index 0000000000..0513bef608
--- /dev/null
+++ b/src/qmldebug/qqmlprofilerclient_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** 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 QQMLPROFILERCLIENT_P_H
+#define QQMLPROFILERCLIENT_P_H
+
+#include "qqmldebugclient_p.h"
+#include "qqmleventlocation_p.h"
+#include <private/qqmlprofilerdefinitions_p.h>
+#include <private/qpacket_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlProfilerClientPrivate;
+class QQmlProfilerClient : public QQmlDebugClient
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQmlProfilerClient)
+
+public:
+ QQmlProfilerClient(QQmlDebugConnection *connection);
+ void setFeatures(quint64 features);
+
+public slots:
+ void sendRecordingStatus(bool record, int engineId = -1, quint32 flushInterval = 0);
+
+protected:
+ QQmlProfilerClient(QQmlProfilerClientPrivate &dd);
+
+private:
+ virtual void messageReceived(const QByteArray &message);
+
+ virtual void traceStarted(qint64 time, int engineId);
+ virtual void traceFinished(qint64 time, int engineId);
+
+ virtual void rangeStart(QQmlProfilerDefinitions::RangeType type, qint64 startTime);
+ virtual void rangeData(QQmlProfilerDefinitions::RangeType type, qint64 time,
+ const QString &data);
+ virtual void rangeLocation(QQmlProfilerDefinitions::RangeType type, qint64 time,
+ const QQmlEventLocation &location);
+ virtual void rangeEnd(QQmlProfilerDefinitions::RangeType type, qint64 endTime);
+
+ virtual void animationFrame(qint64 time, int frameRate, int animationCount, int threadId);
+
+ virtual void sceneGraphEvent(QQmlProfilerDefinitions::SceneGraphFrameType type, qint64 time,
+ qint64 numericData1, qint64 numericData2, qint64 numericData3,
+ qint64 numericData4, qint64 numericData5);
+
+ virtual void pixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type, qint64 time,
+ const QString &url, int numericData1, int numericData2);
+
+ virtual void memoryAllocation(QQmlProfilerDefinitions::MemoryType type, qint64 time,
+ qint64 amount);
+
+ virtual void inputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time, int a,
+ int b);
+
+ virtual void complete();
+
+ virtual void unknownEvent(QQmlProfilerDefinitions::Message messageType, qint64 time,
+ int detailType);
+ virtual void unknownData(QPacket &stream);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROFILERCLIENT_P_H
diff --git a/src/qmldebug/qqmlprofilerclient_p_p.h b/src/qmldebug/qqmlprofilerclient_p_p.h
new file mode 100644
index 0000000000..c522eb7f52
--- /dev/null
+++ b/src/qmldebug/qqmlprofilerclient_p_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** 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 QQMLPROFILERCLIENT_P_P_H
+#define QQMLPROFILERCLIENT_P_P_H
+
+#include "qqmlprofilerclient_p.h"
+#include "qqmldebugclient_p_p.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlProfilerClientPrivate : public QQmlDebugClientPrivate
+{
+ Q_DECLARE_PUBLIC(QQmlProfilerClient)
+public:
+ QQmlProfilerClientPrivate(QQmlDebugConnection *connection);
+ quint64 features;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROFILERCLIENT_P_P_H
+
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index fd1b74d32d..23d13c2fd4 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -2323,7 +2323,7 @@ QQuickItem::~QQuickItem()
// XXX todo - optimize
while (!d->childItems.isEmpty())
- d->childItems.first()->setParentItem(0);
+ d->childItems.constFirst()->setParentItem(0);
for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
QQuickAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
@@ -2485,7 +2485,7 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
from = item->parentItem();
} else {
if (!item->childItems().isEmpty())
- from = item->childItems().first();
+ from = item->d_func()->childItems.constFirst();
else
from = item->parentItem();
}
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 0211e9f285..955e1f1e00 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -1319,10 +1319,10 @@ void QQuickListViewPrivate::updateFooter()
}
FxListItemSG *listItem = static_cast<FxListItemSG*>(footer);
- if (visibleItems.count()) {
- if (footerPositioning == QQuickListView::OverlayFooter) {
- listItem->setPosition(isContentFlowReversed() ? -position() - footerSize() : position() + size() - footerSize());
- } else if (footerPositioning == QQuickListView::PullBackFooter) {
+ if (footerPositioning == QQuickListView::OverlayFooter) {
+ listItem->setPosition(isContentFlowReversed() ? -position() - footerSize() : position() + size() - footerSize());
+ } else if (visibleItems.count()) {
+ if (footerPositioning == QQuickListView::PullBackFooter) {
qreal viewPos = isContentFlowReversed() ? -position() : position() + size();
qreal clampedPos = qBound(originPosition() - footerSize() + size(), listItem->position(), lastPosition());
listItem->setPosition(qBound(viewPos - footerSize(), clampedPos, viewPos));
@@ -1358,26 +1358,24 @@ void QQuickListViewPrivate::updateHeader()
}
FxListItemSG *listItem = static_cast<FxListItemSG*>(header);
- if (listItem) {
- if (visibleItems.count()) {
- if (headerPositioning == QQuickListView::OverlayHeader) {
- listItem->setPosition(isContentFlowReversed() ? -position() - size() : position());
- } else if (headerPositioning == QQuickListView::PullBackHeader) {
- qreal viewPos = isContentFlowReversed() ? -position() - size() : position();
- qreal clampedPos = qBound(originPosition() - headerSize(), listItem->position(), lastPosition() - headerSize() - size());
- listItem->setPosition(qBound(viewPos - headerSize(), clampedPos, viewPos));
+ if (headerPositioning == QQuickListView::OverlayHeader) {
+ listItem->setPosition(isContentFlowReversed() ? -position() - size() : position());
+ } else if (visibleItems.count()) {
+ if (headerPositioning == QQuickListView::PullBackHeader) {
+ qreal viewPos = isContentFlowReversed() ? -position() - size() : position();
+ qreal clampedPos = qBound(originPosition() - headerSize(), listItem->position(), lastPosition() - headerSize() - size());
+ listItem->setPosition(qBound(viewPos - headerSize(), clampedPos, viewPos));
+ } else {
+ qreal startPos = originPosition();
+ if (visibleIndex == 0) {
+ listItem->setPosition(startPos - headerSize());
} else {
- qreal startPos = originPosition();
- if (visibleIndex == 0) {
+ if (position() <= startPos || listItem->position() > startPos - headerSize())
listItem->setPosition(startPos - headerSize());
- } else {
- if (position() <= startPos || listItem->position() > startPos - headerSize())
- listItem->setPosition(startPos - headerSize());
- }
}
- } else {
- listItem->setPosition(-headerSize());
}
+ } else {
+ listItem->setPosition(-headerSize());
}
if (created)
@@ -2840,8 +2838,15 @@ void QQuickListView::viewportMoved(Qt::Orientations orient)
{
Q_D(QQuickListView);
QQuickItemView::viewportMoved(orient);
- if (!d->itemCount)
+
+ if (!d->itemCount) {
+ if (d->hasStickyHeader())
+ d->updateHeader();
+ if (d->hasStickyFooter())
+ d->updateFooter();
return;
+ }
+
// Recursion can occur due to refill changing the content size.
if (d->inViewportMoved)
return;
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index 456eedd0be..0040843929 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -852,6 +852,11 @@ likelihood of glitches in animation. When loading asynchronously the status
will change to Loader.Loading. Once the entire component has been created, the
\l item will be available and the status will change to Loader.Ready.
+Changing the value of this property to \c false while an asynchronous load is in
+progress will force immediate, synchronous completion. This allows beginning an
+asynchronous load and then forcing completion if the Loader content must be
+accessed before the asynchronous load has completed.
+
To avoid seeing the items loading progressively set \c visible appropriately, e.g.
\code
@@ -878,6 +883,19 @@ void QQuickLoader::setAsynchronous(bool a)
return;
d->asynchronous = a;
+
+ if (!d->asynchronous && isComponentComplete() && d->active) {
+ if (d->loadingFromSource && d->component && d->component->isLoading()) {
+ // Force a synchronous component load
+ QUrl currentSource = d->source;
+ d->clear();
+ d->source = currentSource;
+ loadFromSource();
+ } else if (d->incubator && d->incubator->isLoading()) {
+ d->incubator->forceCompletion();
+ }
+ }
+
emit asynchronousChanged();
}
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 223219a3f9..d32b194803 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -73,7 +73,11 @@ QQuickTextPrivate::QQuickTextPrivate()
, elideMode(QQuickText::ElideNone), hAlign(QQuickText::AlignLeft), vAlign(QQuickText::AlignTop)
, format(QQuickText::AutoText), wrapMode(QQuickText::NoWrap)
, style(QQuickText::Normal)
+#if defined(QT_QUICK_DEFAULT_TEXT_RENDER_TYPE)
+ , renderType(QQuickText::QT_QUICK_DEFAULT_TEXT_RENDER_TYPE)
+#else
, renderType(QQuickText::QtRendering)
+#endif
, updateType(UpdatePaintNode)
, maximumLineCountValid(false), updateOnComponentComplete(true), richText(false)
, styledText(false), widthExceeded(false), heightExceeded(false), internalWidthUpdate(false)
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index 04e43c017e..d0678b4278 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -1419,7 +1419,7 @@ QVariant QQuickTextControl::inputMethodQuery(Qt::InputMethodQuery property, QVar
tmpCursor.movePosition(QTextCursor::NextBlock);
--numBlocks;
}
- result += block.text().mid(0,localPos);
+ result += block.text().midRef(0,localPos);
return QVariant(result);
}
default:
diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h
index fed0688fd7..a2b4c1ab99 100644
--- a/src/quick/items/qquicktextedit_p_p.h
+++ b/src/quick/items/qquicktextedit_p_p.h
@@ -106,7 +106,11 @@ public:
, quickDocument(0), lastSelectionStart(0), lastSelectionEnd(0), lineCount(0)
, hAlign(QQuickTextEdit::AlignLeft), vAlign(QQuickTextEdit::AlignTop)
, format(QQuickTextEdit::PlainText), wrapMode(QQuickTextEdit::NoWrap)
+#if defined(QT_QUICK_DEFAULT_TEXT_RENDER_TYPE)
+ , renderType(QQuickTextEdit::QT_QUICK_DEFAULT_TEXT_RENDER_TYPE)
+#else
, renderType(QQuickTextEdit::QtRendering)
+#endif
, contentDirection(Qt::LayoutDirectionAuto)
, mouseSelectionMode(QQuickTextEdit::SelectCharacters)
#ifndef QT_NO_IM
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 087b8b8135..fe18fc2231 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -3533,7 +3533,7 @@ void QQuickTextInputPrivate::internalInsert(const QString &s)
int remaining = m_maxLength - m_text.length();
if (remaining != 0) {
m_text.insert(m_cursor, s.left(remaining));
- for (int i = 0; i < (int) s.left(remaining).length(); ++i)
+ for (int i = 0; i < (int) s.leftRef(remaining).length(); ++i)
addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1));
m_textDirty = true;
}
@@ -3886,14 +3886,14 @@ QString QQuickTextInputPrivate::maskString(uint pos, const QString &str, bool cl
int n = findInMask(i, true, true, str[(int)strIndex]);
if (n != -1) {
if (str.length() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[(int)strIndex]))) {
- s += fill.mid(i, n-i+1);
+ s += fill.midRef(i, n-i+1);
i = n + 1; // update i to find + 1
}
} else {
// search for valid m_blank if not
n = findInMask(i, true, false, str[(int)strIndex]);
if (n != -1) {
- s += fill.mid(i, n-i);
+ s += fill.midRef(i, n-i);
switch (m_maskData[n].caseMode) {
case MaskInputData::Upper:
s += str[(int)strIndex].toUpper();
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 00d9b2b0fa..6aaa630839 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -115,7 +115,11 @@ public:
, vAlign(QQuickTextInput::AlignTop)
, wrapMode(QQuickTextInput::NoWrap)
, m_echoMode(QQuickTextInput::Normal)
+#if defined(QT_QUICK_DEFAULT_TEXT_RENDER_TYPE)
+ , renderType(QQuickTextInput::QT_QUICK_DEFAULT_TEXT_RENDER_TYPE)
+#else
, renderType(QQuickTextInput::QtRendering)
+#endif
, updateType(UpdatePaintNode)
, mouseSelectionMode(QQuickTextInput::SelectCharacters)
, m_layoutDirection(Qt::LayoutDirectionAuto)
diff --git a/src/quick/items/qquicktextnode_p.h b/src/quick/items/qquicktextnode_p.h
index c6a1059e8a..01de0dbf2f 100644
--- a/src/quick/items/qquicktextnode_p.h
+++ b/src/quick/items/qquicktextnode_p.h
@@ -68,7 +68,7 @@ class QSGTexture;
class QQuickTextNodeEngine;
-class QQuickTextNode : public QSGTransformNode
+class Q_QUICK_PRIVATE_EXPORT QQuickTextNode : public QSGTransformNode
{
public:
enum Decoration {
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index 867f7d9d15..96f6b7ddd1 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -601,40 +601,30 @@ void QQuickView::resizeEvent(QResizeEvent *e)
/*! \reimp */
void QQuickView::keyPressEvent(QKeyEvent *e)
{
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Key>());
-
QQuickWindow::keyPressEvent(e);
}
/*! \reimp */
void QQuickView::keyReleaseEvent(QKeyEvent *e)
{
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Key>());
-
QQuickWindow::keyReleaseEvent(e);
}
/*! \reimp */
void QQuickView::mouseMoveEvent(QMouseEvent *e)
{
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
-
QQuickWindow::mouseMoveEvent(e);
}
/*! \reimp */
void QQuickView::mousePressEvent(QMouseEvent *e)
{
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
-
QQuickWindow::mousePressEvent(e);
}
/*! \reimp */
void QQuickView::mouseReleaseEvent(QMouseEvent *e)
{
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
-
QQuickWindow::mouseReleaseEvent(e);
}
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 6542bde4f1..9224c071fd 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -46,6 +46,7 @@
#include <private/qsgrenderloop_p.h>
#include <private/qquickrendercontrol_p.h>
#include <private/qquickanimatorcontroller_p.h>
+#include <private/qquickprofiler_p.h>
#include <private/qguiapplication_p.h>
#include <QtGui/QInputMethod>
@@ -1420,6 +1421,8 @@ bool QQuickWindow::event(QEvent *e)
void QQuickWindow::keyPressEvent(QKeyEvent *e)
{
Q_D(QQuickWindow);
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Key, QQuickProfiler::InputKeyPress, e->key(),
+ e->modifiers());
d->deliverKeyEvent(e);
}
@@ -1427,6 +1430,8 @@ void QQuickWindow::keyPressEvent(QKeyEvent *e)
void QQuickWindow::keyReleaseEvent(QKeyEvent *e)
{
Q_D(QQuickWindow);
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Key, QQuickProfiler::InputKeyRelease, e->key(),
+ e->modifiers());
d->deliverKeyEvent(e);
}
@@ -1524,6 +1529,8 @@ bool QQuickWindowPrivate::deliverMouseEvent(QMouseEvent *event)
void QQuickWindow::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickWindow);
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMousePress, event->button(),
+ event->buttons());
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
event->accept();
@@ -1538,6 +1545,8 @@ void QQuickWindow::mousePressEvent(QMouseEvent *event)
void QQuickWindow::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickWindow);
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseRelease, event->button(),
+ event->buttons());
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
event->accept();
@@ -1560,6 +1569,8 @@ void QQuickWindow::mouseReleaseEvent(QMouseEvent *event)
void QQuickWindow::mouseDoubleClickEvent(QMouseEvent *event)
{
Q_D(QQuickWindow);
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseDoubleClick,
+ event->button(), event->buttons());
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
event->accept();
@@ -1604,6 +1615,8 @@ bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
void QQuickWindow::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QQuickWindow);
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseMove,
+ event->localPos().x(), event->localPos().y());
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
event->accept();
@@ -1749,6 +1762,9 @@ bool QQuickWindowPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event
void QQuickWindow::wheelEvent(QWheelEvent *event)
{
Q_D(QQuickWindow);
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseWheel,
+ event->angleDelta().x(), event->angleDelta().y());
+
qCDebug(DBG_MOUSE) << "QQuickWindow::wheelEvent()" << event->pixelDelta() << event->angleDelta() << event->phase();
//if the actual wheel event was accepted, accept the compatibility wheel event and return early
diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp
index ecf6865895..cabf0589e2 100644
--- a/src/quick/qtquick2.cpp
+++ b/src/quick/qtquick2.cpp
@@ -190,10 +190,6 @@ void QQmlQtQuick2Module::defineModule()
QQmlEngineDebugService *debugService = QQmlDebugConnector::service<QQmlEngineDebugService>();
if (debugService)
debugService->setStatesDelegate(new QQmlQtQuick2DebugStatesDelegate);
-
- QQmlProfilerService *profilerService = QQmlDebugConnector::service<QQmlProfilerService>();
- if (profilerService)
- QQuickProfiler::initialize(profilerService);
}
void QQmlQtQuick2Module::undefineModule()
diff --git a/src/quick/scenegraph/util/qsgdistancefieldutil.cpp b/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
index 96b606aa3c..883657da24 100644
--- a/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
+++ b/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
@@ -71,7 +71,7 @@ QSGDistanceFieldGlyphCacheManager::QSGDistanceFieldGlyphCacheManager()
QSGDistanceFieldGlyphCacheManager::~QSGDistanceFieldGlyphCacheManager()
{
- qDeleteAll(m_caches.values());
+ qDeleteAll(m_caches);
}
QSGDistanceFieldGlyphCache *QSGDistanceFieldGlyphCacheManager::cache(const QRawFont &font)
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index 0182f8abfb..d0330398e5 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -79,7 +79,8 @@ QQuickAnimatorProxyJob::QQuickAnimatorProxyJob(QAbstractAnimationJob *job, QObje
QQuickItem *item = qobject_cast<QQuickItem *>(ctx);
if (item->window())
setWindow(item->window());
- connect(item, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(windowChanged(QQuickWindow*)));
+
+ qmlobject_connect(item, QQuickItem, SIGNAL(windowChanged(QQuickWindow*)), this, QQuickAnimatorProxyJob, SLOT(windowChanged(QQuickWindow*)));
}
}
diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp
index 2ea1a062d8..d1ca02d79f 100644
--- a/src/quick/util/qquickglobal.cpp
+++ b/src/quick/util/qquickglobal.cpp
@@ -231,10 +231,10 @@ public:
int index3 = s.indexOf(QLatin1Char(','), index2+1);
bool sGood, xGood, yGood, zGood;
- qreal sCoord = s.left(index).toDouble(&sGood);
- qreal xCoord = s.mid(index+1, index2-index-1).toDouble(&xGood);
- qreal yCoord = s.mid(index2+1, index3-index2-1).toDouble(&yGood);
- qreal zCoord = s.mid(index3+1).toDouble(&zGood);
+ qreal sCoord = s.leftRef(index).toDouble(&sGood);
+ qreal xCoord = s.midRef(index+1, index2-index-1).toDouble(&xGood);
+ qreal yCoord = s.midRef(index2+1, index3-index2-1).toDouble(&yGood);
+ qreal zCoord = s.midRef(index3+1).toDouble(&zGood);
if (sGood && xGood && yGood && zGood) {
if (ok) *ok = true;
@@ -254,7 +254,7 @@ public:
QString mutableStr = s;
for (int i = 0; vOK && i < 16; ++i) {
int cidx = mutableStr.indexOf(QLatin1Char(','));
- matValues[i] = mutableStr.left(cidx).toDouble(&vOK);
+ matValues[i] = mutableStr.leftRef(cidx).toDouble(&vOK);
mutableStr = mutableStr.mid(cidx + 1);
}
diff --git a/src/quick/util/qquickprofiler.cpp b/src/quick/util/qquickprofiler.cpp
index 77ffda474a..cb6212196e 100644
--- a/src/quick/util/qquickprofiler.cpp
+++ b/src/quick/util/qquickprofiler.cpp
@@ -32,8 +32,11 @@
****************************************************************************/
#include "qquickprofiler_p.h"
-#include <QCoreApplication>
-#include <private/qqmldebugserviceinterfaces_p.h>
+
+#include <QtQml/private/qqmlabstractprofileradapter_p.h>
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qthread.h>
QT_BEGIN_NAMESPACE
@@ -41,93 +44,10 @@ QT_BEGIN_NAMESPACE
QQuickProfiler *QQuickProfiler::s_instance = 0;
quint64 QQuickProfiler::featuresEnabled = 0;
-// convert to QByteArrays that can be sent to the debug client
-// use of QDataStream can skew results
-// (see tst_qqmldebugtrace::trace() benchmark)
-void QQuickProfilerData::toByteArrays(QList<QByteArray> &messages) const
-{
- QByteArray data;
- Q_ASSERT_X(((messageType | detailType) & (1 << 31)) == 0, Q_FUNC_INFO, "You can use at most 31 message types and 31 detail types.");
- for (uint decodedMessageType = 0; (messageType >> decodedMessageType) != 0; ++decodedMessageType) {
- if ((messageType & (1 << decodedMessageType)) == 0)
- continue;
-
- for (uint decodedDetailType = 0; (detailType >> decodedDetailType) != 0; ++decodedDetailType) {
- if ((detailType & (1 << decodedDetailType)) == 0)
- continue;
-
- //### using QDataStream is relatively expensive
- QQmlDebugStream ds(&data, QIODevice::WriteOnly);
- ds << time << decodedMessageType << decodedDetailType;
-
- switch (decodedMessageType) {
- case QQuickProfiler::Event:
- if (decodedDetailType == (int)QQuickProfiler::AnimationFrame)
- ds << framerate << count << threadId;
- break;
- case QQuickProfiler::PixmapCacheEvent:
- ds << detailUrl.toString();
- switch (decodedDetailType) {
- case QQuickProfiler::PixmapSizeKnown: ds << x << y; break;
- case QQuickProfiler::PixmapReferenceCountChanged: ds << count; break;
- case QQuickProfiler::PixmapCacheCountChanged: ds << count; break;
- default: break;
- }
- break;
- case QQuickProfiler::SceneGraphFrame:
- switch (decodedDetailType) {
- // RendererFrame: preprocessTime, updateTime, bindingTime, renderTime
- case QQuickProfiler::SceneGraphRendererFrame: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break;
- // AdaptationLayerFrame: glyphCount (which is an integer), glyphRenderTime, glyphStoreTime
- case QQuickProfiler::SceneGraphAdaptationLayerFrame: ds << subtime_3 << subtime_1 << subtime_2; break;
- // ContextFrame: compiling material time
- case QQuickProfiler::SceneGraphContextFrame: ds << subtime_1; break;
- // RenderLoop: syncTime, renderTime, swapTime
- case QQuickProfiler::SceneGraphRenderLoopFrame: ds << subtime_1 << subtime_2 << subtime_3; break;
- // TexturePrepare: bind, convert, swizzle, upload, mipmap
- case QQuickProfiler::SceneGraphTexturePrepare: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4 << subtime_5; break;
- // TextureDeletion: deletionTime
- case QQuickProfiler::SceneGraphTextureDeletion: ds << subtime_1; break;
- // PolishAndSync: polishTime, waitTime, syncTime, animationsTime,
- case QQuickProfiler::SceneGraphPolishAndSync: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break;
- // WindowsRenderLoop: GL time, make current time, SceneGraph time
- case QQuickProfiler::SceneGraphWindowsRenderShow: ds << subtime_1 << subtime_2 << subtime_3; break;
- // WindowsAnimations: update time
- case QQuickProfiler::SceneGraphWindowsAnimations: ds << subtime_1; break;
- // non-threaded rendering: polish time
- case QQuickProfiler::SceneGraphPolishFrame: ds << subtime_1; break;
- default:break;
- }
- break;
- default:
- Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
- break;
- }
- messages << data;
- data.clear();
- }
- }
-}
-
-qint64 QQuickProfiler::sendMessages(qint64 until, QList<QByteArray> &messages)
-{
- QMutexLocker lock(&m_dataMutex);
- while (next < m_data.size()) {
- if (m_data[next].time <= until)
- m_data[next++].toByteArrays(messages);
- else
- return m_data[next].time;
- }
- m_data.clear();
- next = 0;
- return -1;
-}
-
-void QQuickProfiler::initialize(QQmlProfilerService *service)
+void QQuickProfiler::initialize(QObject *parent)
{
Q_ASSERT(s_instance == 0);
- s_instance = new QQuickProfiler(service);
- service->addGlobalProfiler(s_instance);
+ s_instance = new QQuickProfiler(parent);
}
void animationTimerCallback(qint64 delta)
@@ -154,26 +74,10 @@ public slots:
#include "qquickprofiler.moc"
-QQuickProfiler::QQuickProfiler(QQmlProfilerService *service) :
- QQmlAbstractProfilerAdapter(service), next(0)
+QQuickProfiler::QQuickProfiler(QObject *parent) : QObject(parent)
{
// This is safe because at this point the m_instance isn't initialized, yet.
m_timer.start();
-
- // We can always do DirectConnection here as all methods are protected by mutexes
- connect(this, SIGNAL(profilingEnabled(quint64)), this, SLOT(startProfilingImpl(quint64)),
- Qt::DirectConnection);
- connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
- this, SLOT(startProfilingImpl(quint64)), Qt::DirectConnection);
- connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)), this, SLOT(setTimer(QElapsedTimer)),
- Qt::DirectConnection);
- connect(this, SIGNAL(profilingDisabled()), this, SLOT(stopProfilingImpl()),
- Qt::DirectConnection);
- connect(this, SIGNAL(profilingDisabledWhileWaiting()), this, SLOT(stopProfilingImpl()),
- Qt::DirectConnection);
- connect(this, SIGNAL(dataRequested()), this, SLOT(reportDataImpl()),
- Qt::DirectConnection);
-
CallbackRegistrationHelper *helper = new CallbackRegistrationHelper; // will delete itself
helper->moveToThread(QCoreApplication::instance()->thread());
QMetaObject::invokeMethod(helper, "registerAnimationTimerCallback", Qt::QueuedConnection);
@@ -189,7 +93,6 @@ QQuickProfiler::~QQuickProfiler()
void QQuickProfiler::startProfilingImpl(quint64 features)
{
QMutexLocker lock(&m_dataMutex);
- next = 0;
m_data.clear();
featuresEnabled = features;
}
@@ -200,12 +103,12 @@ void QQuickProfiler::stopProfilingImpl()
QMutexLocker lock(&m_dataMutex);
featuresEnabled = 0;
}
- service->dataReady(this);
+ emit dataReady(m_data);
}
void QQuickProfiler::reportDataImpl()
{
- service->dataReady(this);
+ emit dataReady(m_data);
}
void QQuickProfiler::setTimer(const QElapsedTimer &t)
diff --git a/src/quick/util/qquickprofiler_p.h b/src/quick/util/qquickprofiler_p.h
index 6b6e7fa062..4983adf63b 100644
--- a/src/quick/util/qquickprofiler_p.h
+++ b/src/quick/util/qquickprofiler_p.h
@@ -45,13 +45,14 @@
// We mean it.
//
-#include <private/qtquickglobal_p.h>
#include <QtCore/private/qabstractanimation_p.h>
-#include <QtQml/private/qqmlabstractprofileradapter_p.h>
-#include <QUrl>
-#include <QSize>
-#include <QMutex>
-#include <QThreadStorage>
+#include <QtQml/private/qqmlprofilerdefinitions_p.h>
+#include <QtQuick/private/qtquickglobal_p.h>
+
+#include <QtCore/qurl.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qthreadstorage.h>
QT_BEGIN_NAMESPACE
@@ -97,8 +98,9 @@ QT_BEGIN_NAMESPACE
(QQuickProfiler::reportSceneGraphFrame<Type, true>(Payload)))
-#define Q_QUICK_INPUT_PROFILE(Method)\
- Q_QUICK_PROFILE(QQuickProfiler::ProfileInputEvents, Method)
+#define Q_QUICK_INPUT_PROFILE(Type, DetailType, A, B)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileInputEvents,\
+ (QQuickProfiler::inputEvent<Type, DetailType>(A, B)))
// This struct is somewhat dangerous to use:
// You can save values either with 32 or 64 bit precision. toByteArrays will
@@ -117,10 +119,10 @@ struct Q_AUTOTEST_EXPORT QQuickProfilerData
time(time), messageType(messageType), detailType(detailType), detailUrl(url), x(x), y(y),
framerate(framerate), count(count) {}
- QQuickProfilerData(qint64 time, int messageType, int detailType, int framerate = 0,
- int count = 0, int threadId = 0) :
- time(time), messageType(messageType), detailType(detailType), framerate(framerate),
- count(count), threadId(threadId) {}
+ QQuickProfilerData(qint64 time, int messageType, int detailType, int framerateOrInputType = 0,
+ int countOrInputA = 0, int threadIdOrInputB = 0) :
+ time(time), messageType(messageType), detailType(detailType),
+ framerate(framerateOrInputType), count(countOrInputA), threadId(threadIdOrInputB) {}
// Special ctor for scenegraph frames. Note that it's missing the QString/QUrl params.
// This is slightly ugly, but makes it easier to disambiguate between int and qint64 params.
@@ -149,19 +151,20 @@ struct Q_AUTOTEST_EXPORT QQuickProfilerData
union {
qint64 subtime_3;
int framerate; //used by animation events
+ int inputType;
};
union {
qint64 subtime_4;
int count; //used by animation events and for pixmaps
+ int inputA; //used by input events
};
union {
qint64 subtime_5;
int threadId;
+ int inputB; //used by input events
};
-
- void toByteArrays(QList<QByteArray> &messages) const;
};
Q_DECLARE_TYPEINFO(QQuickProfilerData, Q_MOVABLE_TYPE);
@@ -199,7 +202,7 @@ public:
}
};
-class Q_QUICK_PRIVATE_EXPORT QQuickProfiler : public QQmlAbstractProfilerAdapter {
+class Q_QUICK_PRIVATE_EXPORT QQuickProfiler : public QObject, public QQmlProfilerDefinitions {
Q_OBJECT
public:
@@ -208,11 +211,11 @@ public:
RenderThread
};
- template<EventType DetailType>
- static void addEvent()
+ template<EventType DetailType, InputEventType InputType>
+ static void inputEvent(int x, int y = 0)
{
s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(), 1 << Event,
- 1 << DetailType));
+ 1 << DetailType, InputType, x, y));
}
static void animationFrame(qint64 delta, AnimationThread threadId)
@@ -310,7 +313,6 @@ public:
qint64 timestamp() { return m_timer.nsecsElapsed(); }
- qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
static quint64 featuresEnabled;
static bool profilingSceneGraph()
@@ -318,19 +320,20 @@ public:
return featuresEnabled & (1 << QQuickProfiler::ProfileSceneGraph);
}
- static void initialize(QQmlProfilerService *service);
+ static void initialize(QObject *parent);
virtual ~QQuickProfiler();
protected:
- int next;
+ friend class QQuickProfilerAdapter;
+
static QQuickProfiler *s_instance;
QMutex m_dataMutex;
QElapsedTimer m_timer;
- QVarLengthArray<QQuickProfilerData> m_data;
+ QVector<QQuickProfilerData> m_data;
QQuickProfilerSceneGraphData m_sceneGraphData;
- QQuickProfiler(QQmlProfilerService *service);
+ QQuickProfiler(QObject *parent);
void processMessage(const QQuickProfilerData &message)
{
@@ -338,6 +341,9 @@ protected:
m_data.append(message);
}
+signals:
+ void dataReady(const QVector<QQuickProfilerData> &data);
+
protected slots:
void startProfilingImpl(quint64 features);
void stopProfilingImpl();
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index cc7ece9c5b..875b68b3ac 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -1039,7 +1039,8 @@ void QQuickWidget::resizeEvent(QResizeEvent *e)
void QQuickWidget::keyPressEvent(QKeyEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Key>());
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Key, QQuickProfiler::InputKeyPress, e->key(),
+ e->modifiers());
QCoreApplication::sendEvent(d->offscreenWindow, e);
}
@@ -1048,7 +1049,8 @@ void QQuickWidget::keyPressEvent(QKeyEvent *e)
void QQuickWidget::keyReleaseEvent(QKeyEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Key>());
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Key, QQuickProfiler::InputKeyRelease, e->key(),
+ e->modifiers());
QCoreApplication::sendEvent(d->offscreenWindow, e);
}
@@ -1057,7 +1059,8 @@ void QQuickWidget::keyReleaseEvent(QKeyEvent *e)
void QQuickWidget::mouseMoveEvent(QMouseEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseMove, e->localPos().x(),
+ e->localPos().y());
// Use the constructor taking localPos and screenPos. That puts localPos into the
// event's localPos and windowPos, and screenPos into the event's screenPos. This way
@@ -1072,7 +1075,8 @@ void QQuickWidget::mouseMoveEvent(QMouseEvent *e)
void QQuickWidget::mouseDoubleClickEvent(QMouseEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseDoubleClick,
+ e->button(), e->buttons());
// As the second mouse press is suppressed in widget windows we emulate it here for QML.
// See QTBUG-25831
@@ -1120,7 +1124,8 @@ void QQuickWidget::hideEvent(QHideEvent *)
void QQuickWidget::mousePressEvent(QMouseEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMousePress, e->button(),
+ e->buttons());
QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
@@ -1131,7 +1136,8 @@ void QQuickWidget::mousePressEvent(QMouseEvent *e)
void QQuickWidget::mouseReleaseEvent(QMouseEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseRelease, e->button(),
+ e->buttons());
QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
@@ -1143,7 +1149,8 @@ void QQuickWidget::mouseReleaseEvent(QMouseEvent *e)
void QQuickWidget::wheelEvent(QWheelEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseWheel,
+ e->angleDelta().x(), e->angleDelta().y());
// Wheel events only have local and global positions, no need to map.
QCoreApplication::sendEvent(d->offscreenWindow, e);
diff --git a/src/src.pro b/src/src.pro
index ac48f017e6..18e9ba6704 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -14,6 +14,7 @@ qtHaveModule(gui):contains(QT_CONFIG, opengl(es1|es2)?) {
SUBDIRS += \
plugins \
+ qmldebug \
imports \
qmldevtools