diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/qmleasing/splineeditor.cpp | 2 | ||||
-rw-r--r-- | tools/qmleasing/splineeditor.h | 2 | ||||
-rw-r--r-- | tools/qmlmin/main.cpp | 2 | ||||
-rw-r--r-- | tools/qmlprofiler/qmlprofiler.pro | 11 | ||||
-rw-r--r-- | tools/qmlprofiler/qmlprofilerapplication.cpp | 151 | ||||
-rw-r--r-- | tools/qmlprofiler/qmlprofilerapplication.h | 24 | ||||
-rw-r--r-- | tools/qmlprofiler/qmlprofilerclient.cpp | 370 | ||||
-rw-r--r-- | tools/qmlprofiler/qmlprofilerclient.h | 111 | ||||
-rw-r--r-- | tools/qmlprofiler/qmlprofilerdata.cpp | 234 | ||||
-rw-r--r-- | tools/qmlprofiler/qmlprofilerdata.h | 18 | ||||
-rw-r--r-- | tools/qmlprofiler/qmlprofilereventlocation.h | 53 | ||||
-rw-r--r-- | tools/qmlprofiler/qpacketprotocol.cpp | 527 | ||||
-rw-r--r-- | tools/qmlprofiler/qpacketprotocol.h | 109 | ||||
-rw-r--r-- | tools/qmlprofiler/qqmldebugclient.cpp | 403 | ||||
-rw-r--r-- | tools/qmlprofiler/qqmldebugclient.h | 101 |
15 files changed, 275 insertions, 1843 deletions
diff --git a/tools/qmleasing/splineeditor.cpp b/tools/qmleasing/splineeditor.cpp index 9e35af6189..2ae4d11309 100644 --- a/tools/qmleasing/splineeditor.cpp +++ b/tools/qmleasing/splineeditor.cpp @@ -228,6 +228,7 @@ void SplineEditor::mouseReleaseEvent(QMouseEvent *e) } } +#ifndef QT_NO_CONTEXTMENU void SplineEditor::contextMenuEvent(QContextMenuEvent *e) { int index = findControlPoint(e->pos()); @@ -247,6 +248,7 @@ void SplineEditor::contextMenuEvent(QContextMenuEvent *e) addPoint(e->pos()); } } +#endif // QT_NO_CONTEXTMENU void SplineEditor::invalidate() { diff --git a/tools/qmleasing/splineeditor.h b/tools/qmleasing/splineeditor.h index 595580bba2..4b9da14a7a 100644 --- a/tools/qmleasing/splineeditor.h +++ b/tools/qmleasing/splineeditor.h @@ -84,7 +84,9 @@ protected: void mousePressEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); +#ifndef QT_NO_CONTEXTMENU void contextMenuEvent(QContextMenuEvent *); +#endif // QT_NO_CONTEXTMENU void invalidate(); void invalidateSmoothList(); diff --git a/tools/qmlmin/main.cpp b/tools/qmlmin/main.cpp index a3f2b92bde..82fdb92801 100644 --- a/tools/qmlmin/main.cpp +++ b/tools/qmlmin/main.cpp @@ -590,7 +590,7 @@ int runQmlmin(int argc, char *argv[]) } } else if (arg.startsWith(QLatin1String("-w"))) { bool ok; - width = arg.mid(2).toInt(&ok); + width = arg.midRef(2).toInt(&ok); if (!ok) { std::cerr << "qmlmin: argument to '-w' is invalid" << std::endl; diff --git a/tools/qmlprofiler/qmlprofiler.pro b/tools/qmlprofiler/qmlprofiler.pro index 4fa36f5127..a65e25c657 100644 --- a/tools/qmlprofiler/qmlprofiler.pro +++ b/tools/qmlprofiler/qmlprofiler.pro @@ -1,22 +1,17 @@ -QT = qml qml-private network core-private +QT = qml-private network core qmldebug-private CONFIG += no_import_scan SOURCES += main.cpp \ qmlprofilerapplication.cpp \ commandlistener.cpp \ - qqmldebugclient.cpp \ qmlprofilerdata.cpp \ - qmlprofilerclient.cpp \ - qpacketprotocol.cpp + qmlprofilerclient.cpp HEADERS += \ qmlprofilerapplication.h \ commandlistener.h \ constants.h \ qmlprofilerdata.h \ - qmlprofilerclient.h \ - qmlprofilereventlocation.h \ - qqmldebugclient.h \ - qpacketprotocol.h + qmlprofilerclient.h load(qt_tool) diff --git a/tools/qmlprofiler/qmlprofilerapplication.cpp b/tools/qmlprofiler/qmlprofilerapplication.cpp index 347e7d3b55..cd34cd603f 100644 --- a/tools/qmlprofiler/qmlprofilerapplication.cpp +++ b/tools/qmlprofiler/qmlprofilerapplication.cpp @@ -41,6 +41,7 @@ #include <QtCore/QFileInfo> #include <QtCore/QDebug> #include <QtCore/QCommandLineParser> +#include <QtCore/QTemporaryFile> static const char commandTextC[] = "The following commands are available:\n" @@ -78,52 +79,23 @@ QmlProfilerApplication::QmlProfilerApplication(int &argc, char **argv) : m_runMode(LaunchMode), m_process(0), m_hostName(QLatin1String("127.0.0.1")), - m_port(3768), + m_port(0), m_pendingRequest(REQUEST_NONE), m_verbose(false), m_recording(true), m_interactive(false), - m_qmlProfilerClient(&m_connection), - m_v8profilerClient(&m_connection), - m_connectionAttempts(0), - m_qmlDataReady(false), - m_v8DataReady(false) + m_qmlProfilerClient(&m_connection, &m_profilerData), + m_connectionAttempts(0) { m_connectTimer.setInterval(1000); connect(&m_connectTimer, SIGNAL(timeout()), this, SLOT(tryToConnect())); connect(&m_connection, SIGNAL(connected()), this, SLOT(connected())); - connect(&m_connection, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(connectionStateChanged(QAbstractSocket::SocketState))); - connect(&m_connection, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectionError(QAbstractSocket::SocketError))); - - connect(&m_qmlProfilerClient, SIGNAL(enabledChanged()), this, SLOT(traceClientEnabled())); - connect(&m_qmlProfilerClient, SIGNAL(range(QQmlProfilerDefinitions::RangeType,QQmlProfilerDefinitions::BindingType,qint64,qint64,QStringList,QmlEventLocation)), - &m_profilerData, SLOT(addQmlEvent(QQmlProfilerDefinitions::RangeType,QQmlProfilerDefinitions::BindingType,qint64,qint64,QStringList,QmlEventLocation))); - connect(&m_qmlProfilerClient, SIGNAL(traceFinished(qint64)), &m_profilerData, SLOT(setTraceEndTime(qint64))); - connect(&m_qmlProfilerClient, SIGNAL(traceStarted(qint64)), &m_profilerData, SLOT(setTraceStartTime(qint64))); - connect(&m_qmlProfilerClient, SIGNAL(traceStarted(qint64)), this, SLOT(notifyTraceStarted())); - connect(&m_qmlProfilerClient, SIGNAL(frame(qint64,int,int,int)), &m_profilerData, SLOT(addFrameEvent(qint64,int,int,int))); - connect(&m_qmlProfilerClient, SIGNAL(sceneGraphFrame(QQmlProfilerDefinitions::SceneGraphFrameType, - qint64,qint64,qint64,qint64,qint64,qint64)), - &m_profilerData, SLOT(addSceneGraphFrameEvent(QQmlProfilerDefinitions::SceneGraphFrameType, - qint64,qint64,qint64,qint64,qint64,qint64))); - connect(&m_qmlProfilerClient, SIGNAL(pixmapCache(QQmlProfilerDefinitions::PixmapEventType,qint64, - QmlEventLocation,int,int,int)), - &m_profilerData, SLOT(addPixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType,qint64, - QmlEventLocation,int,int,int))); - connect(&m_qmlProfilerClient, SIGNAL(memoryAllocation(QQmlProfilerDefinitions::MemoryType,qint64, - qint64)), - &m_profilerData, SLOT(addMemoryEvent(QQmlProfilerDefinitions::MemoryType,qint64, - qint64))); - connect(&m_qmlProfilerClient, SIGNAL(inputEvent(QQmlProfilerDefinitions::EventType,qint64)), - &m_profilerData, SLOT(addInputEvent(QQmlProfilerDefinitions::EventType,qint64))); - - connect(&m_qmlProfilerClient, SIGNAL(complete()), this, SLOT(qmlComplete())); - - connect(&m_v8profilerClient, SIGNAL(enabledChanged()), this, SLOT(profilerClientEnabled())); - connect(&m_v8profilerClient, SIGNAL(range(int,QString,QString,int,double,double)), - &m_profilerData, SLOT(addV8Event(int,QString,QString,int,double,double))); - connect(&m_v8profilerClient, SIGNAL(complete()), this, SLOT(v8Complete())); + + connect(&m_qmlProfilerClient, SIGNAL(enabledChanged(bool)), + this, SLOT(traceClientEnabledChanged(bool))); + connect(&m_qmlProfilerClient, SIGNAL(recordingStarted()), this, SLOT(notifyTraceStarted())); + connect(&m_qmlProfilerClient, SIGNAL(error(QString)), this, SLOT(logError(QString))); connect(&m_profilerData, SIGNAL(error(QString)), this, SLOT(logError(QString))); connect(&m_profilerData, SIGNAL(dataReady()), this, SLOT(traceFinished())); @@ -228,6 +200,7 @@ void QmlProfilerApplication::parseArguments() if (parser.isSet(attach)) { m_hostName = parser.value(attach); m_runMode = AttachMode; + m_port = 3768; } if (parser.isSet(port)) { @@ -237,6 +210,10 @@ void QmlProfilerApplication::parseArguments() logError(tr("'%1' is not a valid port.").arg(parser.value(port))); parser.showHelp(1); } + } else if (m_port == 0) { + QTemporaryFile file; + if (file.open()) + m_socketFile = file.fileName(); } m_outputFile = parser.value(output); @@ -316,7 +293,6 @@ void QmlProfilerApplication::flush() if (m_recording) { m_pendingRequest = REQUEST_FLUSH; m_qmlProfilerClient.sendRecordingStatus(false); - m_v8profilerClient.sendRecordingStatus(false); } else { if (m_profilerData.save(m_interactiveOutputFile)) { m_profilerData.clear(); @@ -407,7 +383,6 @@ void QmlProfilerApplication::userCommand(const QString &command) if (cmd == Constants::CMD_RECORD || cmd == Constants::CMD_RECORD2) { m_pendingRequest = REQUEST_TOGGLE_RECORDING; m_qmlProfilerClient.sendRecordingStatus(!m_recording); - m_v8profilerClient.sendRecordingStatus(!m_recording); } else if (cmd == Constants::CMD_QUIT || cmd == Constants::CMD_QUIT2) { m_pendingRequest = REQUEST_QUIT; if (m_recording) { @@ -474,10 +449,15 @@ void QmlProfilerApplication::outputData() void QmlProfilerApplication::run() { if (m_runMode == LaunchMode) { + if (!m_socketFile.isEmpty()) { + logStatus(QString::fromLatin1("Listening on %1 ...").arg(m_socketFile)); + m_connection.startLocalServer(m_socketFile); + } m_process = new QProcess(this); QStringList arguments; - arguments << QString::fromLatin1("-qmljsdebugger=port:%1,block,services:CanvasFrameRate") - .arg(m_port); + arguments << QString::fromLatin1("-qmljsdebugger=%1:%2,block,services:CanvasFrameRate") + .arg(QLatin1String(m_socketFile.isEmpty() ? "port" : "file")) + .arg(m_socketFile.isEmpty() ? QString::number(m_port) : m_socketFile); arguments << m_programArguments; m_process->setProcessChannelMode(QProcess::MergedChannels); @@ -492,7 +472,6 @@ void QmlProfilerApplication::run() m_process->errorString())); exit(1); } - } m_connectTimer.start(); } @@ -503,15 +482,18 @@ void QmlProfilerApplication::tryToConnect() ++ m_connectionAttempts; if (!m_verbose && !(m_connectionAttempts % 5)) {// print every 5 seconds - if (!m_verbose) - logError(QString("Could not connect to %1:%2 for %3 seconds ...").arg( - m_hostName, QString::number(m_port), - QString::number(m_connectionAttempts))); + if (m_verbose) { + if (m_socketFile.isEmpty()) + logError(QString::fromLatin1("Could not connect to %1:%2 for %3 seconds ...") + .arg(m_hostName).arg(m_port).arg(m_connectionAttempts)); + else + logError(QString::fromLatin1("No connection received on %1 for %2 seconds ...") + .arg(m_socketFile).arg(m_connectionAttempts)); + } } - if (m_connection.state() == QAbstractSocket::UnconnectedState) { - logStatus(QString("Connecting to %1:%2 ...").arg(m_hostName, - QString::number(m_port))); + if (m_socketFile.isEmpty()) { + logStatus(QString::fromLatin1("Connecting to %1:%2 ...").arg(m_hostName).arg(m_port)); m_connection.connectToHost(m_hostName, m_port); } } @@ -519,22 +501,12 @@ void QmlProfilerApplication::tryToConnect() void QmlProfilerApplication::connected() { m_connectTimer.stop(); - prompt(tr("Connected to host:port %1:%2. Wait for profile data or type a command (type 'help' " - "to show list of commands).\nRecording Status: %3") - .arg(m_hostName).arg((m_port)).arg(m_recording ? tr("on") : tr("off"))); -} - -void QmlProfilerApplication::connectionStateChanged( - QAbstractSocket::SocketState state) -{ - if (m_verbose) - qDebug() << state; -} - -void QmlProfilerApplication::connectionError(QAbstractSocket::SocketError error) -{ - if (m_verbose) - qDebug() << error; + QString endpoint = m_socketFile.isEmpty() ? + QString::fromLatin1("%1:%2").arg(m_hostName).arg(m_port) : + m_socketFile; + prompt(tr("Connected to %1. Wait for profile data or type a command (type 'help' to show list " + "of commands).\nRecording Status: %2") + .arg(endpoint).arg(m_recording ? tr("on") : tr("off"))); } void QmlProfilerApplication::processHasOutput() @@ -562,35 +534,24 @@ void QmlProfilerApplication::processFinished() } if (!m_interactive) exit(exitCode); + else + m_qmlProfilerClient.clearPendingData(); } -void QmlProfilerApplication::traceClientEnabled() -{ - logStatus("Trace client is attached."); - // blocked server is waiting for recording message from both clients - // once the last one is connected, both messages should be sent - m_qmlProfilerClient.sendRecordingStatus(m_recording); - m_v8profilerClient.sendRecordingStatus(m_recording); -} - -void QmlProfilerApplication::profilerClientEnabled() +void QmlProfilerApplication::traceClientEnabledChanged(bool enabled) { - logStatus("Profiler client is attached."); - - // blocked server is waiting for recording message from both clients - // once the last one is connected, both messages should be sent - m_qmlProfilerClient.sendRecordingStatus(m_recording); - m_v8profilerClient.sendRecordingStatus(m_recording); + if (enabled) { + logStatus("Trace client is attached."); + // blocked server is waiting for recording message from both clients + // once the last one is connected, both messages should be sent + m_qmlProfilerClient.sendRecordingStatus(m_recording); + } } void QmlProfilerApplication::traceFinished() { m_recording = false; // only on "Complete" we know that the trace is really finished. - // after receiving both notifications, reset the flags - m_qmlDataReady = false; - m_v8DataReady = false; - if (m_pendingRequest == REQUEST_FLUSH) { flush(); } else if (m_pendingRequest == REQUEST_TOGGLE_RECORDING) { @@ -599,6 +560,8 @@ void QmlProfilerApplication::traceFinished() } else { prompt(tr("Application stopped recording."), false); } + + m_qmlProfilerClient.clearPendingData(); } void QmlProfilerApplication::prompt(const QString &line, bool ready) @@ -626,21 +589,3 @@ void QmlProfilerApplication::logStatus(const QString &status) QTextStream err(stderr); err << status << endl; } - -void QmlProfilerApplication::qmlComplete() -{ - m_qmlDataReady = true; - if (m_v8profilerClient.state() != QQmlDebugClient::Enabled || - m_v8DataReady) { - m_profilerData.complete(); - } -} - -void QmlProfilerApplication::v8Complete() -{ - m_v8DataReady = true; - if (m_qmlProfilerClient.state() != QQmlDebugClient::Enabled || - m_qmlDataReady) { - m_profilerData.complete(); - } -} diff --git a/tools/qmlprofiler/qmlprofilerapplication.h b/tools/qmlprofiler/qmlprofilerapplication.h index f1bf6c3e93..ef79a902e7 100644 --- a/tools/qmlprofiler/qmlprofilerapplication.h +++ b/tools/qmlprofiler/qmlprofilerapplication.h @@ -34,13 +34,16 @@ #ifndef QMLPROFILERAPPLICATION_H #define QMLPROFILERAPPLICATION_H -#include <QtCore/QCoreApplication> -#include <QtCore/QProcess> -#include <QtCore/QTimer> - #include "qmlprofilerclient.h" #include "qmlprofilerdata.h" +#include <private/qqmldebugconnection_p.h> + +#include <QtCore/qcoreapplication.h> +#include <QtCore/qprocess.h> +#include <QtCore/qtimer.h> +#include <QtNetwork/qabstractsocket.h> + enum PendingRequest { REQUEST_QUIT, REQUEST_FLUSH_FILE, @@ -73,22 +76,16 @@ private slots: void run(); void tryToConnect(); void connected(); - void connectionStateChanged(QAbstractSocket::SocketState state); - void connectionError(QAbstractSocket::SocketError error); void processHasOutput(); void processFinished(); - void traceClientEnabled(); - void profilerClientEnabled(); + void traceClientEnabledChanged(bool enabled); void traceFinished(); void prompt(const QString &line = QString(), bool ready = true); void logError(const QString &error); void logStatus(const QString &status); - void qmlComplete(); - void v8Complete(); - private: quint64 parseFeatures(const QStringList &featureList, const QString &values, bool exclude); bool checkOutputFile(PendingRequest pending); @@ -105,6 +102,7 @@ private: QStringList m_programArguments; QProcess *m_process; + QString m_socketFile; QString m_hostName; quint16 m_port; QString m_outputFile; @@ -117,13 +115,9 @@ private: QQmlDebugConnection m_connection; QmlProfilerClient m_qmlProfilerClient; - V8ProfilerClient m_v8profilerClient; QmlProfilerData m_profilerData; QTimer m_connectTimer; uint m_connectionAttempts; - - bool m_qmlDataReady; - bool m_v8DataReady; }; #endif // QMLPROFILERAPPLICATION_H diff --git a/tools/qmlprofiler/qmlprofilerclient.cpp b/tools/qmlprofiler/qmlprofilerclient.cpp index b4768e6934..018f1ec803 100644 --- a/tools/qmlprofiler/qmlprofilerclient.cpp +++ b/tools/qmlprofiler/qmlprofilerclient.cpp @@ -32,6 +32,9 @@ ****************************************************************************/ #include "qmlprofilerclient.h" +#include "qmlprofilerdata.h" + +#include <private/qqmlprofilerclient_p_p.h> #include <QtCore/QStack> #include <QtCore/QStringList> @@ -39,310 +42,165 @@ #include <limits> -ProfilerClient::ProfilerClient(const QString &clientName, - QQmlDebugConnection *client) - : QQmlDebugClient(clientName, client), - m_enabled(false) -{ -} - -ProfilerClient::~ProfilerClient() -{ -} - -void ProfilerClient::clearData() -{ - emit cleared(); -} - -bool ProfilerClient::isEnabled() const -{ - return m_enabled; -} - -void ProfilerClient::stateChanged(State status) -{ - if ((m_enabled && status != Enabled) || - (!m_enabled && status == Enabled)) - emit enabledChanged(); - - m_enabled = status == Enabled; - -} - -class QmlProfilerClientPrivate +class QmlProfilerClientPrivate : public QQmlProfilerClientPrivate { + Q_DECLARE_PUBLIC(QmlProfilerClient) public: - QmlProfilerClientPrivate() - : inProgressRanges(0) , features(std::numeric_limits<quint64>::max()) - { - ::memset(rangeCount, 0, QQmlProfilerDefinitions::MaximumRangeType * sizeof(int)); - } + QmlProfilerClientPrivate(QQmlDebugConnection *connection, QmlProfilerData *data); + + QmlProfilerData *data; qint64 inProgressRanges; QStack<qint64> rangeStartTimes[QQmlProfilerDefinitions::MaximumRangeType]; QStack<QStringList> rangeDatas[QQmlProfilerDefinitions::MaximumRangeType]; - QStack<QmlEventLocation> rangeLocations[QQmlProfilerDefinitions::MaximumRangeType]; - QStack<QQmlProfilerDefinitions::BindingType> bindingTypes; + QStack<QQmlEventLocation> rangeLocations[QQmlProfilerDefinitions::MaximumRangeType]; int rangeCount[QQmlProfilerDefinitions::MaximumRangeType]; - quint64 features; + bool enabled; }; -QmlProfilerClient::QmlProfilerClient( - QQmlDebugConnection *client) - : ProfilerClient(QStringLiteral("CanvasFrameRate"), client), - d(new QmlProfilerClientPrivate) +QmlProfilerClientPrivate::QmlProfilerClientPrivate(QQmlDebugConnection *connection, + QmlProfilerData *data) : + QQmlProfilerClientPrivate(connection), data(data), inProgressRanges(0), enabled(false) { + ::memset(rangeCount, 0, QQmlProfilerDefinitions::MaximumRangeType * sizeof(int)); } -QmlProfilerClient::~QmlProfilerClient() +QmlProfilerClient::QmlProfilerClient(QQmlDebugConnection *connection, QmlProfilerData *data) : + QQmlProfilerClient(*(new QmlProfilerClientPrivate(connection, data))) { - delete d; } -void QmlProfilerClient::setFeatures(quint64 features) +void QmlProfilerClient::clearPendingData() { - d->features = features; + Q_D(QmlProfilerClient); + for (int i = 0; i < QQmlProfilerDefinitions::MaximumRangeType; ++i) { + d->rangeCount[i] = 0; + d->rangeDatas[i].clear(); + d->rangeLocations[i].clear(); + } } -void QmlProfilerClient::clearData() +void QmlProfilerClient::stateChanged(State state) { - ::memset(d->rangeCount, 0, QQmlProfilerDefinitions::MaximumRangeType * sizeof(int)); - d->bindingTypes.clear(); - ProfilerClient::clearData(); + Q_D(QmlProfilerClient); + if ((d->enabled && state != Enabled) || (!d->enabled && state == Enabled)) { + d->enabled = (state == Enabled); + emit enabledChanged(d->enabled); + } } -void QmlProfilerClient::sendRecordingStatus(bool record) +void QmlProfilerClient::traceStarted(qint64 time, int engineId) { - QByteArray ba; - QDataStream stream(&ba, QIODevice::WriteOnly); - stream.setVersion(QDataStream::Qt_4_7); - stream << record << -1 << d->features; - sendMessage(ba); + Q_UNUSED(engineId); + Q_D(QmlProfilerClient); + d->data->setTraceStartTime(time); + emit recordingStarted(); } -inline QQmlProfilerDefinitions::ProfileFeature featureFromRangeType( - QQmlProfilerDefinitions::RangeType range) +void QmlProfilerClient::traceFinished(qint64 time, int engineId) { - 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; - } + Q_UNUSED(engineId); + Q_D(QmlProfilerClient); + d->data->setTraceEndTime(time); } -void QmlProfilerClient::messageReceived(const QByteArray &data) +void QmlProfilerClient::rangeStart(QQmlProfilerDefinitions::RangeType type, qint64 startTime) { - QByteArray rwData = data; - QDataStream stream(&rwData, QIODevice::ReadOnly); - stream.setVersion(QDataStream::Qt_4_7); + Q_D(QmlProfilerClient); + d->rangeStartTimes[type].push(startTime); + d->inProgressRanges |= (static_cast<qint64>(1) << type); + ++d->rangeCount[type]; +} - // Force all the 1 << <FLAG> expressions to be done in 64 bit, to silence some warnings - const quint64 one = static_cast<quint64>(1); +void QmlProfilerClient::rangeData(QQmlProfilerDefinitions::RangeType type, qint64 time, + const QString &data) +{ + Q_UNUSED(time); + Q_D(QmlProfilerClient); + int count = d->rangeCount[type]; + if (count > 0) { + while (d->rangeDatas[type].count() < count) + d->rangeDatas[type].push(QStringList()); + d->rangeDatas[type][count - 1] << data; + } +} - qint64 time; - int messageType; +void QmlProfilerClient::rangeLocation(QQmlProfilerDefinitions::RangeType type, qint64 time, + const QQmlEventLocation &location) +{ + Q_UNUSED(time); + Q_D(QmlProfilerClient); + if (d->rangeCount[type] > 0) + d->rangeLocations[type].push(location); +} - stream >> time >> messageType; +void QmlProfilerClient::rangeEnd(QQmlProfilerDefinitions::RangeType type, qint64 endTime) +{ + Q_D(QmlProfilerClient); - if (messageType >= QQmlProfilerDefinitions::MaximumMessage) + if (d->rangeCount[type] == 0) { + emit error(tr("Spurious range end detected.")); return; + } - if (messageType == QQmlProfilerDefinitions::Event) { - int event; - stream >> event; - - if (event == QQmlProfilerDefinitions::EndTrace) { - emit this->traceFinished(time); - } else if (event == QQmlProfilerDefinitions::AnimationFrame) { - if (!(d->features & one << QQmlProfilerDefinitions::ProfileAnimations)) - return; - int frameRate, animationCount; - int threadId = 0; - stream >> frameRate >> animationCount; - if (!stream.atEnd()) - stream >> threadId; - emit this->frame(time, frameRate, animationCount, threadId); - } else if (event == QQmlProfilerDefinitions::StartTrace) { - emit this->traceStarted(time); - } else if (event == QQmlProfilerDefinitions::Key || - event == QQmlProfilerDefinitions::Mouse) { - if (!(d->features & one << QQmlProfilerDefinitions::ProfileInputEvents)) - return; - emit this->inputEvent((QQmlProfilerDefinitions::EventType)event, time); - } - } else if (messageType == QQmlProfilerDefinitions::Complete) { - emit complete(); - } else if (messageType == QQmlProfilerDefinitions::SceneGraphFrame) { - if (!(d->features & one << QQmlProfilerDefinitions::ProfileSceneGraph)) - return; - int sgEventType; - int count = 0; - qint64 params[5]; - - stream >> sgEventType; - while (!stream.atEnd()) { - stream >> params[count++]; - } - while (count<5) - params[count++] = 0; - emit sceneGraphFrame((QQmlProfilerDefinitions::SceneGraphFrameType)sgEventType, time, - params[0], params[1], params[2], params[3], params[4]); - } else if (messageType == QQmlProfilerDefinitions::PixmapCacheEvent) { - if (!(d->features & one << QQmlProfilerDefinitions::ProfilePixmapCache)) - return; - int pixEvTy, width = 0, height = 0, refcount = 0; - QString pixUrl; - stream >> pixEvTy >> pixUrl; - if (pixEvTy == (int)QQmlProfilerDefinitions::PixmapReferenceCountChanged || - pixEvTy == (int)QQmlProfilerDefinitions::PixmapCacheCountChanged) { - stream >> refcount; - } else if (pixEvTy == (int)QQmlProfilerDefinitions::PixmapSizeKnown) { - stream >> width >> height; - refcount = 1; - } - emit pixmapCache((QQmlProfilerDefinitions::PixmapEventType)pixEvTy, time, - QmlEventLocation(pixUrl,0,0), width, height, refcount); - } else if (messageType == QQmlProfilerDefinitions::MemoryAllocation) { - if (!(d->features & one << QQmlProfilerDefinitions::ProfileMemory)) - return; - int type; - qint64 delta; - stream >> type >> delta; - emit memoryAllocation((QQmlProfilerDefinitions::MemoryType)type, time, delta); - } else { - int range; - stream >> range; - - if (range >= QQmlProfilerDefinitions::MaximumRangeType) - return; - - if (!(d->features & one << featureFromRangeType( - static_cast<QQmlProfilerDefinitions::RangeType>(range)))) - return; - - if (messageType == QQmlProfilerDefinitions::RangeStart) { - d->rangeStartTimes[range].push(time); - d->inProgressRanges |= (static_cast<qint64>(1) << range); - ++d->rangeCount[range]; - - // read binding type - if (range == (int)QQmlProfilerDefinitions::Binding) { - int bindingType = (int)QQmlProfilerDefinitions::QmlBinding; - if (!stream.atEnd()) - stream >> bindingType; - d->bindingTypes.push((QQmlProfilerDefinitions::BindingType)bindingType); - } - } else if (messageType == QQmlProfilerDefinitions::RangeData) { - QString data; - stream >> data; - - int count = d->rangeCount[range]; - if (count > 0) { - while (d->rangeDatas[range].count() < count) - d->rangeDatas[range].push(QStringList()); - d->rangeDatas[range][count-1] << data; - } - - } else if (messageType == QQmlProfilerDefinitions::RangeLocation) { - QString fileName; - int line; - int column = -1; - stream >> fileName >> line; - - if (!stream.atEnd()) - stream >> column; - - if (d->rangeCount[range] > 0) { - d->rangeLocations[range].push(QmlEventLocation(fileName, line, - column)); - } - } else { - if (d->rangeCount[range] > 0) { - --d->rangeCount[range]; - if (d->inProgressRanges & (static_cast<qint64>(1) << range)) - d->inProgressRanges &= ~(static_cast<qint64>(1) << range); - - QStringList data = d->rangeDatas[range].count() ? - d->rangeDatas[range].pop() : QStringList(); - QmlEventLocation location = d->rangeLocations[range].count() ? - d->rangeLocations[range].pop() : QmlEventLocation(); - - qint64 startTime = d->rangeStartTimes[range].pop(); - QQmlProfilerDefinitions::BindingType bindingType = - QQmlProfilerDefinitions::QmlBinding; - if (range == (int)QQmlProfilerDefinitions::Binding) - bindingType = d->bindingTypes.pop(); - emit this->range((QQmlProfilerDefinitions::RangeType)range, - bindingType, startTime, time - startTime, data, location); - if (d->rangeCount[range] == 0) { - int count = d->rangeDatas[range].count() + - d->rangeStartTimes[range].count() + - d->rangeLocations[range].count(); - if (count != 0) - qWarning() << "incorrectly nested data"; - } - } - } + --d->rangeCount[type]; + if (d->inProgressRanges & (static_cast<qint64>(1) << type)) + d->inProgressRanges &= ~(static_cast<qint64>(1) << type); + QStringList data = d->rangeDatas[type].count() ? d->rangeDatas[type].pop() : QStringList(); + QQmlEventLocation location = d->rangeLocations[type].count() ? d->rangeLocations[type].pop() : + QQmlEventLocation(); + qint64 startTime = d->rangeStartTimes[type].pop(); + + if (d->rangeCount[type] == 0 && d->rangeDatas[type].count() + d->rangeStartTimes[type].count() + + d->rangeLocations[type].count() != 0) { + emit error(tr("Incorrectly nested range data")); + return; } + + d->data->addQmlEvent(type, QQmlProfilerDefinitions::QmlBinding, startTime, endTime - startTime, + data, location); } -V8ProfilerClient::V8ProfilerClient(QQmlDebugConnection *client) - : ProfilerClient(QStringLiteral("V8Profiler"), client) +void QmlProfilerClient::animationFrame(qint64 time, int frameRate, int animationCount, int threadId) { + Q_D(QmlProfilerClient); + d->data->addFrameEvent(time, frameRate, animationCount, threadId); } -V8ProfilerClient::~V8ProfilerClient() +void QmlProfilerClient::sceneGraphEvent(QQmlProfilerDefinitions::SceneGraphFrameType type, + qint64 time, qint64 numericData1, qint64 numericData2, + qint64 numericData3, qint64 numericData4, + qint64 numericData5) { + Q_D(QmlProfilerClient); + d->data->addSceneGraphFrameEvent(type, time, numericData1, numericData2, numericData3, + numericData4, numericData5); } -void V8ProfilerClient::sendRecordingStatus(bool record) +void QmlProfilerClient::pixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type, qint64 time, + const QString &url, int numericData1, int numericData2) { - QByteArray ba; - QDataStream stream(&ba, QIODevice::WriteOnly); - QByteArray cmd("V8PROFILER"); - QByteArray option(record ? "start" : "stop"); - QByteArray title(""); - - stream << cmd << option << title; - sendMessage(ba); + Q_D(QmlProfilerClient); + d->data->addPixmapCacheEvent(type, time, url, numericData1, numericData2); } -void V8ProfilerClient::messageReceived(const QByteArray &data) +void QmlProfilerClient::memoryAllocation(QQmlProfilerDefinitions::MemoryType type, qint64 time, + qint64 amount) { - QByteArray rwData = data; - QDataStream stream(&rwData, QIODevice::ReadOnly); - - int messageType; - - stream >> messageType; - - if (messageType == V8Complete) { - emit complete(); - } else if (messageType == V8Entry) { - QString filename; - QString function; - int lineNumber; - double totalTime; - double selfTime; - int depth; + Q_D(QmlProfilerClient); + d->data->addMemoryEvent(type, time, amount); +} - stream >> filename >> function >> lineNumber >> totalTime >> - selfTime >> depth; - emit this->range(depth, function, filename, lineNumber, totalTime, - selfTime); - } +void QmlProfilerClient::inputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time, + int a, int b) +{ + Q_D(QmlProfilerClient); + d->data->addInputEvent(type, time, a, b); } +void QmlProfilerClient::complete() +{ + Q_D(QmlProfilerClient); + d->data->complete(); +} diff --git a/tools/qmlprofiler/qmlprofilerclient.h b/tools/qmlprofiler/qmlprofilerclient.h index 731ab99973..fc4dad639d 100644 --- a/tools/qmlprofiler/qmlprofilerclient.h +++ b/tools/qmlprofiler/qmlprofilerclient.h @@ -34,100 +34,45 @@ #ifndef QMLPROFILERCLIENT_H #define QMLPROFILERCLIENT_H -#include "qqmldebugclient.h" -#include "qmlprofilereventlocation.h" -#include <QtQml/private/qqmlprofilerdefinitions_p.h> +#include <private/qqmleventlocation_p.h> +#include <private/qqmlprofilerclient_p.h> +#include <private/qqmlprofilerdefinitions_p.h> -class ProfilerClientPrivate; -class ProfilerClient : public QQmlDebugClient +class QmlProfilerData; +class QmlProfilerClientPrivate; +class QmlProfilerClient : public QQmlProfilerClient { Q_OBJECT + Q_DECLARE_PRIVATE(QmlProfilerClient) - Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged) public: - ProfilerClient(const QString &clientName, - QQmlDebugConnection *client); - ~ProfilerClient(); - - bool isEnabled() const; - -public slots: - virtual void clearData(); + QmlProfilerClient(QQmlDebugConnection *connection, QmlProfilerData *data); + void clearPendingData(); signals: - void complete(); - void enabledChanged(); - void cleared(); - -protected: - virtual void stateChanged(State); - -protected: - bool m_enabled; -}; - -class QmlProfilerClient : public ProfilerClient -{ - Q_OBJECT - -public: - QmlProfilerClient(QQmlDebugConnection *client); - ~QmlProfilerClient(); - - void setFeatures(quint64 features); + void enabledChanged(bool enabled); + void recordingStarted(); + void error(const QString &error); -public slots: - void clearData(); - void sendRecordingStatus(bool record); - -signals: - void traceFinished( qint64 time ); - void traceStarted( qint64 time ); - void range(QQmlProfilerDefinitions::RangeType type, - QQmlProfilerDefinitions::BindingType bindingType, - qint64 startTime, qint64 length, - const QStringList &data, - const QmlEventLocation &location); - void frame(qint64 time, int frameRate, int animationCount, int threadId); - void sceneGraphFrame(QQmlProfilerDefinitions::SceneGraphFrameType type, qint64 time, +private: + virtual void stateChanged(State state); + + void traceStarted(qint64 time, int engineId); + void traceFinished(qint64 time, int engineId); + void rangeStart(QQmlProfilerDefinitions::RangeType type, qint64 startTime); + void rangeData(QQmlProfilerDefinitions::RangeType type, qint64 time, const QString &data); + void rangeLocation(QQmlProfilerDefinitions::RangeType type, qint64 time, + const QQmlEventLocation &location); + void rangeEnd(QQmlProfilerDefinitions::RangeType type, qint64 endTime); + void animationFrame(qint64 time, int frameRate, int animationCount, int threadId); + void sceneGraphEvent(QQmlProfilerDefinitions::SceneGraphFrameType type, qint64 time, qint64 numericData1, qint64 numericData2, qint64 numericData3, qint64 numericData4, qint64 numericData5); - void pixmapCache(QQmlProfilerDefinitions::PixmapEventType, qint64 time, - const QmlEventLocation &location, int width, int height, int refCount); + void pixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type, qint64 time, + const QString &url, int numericData1, int numericData2); void memoryAllocation(QQmlProfilerDefinitions::MemoryType type, qint64 time, qint64 amount); - void inputEvent(QQmlProfilerDefinitions::EventType, qint64 time); - -protected: - virtual void messageReceived(const QByteArray &); - -private: - class QmlProfilerClientPrivate *d; -}; - -class V8ProfilerClient : public ProfilerClient -{ - Q_OBJECT - -public: - enum Message { - V8Entry, - V8Complete, - - V8MaximumMessage - }; - - V8ProfilerClient(QQmlDebugConnection *client); - ~V8ProfilerClient(); - -public slots: - void sendRecordingStatus(bool record); - -signals: - void range(int depth, const QString &function, const QString &filename, - int lineNumber, double totalTime, double selfTime); - -protected: - virtual void messageReceived(const QByteArray &); + void inputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time, int a, int b); + void complete(); }; #endif // QMLPROFILERCLIENT_H diff --git a/tools/qmlprofiler/qmlprofilerdata.cpp b/tools/qmlprofiler/qmlprofilerdata.cpp index 307b9d3686..9465e4931d 100644 --- a/tools/qmlprofiler/qmlprofilerdata.cpp +++ b/tools/qmlprofiler/qmlprofilerdata.cpp @@ -73,14 +73,14 @@ Q_STATIC_ASSERT(sizeof(MESSAGE_STRINGS) == struct QmlRangeEventData { QmlRangeEventData() {} // never called QmlRangeEventData(const QString &_displayName, int _detailType, const QString &_eventHashStr, - const QmlEventLocation &_location, const QString &_details, + const QQmlEventLocation &_location, const QString &_details, QQmlProfilerDefinitions::Message _message, QQmlProfilerDefinitions::RangeType _rangeType) : displayName(_displayName), eventHashStr(_eventHashStr), location(_location), details(_details), message(_message), rangeType(_rangeType), detailType(_detailType) {} QString displayName; QString eventHashStr; - QmlEventLocation location; + QQmlEventLocation location; QString details; QQmlProfilerDefinitions::Message message; QQmlProfilerDefinitions::RangeType rangeType; @@ -107,14 +107,17 @@ struct QmlRangeEventStartInstance { qint64 duration; union { int frameRate; + int inputType; qint64 numericData1; }; union { int animationCount; + int inputA; qint64 numericData2; }; union { int threadId; + int inputB; qint64 numericData3; }; qint64 numericData4; @@ -127,18 +130,6 @@ Q_DECLARE_TYPEINFO(QmlRangeEventData, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QmlRangeEventStartInstance, Q_MOVABLE_TYPE); QT_END_NAMESPACE -struct QV8EventInfo { - QString displayName; - QString eventHashStr; - QString functionName; - QString fileName; - int line; - qint64 totalTime; - qint64 selfTime; - - QHash<QString, qint64> v8children; -}; - ///////////////////////////////////////////////////////////////// class QmlProfilerDataPrivate { @@ -148,18 +139,12 @@ public: // data storage QHash<QString, QmlRangeEventData *> eventDescriptions; QVector<QmlRangeEventStartInstance> startInstanceList; - QHash<QString, QV8EventInfo *> v8EventHash; qint64 traceStartTime; qint64 traceEndTime; // internal state while collecting events qint64 qmlMeasuredTime; - qint64 v8MeasuredTime; - QHash<int, QV8EventInfo *> v8parents; - void clearV8RootEvent(); - QV8EventInfo v8RootEvent; - QmlProfilerData::State state; }; @@ -183,12 +168,6 @@ void QmlProfilerData::clear() d->eventDescriptions.clear(); d->startInstanceList.clear(); - qDeleteAll(d->v8EventHash); - d->v8EventHash.clear(); - d->v8parents.clear(); - d->clearV8RootEvent(); - d->v8MeasuredTime = 0; - d->traceEndTime = std::numeric_limits<qint64>::min(); d->traceStartTime = std::numeric_limits<qint64>::max(); d->qmlMeasuredTime = 0; @@ -196,7 +175,7 @@ void QmlProfilerData::clear() setState(Empty); } -QString QmlProfilerData::getHashStringForQmlEvent(const QmlEventLocation &location, int eventType) +QString QmlProfilerData::getHashStringForQmlEvent(const QQmlEventLocation &location, int eventType) { return QString(QStringLiteral("%1:%2:%3:%4")).arg( location.filename, @@ -205,14 +184,9 @@ QString QmlProfilerData::getHashStringForQmlEvent(const QmlEventLocation &locati QString::number(eventType)); } -QString QmlProfilerData::getHashStringForV8Event(const QString &displayName, const QString &function) -{ - return QString(QStringLiteral("%1:%2")).arg(displayName, function); -} - QString QmlProfilerData::qmlRangeTypeAsString(QQmlProfilerDefinitions::RangeType type) { - if (type * sizeof(QString) < sizeof(RANGE_TYPE_STRINGS)) + if (type * sizeof(char *) < sizeof(RANGE_TYPE_STRINGS)) return QLatin1String(RANGE_TYPE_STRINGS[type]); else return QString::number(type); @@ -220,7 +194,7 @@ QString QmlProfilerData::qmlRangeTypeAsString(QQmlProfilerDefinitions::RangeType QString QmlProfilerData::qmlMessageAsString(QQmlProfilerDefinitions::Message type) { - if (type * sizeof(QString) < sizeof(MESSAGE_STRINGS)) + if (type * sizeof(char *) < sizeof(MESSAGE_STRINGS)) return QLatin1String(MESSAGE_STRINGS[type]); else return QString::number(type); @@ -253,7 +227,7 @@ void QmlProfilerData::addQmlEvent(QQmlProfilerDefinitions::RangeType type, qint64 startTime, qint64 duration, const QStringList &data, - const QmlEventLocation &location) + const QQmlEventLocation &location) { setState(AcquiringData); @@ -273,7 +247,7 @@ void QmlProfilerData::addQmlEvent(QQmlProfilerDefinitions::RangeType type, details = details.mid(details.lastIndexOf(QLatin1Char('/')) + 1); } - QmlEventLocation eventLocation = location; + QQmlEventLocation eventLocation = location; QString displayName, eventHashStr; // generate hash if (eventLocation.filename.isEmpty()) { @@ -315,7 +289,7 @@ void QmlProfilerData::addFrameEvent(qint64 time, int framerate, int animationcou } else { newEvent = new QmlRangeEventData(displayName, QQmlProfilerDefinitions::AnimationFrame, eventHashStr, - QmlEventLocation(), details, + QQmlEventLocation(), details, QQmlProfilerDefinitions::Event, QQmlProfilerDefinitions::MaximumRangeType); d->eventDescriptions.insert(eventHashStr, newEvent); @@ -340,7 +314,7 @@ void QmlProfilerData::addSceneGraphFrameEvent(QQmlProfilerDefinitions::SceneGrap newEvent = d->eventDescriptions[eventHashStr]; } else { newEvent = new QmlRangeEventData(QStringLiteral("<SceneGraph>"), type, eventHashStr, - QmlEventLocation(), QString(), + QQmlEventLocation(), QString(), QQmlProfilerDefinitions::SceneGraphFrame, QQmlProfilerDefinitions::MaximumRangeType); d->eventDescriptions.insert(eventHashStr, newEvent); @@ -353,12 +327,12 @@ void QmlProfilerData::addSceneGraphFrameEvent(QQmlProfilerDefinitions::SceneGrap } void QmlProfilerData::addPixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type, - qint64 time, const QmlEventLocation &location, - int width, int height, int refcount) + qint64 time, const QString &location, + int numericData1, int numericData2) { setState(AcquiringData); - QString filePath = QUrl(location.filename).path(); + QString filePath = QUrl(location).path(); QString eventHashStr = filePath.mid(filePath.lastIndexOf(QLatin1Char('/')) + 1) + QStringLiteral(":") + QString::number(type); @@ -366,13 +340,14 @@ void QmlProfilerData::addPixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventTy if (d->eventDescriptions.contains(eventHashStr)) { newEvent = d->eventDescriptions[eventHashStr]; } else { - newEvent = new QmlRangeEventData(eventHashStr, type, eventHashStr, location, QString(), + newEvent = new QmlRangeEventData(eventHashStr, type, eventHashStr, + QQmlEventLocation(location, -1, -1), QString(), QQmlProfilerDefinitions::PixmapCacheEvent, QQmlProfilerDefinitions::MaximumRangeType); d->eventDescriptions.insert(eventHashStr, newEvent); } - QmlRangeEventStartInstance rangeEventStartInstance(time, width, height, refcount, 0, 0, + QmlRangeEventStartInstance rangeEventStartInstance(time, numericData1, numericData2, 0, 0, 0, newEvent); d->startInstanceList.append(rangeEventStartInstance); } @@ -386,7 +361,7 @@ void QmlProfilerData::addMemoryEvent(QQmlProfilerDefinitions::MemoryType type, q if (d->eventDescriptions.contains(eventHashStr)) { newEvent = d->eventDescriptions[eventHashStr]; } else { - newEvent = new QmlRangeEventData(eventHashStr, type, eventHashStr, QmlEventLocation(), + newEvent = new QmlRangeEventData(eventHashStr, type, eventHashStr, QQmlEventLocation(), QString(), QQmlProfilerDefinitions::MemoryAllocation, QQmlProfilerDefinitions::MaximumRangeType); d->eventDescriptions.insert(eventHashStr, newEvent); @@ -395,93 +370,36 @@ void QmlProfilerData::addMemoryEvent(QQmlProfilerDefinitions::MemoryType type, q d->startInstanceList.append(rangeEventStartInstance); } -void QmlProfilerData::addInputEvent(QQmlProfilerDefinitions::EventType type, qint64 time) +void QmlProfilerData::addInputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time, + int a, int b) { setState(AcquiringData); - QString eventHashStr = QString::fromLatin1("Input:%1").arg(type); + QQmlProfilerDefinitions::EventType eventType; + switch (type) { + case QQmlProfilerDefinitions::InputKeyPress: + case QQmlProfilerDefinitions::InputKeyRelease: + case QQmlProfilerDefinitions::InputKeyUnknown: + eventType = QQmlProfilerDefinitions::Key; + break; + default: + eventType = QQmlProfilerDefinitions::Mouse; + break; + } + + QString eventHashStr = QString::fromLatin1("Input:%1").arg(eventType); QmlRangeEventData *newEvent; if (d->eventDescriptions.contains(eventHashStr)) { newEvent = d->eventDescriptions[eventHashStr]; } else { - newEvent = new QmlRangeEventData(QString(), type, eventHashStr, QmlEventLocation(), + newEvent = new QmlRangeEventData(QString(), eventType, eventHashStr, QQmlEventLocation(), QString(), QQmlProfilerDefinitions::Event, QQmlProfilerDefinitions::MaximumRangeType); d->eventDescriptions.insert(eventHashStr, newEvent); } - d->startInstanceList.append(QmlRangeEventStartInstance(time, -1, 0, 0, 0, newEvent)); -} - -QString QmlProfilerData::rootEventName() -{ - return tr("<program>"); -} - -QString QmlProfilerData::rootEventDescription() -{ - return tr("Main Program"); -} - -void QmlProfilerDataPrivate::clearV8RootEvent() -{ - v8RootEvent.displayName = QmlProfilerData::rootEventName(); - v8RootEvent.eventHashStr = QmlProfilerData::rootEventName(); - v8RootEvent.functionName = QmlProfilerData::rootEventDescription(); - v8RootEvent.line = -1; - v8RootEvent.totalTime = 0; - v8RootEvent.selfTime = 0; - v8RootEvent.v8children.clear(); -} - -void QmlProfilerData::addV8Event(int depth, const QString &function, const QString &filename, - int lineNumber, double totalTime, double selfTime) -{ - QString displayName = filename.mid(filename.lastIndexOf(QLatin1Char('/')) + 1) + - QLatin1Char(':') + QString::number(lineNumber); - QString hashStr = getHashStringForV8Event(displayName, function); - - setState(AcquiringData); - - // time is given in milliseconds, but internally we store it in microseconds - totalTime *= 1e6; - selfTime *= 1e6; - - // accumulate information - QV8EventInfo *eventData = d->v8EventHash[hashStr]; - if (!eventData) { - eventData = new QV8EventInfo; - eventData->displayName = displayName; - eventData->eventHashStr = hashStr; - eventData->fileName = filename; - eventData->functionName = function; - eventData->line = lineNumber; - eventData->totalTime = totalTime; - eventData->selfTime = selfTime; - d->v8EventHash[hashStr] = eventData; - } else { - eventData->totalTime += totalTime; - eventData->selfTime += selfTime; - } - d->v8parents[depth] = eventData; - - QV8EventInfo *parentEvent = 0; - if (depth == 0) { - parentEvent = &d->v8RootEvent; - d->v8MeasuredTime += totalTime; - } - if (depth > 0 && d->v8parents.contains(depth-1)) { - parentEvent = d->v8parents.value(depth-1); - } - - if (parentEvent != 0) { - if (!parentEvent->v8children.contains(eventData->eventHashStr)) { - parentEvent->v8children[eventData->eventHashStr] = totalTime; - } else { - parentEvent->v8children[eventData->eventHashStr] += totalTime; - } - } + d->startInstanceList.append(QmlRangeEventStartInstance(time, -1, type, a, b, newEvent)); } void QmlProfilerData::computeQmlTime() @@ -567,7 +485,7 @@ void QmlProfilerData::complete() bool QmlProfilerData::isEmpty() const { - return d->startInstanceList.isEmpty() && d->v8EventHash.isEmpty(); + return d->startInstanceList.isEmpty(); } bool QmlProfilerData::save(const QString &filename) @@ -608,21 +526,24 @@ bool QmlProfilerData::save(const QString &filename) stream.writeStartElement(QStringLiteral("event")); stream.writeAttribute(QStringLiteral("index"), QString::number( d->eventDescriptions.keys().indexOf(eventData->eventHashStr))); - stream.writeTextElement(QStringLiteral("displayname"), eventData->displayName); + if (!eventData->displayName.isEmpty()) + stream.writeTextElement(QStringLiteral("displayname"), eventData->displayName); if (eventData->rangeType != QQmlProfilerDefinitions::MaximumRangeType) stream.writeTextElement(QStringLiteral("type"), qmlRangeTypeAsString(eventData->rangeType)); else stream.writeTextElement(QStringLiteral("type"), qmlMessageAsString(eventData->message)); - if (!eventData->location.filename.isEmpty()) { + if (!eventData->location.filename.isEmpty()) stream.writeTextElement(QStringLiteral("filename"), eventData->location.filename); + if (eventData->location.line >= 0) stream.writeTextElement(QStringLiteral("line"), QString::number(eventData->location.line)); + if (eventData->location.column >= 0) stream.writeTextElement(QStringLiteral("column"), QString::number(eventData->location.column)); - } - stream.writeTextElement(QStringLiteral("details"), eventData->details); + if (!eventData->details.isEmpty()) + stream.writeTextElement(QStringLiteral("details"), eventData->details); if (eventData->rangeType == QQmlProfilerDefinitions::Binding) stream.writeTextElement(QStringLiteral("bindingType"), QString::number((int)eventData->detailType)); @@ -663,13 +584,23 @@ bool QmlProfilerData::save(const QString &filename) QString::number(event.duration)); stream.writeAttribute(QStringLiteral("eventIndex"), QString::number( d->eventDescriptions.keys().indexOf(event.data->eventHashStr))); - if (event.data->message == QQmlProfilerDefinitions::Event && - event.data->detailType == QQmlProfilerDefinitions::AnimationFrame) { - // special: animation frame - stream.writeAttribute(QStringLiteral("framerate"), QString::number(event.frameRate)); - stream.writeAttribute(QStringLiteral("animationcount"), - QString::number(event.animationCount)); - stream.writeAttribute(QStringLiteral("thread"), QString::number(event.threadId)); + if (event.data->message == QQmlProfilerDefinitions::Event) { + if (event.data->detailType == QQmlProfilerDefinitions::AnimationFrame) { + // special: animation frame + stream.writeAttribute(QStringLiteral("framerate"), QString::number(event.frameRate)); + stream.writeAttribute(QStringLiteral("animationcount"), + QString::number(event.animationCount)); + stream.writeAttribute(QStringLiteral("thread"), QString::number(event.threadId)); + } else if (event.data->detailType == QQmlProfilerDefinitions::Key || + event.data->detailType == QQmlProfilerDefinitions::Mouse) { + // numerical value here, to keep the format a bit more compact + stream.writeAttribute(QStringLiteral("type"), + QString::number(event.inputType)); + stream.writeAttribute(QStringLiteral("data1"), + QString::number(event.inputA)); + stream.writeAttribute(QStringLiteral("data2"), + QString::number(event.inputB)); + } } else if (event.data->message == QQmlProfilerDefinitions::PixmapCacheEvent) { // special: pixmap cache event if (event.data->detailType == QQmlProfilerDefinitions::PixmapSizeKnown) { @@ -682,7 +613,7 @@ bool QmlProfilerData::save(const QString &filename) event.data->detailType == QQmlProfilerDefinitions::PixmapCacheCountChanged) { stream.writeAttribute(QStringLiteral("refCount"), - QString::number(event.numericData3)); + QString::number(event.numericData1)); } } else if (event.data->message == QQmlProfilerDefinitions::SceneGraphFrame) { // special: scenegraph frame events @@ -708,38 +639,6 @@ bool QmlProfilerData::save(const QString &filename) } stream.writeEndElement(); // profilerDataModel - stream.writeStartElement(QStringLiteral("v8profile")); // v8 profiler output - stream.writeAttribute(QStringLiteral("totalTime"), QString::number(d->v8MeasuredTime)); - foreach (QV8EventInfo *v8event, d->v8EventHash.values()) { - stream.writeStartElement(QStringLiteral("event")); - stream.writeAttribute(QStringLiteral("index"),QString::number( - d->v8EventHash.keys().indexOf(v8event->eventHashStr))); - stream.writeTextElement(QStringLiteral("displayname"), v8event->displayName); - stream.writeTextElement(QStringLiteral("functionname"), v8event->functionName); - if (!v8event->fileName.isEmpty()) { - stream.writeTextElement(QStringLiteral("filename"), v8event->fileName); - stream.writeTextElement(QStringLiteral("line"), QString::number(v8event->line)); - } - stream.writeTextElement(QStringLiteral("totalTime"), QString::number(v8event->totalTime)); - stream.writeTextElement(QStringLiteral("selfTime"), QString::number(v8event->selfTime)); - if (!v8event->v8children.isEmpty()) { - stream.writeStartElement(QStringLiteral("childrenEvents")); - QStringList childrenIndexes; - QStringList childrenTimes; - foreach (const QString &childHash, v8event->v8children.keys()) { - childrenIndexes << QString::number(v8EventIndex(childHash)); - childrenTimes << QString::number(v8event->v8children[childHash]); - } - - stream.writeAttribute(QStringLiteral("list"), childrenIndexes.join(QString(", "))); - stream.writeAttribute(QStringLiteral("childrenTimes"), - childrenTimes.join(QString(", "))); - stream.writeEndElement(); - } - stream.writeEndElement(); - } - stream.writeEndElement(); // v8 profiler output - stream.writeEndElement(); // trace stream.writeEndDocument(); @@ -747,15 +646,6 @@ bool QmlProfilerData::save(const QString &filename) return true; } -int QmlProfilerData::v8EventIndex(const QString &hashStr) -{ - if (!d->v8EventHash.contains(hashStr)) { - emit error("Trying to index nonexisting v8 event"); - return -1; - } - return d->v8EventHash.keys().indexOf( hashStr ); -} - void QmlProfilerData::setState(QmlProfilerData::State state) { // It's not an error, we are continuously calling "AcquiringData" for example diff --git a/tools/qmlprofiler/qmlprofilerdata.h b/tools/qmlprofiler/qmlprofilerdata.h index 91c16c3222..345f7f2d12 100644 --- a/tools/qmlprofiler/qmlprofilerdata.h +++ b/tools/qmlprofiler/qmlprofilerdata.h @@ -34,9 +34,9 @@ #ifndef QMLPROFILERDATA_H #define QMLPROFILERDATA_H -#include "qmlprofilereventlocation.h" +#include <private/qqmleventlocation_p.h> +#include <private/qqmlprofilerdefinitions_p.h> -#include <QtQml/private/qqmlprofilerdefinitions_p.h> #include <QObject> class QmlProfilerDataPrivate; @@ -54,12 +54,9 @@ public: explicit QmlProfilerData(QObject *parent = 0); ~QmlProfilerData(); - static QString getHashStringForQmlEvent(const QmlEventLocation &location, int eventType); - static QString getHashStringForV8Event(const QString &displayName, const QString &function); + static QString getHashStringForQmlEvent(const QQmlEventLocation &location, int eventType); static QString qmlRangeTypeAsString(QQmlProfilerDefinitions::RangeType type); static QString qmlMessageAsString(QQmlProfilerDefinitions::Message type); - static QString rootEventName(); - static QString rootEventDescription(); qint64 traceStartTime() const; qint64 traceEndTime() const; @@ -78,24 +75,21 @@ public slots: void addQmlEvent(QQmlProfilerDefinitions::RangeType type, QQmlProfilerDefinitions::BindingType bindingType, qint64 startTime, qint64 duration, const QStringList &data, - const QmlEventLocation &location); - void addV8Event(int depth, const QString &function, const QString &filename, - int lineNumber, double totalTime, double selfTime); + const QQmlEventLocation &location); void addFrameEvent(qint64 time, int framerate, int animationcount, int threadId); void addSceneGraphFrameEvent(QQmlProfilerDefinitions::SceneGraphFrameType type, qint64 time, qint64 numericData1, qint64 numericData2, qint64 numericData3, qint64 numericData4, qint64 numericData5); void addPixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type, qint64 time, - const QmlEventLocation &location, int width, int height, int refcount); + const QString &location, int numericData1, int numericData2); void addMemoryEvent(QQmlProfilerDefinitions::MemoryType type, qint64 time, qint64 size); - void addInputEvent(QQmlProfilerDefinitions::EventType type, qint64 time); + void addInputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time, int a, int b); void complete(); bool save(const QString &filename); private: void sortStartTimes(); - int v8EventIndex(const QString &hashStr); void computeQmlTime(); void setState(QmlProfilerData::State state); diff --git a/tools/qmlprofiler/qmlprofilereventlocation.h b/tools/qmlprofiler/qmlprofilereventlocation.h deleted file mode 100644 index ebf9f2eed6..0000000000 --- a/tools/qmlprofiler/qmlprofilereventlocation.h +++ /dev/null @@ -1,53 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMLPROFILEREVENTLOCATION_H -#define QMLPROFILEREVENTLOCATION_H - -#include <QString> - -struct QmlEventLocation -{ - QmlEventLocation() : line(-1), column(-1) {} - QmlEventLocation(const QString &file, int lineNumber, int columnNumber) - : filename(file), line(lineNumber), column(columnNumber) {} - QString filename; - int line; - int column; -}; - -QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(QmlEventLocation, Q_MOVABLE_TYPE); -QT_END_NAMESPACE - -#endif // QMLPROFILEREVENTLOCATION_H diff --git a/tools/qmlprofiler/qpacketprotocol.cpp b/tools/qmlprofiler/qpacketprotocol.cpp deleted file mode 100644 index 096bc142c5..0000000000 --- a/tools/qmlprofiler/qpacketprotocol.cpp +++ /dev/null @@ -1,527 +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> // for qt_subtract_from_timeout - -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); -} - -#include <qpacketprotocol.moc> diff --git a/tools/qmlprofiler/qpacketprotocol.h b/tools/qmlprofiler/qpacketprotocol.h deleted file mode 100644 index 17608033f4..0000000000 --- a/tools/qmlprofiler/qpacketprotocol.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPACKETPROTOCOL_H -#define QPACKETPROTOCOL_H - -#include <QtCore/qobject.h> -#include <QtCore/qdatastream.h> - -QT_BEGIN_NAMESPACE -class QIODevice; -class QBuffer; -QT_END_NAMESPACE -class QPacket; -class QPacketAutoSend; -class QPacketProtocolPrivate; - -class QPacketProtocol : public QObject -{ - Q_OBJECT -public: - explicit QPacketProtocol(QIODevice *dev, QObject *parent = 0); - virtual ~QPacketProtocol(); - - qint32 maximumPacketSize() const; - qint32 setMaximumPacketSize(qint32); - - QPacketAutoSend send(); - void send(const QPacket &); - - qint64 packetsAvailable() const; - QPacket 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; -}; - -#endif diff --git a/tools/qmlprofiler/qqmldebugclient.cpp b/tools/qmlprofiler/qqmldebugclient.cpp deleted file mode 100644 index f87d4b0a7c..0000000000 --- a/tools/qmlprofiler/qqmldebugclient.cpp +++ /dev/null @@ -1,403 +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 "qqmldebugclient.h" -#include "qpacketprotocol.h" - -#include <QtCore/qdebug.h> -#include <QtCore/qstringlist.h> -#include <QtNetwork/qnetworkproxy.h> - -const int protocolVersion = 1; -const QString serverId = QLatin1String("QDeclarativeDebugServer"); -const QString clientId = QLatin1String("QDeclarativeDebugClient"); - -class QQmlDebugClientPrivate -{ -public: - QQmlDebugClientPrivate(); - - QString name; - QQmlDebugConnection *connection; -}; - -class QQmlDebugConnectionPrivate : public QObject -{ - Q_OBJECT -public: - QQmlDebugConnectionPrivate(QQmlDebugConnection *c); - QQmlDebugConnection *q; - QPacketProtocol *protocol; - QIODevice *device; - - bool gotHello; - QHash <QString, float> serverPlugins; - QHash<QString, QQmlDebugClient *> plugins; - - void advertisePlugins(); - void connectDeviceSignals(); - -public Q_SLOTS: - void connected(); - void readyRead(); - void deviceAboutToClose(); -}; - -QQmlDebugConnectionPrivate::QQmlDebugConnectionPrivate(QQmlDebugConnection *c) - : QObject(c), q(c), protocol(0), device(0), gotHello(false) -{ - protocol = new QPacketProtocol(q, this); - QObject::connect(c, SIGNAL(connected()), this, SLOT(connected())); - QObject::connect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); -} - -void QQmlDebugConnectionPrivate::advertisePlugins() -{ - if (!q->isConnected()) - return; - - QPacket pack; - pack << serverId << 1 << plugins.keys(); - protocol->send(pack); - q->flush(); -} - -void QQmlDebugConnectionPrivate::connected() -{ - QPacket pack; - pack << serverId << 0 << protocolVersion << plugins.keys(); - protocol->send(pack); - q->flush(); -} - -void QQmlDebugConnectionPrivate::readyRead() -{ - if (!gotHello) { - QPacket pack = 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.isEmpty()) - 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); - serverPlugins.insert(pluginNames.at(i), pluginVersion); - } - - validHello = true; - } - } - } - - if (!validHello) { - qWarning("QQmlDebugConnection: Invalid hello message"); - QObject::disconnect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); - return; - } - gotHello = true; - - QHash<QString, QQmlDebugClient *>::Iterator iter = plugins.begin(); - for (; iter != plugins.end(); ++iter) { - QQmlDebugClient::State newState = QQmlDebugClient::Unavailable; - if (serverPlugins.contains(iter.key())) - newState = QQmlDebugClient::Enabled; - iter.value()->stateChanged(newState); - } - } - - while (protocol->packetsAvailable()) { - QPacket pack = protocol->read(); - QString name; - pack >> name; - - if (name == clientId) { - int op = -1; - pack >> op; - - if (op == 1) { - // Service Discovery - QHash<QString, float> oldServerPlugins = serverPlugins; - serverPlugins.clear(); - - QStringList pluginNames; - QList<float> pluginVersions; - pack >> pluginNames; - if (!pack.isEmpty()) - 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); - serverPlugins.insert(pluginNames.at(i), pluginVersion); - } - - QHash<QString, QQmlDebugClient *>::Iterator iter = plugins.begin(); - for (; iter != plugins.end(); ++iter) { - const QString pluginName = iter.key(); - QQmlDebugClient::State newSate = QQmlDebugClient::Unavailable; - if (serverPlugins.contains(pluginName)) - newSate = QQmlDebugClient::Enabled; - - if (oldServerPlugins.contains(pluginName) - != 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 = - plugins.find(name); - if (iter == plugins.end()) { - qWarning() << "QQmlDebugConnection: Message received for missing plugin" << name; - } else { - (*iter)->messageReceived(message); - } - } - } -} - -void QQmlDebugConnectionPrivate::deviceAboutToClose() -{ - // This is nasty syntax but we want to emit our own aboutToClose signal (by calling QIODevice::close()) - // without calling the underlying device close fn as that would cause an infinite loop - q->QIODevice::close(); -} - -QQmlDebugConnection::QQmlDebugConnection(QObject *parent) - : QIODevice(parent), d(new QQmlDebugConnectionPrivate(this)) -{ -} - -QQmlDebugConnection::~QQmlDebugConnection() -{ - QHash<QString, QQmlDebugClient*>::iterator iter = d->plugins.begin(); - for (; iter != d->plugins.end(); ++iter) { - iter.value()->d->connection = 0; - iter.value()->stateChanged(QQmlDebugClient::NotConnected); - } -} - -bool QQmlDebugConnection::isConnected() const -{ - return state() == QAbstractSocket::ConnectedState; -} - -qint64 QQmlDebugConnection::readData(char *data, qint64 maxSize) -{ - return d->device->read(data, maxSize); -} - -qint64 QQmlDebugConnection::writeData(const char *data, qint64 maxSize) -{ - return d->device->write(data, maxSize); -} - -qint64 QQmlDebugConnection::bytesAvailable() const -{ - return d->device->bytesAvailable(); -} - -bool QQmlDebugConnection::isSequential() const -{ - return true; -} - -void QQmlDebugConnection::close() -{ - if (isOpen()) { - QIODevice::close(); - d->device->close(); - emit stateChanged(QAbstractSocket::UnconnectedState); - - QHash<QString, QQmlDebugClient*>::iterator iter = d->plugins.begin(); - for (; iter != d->plugins.end(); ++iter) { - iter.value()->stateChanged(QQmlDebugClient::NotConnected); - } - } -} - -bool QQmlDebugConnection::waitForConnected(int msecs) -{ - QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(d->device); - if (socket) - return socket->waitForConnected(msecs); - return false; -} - -QAbstractSocket::SocketState QQmlDebugConnection::state() const -{ - QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(d->device); - if (socket) - return socket->state(); - - return QAbstractSocket::UnconnectedState; -} - -void QQmlDebugConnection::flush() -{ - QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(d->device); - if (socket) { - socket->flush(); - return; - } -} - -void QQmlDebugConnection::connectToHost(const QString &hostName, quint16 port) -{ - QTcpSocket *socket = new QTcpSocket(d); -#ifndef QT_NO_NETWORKPROXY - socket->setProxy(QNetworkProxy::NoProxy); -#endif - d->device = socket; - d->connectDeviceSignals(); - d->gotHello = false; - connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SIGNAL(stateChanged(QAbstractSocket::SocketState))); - connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(error(QAbstractSocket::SocketError))); - connect(socket, SIGNAL(connected()), this, SIGNAL(connected())); - socket->connectToHost(hostName, port); - QIODevice::open(ReadWrite | Unbuffered); -} - -void QQmlDebugConnectionPrivate::connectDeviceSignals() -{ - connect(device, SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64))); - connect(device, SIGNAL(readyRead()), q, SIGNAL(readyRead())); - connect(device, SIGNAL(aboutToClose()), this, SLOT(deviceAboutToClose())); -} - -// - -QQmlDebugClientPrivate::QQmlDebugClientPrivate() - : connection(0) -{ -} - -QQmlDebugClient::QQmlDebugClient(const QString &name, - QQmlDebugConnection *parent) - : QObject(parent), - d(new QQmlDebugClientPrivate) -{ - d->name = name; - d->connection = parent; - - if (!d->connection) - return; - - if (d->connection->d->plugins.contains(name)) { - qWarning() << "QQmlDebugClient: Conflicting plugin name" << name; - d->connection = 0; - } else { - d->connection->d->plugins.insert(name, this); - d->connection->d->advertisePlugins(); - } -} - -QQmlDebugClient::~QQmlDebugClient() -{ - if (d->connection && d->connection->d) { - d->connection->d->plugins.remove(d->name); - d->connection->d->advertisePlugins(); - } - delete d; -} - -QString QQmlDebugClient::name() const -{ - return d->name; -} - -float QQmlDebugClient::serviceVersion() const -{ - if (d->connection->d->serverPlugins.contains(d->name)) - return d->connection->d->serverPlugins.value(d->name); - return -1; -} - -QQmlDebugClient::State QQmlDebugClient::state() const -{ - if (!d->connection - || !d->connection->isConnected() - || !d->connection->d->gotHello) - return NotConnected; - - if (d->connection->d->serverPlugins.contains(d->name)) - return Enabled; - - return Unavailable; -} - -void QQmlDebugClient::sendMessage(const QByteArray &message) -{ - if (state() != Enabled) - return; - - QPacket pack; - pack << d->name << message; - d->connection->d->protocol->send(pack); - d->connection->flush(); -} - -void QQmlDebugClient::stateChanged(State) -{ -} - -void QQmlDebugClient::messageReceived(const QByteArray &) -{ -} - -#include <qqmldebugclient.moc> diff --git a/tools/qmlprofiler/qqmldebugclient.h b/tools/qmlprofiler/qqmldebugclient.h deleted file mode 100644 index 522f6bca2f..0000000000 --- a/tools/qmlprofiler/qqmldebugclient.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQMLDEBUGCLIENT_H -#define QQMLDEBUGCLIENT_H - -#include <QtNetwork/qtcpsocket.h> - -class QQmlDebugConnectionPrivate; -class QQmlDebugConnection : public QIODevice -{ - Q_OBJECT - Q_DISABLE_COPY(QQmlDebugConnection) -public: - QQmlDebugConnection(QObject * = 0); - ~QQmlDebugConnection(); - - void connectToHost(const QString &hostName, quint16 port); - - qint64 bytesAvailable() const; - bool isConnected() const; - QAbstractSocket::SocketState state() const; - void flush(); - bool isSequential() const; - void close(); - bool waitForConnected(int msecs = 30000); - -signals: - void connected(); - void stateChanged(QAbstractSocket::SocketState socketState); - void error(QAbstractSocket::SocketError socketError); - -protected: - qint64 readData(char *data, qint64 maxSize); - qint64 writeData(const char *data, qint64 maxSize); - -private: - QQmlDebugConnectionPrivate *d; - friend class QQmlDebugClient; - friend class QQmlDebugClientPrivate; -}; - -class QQmlDebugClientPrivate; -class QQmlDebugClient : public QObject -{ - Q_OBJECT - Q_DISABLE_COPY(QQmlDebugClient) - -public: - enum State { NotConnected, Unavailable, Enabled }; - - QQmlDebugClient(const QString &, QQmlDebugConnection *parent); - ~QQmlDebugClient(); - - QString name() const; - float serviceVersion() const; - State state() const; - - virtual void sendMessage(const QByteArray &); - -protected: - virtual void stateChanged(State); - virtual void messageReceived(const QByteArray &); - -private: - QQmlDebugClientPrivate *d; - friend class QQmlDebugConnection; - friend class QQmlDebugConnectionPrivate; -}; - -#endif // QQMLDEBUGCLIENT_H |