forked from qt-creator/qt-creator
QmlProfiler: Refactor
The code of the qmlprofiler client has become a bit too complex, this patch reorganizes the modules in a more sensible way, having the modules communicate with each other through a state machine instead of the excess of signals and slots from before. Change-Id: I76f7313779888a1bd07a1cdb1acbf2e47aacf42a Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
This commit is contained in:
@@ -7,11 +7,11 @@ contains(CONFIG, dll) {
|
|||||||
INCLUDEPATH += $$PWD/..
|
INCLUDEPATH += $$PWD/..
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
$$PWD/qmlprofilereventlocation.h \
|
||||||
$$PWD/qdeclarativedebugclient.h \
|
$$PWD/qdeclarativedebugclient.h \
|
||||||
$$PWD/qdeclarativeenginedebug.h \
|
$$PWD/qdeclarativeenginedebug.h \
|
||||||
$$PWD/qdeclarativeoutputparser.h \
|
$$PWD/qdeclarativeoutputparser.h \
|
||||||
$$PWD/qmljsdebugclient_global.h \
|
$$PWD/qmljsdebugclient_global.h \
|
||||||
$$PWD/qmlprofilereventlist.h \
|
|
||||||
$$PWD/qmlprofilereventtypes.h \
|
$$PWD/qmlprofilereventtypes.h \
|
||||||
$$PWD/qmlprofilertraceclient.h \
|
$$PWD/qmlprofilertraceclient.h \
|
||||||
$$PWD/qpacketprotocol.h \
|
$$PWD/qpacketprotocol.h \
|
||||||
@@ -23,7 +23,6 @@ SOURCES += \
|
|||||||
$$PWD/qdeclarativedebugclient.cpp \
|
$$PWD/qdeclarativedebugclient.cpp \
|
||||||
$$PWD/qdeclarativeenginedebug.cpp \
|
$$PWD/qdeclarativeenginedebug.cpp \
|
||||||
$$PWD/qdeclarativeoutputparser.cpp \
|
$$PWD/qdeclarativeoutputparser.cpp \
|
||||||
$$PWD/qmlprofilereventlist.cpp \
|
|
||||||
$$PWD/qmlprofilertraceclient.cpp \
|
$$PWD/qmlprofilertraceclient.cpp \
|
||||||
$$PWD/qpacketprotocol.cpp \
|
$$PWD/qpacketprotocol.cpp \
|
||||||
$$PWD/qv8profilerclient.cpp \
|
$$PWD/qv8profilerclient.cpp \
|
||||||
|
@@ -11,6 +11,3 @@ OTHER_FILES += \
|
|||||||
qmljsdebugclient.pri \
|
qmljsdebugclient.pri \
|
||||||
qmljsdebugclient-lib.pri
|
qmljsdebugclient-lib.pri
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
qmlprofilereventlocation.h
|
|
||||||
|
|
||||||
|
@@ -24,7 +24,7 @@ DynamicLibrary {
|
|||||||
"qdeclarativeoutputparser.h",
|
"qdeclarativeoutputparser.h",
|
||||||
"qmljsdebugclient_global.h",
|
"qmljsdebugclient_global.h",
|
||||||
"qmljsdebugclientconstants.h",
|
"qmljsdebugclientconstants.h",
|
||||||
"qmlprofilereventlist.h",
|
"qmlprofilereventlocation.h",
|
||||||
"qmlprofilertraceclient.cpp",
|
"qmlprofilertraceclient.cpp",
|
||||||
"qpacketprotocol.cpp",
|
"qpacketprotocol.cpp",
|
||||||
"qv8profilerclient.cpp",
|
"qv8profilerclient.cpp",
|
||||||
@@ -36,7 +36,6 @@ DynamicLibrary {
|
|||||||
"qmlprofilertraceclient.h",
|
"qmlprofilertraceclient.h",
|
||||||
"qpacketprotocol.h",
|
"qpacketprotocol.h",
|
||||||
"qdebugmessageclient.cpp",
|
"qdebugmessageclient.cpp",
|
||||||
"qmlprofilereventlist.cpp",
|
|
||||||
"qdebugmessageclient.h"
|
"qdebugmessageclient.h"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -35,6 +35,8 @@
|
|||||||
|
|
||||||
#include "qmljsdebugclient_global.h"
|
#include "qmljsdebugclient_global.h"
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
namespace QmlJsDebugClient {
|
namespace QmlJsDebugClient {
|
||||||
|
|
||||||
struct QMLJSDEBUGCLIENT_EXPORT QmlEventLocation
|
struct QMLJSDEBUGCLIENT_EXPORT QmlEventLocation
|
||||||
|
@@ -33,8 +33,6 @@
|
|||||||
#ifndef QMLPROFILEREVENTTYPES_H
|
#ifndef QMLPROFILEREVENTTYPES_H
|
||||||
#define QMLPROFILEREVENTTYPES_H
|
#define QMLPROFILEREVENTTYPES_H
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
namespace QmlJsDebugClient {
|
namespace QmlJsDebugClient {
|
||||||
|
|
||||||
enum QmlEventType {
|
enum QmlEventType {
|
||||||
@@ -47,8 +45,15 @@ enum QmlEventType {
|
|||||||
MaximumQmlEventType
|
MaximumQmlEventType
|
||||||
};
|
};
|
||||||
|
|
||||||
QString qmlEventType(QmlEventType typeEnum);
|
namespace Constants {
|
||||||
QmlEventType qmlEventType(const QString &typeString);
|
const char TYPE_PAINTING_STR[] = "Painting";
|
||||||
|
const char TYPE_COMPILING_STR[] = "Compiling";
|
||||||
|
const char TYPE_CREATING_STR[] = "Creating";
|
||||||
|
const char TYPE_BINDING_STR[] = "Binding";
|
||||||
|
const char TYPE_HANDLINGSIGNAL_STR[] = "HandlingSignal";
|
||||||
|
const char PROFILER_FILE_VERSION[] = "1.02";
|
||||||
|
const int QML_MIN_LEVEL = 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QmlJsDebugClient
|
} // namespace QmlJsDebugClient
|
||||||
|
|
||||||
|
@@ -159,6 +159,12 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
|
|||||||
int event;
|
int event;
|
||||||
stream >> event;
|
stream >> event;
|
||||||
|
|
||||||
|
// stop with the first data
|
||||||
|
if (d->recording && event != StartTrace)
|
||||||
|
setRecordingFromServer(false);
|
||||||
|
else if ((!d->recording) && event == StartTrace)
|
||||||
|
setRecordingFromServer(true);
|
||||||
|
|
||||||
if (event == EndTrace) {
|
if (event == EndTrace) {
|
||||||
emit this->traceFinished(time);
|
emit this->traceFinished(time);
|
||||||
d->maximumTime = time;
|
d->maximumTime = time;
|
||||||
@@ -169,9 +175,6 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
|
|||||||
emit this->frame(time, frameRate, animationCount);
|
emit this->frame(time, frameRate, animationCount);
|
||||||
d->maximumTime = qMax(time, d->maximumTime);
|
d->maximumTime = qMax(time, d->maximumTime);
|
||||||
} else if (event == StartTrace) {
|
} else if (event == StartTrace) {
|
||||||
// special: StartTrace is now asynchronous
|
|
||||||
if (!d->recording)
|
|
||||||
setRecordingFromServer(true);
|
|
||||||
emit this->traceStarted(time);
|
emit this->traceStarted(time);
|
||||||
d->maximumTime = time;
|
d->maximumTime = time;
|
||||||
} else if (event < MaximumEventType) {
|
} else if (event < MaximumEventType) {
|
||||||
@@ -191,6 +194,9 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
|
|||||||
d->rangeStartTimes[range].push(time);
|
d->rangeStartTimes[range].push(time);
|
||||||
d->inProgressRanges |= (static_cast<qint64>(1) << range);
|
d->inProgressRanges |= (static_cast<qint64>(1) << range);
|
||||||
++d->rangeCount[range];
|
++d->rangeCount[range];
|
||||||
|
// stop with the first data
|
||||||
|
if (d->recording)
|
||||||
|
setRecordingFromServer(false);
|
||||||
} else if (messageType == RangeData) {
|
} else if (messageType == RangeData) {
|
||||||
QString data;
|
QString data;
|
||||||
stream >> data;
|
stream >> data;
|
||||||
|
@@ -80,10 +80,9 @@ public:
|
|||||||
|
|
||||||
bool isEnabled() const;
|
bool isEnabled() const;
|
||||||
bool isRecording() const;
|
bool isRecording() const;
|
||||||
|
void setRecording(bool);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setRecording(bool);
|
|
||||||
void setRecordingFromServer(bool);
|
|
||||||
void clearData();
|
void clearData();
|
||||||
void sendRecordingStatus();
|
void sendRecordingStatus();
|
||||||
|
|
||||||
@@ -106,6 +105,9 @@ protected:
|
|||||||
virtual void statusChanged(Status);
|
virtual void statusChanged(Status);
|
||||||
virtual void messageReceived(const QByteArray &);
|
virtual void messageReceived(const QByteArray &);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setRecordingFromServer(bool);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class QmlProfilerTraceClientPrivate *d;
|
class QmlProfilerTraceClientPrivate *d;
|
||||||
};
|
};
|
||||||
|
@@ -118,6 +118,16 @@ void QV8ProfilerClient::setRecording(bool v)
|
|||||||
emit recordingChanged(v);
|
emit recordingChanged(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QV8ProfilerClient::setRecordingFromServer(bool v)
|
||||||
|
{
|
||||||
|
if (v == d->recording)
|
||||||
|
return;
|
||||||
|
|
||||||
|
d->recording = v;
|
||||||
|
|
||||||
|
emit recordingChanged(v);
|
||||||
|
}
|
||||||
|
|
||||||
void QV8ProfilerClient::statusChanged(Status /*status*/)
|
void QV8ProfilerClient::statusChanged(Status /*status*/)
|
||||||
{
|
{
|
||||||
emit enabledChanged();
|
emit enabledChanged();
|
||||||
@@ -133,7 +143,10 @@ void QV8ProfilerClient::messageReceived(const QByteArray &data)
|
|||||||
stream >> messageType;
|
stream >> messageType;
|
||||||
|
|
||||||
if (messageType == V8Complete) {
|
if (messageType == V8Complete) {
|
||||||
|
setRecordingFromServer(false);
|
||||||
emit complete();
|
emit complete();
|
||||||
|
} else if (messageType == V8ProfilingStarted) {
|
||||||
|
setRecordingFromServer(true);
|
||||||
} else if (messageType == V8Entry) {
|
} else if (messageType == V8Entry) {
|
||||||
QString filename;
|
QString filename;
|
||||||
QString function;
|
QString function;
|
||||||
|
@@ -52,6 +52,9 @@ public:
|
|||||||
enum Message {
|
enum Message {
|
||||||
V8Entry,
|
V8Entry,
|
||||||
V8Complete,
|
V8Complete,
|
||||||
|
V8SnapshotChunk,
|
||||||
|
V8SnapshotComplete,
|
||||||
|
V8ProfilingStarted,
|
||||||
|
|
||||||
V8MaximumMessage
|
V8MaximumMessage
|
||||||
};
|
};
|
||||||
@@ -61,9 +64,9 @@ public:
|
|||||||
|
|
||||||
bool isEnabled() const;
|
bool isEnabled() const;
|
||||||
bool isRecording() const;
|
bool isRecording() const;
|
||||||
|
void setRecording(bool);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setRecording(bool);
|
|
||||||
void clearData();
|
void clearData();
|
||||||
void sendRecordingStatus();
|
void sendRecordingStatus();
|
||||||
|
|
||||||
@@ -77,6 +80,9 @@ signals:
|
|||||||
void enabledChanged();
|
void enabledChanged();
|
||||||
void cleared();
|
void cleared();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setRecordingFromServer(bool);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void statusChanged(Status);
|
virtual void statusChanged(Status);
|
||||||
virtual void messageReceived(const QByteArray &);
|
virtual void messageReceived(const QByteArray &);
|
||||||
|
@@ -60,17 +60,19 @@ Item {
|
|||||||
|
|
||||||
function updateHeight() {
|
function updateHeight() {
|
||||||
height = root.singleRowHeight * (1 +
|
height = root.singleRowHeight * (1 +
|
||||||
(expanded ? qmlEventList.uniqueEventsOfType(typeIndex) : qmlEventList.maxNestingForType(typeIndex)));
|
(expanded ? qmlProfilerDataModel.uniqueEventsOfType(typeIndex) :
|
||||||
|
qmlProfilerDataModel.maxNestingForType(typeIndex)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDescriptions() {
|
function getDescriptions() {
|
||||||
var desc=[];
|
var desc=[];
|
||||||
var ids=[];
|
var ids=[];
|
||||||
var extdesc=[];
|
var extdesc=[];
|
||||||
for (var i=0; i<qmlEventList.uniqueEventsOfType(typeIndex); i++) {
|
for (var i=0; i<qmlProfilerDataModel.uniqueEventsOfType(typeIndex); i++) {
|
||||||
desc[i] = qmlEventList.eventTextForType(typeIndex, i);
|
desc[i] = qmlProfilerDataModel.eventTextForType(typeIndex, i);
|
||||||
ids[i] = qmlEventList.eventIdForType(typeIndex, i);
|
ids[i] = qmlProfilerDataModel.eventIdForType(typeIndex, i);
|
||||||
extdesc[i] = qmlEventList.eventDisplayNameForType(typeIndex, i) + " : " + desc[i];
|
extdesc[i] = qmlProfilerDataModel.eventDisplayNameForType(typeIndex, i) +
|
||||||
|
" : " + desc[i];
|
||||||
}
|
}
|
||||||
descriptions = desc;
|
descriptions = desc;
|
||||||
eventIds = ids;
|
eventIds = ids;
|
||||||
@@ -79,18 +81,18 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: qmlEventList
|
target: qmlProfilerDataModel
|
||||||
onReloadDetailLabels: getDescriptions();
|
onReloadDetailLabels: getDescriptions();
|
||||||
onStateChanged: {
|
onStateChanged: {
|
||||||
// Empty
|
// Empty
|
||||||
if (qmlEventList.getCurrentStateFromQml() == 0) {
|
if (qmlProfilerDataModel.getCurrentStateFromQml() == 0) {
|
||||||
descriptions = [];
|
descriptions = [];
|
||||||
eventIds = [];
|
eventIds = [];
|
||||||
extdescriptions = [];
|
extdescriptions = [];
|
||||||
updateHeight();
|
updateHeight();
|
||||||
} else
|
} else
|
||||||
// Done
|
// Done
|
||||||
if (qmlEventList.getCurrentStateFromQml() == 3) {
|
if (qmlProfilerDataModel.getCurrentStateFromQml() == 3) {
|
||||||
getDescriptions();
|
getDescriptions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -51,11 +51,16 @@ Rectangle {
|
|||||||
property alias selectionLocked : view.selectionLocked
|
property alias selectionLocked : view.selectionLocked
|
||||||
signal updateLockButton
|
signal updateLockButton
|
||||||
property alias selectedItem: view.selectedItem
|
property alias selectedItem: view.selectedItem
|
||||||
signal selectedEventIdChanged(int eventId)
|
signal selectedEventChanged(int eventId)
|
||||||
property bool lockItemSelection : false
|
property bool lockItemSelection : false
|
||||||
|
|
||||||
property variant names: [ qsTr("Painting"), qsTr("Compiling"), qsTr("Creating"), qsTr("Binding"), qsTr("Handling Signal")]
|
property variant names: [ qsTr("Painting"),
|
||||||
property variant colors : [ "#99CCB3", "#99CCCC", "#99B3CC", "#9999CC", "#CC99B3", "#CC99CC", "#CCCC99", "#CCB399" ]
|
qsTr("Compiling"),
|
||||||
|
qsTr("Creating"),
|
||||||
|
qsTr("Binding"),
|
||||||
|
qsTr("Handling Signal")]
|
||||||
|
property variant colors : [ "#99CCB3", "#99CCCC", "#99B3CC",
|
||||||
|
"#9999CC", "#CC99B3", "#CC99CC", "#CCCC99", "#CCB399" ]
|
||||||
|
|
||||||
property variant mainviewTimePerPixel : 0
|
property variant mainviewTimePerPixel : 0
|
||||||
|
|
||||||
@@ -64,9 +69,6 @@ Rectangle {
|
|||||||
property int lineNumber: -1
|
property int lineNumber: -1
|
||||||
property int columnNumber: 0
|
property int columnNumber: 0
|
||||||
|
|
||||||
property real elapsedTime
|
|
||||||
signal updateTimer
|
|
||||||
|
|
||||||
signal updateRangeButton
|
signal updateRangeButton
|
||||||
property bool selectionRangeMode: false
|
property bool selectionRangeMode: false
|
||||||
|
|
||||||
@@ -77,7 +79,11 @@ Rectangle {
|
|||||||
signal changeToolTip(string text)
|
signal changeToolTip(string text)
|
||||||
signal updateVerticalScroll(int newPosition)
|
signal updateVerticalScroll(int newPosition)
|
||||||
|
|
||||||
property bool applicationDied : false
|
property bool recordingEnabled: false
|
||||||
|
property bool appKilled : false
|
||||||
|
|
||||||
|
property date recordingStartDate
|
||||||
|
property real elapsedTime
|
||||||
|
|
||||||
// ***** connections with external objects
|
// ***** connections with external objects
|
||||||
Connections {
|
Connections {
|
||||||
@@ -92,7 +98,8 @@ Rectangle {
|
|||||||
backgroundMarks.updateMarks(startTime, endTime);
|
backgroundMarks.updateMarks(startTime, endTime);
|
||||||
view.updateFlickRange(startTime, endTime);
|
view.updateFlickRange(startTime, endTime);
|
||||||
if (duration > 0) {
|
if (duration > 0) {
|
||||||
var candidateWidth = qmlEventList.traceDuration() * flick.width / duration;
|
var candidateWidth = qmlProfilerDataModel.traceDuration() *
|
||||||
|
flick.width / duration;
|
||||||
if (flick.contentWidth !== candidateWidth)
|
if (flick.contentWidth !== candidateWidth)
|
||||||
flick.contentWidth = candidateWidth;
|
flick.contentWidth = candidateWidth;
|
||||||
}
|
}
|
||||||
@@ -101,20 +108,21 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: qmlEventList
|
target: qmlProfilerDataModel
|
||||||
onCountChanged: {
|
onCountChanged: {
|
||||||
eventCount = qmlEventList.count();
|
eventCount = qmlProfilerDataModel.count();
|
||||||
if (eventCount === 0)
|
if (eventCount === 0)
|
||||||
root.clearAll();
|
root.clearAll();
|
||||||
if (eventCount > 1) {
|
if (eventCount > 1) {
|
||||||
root.progress = Math.min(1.0,
|
root.progress = Math.min(1.0,
|
||||||
(qmlEventList.lastTimeMark() - qmlEventList.traceStartTime()) / root.elapsedTime * 1e-9 );
|
(qmlProfilerDataModel.lastTimeMark() -
|
||||||
|
qmlProfilerDataModel.traceStartTime()) / root.elapsedTime * 1e-9 );
|
||||||
} else {
|
} else {
|
||||||
root.progress = 0;
|
root.progress = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onStateChanged: {
|
onStateChanged: {
|
||||||
switch (qmlEventList.getCurrentStateFromQml()) {
|
switch (qmlProfilerDataModel.getCurrentStateFromQml()) {
|
||||||
case 0: {
|
case 0: {
|
||||||
root.clearAll();
|
root.clearAll();
|
||||||
break;
|
break;
|
||||||
@@ -133,7 +141,9 @@ Rectangle {
|
|||||||
dataAvailable = true;
|
dataAvailable = true;
|
||||||
view.visible = true;
|
view.visible = true;
|
||||||
view.requestPaint();
|
view.requestPaint();
|
||||||
zoomControl.setRange(qmlEventList.traceStartTime(), qmlEventList.traceStartTime() + qmlEventList.traceDuration()/10);
|
zoomControl.setRange(qmlProfilerDataModel.traceStartTime(),
|
||||||
|
qmlProfilerDataModel.traceStartTime() +
|
||||||
|
qmlProfilerDataModel.traceDuration()/10);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,7 +161,7 @@ Rectangle {
|
|||||||
function clearData() {
|
function clearData() {
|
||||||
view.clearData();
|
view.clearData();
|
||||||
dataAvailable = false;
|
dataAvailable = false;
|
||||||
applicationDied = false;
|
appKilled = false;
|
||||||
eventCount = 0;
|
eventCount = 0;
|
||||||
hideRangeDetails();
|
hideRangeDetails();
|
||||||
selectionRangeMode = false;
|
selectionRangeMode = false;
|
||||||
@@ -166,8 +176,6 @@ Rectangle {
|
|||||||
|
|
||||||
function clearAll() {
|
function clearAll() {
|
||||||
clearDisplay();
|
clearDisplay();
|
||||||
root.elapsedTime = 0;
|
|
||||||
root.updateTimer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function nextEvent() {
|
function nextEvent() {
|
||||||
@@ -180,9 +188,10 @@ Rectangle {
|
|||||||
|
|
||||||
function updateWindowLength(absoluteFactor) {
|
function updateWindowLength(absoluteFactor) {
|
||||||
var windowLength = view.endTime - view.startTime;
|
var windowLength = view.endTime - view.startTime;
|
||||||
if (qmlEventList.traceEndTime() <= qmlEventList.traceStartTime() || windowLength <= 0)
|
if (qmlProfilerDataModel.traceEndTime() <= qmlProfilerDataModel.traceStartTime() ||
|
||||||
|
windowLength <= 0)
|
||||||
return;
|
return;
|
||||||
var currentFactor = windowLength / qmlEventList.traceDuration();
|
var currentFactor = windowLength / qmlProfilerDataModel.traceDuration();
|
||||||
updateZoom(absoluteFactor / currentFactor);
|
updateZoom(absoluteFactor / currentFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,8 +202,8 @@ Rectangle {
|
|||||||
windowLength = min_length;
|
windowLength = min_length;
|
||||||
var newWindowLength = windowLength * relativeFactor;
|
var newWindowLength = windowLength * relativeFactor;
|
||||||
|
|
||||||
if (newWindowLength > qmlEventList.traceDuration()) {
|
if (newWindowLength > qmlProfilerDataModel.traceDuration()) {
|
||||||
newWindowLength = qmlEventList.traceDuration();
|
newWindowLength = qmlProfilerDataModel.traceDuration();
|
||||||
relativeFactor = newWindowLength / windowLength;
|
relativeFactor = newWindowLength / windowLength;
|
||||||
}
|
}
|
||||||
if (newWindowLength < min_length) {
|
if (newWindowLength < min_length) {
|
||||||
@@ -205,7 +214,7 @@ Rectangle {
|
|||||||
var fixedPoint = (view.startTime + view.endTime) / 2;
|
var fixedPoint = (view.startTime + view.endTime) / 2;
|
||||||
if (view.selectedItem !== -1) {
|
if (view.selectedItem !== -1) {
|
||||||
// center on selected item if it's inside the current screen
|
// center on selected item if it's inside the current screen
|
||||||
var newFixedPoint = qmlEventList.getStartTime(view.selectedItem);
|
var newFixedPoint = qmlProfilerDataModel.getStartTime(view.selectedItem);
|
||||||
if (newFixedPoint >= view.startTime && newFixedPoint < view.endTime)
|
if (newFixedPoint >= view.startTime && newFixedPoint < view.endTime)
|
||||||
fixedPoint = newFixedPoint;
|
fixedPoint = newFixedPoint;
|
||||||
}
|
}
|
||||||
@@ -222,8 +231,8 @@ Rectangle {
|
|||||||
windowLength = min_length;
|
windowLength = min_length;
|
||||||
var newWindowLength = windowLength * relativeFactor;
|
var newWindowLength = windowLength * relativeFactor;
|
||||||
|
|
||||||
if (newWindowLength > qmlEventList.traceDuration()) {
|
if (newWindowLength > qmlProfilerDataModel.traceDuration()) {
|
||||||
newWindowLength = qmlEventList.traceDuration();
|
newWindowLength = qmlProfilerDataModel.traceDuration();
|
||||||
relativeFactor = newWindowLength / windowLength;
|
relativeFactor = newWindowLength / windowLength;
|
||||||
}
|
}
|
||||||
if (newWindowLength < min_length) {
|
if (newWindowLength < min_length) {
|
||||||
@@ -241,8 +250,8 @@ Rectangle {
|
|||||||
var newStart = Math.floor(centerPoint - windowLength/2);
|
var newStart = Math.floor(centerPoint - windowLength/2);
|
||||||
if (newStart < 0)
|
if (newStart < 0)
|
||||||
newStart = 0;
|
newStart = 0;
|
||||||
if (newStart + windowLength > qmlEventList.traceEndTime())
|
if (newStart + windowLength > qmlProfilerDataModel.traceEndTime())
|
||||||
newStart = qmlEventList.traceEndTime() - windowLength;
|
newStart = qmlProfilerDataModel.traceEndTime() - windowLength;
|
||||||
zoomControl.setRange(newStart, newStart + windowLength);
|
zoomControl.setRange(newStart, newStart + windowLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,17 +261,16 @@ Rectangle {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// if item is outside of the view, jump back to its position
|
// if item is outside of the view, jump back to its position
|
||||||
if (qmlEventList.getEndTime(itemIndex) < view.startTime || qmlEventList.getStartTime(itemIndex) > view.endTime) {
|
if (qmlProfilerDataModel.getEndTime(itemIndex) < view.startTime ||
|
||||||
recenter((qmlEventList.getStartTime(itemIndex) + qmlEventList.getEndTime(itemIndex)) / 2);
|
qmlProfilerDataModel.getStartTime(itemIndex) > view.endTime) {
|
||||||
|
recenter((qmlProfilerDataModel.getStartTime(itemIndex) +
|
||||||
|
qmlProfilerDataModel.getEndTime(itemIndex)) / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function globalZoom() {
|
|
||||||
zoomControl.setRange(qmlEventList.traceStartTime(), qmlEventList.traceEndTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
function wheelZoom(wheelCenter, wheelDelta) {
|
function wheelZoom(wheelCenter, wheelDelta) {
|
||||||
if (qmlEventList.traceEndTime() > qmlEventList.traceStartTime() && wheelDelta !== 0) {
|
if (qmlProfilerDataModel.traceEndTime() > qmlProfilerDataModel.traceStartTime() &&
|
||||||
|
wheelDelta !== 0) {
|
||||||
if (wheelDelta>0)
|
if (wheelDelta>0)
|
||||||
updateZoomCentered(wheelCenter, 1/1.2);
|
updateZoomCentered(wheelCenter, 1/1.2);
|
||||||
else
|
else
|
||||||
@@ -311,34 +319,22 @@ Rectangle {
|
|||||||
onSelectedItemChanged: {
|
onSelectedItemChanged: {
|
||||||
if (selectedItem != -1 && !lockItemSelection) {
|
if (selectedItem != -1 && !lockItemSelection) {
|
||||||
lockItemSelection = true;
|
lockItemSelection = true;
|
||||||
selectedEventIdChanged( qmlEventList.getEventId(selectedItem) );
|
selectedEventChanged( qmlProfilerDataModel.getEventId(selectedItem) );
|
||||||
lockItemSelection = false;
|
lockItemSelection = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ***** child items
|
onRecordingEnabledChanged: {
|
||||||
Timer {
|
if (recordingEnabled) {
|
||||||
id: elapsedTimer
|
recordingStartDate = new Date();
|
||||||
property date startDate
|
elapsedTime = 0;
|
||||||
property bool reset: true
|
} else {
|
||||||
running: connection.recording && connection.enabled
|
elapsedTime = (new Date() - recordingStartDate)/1000.0;
|
||||||
repeat: true
|
|
||||||
onRunningChanged: {
|
|
||||||
if (running) reset = true;
|
|
||||||
}
|
|
||||||
interval: 100
|
|
||||||
triggeredOnStart: true
|
|
||||||
onTriggered: {
|
|
||||||
if (reset) {
|
|
||||||
startDate = new Date();
|
|
||||||
reset = false;
|
|
||||||
}
|
|
||||||
var time = (new Date() - startDate)/1000;
|
|
||||||
root.elapsedTime = time.toFixed(1);
|
|
||||||
root.updateTimer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ***** child items
|
||||||
TimeMarks {
|
TimeMarks {
|
||||||
id: backgroundMarks
|
id: backgroundMarks
|
||||||
y: labels.y
|
y: labels.y
|
||||||
@@ -380,7 +376,8 @@ Rectangle {
|
|||||||
selectionRange.isDragging = false;
|
selectionRange.isDragging = false;
|
||||||
}
|
}
|
||||||
onDoubleClicked: {
|
onDoubleClicked: {
|
||||||
zoomControl.setRange(selectionRange.startTime, selectionRange.startTime + selectionRange.duration);
|
zoomControl.setRange(selectionRange.startTime,
|
||||||
|
selectionRange.startTime + selectionRange.duration);
|
||||||
root.selectionRangeMode = false;
|
root.selectionRangeMode = false;
|
||||||
root.updateRangeButton();
|
root.updateRangeButton();
|
||||||
}
|
}
|
||||||
@@ -394,10 +391,10 @@ Rectangle {
|
|||||||
z: 2
|
z: 2
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineView {
|
TimelineRenderer {
|
||||||
id: view
|
id: view
|
||||||
|
|
||||||
eventList: qmlEventList
|
profilerDataModel: qmlProfilerDataModel
|
||||||
|
|
||||||
x: flick.contentX
|
x: flick.contentX
|
||||||
width: flick.width
|
width: flick.width
|
||||||
@@ -405,9 +402,13 @@ Rectangle {
|
|||||||
|
|
||||||
property variant startX: 0
|
property variant startX: 0
|
||||||
onStartXChanged: {
|
onStartXChanged: {
|
||||||
var newStartTime = Math.round(startX * (endTime - startTime) / flick.width) + qmlEventList.traceStartTime();
|
var newStartTime = Math.round(startX * (endTime - startTime) / flick.width) +
|
||||||
|
qmlProfilerDataModel.traceStartTime();
|
||||||
if (Math.abs(newStartTime - startTime) > 1) {
|
if (Math.abs(newStartTime - startTime) > 1) {
|
||||||
var newEndTime = Math.round((startX+flick.width)* (endTime - startTime) / flick.width) + qmlEventList.traceStartTime();
|
var newEndTime = Math.round((startX+flick.width) *
|
||||||
|
(endTime - startTime) /
|
||||||
|
flick.width) +
|
||||||
|
qmlProfilerDataModel.traceStartTime();
|
||||||
zoomControl.setRange(newStartTime, newEndTime);
|
zoomControl.setRange(newStartTime, newEndTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,7 +420,8 @@ Rectangle {
|
|||||||
if (start !== startTime || end !== endTime) {
|
if (start !== startTime || end !== endTime) {
|
||||||
startTime = start;
|
startTime = start;
|
||||||
endTime = end;
|
endTime = end;
|
||||||
var newStartX = (startTime - qmlEventList.traceStartTime()) * flick.width / (endTime-startTime);
|
var newStartX = (startTime - qmlProfilerDataModel.traceStartTime()) *
|
||||||
|
flick.width / (endTime-startTime);
|
||||||
if (Math.abs(newStartX - startX) >= 1)
|
if (Math.abs(newStartX - startX) >= 1)
|
||||||
startX = newStartX;
|
startX = newStartX;
|
||||||
}
|
}
|
||||||
@@ -428,24 +430,25 @@ Rectangle {
|
|||||||
onSelectedItemChanged: {
|
onSelectedItemChanged: {
|
||||||
if (selectedItem !== -1) {
|
if (selectedItem !== -1) {
|
||||||
// display details
|
// display details
|
||||||
rangeDetails.duration = qmlEventList.getDuration(selectedItem)/1000.0;
|
rangeDetails.duration = qmlProfilerDataModel.getDuration(selectedItem)/1000.0;
|
||||||
rangeDetails.label = qmlEventList.getDetails(selectedItem);
|
rangeDetails.label = qmlProfilerDataModel.getDetails(selectedItem);
|
||||||
rangeDetails.file = qmlEventList.getFilename(selectedItem);
|
rangeDetails.file = qmlProfilerDataModel.getFilename(selectedItem);
|
||||||
rangeDetails.line = qmlEventList.getLine(selectedItem);
|
rangeDetails.line = qmlProfilerDataModel.getLine(selectedItem);
|
||||||
rangeDetails.column = qmlEventList.getColumn(selectedItem);
|
rangeDetails.column = qmlProfilerDataModel.getColumn(selectedItem);
|
||||||
rangeDetails.type = root.names[qmlEventList.getType(selectedItem)];
|
rangeDetails.type = root.names[qmlProfilerDataModel.getType(selectedItem)];
|
||||||
rangeDetails.isBindingLoop = qmlEventList.getBindingLoopDest(selectedItem)!==-1;
|
rangeDetails.isBindingLoop = qmlProfilerDataModel.getBindingLoopDest(selectedItem)!==-1;
|
||||||
|
|
||||||
rangeDetails.visible = true;
|
rangeDetails.visible = true;
|
||||||
|
|
||||||
// center view (horizontally)
|
// center view (horizontally)
|
||||||
var windowLength = view.endTime - view.startTime;
|
var windowLength = view.endTime - view.startTime;
|
||||||
var eventStartTime = qmlEventList.getStartTime(selectedItem);
|
var eventStartTime = qmlProfilerDataModel.getStartTime(selectedItem);
|
||||||
var eventEndTime = eventStartTime + qmlEventList.getDuration(selectedItem);
|
var eventEndTime = eventStartTime +
|
||||||
|
qmlProfilerDataModel.getDuration(selectedItem);
|
||||||
|
|
||||||
if (eventEndTime < view.startTime || eventStartTime > view.endTime) {
|
if (eventEndTime < view.startTime || eventStartTime > view.endTime) {
|
||||||
var center = (eventStartTime + eventEndTime)/2;
|
var center = (eventStartTime + eventEndTime)/2;
|
||||||
var from = Math.min(qmlEventList.traceEndTime()-windowLength,
|
var from = Math.min(qmlProfilerDataModel.traceEndTime()-windowLength,
|
||||||
Math.max(0, Math.floor(center - windowLength/2)));
|
Math.max(0, Math.floor(center - windowLength/2)));
|
||||||
|
|
||||||
zoomControl.setRange(from, from + windowLength);
|
zoomControl.setRange(from, from + windowLength);
|
||||||
@@ -456,8 +459,10 @@ Rectangle {
|
|||||||
if (itemY < root.scrollY) {
|
if (itemY < root.scrollY) {
|
||||||
root.updateVerticalScroll(itemY);
|
root.updateVerticalScroll(itemY);
|
||||||
} else
|
} else
|
||||||
if (itemY + root.singleRowHeight > root.scrollY + root.candidateHeight) {
|
if (itemY + root.singleRowHeight >
|
||||||
root.updateVerticalScroll(itemY + root.singleRowHeight - root.candidateHeight);
|
root.scrollY + root.candidateHeight) {
|
||||||
|
root.updateVerticalScroll(itemY + root.singleRowHeight -
|
||||||
|
root.candidateHeight);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
root.hideRangeDetails();
|
root.hideRangeDetails();
|
||||||
@@ -466,14 +471,18 @@ Rectangle {
|
|||||||
|
|
||||||
onItemPressed: {
|
onItemPressed: {
|
||||||
if (pressedItem !== -1) {
|
if (pressedItem !== -1) {
|
||||||
root.gotoSourceLocation(qmlEventList.getFilename(pressedItem), qmlEventList.getLine(pressedItem), qmlEventList.getColumn(pressedItem));
|
root.gotoSourceLocation(qmlProfilerDataModel.getFilename(pressedItem),
|
||||||
|
qmlProfilerDataModel.getLine(pressedItem),
|
||||||
|
qmlProfilerDataModel.getColumn(pressedItem));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// hack to pass mouse events to the other mousearea if enabled
|
// hack to pass mouse events to the other mousearea if enabled
|
||||||
startDragArea: selectionRangeDrag.enabled ? selectionRangeDrag.x : -flick.contentX
|
startDragArea: selectionRangeDrag.enabled ? selectionRangeDrag.x :
|
||||||
|
-flick.contentX
|
||||||
endDragArea: selectionRangeDrag.enabled ?
|
endDragArea: selectionRangeDrag.enabled ?
|
||||||
selectionRangeDrag.x + selectionRangeDrag.width : -flick.contentX-1
|
selectionRangeDrag.x + selectionRangeDrag.width :
|
||||||
|
-flick.contentX-1
|
||||||
}
|
}
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: selectionRangeControl
|
id: selectionRangeControl
|
||||||
|
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
.pragma library
|
.pragma library
|
||||||
|
|
||||||
var qmlEventList = 0;
|
var qmlProfilerDataModel = 0;
|
||||||
|
|
||||||
//draw background of the graph
|
//draw background of the graph
|
||||||
function drawGraph(canvas, ctxt, region)
|
function drawGraph(canvas, ctxt, region)
|
||||||
@@ -44,7 +44,7 @@ function drawGraph(canvas, ctxt, region)
|
|||||||
//draw the actual data to be graphed
|
//draw the actual data to be graphed
|
||||||
function drawData(canvas, ctxt, region)
|
function drawData(canvas, ctxt, region)
|
||||||
{
|
{
|
||||||
if ((!qmlEventList) || qmlEventList.count() == 0)
|
if ((!qmlProfilerDataModel) || qmlProfilerDataModel.count() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var typeCount = 5;
|
var typeCount = 5;
|
||||||
@@ -53,17 +53,18 @@ function drawData(canvas, ctxt, region)
|
|||||||
var height = canvas.height - bump;
|
var height = canvas.height - bump;
|
||||||
var blockHeight = height / typeCount;
|
var blockHeight = height / typeCount;
|
||||||
|
|
||||||
var spacing = width / qmlEventList.traceDuration();
|
var spacing = width / qmlProfilerDataModel.traceDuration();
|
||||||
|
|
||||||
var highest = [0,0,0,0,0]; // note: change if typeCount changes
|
var highest = [0,0,0,0,0]; // note: change if typeCount changes
|
||||||
|
|
||||||
for (var ii = 0; ii < qmlEventList.count(); ++ii) {
|
for (var ii = 0; ii < qmlProfilerDataModel.count(); ++ii) {
|
||||||
|
|
||||||
var xx = (qmlEventList.getStartTime(ii) - qmlEventList.traceStartTime()) * spacing;
|
var xx = (qmlProfilerDataModel.getStartTime(ii) -
|
||||||
|
qmlProfilerDataModel.traceStartTime()) * spacing;
|
||||||
if (xx > region.x + region.width)
|
if (xx > region.x + region.width)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var eventWidth = qmlEventList.getDuration(ii) * spacing;
|
var eventWidth = qmlProfilerDataModel.getDuration(ii) * spacing;
|
||||||
if (xx + eventWidth < region.x)
|
if (xx + eventWidth < region.x)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -71,24 +72,26 @@ function drawData(canvas, ctxt, region)
|
|||||||
eventWidth = 1;
|
eventWidth = 1;
|
||||||
|
|
||||||
xx = Math.round(xx);
|
xx = Math.round(xx);
|
||||||
var ty = qmlEventList.getType(ii);
|
var ty = qmlProfilerDataModel.getType(ii);
|
||||||
if (xx + eventWidth > highest[ty]) {
|
if (xx + eventWidth > highest[ty]) {
|
||||||
// special: animations
|
// special: animations
|
||||||
if (ty === 0 && qmlEventList.getAnimationCount(ii) >= 0) {
|
if (ty === 0 && qmlProfilerDataModel.getAnimationCount(ii) >= 0) {
|
||||||
var vertScale = qmlEventList.getMaximumAnimationCount() - qmlEventList.getMinimumAnimationCount();
|
var vertScale = qmlProfilerDataModel.getMaximumAnimationCount() -
|
||||||
|
qmlProfilerDataModel.getMinimumAnimationCount();
|
||||||
if (vertScale < 1)
|
if (vertScale < 1)
|
||||||
vertScale = 1;
|
vertScale = 1;
|
||||||
var fraction = (qmlEventList.getAnimationCount(ii) - qmlEventList.getMinimumAnimationCount()) / vertScale;
|
var fraction = (qmlProfilerDataModel.getAnimationCount(ii) -
|
||||||
|
qmlProfilerDataModel.getMinimumAnimationCount()) / vertScale;
|
||||||
var eventHeight = blockHeight * (fraction * 0.85 + 0.15);
|
var eventHeight = blockHeight * (fraction * 0.85 + 0.15);
|
||||||
var yy = bump + ty*blockHeight + blockHeight - eventHeight;
|
var yy = bump + ty*blockHeight + blockHeight - eventHeight;
|
||||||
|
|
||||||
var fpsFraction = qmlEventList.getFramerate(ii) / 60.0;
|
var fpsFraction = qmlProfilerDataModel.getFramerate(ii) / 60.0;
|
||||||
if (fpsFraction > 1.0)
|
if (fpsFraction > 1.0)
|
||||||
fpsFraction = 1.0;
|
fpsFraction = 1.0;
|
||||||
ctxt.fillStyle = "hsl("+(fpsFraction*0.27+0.028)+",0.3,0.65)";
|
ctxt.fillStyle = "hsl("+(fpsFraction*0.27+0.028)+",0.3,0.65)";
|
||||||
ctxt.fillRect(xx, yy, eventWidth, eventHeight);
|
ctxt.fillRect(xx, yy, eventWidth, eventHeight);
|
||||||
} else {
|
} else {
|
||||||
var hue = ( qmlEventList.getEventId(ii) * 25 ) % 360;
|
var hue = ( qmlProfilerDataModel.getEventId(ii) * 25 ) % 360;
|
||||||
ctxt.fillStyle = "hsl("+(hue/360.0+0.001)+",0.3,0.65)";
|
ctxt.fillStyle = "hsl("+(hue/360.0+0.001)+",0.3,0.65)";
|
||||||
ctxt.fillRect(xx, bump + ty*blockHeight, eventWidth, blockHeight);
|
ctxt.fillRect(xx, bump + ty*blockHeight, eventWidth, blockHeight);
|
||||||
}
|
}
|
||||||
@@ -100,12 +103,13 @@ function drawData(canvas, ctxt, region)
|
|||||||
ctxt.strokeStyle = "orange";
|
ctxt.strokeStyle = "orange";
|
||||||
ctxt.lineWidth = 2;
|
ctxt.lineWidth = 2;
|
||||||
var radius = 1;
|
var radius = 1;
|
||||||
for (var ii = 0; ii < qmlEventList.count(); ++ii) {
|
for (var ii = 0; ii < qmlProfilerDataModel.count(); ++ii) {
|
||||||
if (qmlEventList.getBindingLoopDest(ii) >= 0) {
|
if (qmlProfilerDataModel.getBindingLoopDest(ii) >= 0) {
|
||||||
var xcenter = Math.round(qmlEventList.getStartTime(ii) +
|
var xcenter = Math.round(qmlProfilerDataModel.getStartTime(ii) +
|
||||||
qmlEventList.getDuration(ii) -
|
qmlProfilerDataModel.getDuration(ii) -
|
||||||
qmlEventList.traceStartTime()) * spacing;
|
qmlProfilerDataModel.traceStartTime()) * spacing;
|
||||||
var ycenter = Math.round(bump + qmlEventList.getType(ii) * blockHeight + blockHeight/2);
|
var ycenter = Math.round(bump + qmlProfilerDataModel.getType(ii) *
|
||||||
|
blockHeight + blockHeight/2);
|
||||||
ctxt.arc(xcenter, ycenter, radius, 0, 2*Math.PI, true);
|
ctxt.arc(xcenter, ycenter, radius, 0, 2*Math.PI, true);
|
||||||
ctxt.stroke();
|
ctxt.stroke();
|
||||||
}
|
}
|
||||||
@@ -114,19 +118,20 @@ function drawData(canvas, ctxt, region)
|
|||||||
|
|
||||||
function drawTimeBar(canvas, ctxt, region)
|
function drawTimeBar(canvas, ctxt, region)
|
||||||
{
|
{
|
||||||
if (!qmlEventList)
|
if (!qmlProfilerDataModel)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var width = canvas.width;
|
var width = canvas.width;
|
||||||
var height = 10;
|
var height = 10;
|
||||||
var startTime = qmlEventList.traceStartTime();
|
var startTime = qmlProfilerDataModel.traceStartTime();
|
||||||
var endTime = qmlEventList.traceEndTime();
|
var endTime = qmlProfilerDataModel.traceEndTime();
|
||||||
|
|
||||||
var totalTime = qmlEventList.traceDuration();
|
var totalTime = qmlProfilerDataModel.traceDuration();
|
||||||
var spacing = width / totalTime;
|
var spacing = width / totalTime;
|
||||||
|
|
||||||
var initialBlockLength = 120;
|
var initialBlockLength = 120;
|
||||||
var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / width * initialBlockLength ) / Math.LN2 ) );
|
var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / width *
|
||||||
|
initialBlockLength ) / Math.LN2 ) );
|
||||||
var pixelsPerBlock = timePerBlock * spacing;
|
var pixelsPerBlock = timePerBlock * spacing;
|
||||||
var pixelsPerSection = pixelsPerBlock / 5;
|
var pixelsPerSection = pixelsPerBlock / 5;
|
||||||
var blockCount = width / pixelsPerBlock;
|
var blockCount = width / pixelsPerBlock;
|
||||||
|
@@ -51,8 +51,8 @@ Canvas2D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateRange() {
|
function updateRange() {
|
||||||
var newStartTime = Math.round(rangeMover.x * qmlEventList.traceDuration() / width) + qmlEventList.traceStartTime();
|
var newStartTime = Math.round(rangeMover.x * qmlProfilerDataModel.traceDuration() / width) + qmlProfilerDataModel.traceStartTime();
|
||||||
var newEndTime = Math.round((rangeMover.x + rangeMover.width) * qmlEventList.traceDuration() / width) + qmlEventList.traceStartTime();
|
var newEndTime = Math.round((rangeMover.x + rangeMover.width) * qmlProfilerDataModel.traceDuration() / width) + qmlProfilerDataModel.traceStartTime();
|
||||||
if (startTime !== newStartTime || endTime !== newEndTime) {
|
if (startTime !== newStartTime || endTime !== newEndTime) {
|
||||||
zoomControl.setRange(newStartTime, newEndTime);
|
zoomControl.setRange(newStartTime, newEndTime);
|
||||||
}
|
}
|
||||||
@@ -62,13 +62,13 @@ Canvas2D {
|
|||||||
Connections {
|
Connections {
|
||||||
target: zoomControl
|
target: zoomControl
|
||||||
onRangeChanged: {
|
onRangeChanged: {
|
||||||
if (qmlEventList) {
|
if (qmlProfilerDataModel) {
|
||||||
startTime = zoomControl.startTime();
|
startTime = zoomControl.startTime();
|
||||||
endTime = zoomControl.endTime();
|
endTime = zoomControl.endTime();
|
||||||
var newRangeX = (startTime - qmlEventList.traceStartTime()) * width / qmlEventList.traceDuration();
|
var newRangeX = (startTime - qmlProfilerDataModel.traceStartTime()) * width / qmlProfilerDataModel.traceDuration();
|
||||||
if (rangeMover.x !== newRangeX)
|
if (rangeMover.x !== newRangeX)
|
||||||
rangeMover.x = newRangeX;
|
rangeMover.x = newRangeX;
|
||||||
var newWidth = (endTime-startTime) * width / qmlEventList.traceDuration();
|
var newWidth = (endTime-startTime) * width / qmlProfilerDataModel.traceDuration();
|
||||||
if (rangeMover.width !== newWidth)
|
if (rangeMover.width !== newWidth)
|
||||||
rangeMover.width = newWidth;
|
rangeMover.width = newWidth;
|
||||||
}
|
}
|
||||||
@@ -76,10 +76,10 @@ Canvas2D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: qmlEventList
|
target: qmlProfilerDataModel
|
||||||
onStateChanged: {
|
onStateChanged: {
|
||||||
// State is "done"
|
// State is "done"
|
||||||
if (qmlEventList.getCurrentStateFromQml() == 3) {
|
if (qmlProfilerDataModel.getCurrentStateFromQml() == 3) {
|
||||||
dataAvailable = true;
|
dataAvailable = true;
|
||||||
requestRedraw();
|
requestRedraw();
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ Canvas2D {
|
|||||||
|
|
||||||
// ***** slots
|
// ***** slots
|
||||||
onDrawRegion: {
|
onDrawRegion: {
|
||||||
Plotter.qmlEventList = qmlEventList;
|
Plotter.qmlProfilerDataModel = qmlProfilerDataModel;
|
||||||
if (dataAvailable) {
|
if (dataAvailable) {
|
||||||
Plotter.plot(canvas, ctxt, region);
|
Plotter.plot(canvas, ctxt, region);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -50,7 +50,7 @@ Rectangle {
|
|||||||
property string endTimeString: detailedPrintTime(startTime+duration)
|
property string endTimeString: detailedPrintTime(startTime+duration)
|
||||||
property string durationString: detailedPrintTime(duration)
|
property string durationString: detailedPrintTime(duration)
|
||||||
|
|
||||||
property variant startTime: x * selectionRange.viewTimePerPixel + qmlEventList.traceStartTime()
|
property variant startTime: x * selectionRange.viewTimePerPixel + qmlProfilerDataModel.traceStartTime()
|
||||||
property variant duration: width * selectionRange.viewTimePerPixel
|
property variant duration: width * selectionRange.viewTimePerPixel
|
||||||
property variant viewTimePerPixel: 1
|
property variant viewTimePerPixel: 1
|
||||||
property variant creationState : 0
|
property variant creationState : 0
|
||||||
|
@@ -69,7 +69,7 @@ Item {
|
|||||||
states: [
|
states: [
|
||||||
// no data available
|
// no data available
|
||||||
State {
|
State {
|
||||||
when: (root.eventCount == 0) && !elapsedTimer.running
|
when: (root.eventCount == 0) && !root.recordingEnabled
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: statusDisplay
|
target: statusDisplay
|
||||||
visible: true
|
visible: true
|
||||||
@@ -85,7 +85,7 @@ Item {
|
|||||||
},
|
},
|
||||||
// running app
|
// running app
|
||||||
State {
|
State {
|
||||||
when: elapsedTimer.running
|
when: root.recordingEnabled
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: statusDisplay
|
target: statusDisplay
|
||||||
visible: true
|
visible: true
|
||||||
@@ -99,7 +99,7 @@ Item {
|
|||||||
// loading data
|
// loading data
|
||||||
State {
|
State {
|
||||||
name: "loading"
|
name: "loading"
|
||||||
when: (!root.dataAvailable) && (root.eventCount > 0) && !root.applicationDied
|
when: !root.dataAvailable && (root.eventCount > 0) && !root.appKilled
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: statusDisplay
|
target: statusDisplay
|
||||||
visible: true
|
visible: true
|
||||||
@@ -118,7 +118,7 @@ Item {
|
|||||||
// application died
|
// application died
|
||||||
State {
|
State {
|
||||||
name: "deadApp"
|
name: "deadApp"
|
||||||
when: (!root.dataAvailable) && (root.eventCount > 0) && root.applicationDied
|
when: !root.dataAvailable && (root.eventCount > 0) && root.appKilled
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: statusDisplay
|
target: statusDisplay
|
||||||
visible: true
|
visible: true
|
||||||
|
@@ -91,15 +91,15 @@ Canvas2D {
|
|||||||
|
|
||||||
// gray off out-of-bounds areas
|
// gray off out-of-bounds areas
|
||||||
var rectWidth;
|
var rectWidth;
|
||||||
if (startTime < qmlEventList.traceStartTime()) {
|
if (startTime < qmlProfilerDataModel.traceStartTime()) {
|
||||||
ctxt.fillStyle = "rgba(127,127,127,0.2)";
|
ctxt.fillStyle = "rgba(127,127,127,0.2)";
|
||||||
rectWidth = (qmlEventList.traceStartTime() - startTime) * spacing;
|
rectWidth = (qmlProfilerDataModel.traceStartTime() - startTime) * spacing;
|
||||||
ctxt.fillRect(0, 0, rectWidth, height);
|
ctxt.fillRect(0, 0, rectWidth, height);
|
||||||
}
|
}
|
||||||
if (endTime > qmlEventList.traceEndTime()) {
|
if (endTime > qmlProfilerDataModel.traceEndTime()) {
|
||||||
ctxt.fillStyle = "rgba(127,127,127,0.2)";
|
ctxt.fillStyle = "rgba(127,127,127,0.2)";
|
||||||
var rectX = (qmlEventList.traceEndTime() - startTime) * spacing;
|
var rectX = (qmlProfilerDataModel.traceEndTime() - startTime) * spacing;
|
||||||
rectWidth = (endTime - qmlEventList.traceEndTime()) * spacing;
|
rectWidth = (endTime - qmlProfilerDataModel.traceEndTime()) * spacing;
|
||||||
ctxt.fillRect(rectX, 0, rectWidth, height);
|
ctxt.fillRect(rectX, 0, rectWidth, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,8 +126,8 @@ Canvas2D {
|
|||||||
var cumulatedHeight = 0;
|
var cumulatedHeight = 0;
|
||||||
for (var i=0; i<labels.rowCount; i++) {
|
for (var i=0; i<labels.rowCount; i++) {
|
||||||
cumulatedHeight += root.singleRowHeight + (labels.rowExpanded[i] ?
|
cumulatedHeight += root.singleRowHeight + (labels.rowExpanded[i] ?
|
||||||
qmlEventList.uniqueEventsOfType(i) * root.singleRowHeight :
|
qmlProfilerDataModel.uniqueEventsOfType(i) * root.singleRowHeight :
|
||||||
qmlEventList.maxNestingForType(i) * root.singleRowHeight);
|
qmlProfilerDataModel.maxNestingForType(i) * root.singleRowHeight);
|
||||||
|
|
||||||
ctxt.strokeStyle = "#B0B0B0";
|
ctxt.strokeStyle = "#B0B0B0";
|
||||||
ctxt.beginPath();
|
ctxt.beginPath();
|
||||||
|
@@ -24,14 +24,19 @@ SOURCES += \
|
|||||||
qmlprofilerplugin.cpp \
|
qmlprofilerplugin.cpp \
|
||||||
qmlprofilertool.cpp \
|
qmlprofilertool.cpp \
|
||||||
qmlprofilerengine.cpp \
|
qmlprofilerengine.cpp \
|
||||||
tracewindow.cpp \
|
|
||||||
timelineview.cpp \
|
|
||||||
qmlprofilerattachdialog.cpp \
|
qmlprofilerattachdialog.cpp \
|
||||||
localqmlprofilerrunner.cpp \
|
localqmlprofilerrunner.cpp \
|
||||||
codaqmlprofilerrunner.cpp \
|
codaqmlprofilerrunner.cpp \
|
||||||
remotelinuxqmlprofilerrunner.cpp \
|
remotelinuxqmlprofilerrunner.cpp \
|
||||||
qmlprofilereventview.cpp \
|
qmlprofilereventview.cpp \
|
||||||
qmlprofilerdetailsrewriter.cpp
|
qmlprofilerdetailsrewriter.cpp \
|
||||||
|
qmlprofilertraceview.cpp \
|
||||||
|
timelinerenderer.cpp \
|
||||||
|
qmlprofilerstatemanager.cpp \
|
||||||
|
qv8profilerdatamodel.cpp \
|
||||||
|
qmlprofilerdatamodel.cpp \
|
||||||
|
qmlprofilerclientmanager.cpp \
|
||||||
|
qmlprofilerviewmanager.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
qmlprofilerconstants.h \
|
qmlprofilerconstants.h \
|
||||||
@@ -39,22 +44,26 @@ HEADERS += \
|
|||||||
qmlprofilerplugin.h \
|
qmlprofilerplugin.h \
|
||||||
qmlprofilertool.h \
|
qmlprofilertool.h \
|
||||||
qmlprofilerengine.h \
|
qmlprofilerengine.h \
|
||||||
tracewindow.h \
|
|
||||||
timelineview.h \
|
|
||||||
qmlprofilerattachdialog.h \
|
qmlprofilerattachdialog.h \
|
||||||
abstractqmlprofilerrunner.h \
|
abstractqmlprofilerrunner.h \
|
||||||
localqmlprofilerrunner.h \
|
localqmlprofilerrunner.h \
|
||||||
codaqmlprofilerrunner.h \
|
codaqmlprofilerrunner.h \
|
||||||
remotelinuxqmlprofilerrunner.h \
|
remotelinuxqmlprofilerrunner.h \
|
||||||
qmlprofilereventview.h \
|
qmlprofilereventview.h \
|
||||||
qmlprofilerdetailsrewriter.h
|
qmlprofilerdetailsrewriter.h \
|
||||||
|
qmlprofilertraceview.h \
|
||||||
|
timelinerenderer.h \
|
||||||
|
qmlprofilerstatemanager.h \
|
||||||
|
qv8profilerdatamodel.h \
|
||||||
|
qmlprofilerdatamodel.h \
|
||||||
|
qmlprofilerclientmanager.h \
|
||||||
|
qmlprofilerviewmanager.h
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
qml/qmlprofiler.qrc
|
qml/qmlprofiler.qrc
|
||||||
|
|
||||||
OTHER_FILES += \
|
OTHER_FILES += \
|
||||||
qml/Detail.qml \
|
qml/Detail.qml \
|
||||||
qml/Elapsed.qml \
|
|
||||||
qml/Label.qml \
|
qml/Label.qml \
|
||||||
qml/MainView.qml \
|
qml/MainView.qml \
|
||||||
qml/RangeDetails.qml \
|
qml/RangeDetails.qml \
|
||||||
@@ -64,8 +73,7 @@ OTHER_FILES += \
|
|||||||
qml/StatusDisplay.qml \
|
qml/StatusDisplay.qml \
|
||||||
qml/SelectionRange.qml \
|
qml/SelectionRange.qml \
|
||||||
qml/SelectionRangeDetails.qml \
|
qml/SelectionRangeDetails.qml \
|
||||||
qml/Overview.qml \
|
qml/Overview.qml
|
||||||
qml/Overview.js
|
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
qmlprofilerattachdialog.ui
|
qmlprofilerattachdialog.ui
|
||||||
|
@@ -35,27 +35,37 @@ QtcPlugin {
|
|||||||
"codaqmlprofilerrunner.h",
|
"codaqmlprofilerrunner.h",
|
||||||
"localqmlprofilerrunner.cpp",
|
"localqmlprofilerrunner.cpp",
|
||||||
"localqmlprofilerrunner.h",
|
"localqmlprofilerrunner.h",
|
||||||
"qmlprofiler_global.h",
|
|
||||||
"qmlprofilerattachdialog.cpp",
|
"qmlprofilerattachdialog.cpp",
|
||||||
"qmlprofilerattachdialog.h",
|
"qmlprofilerattachdialog.h",
|
||||||
"qmlprofilerattachdialog.ui",
|
"qmlprofilerattachdialog.ui",
|
||||||
|
"qmlprofilerclientmanager.cpp",
|
||||||
|
"qmlprofilerclientmanager.h",
|
||||||
"qmlprofilerconstants.h",
|
"qmlprofilerconstants.h",
|
||||||
|
"qmlprofilerdatamodel.cpp",
|
||||||
|
"qmlprofilerdatamodel.h",
|
||||||
"qmlprofilerdetailsrewriter.cpp",
|
"qmlprofilerdetailsrewriter.cpp",
|
||||||
"qmlprofilerdetailsrewriter.h",
|
"qmlprofilerdetailsrewriter.h",
|
||||||
"qmlprofilerengine.cpp",
|
"qmlprofilerengine.cpp",
|
||||||
"qmlprofilerengine.h",
|
"qmlprofilerengine.h",
|
||||||
"qmlprofilereventview.cpp",
|
"qmlprofilereventview.cpp",
|
||||||
"qmlprofilereventview.h",
|
"qmlprofilereventview.h",
|
||||||
|
"qmlprofiler_global.h",
|
||||||
"qmlprofilerplugin.cpp",
|
"qmlprofilerplugin.cpp",
|
||||||
"qmlprofilerplugin.h",
|
"qmlprofilerplugin.h",
|
||||||
|
"qmlprofilerstatemanager.cpp",
|
||||||
|
"qmlprofilerstatemanager.h",
|
||||||
"qmlprofilertool.cpp",
|
"qmlprofilertool.cpp",
|
||||||
"qmlprofilertool.h",
|
"qmlprofilertool.h",
|
||||||
|
"qmlprofilertraceview.cpp",
|
||||||
|
"qmlprofilertraceview.h",
|
||||||
|
"qmlprofilerviewmanager.cpp",
|
||||||
|
"qmlprofilerviewmanager.h",
|
||||||
|
"qv8profilerdatamodel.cpp",
|
||||||
|
"qv8profilerdatamodel.h",
|
||||||
"remotelinuxqmlprofilerrunner.cpp",
|
"remotelinuxqmlprofilerrunner.cpp",
|
||||||
"remotelinuxqmlprofilerrunner.h",
|
"remotelinuxqmlprofilerrunner.h",
|
||||||
"timelineview.cpp",
|
"timelinerenderer.cpp",
|
||||||
"timelineview.h",
|
"timelinerenderer.h",
|
||||||
"tracewindow.cpp",
|
|
||||||
"tracewindow.h",
|
|
||||||
"canvas/qdeclarativecanvas.cpp",
|
"canvas/qdeclarativecanvas.cpp",
|
||||||
"canvas/qdeclarativecanvas_p.h",
|
"canvas/qdeclarativecanvas_p.h",
|
||||||
"canvas/qdeclarativecanvastimer.cpp",
|
"canvas/qdeclarativecanvastimer.cpp",
|
||||||
@@ -75,7 +85,8 @@ QtcPlugin {
|
|||||||
"qml/StatusDisplay.qml",
|
"qml/StatusDisplay.qml",
|
||||||
"qml/TimeDisplay.qml",
|
"qml/TimeDisplay.qml",
|
||||||
"qml/TimeMarks.qml",
|
"qml/TimeMarks.qml",
|
||||||
"qml/qmlprofiler.qrc"
|
"qml/qmlprofiler.qrc",
|
||||||
|
"qml/Overview.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
426
src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp
Normal file
426
src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp
Normal file
@@ -0,0 +1,426 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "qmlprofilerclientmanager.h"
|
||||||
|
#include "qmlprofilertool.h"
|
||||||
|
#include "qmlprofilerplugin.h"
|
||||||
|
|
||||||
|
#include <qmljsdebugclient/qdeclarativedebugclient.h>
|
||||||
|
#include <qmljsdebugclient/qmlprofilertraceclient.h>
|
||||||
|
#include <qmljsdebugclient/qv8profilerclient.h>
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <QWeakPointer>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
using namespace QmlJsDebugClient;
|
||||||
|
using namespace Core;
|
||||||
|
|
||||||
|
namespace QmlProfiler {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class QmlProfilerClientManager::QmlProfilerClientManagerPrivate {
|
||||||
|
public:
|
||||||
|
QmlProfilerClientManagerPrivate(QmlProfilerClientManager *qq) { Q_UNUSED(qq); }
|
||||||
|
|
||||||
|
QmlProfilerStateManager* profilerState;
|
||||||
|
|
||||||
|
QDeclarativeDebugConnection *connection;
|
||||||
|
QWeakPointer<QmlProfilerTraceClient> qmlclientplugin;
|
||||||
|
QWeakPointer<QV8ProfilerClient> v8clientplugin;
|
||||||
|
|
||||||
|
QTimer connectionTimer;
|
||||||
|
int connectionAttempts;
|
||||||
|
|
||||||
|
enum ConnectMode {
|
||||||
|
TcpConnection, OstConnection
|
||||||
|
};
|
||||||
|
ConnectMode connectMode;
|
||||||
|
QString tcpHost;
|
||||||
|
quint64 tcpPort;
|
||||||
|
QString ostDevice;
|
||||||
|
QString sysroot;
|
||||||
|
|
||||||
|
bool v8DataReady;
|
||||||
|
bool qmlDataReady;
|
||||||
|
};
|
||||||
|
|
||||||
|
QmlProfilerClientManager::QmlProfilerClientManager(QObject *parent) :
|
||||||
|
QObject(parent), d(new QmlProfilerClientManagerPrivate(this))
|
||||||
|
{
|
||||||
|
setObjectName("QML Profiler Connections");
|
||||||
|
|
||||||
|
d->profilerState = 0;
|
||||||
|
|
||||||
|
d->connection = 0;
|
||||||
|
d->connectionAttempts = 0;
|
||||||
|
d->v8DataReady = false;
|
||||||
|
d->qmlDataReady = false;
|
||||||
|
|
||||||
|
d->connectionTimer.setInterval(200);
|
||||||
|
connect(&d->connectionTimer, SIGNAL(timeout()), SLOT(tryToConnect()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlProfilerClientManager::~QmlProfilerClientManager()
|
||||||
|
{
|
||||||
|
disconnectClientSignals();
|
||||||
|
delete d->connection;
|
||||||
|
delete d->qmlclientplugin.data();
|
||||||
|
delete d->v8clientplugin.data();
|
||||||
|
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// Interface
|
||||||
|
void QmlProfilerClientManager::setTcpConnection(QString host, quint64 port)
|
||||||
|
{
|
||||||
|
d->connectMode = QmlProfilerClientManagerPrivate::TcpConnection;
|
||||||
|
d->tcpHost = host;
|
||||||
|
d->tcpPort = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::setOstConnection(QString ostDevice)
|
||||||
|
{
|
||||||
|
d->connectMode = QmlProfilerClientManagerPrivate::OstConnection;
|
||||||
|
d->ostDevice = ostDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::clearBufferedData()
|
||||||
|
{
|
||||||
|
if (d->qmlclientplugin)
|
||||||
|
d->qmlclientplugin.data()->clearData();
|
||||||
|
if (d->v8clientplugin)
|
||||||
|
d->v8clientplugin.data()->clearData();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// Internal
|
||||||
|
void QmlProfilerClientManager::connectClient(quint16 port)
|
||||||
|
{
|
||||||
|
if (d->connection)
|
||||||
|
delete d->connection;
|
||||||
|
d->connection = new QDeclarativeDebugConnection;
|
||||||
|
enableServices();
|
||||||
|
connect(d->connection, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
|
||||||
|
this, SLOT(connectionStateChanged()));
|
||||||
|
d->connectionTimer.start();
|
||||||
|
d->tcpPort = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::enableServices()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(d->profilerState, return);
|
||||||
|
|
||||||
|
disconnectClientSignals();
|
||||||
|
d->profilerState->setServerRecording(false); // false by default (will be set to true when connected)
|
||||||
|
delete d->qmlclientplugin.data();
|
||||||
|
d->qmlclientplugin = new QmlProfilerTraceClient(d->connection);
|
||||||
|
delete d->v8clientplugin.data();
|
||||||
|
d->v8clientplugin = new QV8ProfilerClient(d->connection);
|
||||||
|
connectClientSignals();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::connectClientSignals()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(d->profilerState, return);
|
||||||
|
if (d->qmlclientplugin) {
|
||||||
|
connect(d->qmlclientplugin.data(), SIGNAL(complete()),
|
||||||
|
this, SLOT(qmlComplete()));
|
||||||
|
connect(d->qmlclientplugin.data(),
|
||||||
|
SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)),
|
||||||
|
this,
|
||||||
|
SIGNAL(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
|
||||||
|
connect(d->qmlclientplugin.data(), SIGNAL(traceFinished(qint64)),
|
||||||
|
this, SIGNAL(traceFinished(qint64)));
|
||||||
|
connect(d->qmlclientplugin.data(), SIGNAL(traceStarted(qint64)),
|
||||||
|
this, SIGNAL(traceStarted(qint64)));
|
||||||
|
connect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)),
|
||||||
|
this, SIGNAL(addFrameEvent(qint64,int,int)));
|
||||||
|
connect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()),
|
||||||
|
d->qmlclientplugin.data(), SLOT(sendRecordingStatus()));
|
||||||
|
// fixme: this should be unified for both clients
|
||||||
|
connect(d->qmlclientplugin.data(), SIGNAL(recordingChanged(bool)),
|
||||||
|
d->profilerState, SLOT(setServerRecording(bool)));
|
||||||
|
}
|
||||||
|
if (d->v8clientplugin) {
|
||||||
|
connect(d->v8clientplugin.data(), SIGNAL(complete()), this, SLOT(v8Complete()));
|
||||||
|
connect(d->v8clientplugin.data(),
|
||||||
|
SIGNAL(v8range(int,QString,QString,int,double,double)),
|
||||||
|
this,
|
||||||
|
SIGNAL(addV8Event(int,QString,QString,int,double,double)));
|
||||||
|
connect(d->v8clientplugin.data(), SIGNAL(enabledChanged()),
|
||||||
|
d->v8clientplugin.data(), SLOT(sendRecordingStatus()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::disconnectClientSignals()
|
||||||
|
{
|
||||||
|
if (d->qmlclientplugin) {
|
||||||
|
disconnect(d->qmlclientplugin.data(), SIGNAL(complete()),
|
||||||
|
this, SLOT(qmlComplete()));
|
||||||
|
disconnect(d->qmlclientplugin.data(),
|
||||||
|
SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)),
|
||||||
|
this,
|
||||||
|
SIGNAL(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
|
||||||
|
disconnect(d->qmlclientplugin.data(), SIGNAL(traceFinished(qint64)),
|
||||||
|
this, SIGNAL(traceFinished(qint64)));
|
||||||
|
disconnect(d->qmlclientplugin.data(), SIGNAL(traceStarted(qint64)),
|
||||||
|
this, SIGNAL(traceStarted(qint64)));
|
||||||
|
disconnect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)),
|
||||||
|
this, SIGNAL(addFrameEvent(qint64,int,int)));
|
||||||
|
disconnect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()),
|
||||||
|
d->qmlclientplugin.data(), SLOT(sendRecordingStatus()));
|
||||||
|
// fixme: this should be unified for both clients
|
||||||
|
disconnect(d->qmlclientplugin.data(), SIGNAL(recordingChanged(bool)),
|
||||||
|
d->profilerState, SLOT(setServerRecording(bool)));
|
||||||
|
}
|
||||||
|
if (d->v8clientplugin) {
|
||||||
|
disconnect(d->v8clientplugin.data(), SIGNAL(complete()), this, SLOT(v8Complete()));
|
||||||
|
disconnect(d->v8clientplugin.data(),
|
||||||
|
SIGNAL(v8range(int,QString,QString,int,double,double)),
|
||||||
|
this,
|
||||||
|
SIGNAL(addV8Event(int,QString,QString,int,double,double)));
|
||||||
|
disconnect(d->v8clientplugin.data(), SIGNAL(enabledChanged()),
|
||||||
|
d->v8clientplugin.data(), SLOT(sendRecordingStatus()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::connectToClient()
|
||||||
|
{
|
||||||
|
if (!d->connection || d->connection->state() != QAbstractSocket::UnconnectedState)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (d->connectMode == QmlProfilerClientManagerPrivate::TcpConnection) {
|
||||||
|
QmlProfilerTool::logStatus(QString("QML Profiler: Connecting to %1:%2 ...").arg(d->tcpHost, QString::number(d->tcpPort)));
|
||||||
|
d->connection->connectToHost(d->tcpHost, d->tcpPort);
|
||||||
|
} else {
|
||||||
|
QmlProfilerTool::logStatus(QString("QML Profiler: Connecting to %1 ...").arg(d->tcpHost));
|
||||||
|
d->connection->connectToOst(d->ostDevice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::disconnectClient()
|
||||||
|
{
|
||||||
|
// this might be actually be called indirectly by QDDConnectionPrivate::readyRead(), therefore allow
|
||||||
|
// method to complete before deleting object
|
||||||
|
if (d->connection) {
|
||||||
|
d->connection->deleteLater();
|
||||||
|
d->connection = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::tryToConnect()
|
||||||
|
{
|
||||||
|
++d->connectionAttempts;
|
||||||
|
|
||||||
|
if (d->connection && d->connection->isConnected()) {
|
||||||
|
d->connectionTimer.stop();
|
||||||
|
d->connectionAttempts = 0;
|
||||||
|
} else if (d->connectionAttempts == 50) {
|
||||||
|
d->connectionTimer.stop();
|
||||||
|
d->connectionAttempts = 0;
|
||||||
|
|
||||||
|
QMessageBox *infoBox = QmlProfilerTool::requestMessageBox();
|
||||||
|
infoBox->setIcon(QMessageBox::Critical);
|
||||||
|
infoBox->setWindowTitle(tr("Qt Creator"));
|
||||||
|
infoBox->setText(tr("Could not connect to the in-process QML profiler.\n"
|
||||||
|
"Do you want to retry?"));
|
||||||
|
infoBox->setStandardButtons(QMessageBox::Retry |
|
||||||
|
QMessageBox::Cancel |
|
||||||
|
QMessageBox::Help);
|
||||||
|
infoBox->setDefaultButton(QMessageBox::Retry);
|
||||||
|
infoBox->setModal(true);
|
||||||
|
|
||||||
|
connect(infoBox, SIGNAL(finished(int)),
|
||||||
|
this, SLOT(retryMessageBoxFinished(int)));
|
||||||
|
|
||||||
|
infoBox->show();
|
||||||
|
} else {
|
||||||
|
connectToClient();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::connectionStateChanged()
|
||||||
|
{
|
||||||
|
if (!d->connection)
|
||||||
|
return;
|
||||||
|
switch (d->connection->state()) {
|
||||||
|
case QAbstractSocket::UnconnectedState:
|
||||||
|
{
|
||||||
|
if (QmlProfilerPlugin::debugOutput)
|
||||||
|
qWarning("QML Profiler: disconnected");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QAbstractSocket::HostLookupState:
|
||||||
|
break;
|
||||||
|
case QAbstractSocket::ConnectingState: {
|
||||||
|
if (QmlProfilerPlugin::debugOutput)
|
||||||
|
qWarning("QML Profiler: Connecting to debug server ...");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QAbstractSocket::ConnectedState:
|
||||||
|
{
|
||||||
|
if (QmlProfilerPlugin::debugOutput)
|
||||||
|
qWarning("QML Profiler: connected and running");
|
||||||
|
// notify the client recording status
|
||||||
|
clientRecordingChanged();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QAbstractSocket::ClosingState:
|
||||||
|
if (QmlProfilerPlugin::debugOutput)
|
||||||
|
qWarning("QML Profiler: closing ...");
|
||||||
|
break;
|
||||||
|
case QAbstractSocket::BoundState:
|
||||||
|
case QAbstractSocket::ListeningState:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::retryMessageBoxFinished(int result)
|
||||||
|
{
|
||||||
|
switch (result) {
|
||||||
|
case QMessageBox::Retry: {
|
||||||
|
d->connectionAttempts = 0;
|
||||||
|
d->connectionTimer.start();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QMessageBox::Help: {
|
||||||
|
QmlProfilerTool::handleHelpRequest(QString("qthelp://com.nokia.qtcreator/doc/creator-debugging-qml.html"));
|
||||||
|
// fall through
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
if (d->connection) {
|
||||||
|
QmlProfilerTool::logStatus("QML Profiler: Failed to connect! " + d->connection->errorString());
|
||||||
|
} else {
|
||||||
|
QmlProfilerTool::logStatus("QML Profiler: Failed to connect!");
|
||||||
|
}
|
||||||
|
|
||||||
|
emit connectionFailed();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::qmlComplete()
|
||||||
|
{
|
||||||
|
d->qmlDataReady = true;
|
||||||
|
if (!d->v8clientplugin || d->v8clientplugin.data()->status() != QDeclarativeDebugClient::Enabled || d->v8DataReady) {
|
||||||
|
emit dataReadyForProcessing();
|
||||||
|
// once complete is sent, reset the flags
|
||||||
|
d->qmlDataReady = false;
|
||||||
|
d->v8DataReady = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::v8Complete()
|
||||||
|
{
|
||||||
|
d->v8DataReady = true;
|
||||||
|
if (!d->qmlclientplugin || d->qmlclientplugin.data()->status() != QDeclarativeDebugClient::Enabled || d->qmlDataReady) {
|
||||||
|
emit dataReadyForProcessing();
|
||||||
|
// once complete is sent, reset the flags
|
||||||
|
d->v8DataReady = false;
|
||||||
|
d->qmlDataReady = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::stopClientsRecording()
|
||||||
|
{
|
||||||
|
if (d->qmlclientplugin)
|
||||||
|
d->qmlclientplugin.data()->setRecording(false);
|
||||||
|
if (d->v8clientplugin)
|
||||||
|
d->v8clientplugin.data()->setRecording(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// Profiler State
|
||||||
|
void QmlProfilerClientManager::registerProfilerStateManager( QmlProfilerStateManager *profilerState )
|
||||||
|
{
|
||||||
|
if (d->profilerState) {
|
||||||
|
disconnect(d->profilerState, SIGNAL(stateChanged()),
|
||||||
|
this, SLOT(profilerStateChanged()));
|
||||||
|
disconnect(d->profilerState, SIGNAL(clientRecordingChanged()),
|
||||||
|
this, SLOT(clientRecordingChanged()));
|
||||||
|
disconnect(d->profilerState, SIGNAL(serverRecordingChanged()),
|
||||||
|
this, SLOT(serverRecordingChanged()));
|
||||||
|
}
|
||||||
|
|
||||||
|
d->profilerState = profilerState;
|
||||||
|
|
||||||
|
// connect
|
||||||
|
if (d->profilerState) {
|
||||||
|
connect(d->profilerState, SIGNAL(stateChanged()),
|
||||||
|
this, SLOT(profilerStateChanged()));
|
||||||
|
connect(d->profilerState, SIGNAL(clientRecordingChanged()),
|
||||||
|
this, SLOT(clientRecordingChanged()));
|
||||||
|
connect(d->profilerState, SIGNAL(serverRecordingChanged()),
|
||||||
|
this, SLOT(serverRecordingChanged()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::profilerStateChanged()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(d->profilerState, return);
|
||||||
|
switch (d->profilerState->currentState()) {
|
||||||
|
case QmlProfilerStateManager::AppStopRequested :
|
||||||
|
if (d->profilerState->serverRecording()) {
|
||||||
|
stopClientsRecording();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
d->profilerState->setCurrentState(QmlProfilerStateManager::AppReadyToStop);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::clientRecordingChanged()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(d->profilerState, return);
|
||||||
|
if (d->profilerState->currentState() == QmlProfilerStateManager::AppRunning) {
|
||||||
|
if (d->qmlclientplugin)
|
||||||
|
d->qmlclientplugin.data()->setRecording(d->profilerState->clientRecording());
|
||||||
|
if (d->v8clientplugin)
|
||||||
|
d->v8clientplugin.data()->setRecording(d->profilerState->clientRecording());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerClientManager::serverRecordingChanged()
|
||||||
|
{
|
||||||
|
if (d->profilerState->serverRecording()) {
|
||||||
|
d->v8DataReady = false;
|
||||||
|
d->qmlDataReady = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace QmlProfiler
|
102
src/plugins/qmlprofiler/qmlprofilerclientmanager.h
Normal file
102
src/plugins/qmlprofiler/qmlprofilerclientmanager.h
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QMLPROFILERCLIENTMANAGER_H
|
||||||
|
#define QMLPROFILERCLIENTMANAGER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include "qmlprofilerstatemanager.h"
|
||||||
|
#include <qmljsdebugclient/qmlprofilereventlocation.h>
|
||||||
|
|
||||||
|
namespace QmlProfiler {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class QmlProfilerClientManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit QmlProfilerClientManager(QObject *parent = 0);
|
||||||
|
~QmlProfilerClientManager();
|
||||||
|
|
||||||
|
void registerProfilerStateManager(QmlProfilerStateManager *profilerState);
|
||||||
|
|
||||||
|
void setTcpConnection(QString host, quint64 port);
|
||||||
|
void setOstConnection(QString ostDevice);
|
||||||
|
|
||||||
|
void clearBufferedData();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void connectionFailed();
|
||||||
|
|
||||||
|
// data
|
||||||
|
void addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation);
|
||||||
|
void addV8Event(int,QString,QString,int,double,double);
|
||||||
|
void addFrameEvent(qint64,int,int);
|
||||||
|
void traceStarted(qint64);
|
||||||
|
void traceFinished(qint64);
|
||||||
|
void dataReadyForProcessing();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void connectClient(quint16 port);
|
||||||
|
void disconnectClient();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void tryToConnect();
|
||||||
|
void connectionStateChanged();
|
||||||
|
void retryMessageBoxFinished(int result);
|
||||||
|
|
||||||
|
void qmlComplete();
|
||||||
|
void v8Complete();
|
||||||
|
|
||||||
|
void profilerStateChanged();
|
||||||
|
void clientRecordingChanged();
|
||||||
|
void serverRecordingChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class QmlProfilerClientManagerPrivate;
|
||||||
|
QmlProfilerClientManagerPrivate *d;
|
||||||
|
|
||||||
|
void connectToClient();
|
||||||
|
|
||||||
|
void enableServices();
|
||||||
|
void connectClientSignals();
|
||||||
|
void disconnectClientSignals();
|
||||||
|
|
||||||
|
void stopClientsRecording();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // QMLPROFILERCLIENTMANAGER_H
|
@@ -37,6 +37,7 @@ namespace QmlProfiler {
|
|||||||
namespace Constants {
|
namespace Constants {
|
||||||
|
|
||||||
const char ATTACH[] = "Menu.Analyzer.Attach";
|
const char ATTACH[] = "Menu.Analyzer.Attach";
|
||||||
|
const char TraceFileExtension[] = ".qtd";
|
||||||
|
|
||||||
} // namespace Constants
|
} // namespace Constants
|
||||||
} // namespace QmlProfiler
|
} // namespace QmlProfiler
|
||||||
|
1652
src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp
Normal file
1652
src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -30,33 +30,37 @@
|
|||||||
**
|
**
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#ifndef QMLPROFILEREVENTLIST_H
|
#ifndef QMLPROFILERDATAMODEL_H
|
||||||
#define QMLPROFILEREVENTLIST_H
|
#define QMLPROFILERDATAMODEL_H
|
||||||
|
|
||||||
#include "qmlprofilereventtypes.h"
|
#include <qmljsdebugclient/qmlprofilereventtypes.h>
|
||||||
#include "qmlprofilereventlocation.h"
|
#include <qmljsdebugclient/qmlprofilereventlocation.h>
|
||||||
#include "qmljsdebugclient_global.h"
|
#include "qv8profilerdatamodel.h"
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
namespace QmlJsDebugClient {
|
namespace QmlProfiler {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
struct QmlEventSub;
|
// used for parents and children
|
||||||
struct QV8EventSub;
|
struct QmlRangeEventRelative;
|
||||||
|
|
||||||
struct QMLJSDEBUGCLIENT_EXPORT QmlEventData
|
struct QmlRangeEventData
|
||||||
{
|
{
|
||||||
QmlEventData();
|
QmlRangeEventData();
|
||||||
~QmlEventData();
|
~QmlRangeEventData();
|
||||||
|
|
||||||
QString displayname;
|
int eventId;
|
||||||
|
QString displayName;
|
||||||
QString eventHashStr;
|
QString eventHashStr;
|
||||||
QString details;
|
QString details;
|
||||||
QmlEventLocation location;
|
QmlJsDebugClient::QmlEventLocation location;
|
||||||
QmlJsDebugClient::QmlEventType eventType;
|
QmlJsDebugClient::QmlEventType eventType;
|
||||||
QHash <QString, QmlEventSub *> parentHash;
|
|
||||||
QHash <QString, QmlEventSub *> childrenHash;
|
QHash <QString, QmlRangeEventRelative *> parentHash;
|
||||||
|
QHash <QString, QmlRangeEventRelative *> childrenHash;
|
||||||
|
|
||||||
qint64 duration;
|
qint64 duration;
|
||||||
qint64 calls;
|
qint64 calls;
|
||||||
qint64 minTime;
|
qint64 minTime;
|
||||||
@@ -64,54 +68,22 @@ struct QMLJSDEBUGCLIENT_EXPORT QmlEventData
|
|||||||
double timePerCall;
|
double timePerCall;
|
||||||
double percentOfTime;
|
double percentOfTime;
|
||||||
qint64 medianTime;
|
qint64 medianTime;
|
||||||
int eventId;
|
|
||||||
bool isBindingLoop;
|
bool isBindingLoop;
|
||||||
|
|
||||||
QmlEventData &operator=(const QmlEventData &ref);
|
QmlRangeEventData &operator=(const QmlRangeEventData &ref);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QMLJSDEBUGCLIENT_EXPORT QmlEventSub {
|
struct QmlRangeEventRelative {
|
||||||
QmlEventSub(QmlEventData *from) : reference(from), duration(0), calls(0), inLoopPath(false) {}
|
QmlRangeEventRelative(QmlRangeEventData *from) : reference(from), duration(0), calls(0), inLoopPath(false) {}
|
||||||
QmlEventSub(QmlEventSub *from) : reference(from->reference), duration(from->duration), calls(from->calls), inLoopPath(from->inLoopPath) {}
|
QmlRangeEventRelative(QmlRangeEventRelative *from) : reference(from->reference), duration(from->duration), calls(from->calls), inLoopPath(from->inLoopPath) {}
|
||||||
QmlEventData *reference;
|
QmlRangeEventData *reference;
|
||||||
qint64 duration;
|
qint64 duration;
|
||||||
qint64 calls;
|
qint64 calls;
|
||||||
bool inLoopPath;
|
bool inLoopPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QMLJSDEBUGCLIENT_EXPORT QV8EventData
|
class QmlProfilerDataModel : public QObject
|
||||||
{
|
|
||||||
QV8EventData();
|
|
||||||
~QV8EventData();
|
|
||||||
|
|
||||||
QString displayName;
|
|
||||||
QString filename;
|
|
||||||
QString functionName;
|
|
||||||
int line;
|
|
||||||
double totalTime; // given in milliseconds
|
|
||||||
double totalPercent;
|
|
||||||
double selfTime;
|
|
||||||
double selfPercent;
|
|
||||||
QHash <QString, QV8EventSub *> parentHash;
|
|
||||||
QHash <QString, QV8EventSub *> childrenHash;
|
|
||||||
int eventId;
|
|
||||||
|
|
||||||
QV8EventData &operator=(const QV8EventData &ref);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct QMLJSDEBUGCLIENT_EXPORT QV8EventSub {
|
|
||||||
QV8EventSub(QV8EventData *from) : reference(from), totalTime(0) {}
|
|
||||||
QV8EventSub(QV8EventSub *from) : reference(from->reference), totalTime(from->totalTime) {}
|
|
||||||
|
|
||||||
QV8EventData *reference;
|
|
||||||
qint64 totalTime;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef QHash<QString, QmlEventData *> QmlEventHash;
|
|
||||||
typedef QList<QmlEventData *> QmlEventDescriptions;
|
|
||||||
typedef QList<QV8EventData *> QV8EventDescriptions;
|
|
||||||
|
|
||||||
class QMLJSDEBUGCLIENT_EXPORT QmlProfilerEventList : public QObject
|
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -122,23 +94,30 @@ public:
|
|||||||
Done
|
Done
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit QmlProfilerEventList(QObject *parent = 0);
|
explicit QmlProfilerDataModel(QObject *parent = 0);
|
||||||
~QmlProfilerEventList();
|
~QmlProfilerDataModel();
|
||||||
|
|
||||||
QmlEventDescriptions getEventDescriptions() const;
|
QList<QmlRangeEventData *> getEventDescriptions() const;
|
||||||
QmlEventData *eventDescription(int eventId) const;
|
QmlRangeEventData *eventDescription(int eventId) const;
|
||||||
const QV8EventDescriptions& getV8Events() const;
|
QList<QV8EventData *> getV8Events() const;
|
||||||
QV8EventData *v8EventDescription(int eventId) const;
|
QV8EventData *v8EventDescription(int eventId) const;
|
||||||
|
|
||||||
|
static QString getHashStringForQmlEvent(const QmlJsDebugClient::QmlEventLocation &location, int eventType);
|
||||||
|
static QString getHashStringForV8Event(const QString &displayName, const QString &function);
|
||||||
|
static QString rootEventName();
|
||||||
|
static QString rootEventDescription();
|
||||||
|
static QString qmlEventTypeAsString(QmlJsDebugClient::QmlEventType typeEnum);
|
||||||
|
static QmlJsDebugClient::QmlEventType qmlEventTypeAsEnum(const QString &typeString);
|
||||||
|
|
||||||
int findFirstIndex(qint64 startTime) const;
|
int findFirstIndex(qint64 startTime) const;
|
||||||
int findFirstIndexNoParents(qint64 startTime) const;
|
int findFirstIndexNoParents(qint64 startTime) const;
|
||||||
int findLastIndex(qint64 endTime) const;
|
int findLastIndex(qint64 endTime) const;
|
||||||
Q_INVOKABLE qint64 firstTimeMark() const;
|
Q_INVOKABLE qint64 firstTimeMark() const;
|
||||||
Q_INVOKABLE qint64 lastTimeMark() const;
|
Q_INVOKABLE qint64 lastTimeMark() const;
|
||||||
|
|
||||||
Q_INVOKABLE int count() const;
|
|
||||||
|
|
||||||
// data access
|
// data access
|
||||||
|
Q_INVOKABLE int count() const;
|
||||||
|
Q_INVOKABLE bool isEmpty() const;
|
||||||
Q_INVOKABLE qint64 getStartTime(int index) const;
|
Q_INVOKABLE qint64 getStartTime(int index) const;
|
||||||
Q_INVOKABLE qint64 getEndTime(int index) const;
|
Q_INVOKABLE qint64 getEndTime(int index) const;
|
||||||
Q_INVOKABLE qint64 getDuration(int index) const;
|
Q_INVOKABLE qint64 getDuration(int index) const;
|
||||||
@@ -171,7 +150,6 @@ public:
|
|||||||
Q_INVOKABLE qint64 qmlMeasuredTime() const;
|
Q_INVOKABLE qint64 qmlMeasuredTime() const;
|
||||||
Q_INVOKABLE qint64 v8MeasuredTime() const;
|
Q_INVOKABLE qint64 v8MeasuredTime() const;
|
||||||
|
|
||||||
void showErrorDialog(const QString &st ) const;
|
|
||||||
void compileStatistics(qint64 startTime, qint64 endTime);
|
void compileStatistics(qint64 startTime, qint64 endTime);
|
||||||
State currentState() const;
|
State currentState() const;
|
||||||
Q_INVOKABLE int getCurrentStateFromQml() const;
|
Q_INVOKABLE int getCurrentStateFromQml() const;
|
||||||
@@ -188,44 +166,37 @@ signals:
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void addRangedEvent(int type, qint64 startTime, qint64 length,
|
void addRangedEvent(int type, qint64 startTime, qint64 length,
|
||||||
const QStringList &data, const QmlJsDebugClient::QmlEventLocation &location);
|
const QStringList &data, const QmlJsDebugClient::QmlEventLocation &location);
|
||||||
void complete();
|
|
||||||
|
|
||||||
void addV8Event(int depth,const QString &function,const QString &filename, int lineNumber, double totalTime, double selfTime);
|
void addV8Event(int depth,const QString &function,const QString &filename, int lineNumber, double totalTime, double selfTime);
|
||||||
void addFrameEvent(qint64 time, int framerate, int animationcount);
|
void addFrameEvent(qint64 time, int framerate, int animationcount);
|
||||||
|
void setTraceStartTime(qint64 time);
|
||||||
|
void setTraceEndTime(qint64 time);
|
||||||
|
|
||||||
|
void complete();
|
||||||
|
|
||||||
bool save(const QString &filename);
|
bool save(const QString &filename);
|
||||||
void load(const QString &filename);
|
void load(const QString &filename);
|
||||||
void setFilename(const QString &filename);
|
void setFilename(const QString &filename);
|
||||||
void load();
|
void load();
|
||||||
|
|
||||||
void setTraceEndTime( qint64 time );
|
|
||||||
void setTraceStartTime( qint64 time );
|
|
||||||
|
|
||||||
void rewriteDetailsString(int eventType, const QmlJsDebugClient::QmlEventLocation &location, const QString &newString);
|
void rewriteDetailsString(int eventType, const QmlJsDebugClient::QmlEventLocation &location, const QString &newString);
|
||||||
void finishedRewritingDetails();
|
void finishedRewritingDetails();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void postProcess();
|
|
||||||
void sortEndTimes();
|
|
||||||
void findAnimationLimits();
|
|
||||||
void sortStartTimes();
|
|
||||||
void computeLevels();
|
|
||||||
void computeNestingLevels();
|
|
||||||
void computeNestingDepth();
|
|
||||||
void prepareForDisplay();
|
|
||||||
void linkEndsToStarts();
|
|
||||||
void reloadDetails();
|
|
||||||
void findBindingLoops(qint64 startTime, qint64 endTime);
|
|
||||||
bool checkBindingLoop(QmlEventData *from, QmlEventData *current, QList<QmlEventData *>visited);
|
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
|
void reloadDetails();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class QmlProfilerEventListPrivate;
|
class QmlProfilerDataModelPrivate;
|
||||||
QmlProfilerEventListPrivate *d;
|
QmlProfilerDataModelPrivate *d;
|
||||||
|
|
||||||
|
friend class QV8ProfilerDataModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace QmlJsDebugClient
|
} // namespace Internal
|
||||||
|
} // namespace QmlProfiler
|
||||||
|
|
||||||
#endif // QMLPROFILEREVENTLIST_H
|
#endif // QMLPROFILERDATAMODEL_H
|
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "qmljsdebugclient/qmlprofilereventlocation.h"
|
#include <qmljsdebugclient/qmlprofilereventlocation.h>
|
||||||
#include <qmljs/qmljsdocument.h>
|
#include <qmljs/qmljsdocument.h>
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
|
@@ -35,8 +35,6 @@
|
|||||||
#include "codaqmlprofilerrunner.h"
|
#include "codaqmlprofilerrunner.h"
|
||||||
#include "localqmlprofilerrunner.h"
|
#include "localqmlprofilerrunner.h"
|
||||||
#include "remotelinuxqmlprofilerrunner.h"
|
#include "remotelinuxqmlprofilerrunner.h"
|
||||||
#include "qmlprofilerplugin.h"
|
|
||||||
#include "qmlprofilertool.h"
|
|
||||||
|
|
||||||
#include <analyzerbase/analyzermanager.h>
|
#include <analyzerbase/analyzermanager.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
@@ -76,16 +74,11 @@ public:
|
|||||||
|
|
||||||
QmlProfilerEngine *q;
|
QmlProfilerEngine *q;
|
||||||
|
|
||||||
//AnalyzerStartParameters m_params;
|
QmlProfilerStateManager *m_profilerState;
|
||||||
|
|
||||||
AbstractQmlProfilerRunner *m_runner;
|
AbstractQmlProfilerRunner *m_runner;
|
||||||
bool m_running;
|
|
||||||
bool m_fetchingData;
|
|
||||||
bool m_hasData;
|
|
||||||
bool m_fetchDataFromStart;
|
|
||||||
bool m_delayedDelete;
|
|
||||||
QTimer m_noDebugOutputTimer;
|
QTimer m_noDebugOutputTimer;
|
||||||
QmlJsDebugClient::QDeclarativeOutputParser m_outputParser;
|
QmlJsDebugClient::QDeclarativeOutputParser m_outputParser;
|
||||||
QTimer m_runningTimer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractQmlProfilerRunner *
|
AbstractQmlProfilerRunner *
|
||||||
@@ -137,10 +130,7 @@ QmlProfilerEngine::QmlProfilerEngine(IAnalyzerTool *tool,
|
|||||||
: IAnalyzerEngine(tool, sp, runConfiguration)
|
: IAnalyzerEngine(tool, sp, runConfiguration)
|
||||||
, d(new QmlProfilerEnginePrivate(this))
|
, d(new QmlProfilerEnginePrivate(this))
|
||||||
{
|
{
|
||||||
d->m_running = false;
|
d->m_profilerState = 0;
|
||||||
d->m_fetchingData = false;
|
|
||||||
d->m_fetchDataFromStart = false;
|
|
||||||
d->m_delayedDelete = false;
|
|
||||||
|
|
||||||
// Only wait 4 seconds for the 'Waiting for connection' on application ouput, then just try to connect
|
// Only wait 4 seconds for the 'Waiting for connection' on application ouput, then just try to connect
|
||||||
// (application output might be redirected / blocked)
|
// (application output might be redirected / blocked)
|
||||||
@@ -157,29 +147,31 @@ QmlProfilerEngine::QmlProfilerEngine(IAnalyzerTool *tool,
|
|||||||
this, SLOT(processIsRunning()));
|
this, SLOT(processIsRunning()));
|
||||||
connect(&d->m_outputParser, SIGNAL(errorMessage(QString)),
|
connect(&d->m_outputParser, SIGNAL(errorMessage(QString)),
|
||||||
this, SLOT(wrongSetupMessageBox(QString)));
|
this, SLOT(wrongSetupMessageBox(QString)));
|
||||||
|
|
||||||
d->m_runningTimer.setInterval(100); // ten times per second
|
|
||||||
connect(&d->m_runningTimer, SIGNAL(timeout()), this, SIGNAL(timeUpdate()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlProfilerEngine::~QmlProfilerEngine()
|
QmlProfilerEngine::~QmlProfilerEngine()
|
||||||
{
|
{
|
||||||
if (d->m_running)
|
if (d->m_profilerState && d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning)
|
||||||
stop();
|
stop();
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlProfilerEngine::start()
|
bool QmlProfilerEngine::start()
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(d->m_profilerState, return false);
|
||||||
|
|
||||||
if (d->m_runner) {
|
if (d->m_runner) {
|
||||||
delete d->m_runner;
|
delete d->m_runner;
|
||||||
d->m_runner = 0;
|
d->m_runner = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStarting);
|
||||||
|
|
||||||
if (QmlProjectManager::QmlProjectRunConfiguration *rc =
|
if (QmlProjectManager::QmlProjectRunConfiguration *rc =
|
||||||
qobject_cast<QmlProjectManager::QmlProjectRunConfiguration *>(runConfiguration())) {
|
qobject_cast<QmlProjectManager::QmlProjectRunConfiguration *>(runConfiguration())) {
|
||||||
if (rc->observerPath().isEmpty()) {
|
if (rc->observerPath().isEmpty()) {
|
||||||
QmlProjectManager::QmlProjectPlugin::showQmlObserverToolWarning();
|
QmlProjectManager::QmlProjectPlugin::showQmlObserverToolWarning();
|
||||||
|
d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle);
|
||||||
AnalyzerManager::stopTool();
|
AnalyzerManager::stopTool();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -190,13 +182,14 @@ bool QmlProfilerEngine::start()
|
|||||||
if (LocalQmlProfilerRunner *qmlRunner = qobject_cast<LocalQmlProfilerRunner *>(d->m_runner)) {
|
if (LocalQmlProfilerRunner *qmlRunner = qobject_cast<LocalQmlProfilerRunner *>(d->m_runner)) {
|
||||||
if (!qmlRunner->hasExecutable()) {
|
if (!qmlRunner->hasExecutable()) {
|
||||||
showNonmodalWarning(tr("No executable file to launch."));
|
showNonmodalWarning(tr("No executable file to launch."));
|
||||||
|
d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle);
|
||||||
AnalyzerManager::stopTool();
|
AnalyzerManager::stopTool();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->m_runner) {
|
if (d->m_runner) {
|
||||||
connect(d->m_runner, SIGNAL(stopped()), this, SLOT(stopped()));
|
connect(d->m_runner, SIGNAL(stopped()), this, SLOT(processEnded()));
|
||||||
connect(d->m_runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)),
|
connect(d->m_runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)),
|
||||||
this, SLOT(logApplicationMessage(QString,Utils::OutputFormat)));
|
this, SLOT(logApplicationMessage(QString,Utils::OutputFormat)));
|
||||||
d->m_runner->start();
|
d->m_runner->start();
|
||||||
@@ -205,81 +198,80 @@ bool QmlProfilerEngine::start()
|
|||||||
emit processRunning(startParameters().connParams.port);
|
emit processRunning(startParameters().connParams.port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppRunning);
|
||||||
d->m_running = true;
|
|
||||||
d->m_delayedDelete = false;
|
|
||||||
d->m_runningTimer.start();
|
|
||||||
|
|
||||||
if (d->m_fetchDataFromStart) {
|
|
||||||
d->m_fetchingData = true;
|
|
||||||
d->m_hasData = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit starting(this);
|
emit starting(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEngine::stop()
|
void QmlProfilerEngine::stop()
|
||||||
{
|
{
|
||||||
if (d->m_fetchingData) {
|
QTC_ASSERT(d->m_profilerState, return);
|
||||||
if (d->m_running)
|
|
||||||
d->m_delayedDelete = true;
|
switch (d->m_profilerState->currentState()) {
|
||||||
// will result in dataReceived() call
|
case QmlProfilerStateManager::AppRunning : {
|
||||||
emit stopRecording();
|
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopRequested);
|
||||||
d->m_fetchDataFromStart = true;
|
break;
|
||||||
} else {
|
}
|
||||||
finishProcess();
|
case QmlProfilerStateManager::AppReadyToStop : {
|
||||||
d->m_fetchDataFromStart = false;
|
cancelProcess();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QmlProfilerStateManager::AppKilled : {
|
||||||
|
d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
qDebug() << tr("Unexpected engine stop from state %1 in %2:%3").arg(d->m_profilerState->currentStateAsString(), QString(__FILE__), QString::number(__LINE__));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEngine::stopped()
|
void QmlProfilerEngine::processEnded()
|
||||||
{
|
{
|
||||||
// if it was killed, preserve recording flag
|
QTC_ASSERT(d->m_profilerState, return);
|
||||||
if (d->m_running)
|
|
||||||
d->m_fetchDataFromStart = d->m_fetchingData;
|
|
||||||
|
|
||||||
// user feedback
|
switch (d->m_profilerState->currentState()) {
|
||||||
if (d->m_running && d->m_fetchingData && !d->m_hasData) {
|
case QmlProfilerStateManager::AppRunning : {
|
||||||
showNonmodalWarning(tr("Application finished before loading profiled data.\n Please use the stop button instead."));
|
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled);
|
||||||
emit applicationDied();
|
|
||||||
}
|
|
||||||
|
|
||||||
d->m_running = false;
|
|
||||||
d->m_runningTimer.stop();
|
|
||||||
AnalyzerManager::stopTool();
|
AnalyzerManager::stopTool();
|
||||||
|
|
||||||
emit finished();
|
emit finished();
|
||||||
emit recordingChanged(d->m_fetchDataFromStart);
|
break;
|
||||||
|
}
|
||||||
|
case QmlProfilerStateManager::AppStopped :
|
||||||
|
// fallthrough
|
||||||
|
case QmlProfilerStateManager::AppKilled : {
|
||||||
|
d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
qDebug() << tr("Process died unexpectedly from state %1 in %2:%3").arg(d->m_profilerState->currentStateAsString(), QString(__FILE__), QString::number(__LINE__));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEngine::setFetchingData(bool b)
|
void QmlProfilerEngine::cancelProcess()
|
||||||
{
|
{
|
||||||
d->m_fetchingData = b;
|
QTC_ASSERT(d->m_profilerState, return);
|
||||||
if (d->m_running && b)
|
|
||||||
d->m_hasData = false;
|
switch (d->m_profilerState->currentState()) {
|
||||||
if (!d->m_running)
|
case QmlProfilerStateManager::AppReadyToStop : {
|
||||||
d->m_fetchDataFromStart = b;
|
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopped);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QmlProfilerStateManager::AppRunning : {
|
||||||
|
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
qDebug() << tr("Unexpected process termination requested with state %1 in %2:%3").arg(d->m_profilerState->currentStateAsString(), QString(__FILE__), QString::number(__LINE__));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEngine::dataReceived()
|
|
||||||
{
|
|
||||||
if (d->m_delayedDelete)
|
|
||||||
finishProcess();
|
|
||||||
d->m_delayedDelete = false;
|
|
||||||
d->m_hasData = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerEngine::finishProcess()
|
|
||||||
{
|
|
||||||
// user stop?
|
|
||||||
if (d->m_running) {
|
|
||||||
d->m_running = false;
|
|
||||||
d->m_runningTimer.stop();
|
|
||||||
if (d->m_runner)
|
if (d->m_runner)
|
||||||
d->m_runner->stop();
|
d->m_runner->stop();
|
||||||
emit finished();
|
emit finished();
|
||||||
emit recordingChanged(d->m_fetchDataFromStart);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEngine::logApplicationMessage(const QString &msg, Utils::OutputFormat format)
|
void QmlProfilerEngine::logApplicationMessage(const QString &msg, Utils::OutputFormat format)
|
||||||
@@ -305,11 +297,10 @@ void QmlProfilerEngine::wrongSetupMessageBox(const QString &errorMessage)
|
|||||||
|
|
||||||
infoBox->show();
|
infoBox->show();
|
||||||
|
|
||||||
d->m_running = false;
|
// KILL
|
||||||
d->m_runningTimer.stop();
|
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled);
|
||||||
AnalyzerManager::stopTool();
|
AnalyzerManager::stopTool();
|
||||||
emit finished();
|
emit finished();
|
||||||
emit recordingChanged(d->m_fetchDataFromStart);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEngine::wrongSetupMessageBoxFinished(int button)
|
void QmlProfilerEngine::wrongSetupMessageBoxFinished(int button)
|
||||||
@@ -348,5 +339,44 @@ void QmlProfilerEngine::processIsRunning(quint16 port)
|
|||||||
emit processRunning(d->m_runner->debugPort());
|
emit processRunning(d->m_runner->debugPort());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// Profiler State
|
||||||
|
void QmlProfilerEngine::registerProfilerStateManager( QmlProfilerStateManager *profilerState )
|
||||||
|
{
|
||||||
|
// disconnect old
|
||||||
|
if (d->m_profilerState) {
|
||||||
|
disconnect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged()));
|
||||||
|
}
|
||||||
|
|
||||||
|
d->m_profilerState = profilerState;
|
||||||
|
|
||||||
|
// connect
|
||||||
|
if (d->m_profilerState) {
|
||||||
|
connect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerEngine::profilerStateChanged()
|
||||||
|
{
|
||||||
|
switch (d->m_profilerState->currentState()) {
|
||||||
|
case QmlProfilerStateManager::AppReadyToStop : {
|
||||||
|
cancelProcess();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QmlProfilerStateManager::Idle : {
|
||||||
|
// for some reason the engine is not deleted when it goes to idle
|
||||||
|
// a new one will be created on the next run, and this one will
|
||||||
|
// be only deleted if the new one is running the same app
|
||||||
|
|
||||||
|
// we need to explictly disconnect it here without expecting a deletion
|
||||||
|
// as it will not be run any more, otherwise we will get funny side effects
|
||||||
|
registerProfilerStateManager(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace QmlProfiler
|
} // namespace QmlProfiler
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
#define QMLPROFILERENGINE_H
|
#define QMLPROFILERENGINE_H
|
||||||
|
|
||||||
#include <analyzerbase/ianalyzerengine.h>
|
#include <analyzerbase/ianalyzerengine.h>
|
||||||
|
#include "qmlprofilerstatemanager.h"
|
||||||
#include <utils/outputformat.h>
|
#include <utils/outputformat.h>
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
@@ -49,29 +50,29 @@ public:
|
|||||||
ProjectExplorer::RunConfiguration *runConfiguration);
|
ProjectExplorer::RunConfiguration *runConfiguration);
|
||||||
~QmlProfilerEngine();
|
~QmlProfilerEngine();
|
||||||
|
|
||||||
|
void registerProfilerStateManager( QmlProfilerStateManager *profilerState );
|
||||||
|
|
||||||
static void showNonmodalWarning(const QString &warningMsg);
|
static void showNonmodalWarning(const QString &warningMsg);
|
||||||
signals:
|
signals:
|
||||||
void processRunning(quint16 port);
|
void processRunning(quint16 port);
|
||||||
void stopRecording();
|
|
||||||
void timeUpdate();
|
void timeUpdate();
|
||||||
void recordingChanged(bool recording);
|
|
||||||
void applicationDied();
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool start();
|
bool start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void stopped();
|
void processEnded();
|
||||||
|
|
||||||
void setFetchingData(bool);
|
void cancelProcess();
|
||||||
void dataReceived();
|
|
||||||
void finishProcess();
|
|
||||||
void logApplicationMessage(const QString &msg, Utils::OutputFormat format);
|
void logApplicationMessage(const QString &msg, Utils::OutputFormat format);
|
||||||
void wrongSetupMessageBox(const QString &errorMessage);
|
void wrongSetupMessageBox(const QString &errorMessage);
|
||||||
void wrongSetupMessageBoxFinished(int);
|
void wrongSetupMessageBoxFinished(int);
|
||||||
void processIsRunning(quint16 port = 0);
|
void processIsRunning(quint16 port = 0);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void profilerStateChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class QmlProfilerEnginePrivate;
|
class QmlProfilerEnginePrivate;
|
||||||
QmlProfilerEnginePrivate *d;
|
QmlProfilerEnginePrivate *d;
|
||||||
|
@@ -48,6 +48,11 @@
|
|||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
|
#include "qmlprofilerviewmanager.h"
|
||||||
|
#include "qmlprofilertool.h"
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
using namespace QmlJsDebugClient;
|
using namespace QmlJsDebugClient;
|
||||||
|
|
||||||
@@ -90,31 +95,63 @@ public:
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
QmlProfilerEventsWidget::QmlProfilerEventsWidget(QmlJsDebugClient::QmlProfilerEventList *model, QWidget *parent) : QWidget(parent)
|
class QmlProfilerEventsWidget::QmlProfilerEventsWidgetPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QmlProfilerEventsWidgetPrivate(QmlProfilerEventsWidget *qq):q(qq) {}
|
||||||
|
~QmlProfilerEventsWidgetPrivate() {}
|
||||||
|
|
||||||
|
QmlProfilerEventsWidget *q;
|
||||||
|
|
||||||
|
Analyzer::IAnalyzerTool *m_profilerTool;
|
||||||
|
QmlProfilerViewManager *m_viewContainer;
|
||||||
|
|
||||||
|
QmlProfilerEventsMainView *m_eventTree;
|
||||||
|
QmlProfilerEventsParentsAndChildrenView *m_eventChildren;
|
||||||
|
QmlProfilerEventsParentsAndChildrenView *m_eventParents;
|
||||||
|
QmlProfilerDataModel *m_profilerDataModel;
|
||||||
|
|
||||||
|
bool m_globalStatsEnabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
QmlProfilerEventsWidget::QmlProfilerEventsWidget(QWidget *parent,
|
||||||
|
Analyzer::IAnalyzerTool *profilerTool,
|
||||||
|
QmlProfilerViewManager *container,
|
||||||
|
QmlProfilerDataModel *profilerDataModel )
|
||||||
|
: QWidget(parent), d(new QmlProfilerEventsWidgetPrivate(this))
|
||||||
{
|
{
|
||||||
setObjectName("QmlProfilerEventsView");
|
setObjectName("QmlProfilerEventsView");
|
||||||
|
|
||||||
m_eventTree = new QmlProfilerEventsMainView(model, this);
|
d->m_profilerDataModel = profilerDataModel;
|
||||||
m_eventTree->setViewType(QmlProfilerEventsMainView::EventsView);
|
connect(d->m_profilerDataModel, SIGNAL(stateChanged()),
|
||||||
connect(m_eventTree, SIGNAL(gotoSourceLocation(QString,int,int)), this, SIGNAL(gotoSourceLocation(QString,int,int)));
|
this, SLOT(profilerDataModelStateChanged()));
|
||||||
connect(m_eventTree, SIGNAL(showEventInTimeline(int)), this, SIGNAL(showEventInTimeline(int)));
|
|
||||||
|
|
||||||
m_eventChildren = new QmlProfilerEventsParentsAndChildrenView(model, QmlProfilerEventsParentsAndChildrenView::ChildrenView, this);
|
d->m_eventTree = new QmlProfilerEventsMainView(QmlProfilerEventsMainView::EventsView, this, d->m_profilerDataModel);
|
||||||
m_eventParents = new QmlProfilerEventsParentsAndChildrenView(model, QmlProfilerEventsParentsAndChildrenView::ParentsView, this);
|
connect(d->m_eventTree, SIGNAL(gotoSourceLocation(QString,int,int)), this, SIGNAL(gotoSourceLocation(QString,int,int)));
|
||||||
connect(m_eventTree, SIGNAL(eventSelected(int)), m_eventChildren, SLOT(displayEvent(int)));
|
connect(d->m_eventTree, SIGNAL(showEventInTimeline(int)), this, SIGNAL(showEventInTimeline(int)));
|
||||||
connect(m_eventTree, SIGNAL(eventSelected(int)), m_eventParents, SLOT(displayEvent(int)));
|
|
||||||
connect(m_eventChildren, SIGNAL(eventClicked(int)), m_eventTree, SLOT(selectEvent(int)));
|
d->m_eventChildren = new QmlProfilerEventsParentsAndChildrenView(
|
||||||
connect(m_eventParents, SIGNAL(eventClicked(int)), m_eventTree, SLOT(selectEvent(int)));
|
QmlProfilerEventsParentsAndChildrenView::ChildrenView,
|
||||||
|
this,
|
||||||
|
d->m_profilerDataModel);
|
||||||
|
d->m_eventParents = new QmlProfilerEventsParentsAndChildrenView(
|
||||||
|
QmlProfilerEventsParentsAndChildrenView::ParentsView,
|
||||||
|
this,
|
||||||
|
d->m_profilerDataModel);
|
||||||
|
connect(d->m_eventTree, SIGNAL(eventSelected(int)), d->m_eventChildren, SLOT(displayEvent(int)));
|
||||||
|
connect(d->m_eventTree, SIGNAL(eventSelected(int)), d->m_eventParents, SLOT(displayEvent(int)));
|
||||||
|
connect(d->m_eventChildren, SIGNAL(eventClicked(int)), d->m_eventTree, SLOT(selectEvent(int)));
|
||||||
|
connect(d->m_eventParents, SIGNAL(eventClicked(int)), d->m_eventTree, SLOT(selectEvent(int)));
|
||||||
|
|
||||||
// widget arrangement
|
// widget arrangement
|
||||||
QVBoxLayout *groupLayout = new QVBoxLayout;
|
QVBoxLayout *groupLayout = new QVBoxLayout;
|
||||||
groupLayout->setContentsMargins(0,0,0,0);
|
groupLayout->setContentsMargins(0,0,0,0);
|
||||||
groupLayout->setSpacing(0);
|
groupLayout->setSpacing(0);
|
||||||
Core::MiniSplitter *splitterVertical = new Core::MiniSplitter;
|
Core::MiniSplitter *splitterVertical = new Core::MiniSplitter;
|
||||||
splitterVertical->addWidget(m_eventTree);
|
splitterVertical->addWidget(d->m_eventTree);
|
||||||
Core::MiniSplitter *splitterHorizontal = new Core::MiniSplitter;
|
Core::MiniSplitter *splitterHorizontal = new Core::MiniSplitter;
|
||||||
splitterHorizontal->addWidget(m_eventParents);
|
splitterHorizontal->addWidget(d->m_eventParents);
|
||||||
splitterHorizontal->addWidget(m_eventChildren);
|
splitterHorizontal->addWidget(d->m_eventChildren);
|
||||||
splitterHorizontal->setOrientation(Qt::Horizontal);
|
splitterHorizontal->setOrientation(Qt::Horizontal);
|
||||||
splitterVertical->addWidget(splitterHorizontal);
|
splitterVertical->addWidget(splitterHorizontal);
|
||||||
splitterVertical->setOrientation(Qt::Vertical);
|
splitterVertical->setOrientation(Qt::Vertical);
|
||||||
@@ -123,23 +160,21 @@ QmlProfilerEventsWidget::QmlProfilerEventsWidget(QmlJsDebugClient::QmlProfilerEv
|
|||||||
groupLayout->addWidget(splitterVertical);
|
groupLayout->addWidget(splitterVertical);
|
||||||
setLayout(groupLayout);
|
setLayout(groupLayout);
|
||||||
|
|
||||||
m_eventStatistics = model;
|
d->m_profilerTool = profilerTool;
|
||||||
if (model) {
|
d->m_viewContainer = container;
|
||||||
connect(model, SIGNAL(stateChanged()), this, SLOT(eventListStateChanged()));
|
d->m_globalStatsEnabled = true;
|
||||||
}
|
|
||||||
|
|
||||||
m_globalStatsEnabled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlProfilerEventsWidget::~QmlProfilerEventsWidget()
|
QmlProfilerEventsWidget::~QmlProfilerEventsWidget()
|
||||||
{
|
{
|
||||||
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsWidget::eventListStateChanged()
|
void QmlProfilerEventsWidget::profilerDataModelStateChanged()
|
||||||
{
|
{
|
||||||
if (m_eventStatistics) {
|
if (d->m_profilerDataModel) {
|
||||||
QmlProfilerEventList::State newState = m_eventStatistics->currentState();
|
QmlProfilerDataModel::State newState = d->m_profilerDataModel->currentState();
|
||||||
if (newState == QmlProfilerEventList::Empty) {
|
if (newState == QmlProfilerDataModel::Empty) {
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,57 +183,119 @@ void QmlProfilerEventsWidget::eventListStateChanged()
|
|||||||
void QmlProfilerEventsWidget::switchToV8View()
|
void QmlProfilerEventsWidget::switchToV8View()
|
||||||
{
|
{
|
||||||
setObjectName("QmlProfilerV8ProfileView");
|
setObjectName("QmlProfilerV8ProfileView");
|
||||||
m_eventTree->setViewType(QmlProfilerEventsMainView::V8ProfileView);
|
d->m_eventTree->setViewType(QmlProfilerEventsMainView::V8ProfileView);
|
||||||
m_eventParents->setViewType(QmlProfilerEventsParentsAndChildrenView::V8ParentsView);
|
d->m_eventParents->setViewType(QmlProfilerEventsParentsAndChildrenView::V8ParentsView);
|
||||||
m_eventChildren->setViewType(QmlProfilerEventsParentsAndChildrenView::V8ChildrenView);
|
d->m_eventChildren->setViewType(QmlProfilerEventsParentsAndChildrenView::V8ChildrenView);
|
||||||
setToolTip(tr("Trace information from the v8 JavaScript engine. Available only in Qt5 based applications"));
|
setToolTip(tr("Trace information from the v8 JavaScript engine. Available only in Qt5 based applications"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsWidget::clear()
|
void QmlProfilerEventsWidget::clear()
|
||||||
{
|
{
|
||||||
m_eventTree->clear();
|
d->m_eventTree->clear();
|
||||||
m_eventChildren->clear();
|
d->m_eventChildren->clear();
|
||||||
m_eventParents->clear();
|
d->m_eventParents->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsWidget::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd)
|
void QmlProfilerEventsWidget::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
m_eventTree->getStatisticsInRange(rangeStart, rangeEnd);
|
d->m_eventTree->getStatisticsInRange(rangeStart, rangeEnd);
|
||||||
m_globalStatsEnabled = m_eventTree->isRangeGlobal(rangeStart, rangeEnd);
|
d->m_globalStatsEnabled = d->m_eventTree->isRangeGlobal(rangeStart, rangeEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex QmlProfilerEventsWidget::selectedItem() const
|
QModelIndex QmlProfilerEventsWidget::selectedItem() const
|
||||||
{
|
{
|
||||||
return m_eventTree->selectedItem();
|
return d->m_eventTree->selectedItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsWidget::contextMenuEvent(QContextMenuEvent *ev)
|
void QmlProfilerEventsWidget::contextMenuEvent(QContextMenuEvent *ev)
|
||||||
{
|
{
|
||||||
emit contextMenuRequested(ev->globalPos());
|
QTC_ASSERT(d->m_viewContainer, return;);
|
||||||
|
|
||||||
|
QMenu menu;
|
||||||
|
QAction *copyRowAction = 0;
|
||||||
|
QAction *copyTableAction = 0;
|
||||||
|
QAction *showExtendedStatsAction = 0;
|
||||||
|
QAction *getLocalStatsAction = 0;
|
||||||
|
QAction *getGlobalStatsAction = 0;
|
||||||
|
|
||||||
|
QmlProfilerTool *profilerTool = qobject_cast<QmlProfilerTool *>(d->m_profilerTool);
|
||||||
|
QPoint position = ev->globalPos();
|
||||||
|
|
||||||
|
if (profilerTool) {
|
||||||
|
QList <QAction *> commonActions = profilerTool->profilerContextMenuActions();
|
||||||
|
foreach (QAction *act, commonActions) {
|
||||||
|
menu.addAction(act);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouseOnTable(position)) {
|
||||||
|
menu.addSeparator();
|
||||||
|
if (selectedItem().isValid())
|
||||||
|
copyRowAction = menu.addAction(tr("Copy Row"));
|
||||||
|
copyTableAction = menu.addAction(tr("Copy Table"));
|
||||||
|
|
||||||
|
if (isQml()) {
|
||||||
|
// only for qml events view, not for v8
|
||||||
|
showExtendedStatsAction = menu.addAction(tr("Extended Event Statistics"));
|
||||||
|
showExtendedStatsAction->setCheckable(true);
|
||||||
|
showExtendedStatsAction->setChecked(showExtendedStatistics());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isQml()) {
|
||||||
|
menu.addSeparator();
|
||||||
|
getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range"));
|
||||||
|
if (!d->m_viewContainer->hasValidSelection())
|
||||||
|
getLocalStatsAction->setEnabled(false);
|
||||||
|
getGlobalStatsAction = menu.addAction(tr("Reset Events Pane"));
|
||||||
|
if (hasGlobalStats())
|
||||||
|
getGlobalStatsAction->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
QAction *selectedAction = menu.exec(position);
|
||||||
|
|
||||||
|
if (selectedAction) {
|
||||||
|
if (selectedAction == copyRowAction)
|
||||||
|
copyRowToClipboard();
|
||||||
|
if (selectedAction == copyTableAction)
|
||||||
|
copyTableToClipboard();
|
||||||
|
if (selectedAction == getLocalStatsAction) {
|
||||||
|
getStatisticsInRange(d->m_viewContainer->selectionStart(),
|
||||||
|
d->m_viewContainer->selectionEnd());
|
||||||
|
}
|
||||||
|
if (selectedAction == getGlobalStatsAction) {
|
||||||
|
if (d->m_profilerDataModel) {
|
||||||
|
getStatisticsInRange(d->m_profilerDataModel->traceStartTime(),
|
||||||
|
d->m_profilerDataModel->traceEndTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selectedAction == showExtendedStatsAction)
|
||||||
|
setShowExtendedStatistics(!showExtendedStatistics());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlProfilerEventsWidget::mouseOnTable(const QPoint &position) const
|
bool QmlProfilerEventsWidget::mouseOnTable(const QPoint &position) const
|
||||||
{
|
{
|
||||||
QPoint tableTopLeft = m_eventTree->mapToGlobal(QPoint(0,0));
|
QPoint tableTopLeft = d->m_eventTree->mapToGlobal(QPoint(0,0));
|
||||||
QPoint tableBottomRight = m_eventTree->mapToGlobal(QPoint(m_eventTree->width(), m_eventTree->height()));
|
QPoint tableBottomRight = d->m_eventTree->mapToGlobal(QPoint(d->m_eventTree->width(), d->m_eventTree->height()));
|
||||||
return (position.x() >= tableTopLeft.x() && position.x() <= tableBottomRight.x() && position.y() >= tableTopLeft.y() && position.y() <= tableBottomRight.y());
|
return (position.x() >= tableTopLeft.x() && position.x() <= tableBottomRight.x() && position.y() >= tableTopLeft.y() && position.y() <= tableBottomRight.y());
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsWidget::copyTableToClipboard() const
|
void QmlProfilerEventsWidget::copyTableToClipboard() const
|
||||||
{
|
{
|
||||||
m_eventTree->copyTableToClipboard();
|
d->m_eventTree->copyTableToClipboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsWidget::copyRowToClipboard() const
|
void QmlProfilerEventsWidget::copyRowToClipboard() const
|
||||||
{
|
{
|
||||||
m_eventTree->copyRowToClipboard();
|
d->m_eventTree->copyRowToClipboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsWidget::updateSelectedEvent(int eventId) const
|
void QmlProfilerEventsWidget::updateSelectedEvent(int eventId) const
|
||||||
{
|
{
|
||||||
if (m_eventTree->selectedEventId() != eventId)
|
if (d->m_eventTree->selectedEventId() != eventId)
|
||||||
m_eventTree->selectEvent(eventId);
|
d->m_eventTree->selectEvent(eventId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsWidget::selectBySourceLocation(const QString &filename, int line, int column)
|
void QmlProfilerEventsWidget::selectBySourceLocation(const QString &filename, int line, int column)
|
||||||
@@ -207,22 +304,31 @@ void QmlProfilerEventsWidget::selectBySourceLocation(const QString &filename, in
|
|||||||
// Our javascript trace data does not store column information
|
// Our javascript trace data does not store column information
|
||||||
// thus we ignore it here
|
// thus we ignore it here
|
||||||
Q_UNUSED(column);
|
Q_UNUSED(column);
|
||||||
m_eventTree->selectEventByLocation(filename, line);
|
d->m_eventTree->selectEventByLocation(filename, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlProfilerEventsWidget::hasGlobalStats() const
|
bool QmlProfilerEventsWidget::hasGlobalStats() const
|
||||||
{
|
{
|
||||||
return m_globalStatsEnabled;
|
return d->m_globalStatsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsWidget::setShowExtendedStatistics(bool show)
|
void QmlProfilerEventsWidget::setShowExtendedStatistics(bool show)
|
||||||
{
|
{
|
||||||
m_eventTree->setShowExtendedStatistics(show);
|
d->m_eventTree->setShowExtendedStatistics(show);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlProfilerEventsWidget::showExtendedStatistics() const
|
bool QmlProfilerEventsWidget::showExtendedStatistics() const
|
||||||
{
|
{
|
||||||
return m_eventTree->showExtendedStatistics();
|
return d->m_eventTree->showExtendedStatistics();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlProfilerEventsWidget::isQml() const
|
||||||
|
{
|
||||||
|
return d->m_eventTree->viewType() == QmlProfilerEventsMainView::EventsView;
|
||||||
|
}
|
||||||
|
bool QmlProfilerEventsWidget::isV8() const
|
||||||
|
{
|
||||||
|
return d->m_eventTree->viewType() == QmlProfilerEventsMainView::V8ProfileView;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -232,8 +338,8 @@ class QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate
|
|||||||
public:
|
public:
|
||||||
QmlProfilerEventsMainViewPrivate(QmlProfilerEventsMainView *qq) : q(qq) {}
|
QmlProfilerEventsMainViewPrivate(QmlProfilerEventsMainView *qq) : q(qq) {}
|
||||||
|
|
||||||
void buildModelFromList(const QmlEventDescriptions &list, QStandardItem *parentItem, const QmlEventDescriptions &visitedFunctionsList = QmlEventDescriptions() );
|
void buildModelFromList(const QList<QmlRangeEventData *> &list, QStandardItem *parentItem );
|
||||||
void buildV8ModelFromList( const QV8EventDescriptions &list );
|
void buildV8ModelFromList( const QList<QV8EventData *> &list );
|
||||||
int getFieldCount();
|
int getFieldCount();
|
||||||
|
|
||||||
QString textForItem(QStandardItem *item, bool recursive) const;
|
QString textForItem(QStandardItem *item, bool recursive) const;
|
||||||
@@ -242,7 +348,7 @@ public:
|
|||||||
QmlProfilerEventsMainView *q;
|
QmlProfilerEventsMainView *q;
|
||||||
|
|
||||||
QmlProfilerEventsMainView::ViewTypes m_viewType;
|
QmlProfilerEventsMainView::ViewTypes m_viewType;
|
||||||
QmlProfilerEventList *m_eventStatistics;
|
QmlProfilerDataModel *m_profilerDataModel;
|
||||||
QStandardItemModel *m_model;
|
QStandardItemModel *m_model;
|
||||||
QList<bool> m_fieldShown;
|
QList<bool> m_fieldShown;
|
||||||
QHash<int, int> m_columnIndex; // maps field enum to column index
|
QHash<int, int> m_columnIndex; // maps field enum to column index
|
||||||
@@ -254,8 +360,10 @@ public:
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
QmlProfilerEventsMainView::QmlProfilerEventsMainView(QmlProfilerEventList *model, QWidget *parent) :
|
QmlProfilerEventsMainView::QmlProfilerEventsMainView(ViewTypes viewType,
|
||||||
QTreeView(parent), d(new QmlProfilerEventsMainViewPrivate(this))
|
QWidget *parent,
|
||||||
|
QmlProfilerDataModel *dataModel)
|
||||||
|
: QTreeView(parent), d(new QmlProfilerEventsMainViewPrivate(this))
|
||||||
{
|
{
|
||||||
setObjectName("QmlProfilerEventsTable");
|
setObjectName("QmlProfilerEventsTable");
|
||||||
header()->setResizeMode(QHeaderView::Interactive);
|
header()->setResizeMode(QHeaderView::Interactive);
|
||||||
@@ -268,15 +376,17 @@ QmlProfilerEventsMainView::QmlProfilerEventsMainView(QmlProfilerEventList *model
|
|||||||
setModel(d->m_model);
|
setModel(d->m_model);
|
||||||
connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex)));
|
connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex)));
|
||||||
|
|
||||||
d->m_eventStatistics = 0;
|
d->m_profilerDataModel = dataModel;
|
||||||
setEventStatisticsModel(model);
|
connect(d->m_profilerDataModel,SIGNAL(stateChanged()),
|
||||||
|
this,SLOT(profilerDataModelStateChanged()));
|
||||||
|
connect(d->m_profilerDataModel,SIGNAL(detailsChanged(int,QString)),
|
||||||
|
this,SLOT(changeDetailsForEvent(int,QString)));
|
||||||
|
|
||||||
d->m_firstNumericColumn = 0;
|
d->m_firstNumericColumn = 0;
|
||||||
d->m_preventSelectBounce = false;
|
d->m_preventSelectBounce = false;
|
||||||
d->m_showExtendedStatistics = false;
|
d->m_showExtendedStatistics = false;
|
||||||
|
|
||||||
// default view
|
setViewType(viewType);
|
||||||
setViewType(EventsView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlProfilerEventsMainView::~QmlProfilerEventsMainView()
|
QmlProfilerEventsMainView::~QmlProfilerEventsMainView()
|
||||||
@@ -285,24 +395,11 @@ QmlProfilerEventsMainView::~QmlProfilerEventsMainView()
|
|||||||
delete d->m_model;
|
delete d->m_model;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsMainView::setEventStatisticsModel( QmlProfilerEventList *model )
|
void QmlProfilerEventsMainView::profilerDataModelStateChanged()
|
||||||
{
|
{
|
||||||
if (d->m_eventStatistics) {
|
if (d->m_profilerDataModel) {
|
||||||
disconnect(d->m_eventStatistics,SIGNAL(stateChanged()),this,SLOT(eventListStateChanged()));
|
QmlProfilerDataModel::State newState = d->m_profilerDataModel->currentState();
|
||||||
disconnect(d->m_eventStatistics,SIGNAL(detailsChanged(int,QString)),this,SLOT(changeDetailsForEvent(int,QString)));
|
if (newState == QmlProfilerDataModel::Done)
|
||||||
}
|
|
||||||
d->m_eventStatistics = model;
|
|
||||||
if (model) {
|
|
||||||
connect(d->m_eventStatistics,SIGNAL(stateChanged()),this,SLOT(eventListStateChanged()));
|
|
||||||
connect(d->m_eventStatistics,SIGNAL(detailsChanged(int,QString)),this,SLOT(changeDetailsForEvent(int,QString)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerEventsMainView::eventListStateChanged()
|
|
||||||
{
|
|
||||||
if (d->m_eventStatistics) {
|
|
||||||
QmlProfilerEventList::State newState = d->m_eventStatistics->currentState();
|
|
||||||
if (newState == QmlProfilerEventList::Done)
|
|
||||||
buildModel();
|
buildModel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -319,6 +416,11 @@ void QmlProfilerEventsMainView::setFieldViewable(Fields field, bool show)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QmlProfilerEventsMainView::ViewTypes QmlProfilerEventsMainView::viewType() const
|
||||||
|
{
|
||||||
|
return d->m_viewType;
|
||||||
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsMainView::setViewType(ViewTypes type)
|
void QmlProfilerEventsMainView::setViewType(ViewTypes type)
|
||||||
{
|
{
|
||||||
d->m_viewType = type;
|
d->m_viewType = type;
|
||||||
@@ -465,12 +567,12 @@ int QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::getFieldCount()
|
|||||||
|
|
||||||
void QmlProfilerEventsMainView::buildModel()
|
void QmlProfilerEventsMainView::buildModel()
|
||||||
{
|
{
|
||||||
if (d->m_eventStatistics) {
|
if (d->m_profilerDataModel) {
|
||||||
clear();
|
clear();
|
||||||
if (d->m_viewType == V8ProfileView)
|
if (d->m_viewType == V8ProfileView)
|
||||||
d->buildV8ModelFromList( d->m_eventStatistics->getV8Events() );
|
d->buildV8ModelFromList( d->m_profilerDataModel->getV8Events() );
|
||||||
else
|
else
|
||||||
d->buildModelFromList( d->m_eventStatistics->getEventDescriptions(), d->m_model->invisibleRootItem() );
|
d->buildModelFromList( d->m_profilerDataModel->getEventDescriptions(), d->m_model->invisibleRootItem() );
|
||||||
|
|
||||||
setShowExtendedStatistics(d->m_showExtendedStatistics);
|
setShowExtendedStatistics(d->m_showExtendedStatistics);
|
||||||
|
|
||||||
@@ -488,18 +590,15 @@ void QmlProfilerEventsMainView::buildModel()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildModelFromList( const QmlEventDescriptions &list, QStandardItem *parentItem, const QmlEventDescriptions &visitedFunctionsList )
|
void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildModelFromList( const QList<QmlRangeEventData *> &list, QStandardItem *parentItem)
|
||||||
{
|
{
|
||||||
foreach (QmlEventData *binding, list) {
|
foreach (QmlRangeEventData *binding, list) {
|
||||||
if (visitedFunctionsList.contains(binding))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (binding->calls == 0)
|
if (binding->calls == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QList<QStandardItem *> newRow;
|
QList<QStandardItem *> newRow;
|
||||||
if (m_fieldShown[Name]) {
|
if (m_fieldShown[Name]) {
|
||||||
newRow << new EventsViewItem(binding->displayname);
|
newRow << new EventsViewItem(binding->displayName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_fieldShown[Type]) {
|
if (m_fieldShown[Type]) {
|
||||||
@@ -572,7 +671,7 @@ void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildModelFrom
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildV8ModelFromList(const QV8EventDescriptions &list)
|
void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildV8ModelFromList(const QList<QV8EventData *> &list)
|
||||||
{
|
{
|
||||||
for (int index = 0; index < list.count(); index++) {
|
for (int index = 0; index < list.count(); index++) {
|
||||||
QV8EventData *v8event = list.at(index);
|
QV8EventData *v8event = list.at(index);
|
||||||
@@ -649,13 +748,17 @@ QString QmlProfilerEventsMainView::nameForType(int typeNumber)
|
|||||||
|
|
||||||
void QmlProfilerEventsMainView::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd)
|
void QmlProfilerEventsMainView::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd)
|
||||||
{
|
{
|
||||||
d->m_eventStatistics->compileStatistics(rangeStart, rangeEnd);
|
if (d->m_profilerDataModel)
|
||||||
|
d->m_profilerDataModel->compileStatistics(rangeStart, rangeEnd);
|
||||||
buildModel();
|
buildModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlProfilerEventsMainView::isRangeGlobal(qint64 rangeStart, qint64 rangeEnd) const
|
bool QmlProfilerEventsMainView::isRangeGlobal(qint64 rangeStart, qint64 rangeEnd) const
|
||||||
{
|
{
|
||||||
return d->m_eventStatistics->traceStartTime() == rangeStart && d->m_eventStatistics->traceEndTime() == rangeEnd;
|
if (d->m_profilerDataModel)
|
||||||
|
return d->m_profilerDataModel->traceStartTime() == rangeStart && d->m_profilerDataModel->traceEndTime() == rangeEnd;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QmlProfilerEventsMainView::selectedEventId() const
|
int QmlProfilerEventsMainView::selectedEventId() const
|
||||||
@@ -691,7 +794,7 @@ void QmlProfilerEventsMainView::jumpToItem(const QModelIndex &index)
|
|||||||
// show in callers/callees subwindow
|
// show in callers/callees subwindow
|
||||||
emit eventSelected(infoItem->data(EventIdRole).toInt());
|
emit eventSelected(infoItem->data(EventIdRole).toInt());
|
||||||
|
|
||||||
// show in timelineview
|
// show in timelinerenderer
|
||||||
if (d->m_viewType == EventsView) {
|
if (d->m_viewType == EventsView) {
|
||||||
emit showEventInTimeline(infoItem->data(EventIdRole).toInt());
|
emit showEventInTimeline(infoItem->data(EventIdRole).toInt());
|
||||||
}
|
}
|
||||||
@@ -819,9 +922,11 @@ void QmlProfilerEventsMainView::copyRowToClipboard() const
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
QmlProfilerEventsParentsAndChildrenView::QmlProfilerEventsParentsAndChildrenView(QmlJsDebugClient::QmlProfilerEventList *model, SubViewType subtableType, QWidget *parent):QTreeView(parent)
|
QmlProfilerEventsParentsAndChildrenView::QmlProfilerEventsParentsAndChildrenView(
|
||||||
|
SubViewType subtableType, QWidget *parent, QmlProfilerDataModel *model)
|
||||||
|
: QTreeView(parent)
|
||||||
{
|
{
|
||||||
m_eventList = model;
|
m_profilerDataModel = model;
|
||||||
setModel(new QStandardItemModel(this));
|
setModel(new QStandardItemModel(this));
|
||||||
setRootIsDecorated(false);
|
setRootIsDecorated(false);
|
||||||
setFrameStyle(QFrame::NoFrame);
|
setFrameStyle(QFrame::NoFrame);
|
||||||
@@ -843,30 +948,33 @@ void QmlProfilerEventsParentsAndChildrenView::setViewType(SubViewType type)
|
|||||||
|
|
||||||
void QmlProfilerEventsParentsAndChildrenView::displayEvent(int eventId)
|
void QmlProfilerEventsParentsAndChildrenView::displayEvent(int eventId)
|
||||||
{
|
{
|
||||||
|
if (!m_profilerDataModel)
|
||||||
|
return;
|
||||||
|
|
||||||
bool isV8 = m_subtableType == V8ParentsView || m_subtableType == V8ChildrenView;
|
bool isV8 = m_subtableType == V8ParentsView || m_subtableType == V8ChildrenView;
|
||||||
bool isChildren = m_subtableType == ChildrenView || m_subtableType == V8ChildrenView;
|
bool isChildren = m_subtableType == ChildrenView || m_subtableType == V8ChildrenView;
|
||||||
|
|
||||||
if (isV8) {
|
if (isV8) {
|
||||||
QmlJsDebugClient::QV8EventData *v8event = m_eventList->v8EventDescription(eventId);
|
QV8EventData *v8event = m_profilerDataModel->v8EventDescription(eventId);
|
||||||
if (v8event) {
|
if (v8event) {
|
||||||
if (isChildren) {
|
if (isChildren) {
|
||||||
QList <QmlJsDebugClient::QV8EventSub *> childrenList = v8event->childrenHash.values();
|
QList <QV8EventSub *> childrenList = v8event->childrenHash.values();
|
||||||
rebuildTree((QObject *)&childrenList);
|
rebuildTree((QObject *)&childrenList);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
QList <QmlJsDebugClient::QV8EventSub *> parentList = v8event->parentHash.values();
|
QList <QV8EventSub *> parentList = v8event->parentHash.values();
|
||||||
rebuildTree((QObject *)&parentList);
|
rebuildTree((QObject *)&parentList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
QmlJsDebugClient::QmlEventData *qmlEvent = m_eventList->eventDescription(eventId);
|
QmlRangeEventData *qmlEvent = m_profilerDataModel->eventDescription(eventId);
|
||||||
if (qmlEvent) {
|
if (qmlEvent) {
|
||||||
if (isChildren) {
|
if (isChildren) {
|
||||||
QList <QmlJsDebugClient::QmlEventSub *> childrenList = qmlEvent->childrenHash.values();
|
QList <QmlRangeEventRelative *> childrenList = qmlEvent->childrenHash.values();
|
||||||
rebuildTree((QObject *)&childrenList);
|
rebuildTree((QObject *)&childrenList);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
QList <QmlJsDebugClient::QmlEventSub *> parentList = qmlEvent->parentHash.values();
|
QList <QmlRangeEventRelative *> parentList = qmlEvent->parentHash.values();
|
||||||
rebuildTree((QObject *)&parentList);
|
rebuildTree((QObject *)&parentList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -881,7 +989,7 @@ void QmlProfilerEventsParentsAndChildrenView::displayEvent(int eventId)
|
|||||||
sortByColumn(2);
|
sortByColumn(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList)
|
void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *profilerDataModel)
|
||||||
{
|
{
|
||||||
Q_ASSERT(treeModel());
|
Q_ASSERT(treeModel());
|
||||||
treeModel()->clear();
|
treeModel()->clear();
|
||||||
@@ -889,8 +997,8 @@ void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList)
|
|||||||
QStandardItem *topLevelItem = treeModel()->invisibleRootItem();
|
QStandardItem *topLevelItem = treeModel()->invisibleRootItem();
|
||||||
bool isV8 = m_subtableType == V8ParentsView || m_subtableType == V8ChildrenView;
|
bool isV8 = m_subtableType == V8ParentsView || m_subtableType == V8ChildrenView;
|
||||||
|
|
||||||
QList <QmlEventSub *> *qmlList = static_cast< QList <QmlEventSub *> *>(eventList);
|
QList <QmlRangeEventRelative *> *qmlList = static_cast< QList <QmlRangeEventRelative *> *>(profilerDataModel);
|
||||||
QList <QV8EventSub*> *v8List = static_cast< QList <QV8EventSub *> *>(eventList);
|
QList <QV8EventSub*> *v8List = static_cast< QList <QV8EventSub *> *>(profilerDataModel);
|
||||||
|
|
||||||
int listLength;
|
int listLength;
|
||||||
if (!isV8)
|
if (!isV8)
|
||||||
@@ -901,9 +1009,9 @@ void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList)
|
|||||||
for (int index=0; index < listLength; index++) {
|
for (int index=0; index < listLength; index++) {
|
||||||
QList<QStandardItem *> newRow;
|
QList<QStandardItem *> newRow;
|
||||||
if (!isV8) {
|
if (!isV8) {
|
||||||
QmlEventSub *event = qmlList->at(index);
|
QmlRangeEventRelative *event = qmlList->at(index);
|
||||||
|
|
||||||
newRow << new EventsViewItem(event->reference->displayname);
|
newRow << new EventsViewItem(event->reference->displayName);
|
||||||
newRow << new EventsViewItem(QmlProfilerEventsMainView::nameForType(event->reference->eventType));
|
newRow << new EventsViewItem(QmlProfilerEventsMainView::nameForType(event->reference->eventType));
|
||||||
newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event->duration));
|
newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event->duration));
|
||||||
newRow << new EventsViewItem(QString::number(event->calls));
|
newRow << new EventsViewItem(QString::number(event->calls));
|
||||||
|
@@ -34,9 +34,13 @@
|
|||||||
#define QMLPROFILEREVENTVIEW_H
|
#define QMLPROFILEREVENTVIEW_H
|
||||||
|
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
#include <qmljsdebugclient/qmlprofilereventtypes.h>
|
|
||||||
#include <qmljsdebugclient/qmlprofilereventlist.h>
|
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
|
#include <qmljsdebugclient/qmlprofilereventtypes.h>
|
||||||
|
#include "qmlprofilerdatamodel.h"
|
||||||
|
|
||||||
|
#include <analyzerbase/ianalyzertool.h>
|
||||||
|
|
||||||
|
#include "qmlprofilerviewmanager.h"
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -44,9 +48,6 @@ namespace Internal {
|
|||||||
class QmlProfilerEventsMainView;
|
class QmlProfilerEventsMainView;
|
||||||
class QmlProfilerEventsParentsAndChildrenView;
|
class QmlProfilerEventsParentsAndChildrenView;
|
||||||
|
|
||||||
typedef QHash<QString, QmlJsDebugClient::QmlEventData *> QmlEventHash;
|
|
||||||
typedef QList<QmlJsDebugClient::QmlEventData *> QmlEventList;
|
|
||||||
|
|
||||||
enum ItemRole {
|
enum ItemRole {
|
||||||
EventHashStrRole = Qt::UserRole+1,
|
EventHashStrRole = Qt::UserRole+1,
|
||||||
FilenameRole = Qt::UserRole+2,
|
FilenameRole = Qt::UserRole+2,
|
||||||
@@ -59,7 +60,10 @@ class QmlProfilerEventsWidget : public QWidget
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit QmlProfilerEventsWidget(QmlJsDebugClient::QmlProfilerEventList *model, QWidget *parent);
|
explicit QmlProfilerEventsWidget(QWidget *parent,
|
||||||
|
Analyzer::IAnalyzerTool *profilerTool,
|
||||||
|
QmlProfilerViewManager *container,
|
||||||
|
QmlProfilerDataModel *profilerDataModel );
|
||||||
~QmlProfilerEventsWidget();
|
~QmlProfilerEventsWidget();
|
||||||
|
|
||||||
void switchToV8View();
|
void switchToV8View();
|
||||||
@@ -75,9 +79,11 @@ public:
|
|||||||
void setShowExtendedStatistics(bool show);
|
void setShowExtendedStatistics(bool show);
|
||||||
bool showExtendedStatistics() const;
|
bool showExtendedStatistics() const;
|
||||||
|
|
||||||
|
bool isQml() const;
|
||||||
|
bool isV8() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
|
void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
|
||||||
void contextMenuRequested(const QPoint &position);
|
|
||||||
void showEventInTimeline(int eventId);
|
void showEventInTimeline(int eventId);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
@@ -85,18 +91,14 @@ public slots:
|
|||||||
void selectBySourceLocation(const QString &filename, int line, int column);
|
void selectBySourceLocation(const QString &filename, int line, int column);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void eventListStateChanged();
|
void profilerDataModelStateChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void contextMenuEvent(QContextMenuEvent *ev);
|
void contextMenuEvent(QContextMenuEvent *ev);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QmlProfilerEventsMainView *m_eventTree;
|
class QmlProfilerEventsWidgetPrivate;
|
||||||
QmlProfilerEventsParentsAndChildrenView *m_eventChildren;
|
QmlProfilerEventsWidgetPrivate *d;
|
||||||
QmlProfilerEventsParentsAndChildrenView *m_eventParents;
|
|
||||||
QmlJsDebugClient::QmlProfilerEventList *m_eventStatistics;
|
|
||||||
|
|
||||||
bool m_globalStatsEnabled;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class QmlProfilerEventsMainView : public QTreeView
|
class QmlProfilerEventsMainView : public QTreeView
|
||||||
@@ -129,12 +131,14 @@ public:
|
|||||||
MaxViewTypes
|
MaxViewTypes
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit QmlProfilerEventsMainView(QmlJsDebugClient::QmlProfilerEventList *model, QWidget *parent);
|
explicit QmlProfilerEventsMainView(ViewTypes viewType,
|
||||||
|
QWidget *parent,
|
||||||
|
QmlProfilerDataModel *dataModel);
|
||||||
~QmlProfilerEventsMainView();
|
~QmlProfilerEventsMainView();
|
||||||
|
|
||||||
void setEventStatisticsModel(QmlJsDebugClient::QmlProfilerEventList *model);
|
|
||||||
void setFieldViewable(Fields field, bool show);
|
void setFieldViewable(Fields field, bool show);
|
||||||
void setViewType(ViewTypes type);
|
void setViewType(ViewTypes type);
|
||||||
|
ViewTypes viewType() const;
|
||||||
void setShowAnonymousEvents( bool showThem );
|
void setShowAnonymousEvents( bool showThem );
|
||||||
|
|
||||||
QModelIndex selectedItem() const;
|
QModelIndex selectedItem() const;
|
||||||
@@ -157,7 +161,6 @@ signals:
|
|||||||
void showEventInTimeline(int eventId);
|
void showEventInTimeline(int eventId);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void eventListStateChanged();
|
|
||||||
void clear();
|
void clear();
|
||||||
void jumpToItem(const QModelIndex &index);
|
void jumpToItem(const QModelIndex &index);
|
||||||
void selectEvent(int eventId);
|
void selectEvent(int eventId);
|
||||||
@@ -165,6 +168,9 @@ public slots:
|
|||||||
void buildModel();
|
void buildModel();
|
||||||
void changeDetailsForEvent(int eventId, const QString &newString);
|
void changeDetailsForEvent(int eventId, const QString &newString);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void profilerDataModelStateChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setHeaderLabels();
|
void setHeaderLabels();
|
||||||
|
|
||||||
@@ -186,7 +192,9 @@ public:
|
|||||||
MaxSubtableTypes
|
MaxSubtableTypes
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit QmlProfilerEventsParentsAndChildrenView(QmlJsDebugClient::QmlProfilerEventList *model, SubViewType subtableType, QWidget *parent);
|
explicit QmlProfilerEventsParentsAndChildrenView(SubViewType subtableType,
|
||||||
|
QWidget *parent,
|
||||||
|
QmlProfilerDataModel *model);
|
||||||
~QmlProfilerEventsParentsAndChildrenView();
|
~QmlProfilerEventsParentsAndChildrenView();
|
||||||
|
|
||||||
void setViewType(SubViewType type);
|
void setViewType(SubViewType type);
|
||||||
@@ -200,10 +208,10 @@ public slots:
|
|||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void rebuildTree(void *eventList);
|
void rebuildTree(void *profilerDataModel);
|
||||||
void updateHeader();
|
void updateHeader();
|
||||||
QStandardItemModel *treeModel();
|
QStandardItemModel *treeModel();
|
||||||
QmlJsDebugClient::QmlProfilerEventList *m_eventList;
|
QmlProfilerDataModel *m_profilerDataModel;
|
||||||
|
|
||||||
SubViewType m_subtableType;
|
SubViewType m_subtableType;
|
||||||
};
|
};
|
||||||
|
163
src/plugins/qmlprofiler/qmlprofilerstatemanager.cpp
Normal file
163
src/plugins/qmlprofiler/qmlprofilerstatemanager.cpp
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "qmlprofilerstatemanager.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
// uncomment for printing the state changes to debug output
|
||||||
|
//#define _DEBUG_PROFILERSTATE_
|
||||||
|
|
||||||
|
namespace QmlProfiler {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
inline QString stringForState(int state) {
|
||||||
|
switch (state) {
|
||||||
|
case QmlProfilerStateManager::Idle: return QString("Idle");
|
||||||
|
case QmlProfilerStateManager::AppStarting: return QString("AppStarting");
|
||||||
|
case QmlProfilerStateManager::AppRunning: return QString("AppRunning");
|
||||||
|
case QmlProfilerStateManager::AppStopRequested: return QString("AppStopRequested");
|
||||||
|
case QmlProfilerStateManager::AppReadyToStop: return QString("AppReadyToStop");
|
||||||
|
case QmlProfilerStateManager::AppStopped: return QString("AppStopped");
|
||||||
|
case QmlProfilerStateManager::AppKilled: return QString("AppKilled");
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
class QmlProfilerStateManager::QmlProfilerStateManagerPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QmlProfilerStateManagerPrivate(QmlProfilerStateManager *qq) : q(qq) {}
|
||||||
|
~QmlProfilerStateManagerPrivate() {}
|
||||||
|
|
||||||
|
QmlProfilerStateManager *q;
|
||||||
|
|
||||||
|
QmlProfilerStateManager::QmlProfilerState m_currentState;
|
||||||
|
bool m_clientRecording;
|
||||||
|
bool m_serverRecording;
|
||||||
|
};
|
||||||
|
QmlProfilerStateManager::QmlProfilerStateManager(QObject *parent) :
|
||||||
|
QObject(parent),d(new QmlProfilerStateManagerPrivate(this))
|
||||||
|
{
|
||||||
|
d->m_currentState = Idle;
|
||||||
|
d->m_clientRecording = true;
|
||||||
|
d->m_serverRecording = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlProfilerStateManager::~QmlProfilerStateManager()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlProfilerStateManager::QmlProfilerState QmlProfilerStateManager::currentState()
|
||||||
|
{
|
||||||
|
return d->m_currentState;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlProfilerStateManager::clientRecording()
|
||||||
|
{
|
||||||
|
return d->m_clientRecording;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlProfilerStateManager::serverRecording()
|
||||||
|
{
|
||||||
|
return d->m_serverRecording;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QmlProfilerStateManager::currentStateAsString()
|
||||||
|
{
|
||||||
|
return stringForState(d->m_currentState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerStateManager::setCurrentState(QmlProfilerState newState)
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG_PROFILERSTATE_
|
||||||
|
qDebug() << "Profiler state change request from" << stringForState(d->m_currentState) << "to" << stringForState(newState);
|
||||||
|
#endif
|
||||||
|
QTC_ASSERT(d->m_currentState != newState, /**/);
|
||||||
|
switch (newState) {
|
||||||
|
case Idle:
|
||||||
|
QTC_ASSERT(d->m_currentState == AppStarting || d->m_currentState == AppStopped || d->m_currentState == AppKilled, /**/);
|
||||||
|
break;
|
||||||
|
case AppStarting:
|
||||||
|
QTC_ASSERT(d->m_currentState == Idle, /**/);
|
||||||
|
break;
|
||||||
|
case AppRunning:
|
||||||
|
QTC_ASSERT(d->m_currentState == AppStarting, /**/);
|
||||||
|
break;
|
||||||
|
case AppStopRequested:
|
||||||
|
QTC_ASSERT(d->m_currentState == AppRunning, /**/);
|
||||||
|
break;
|
||||||
|
case AppReadyToStop:
|
||||||
|
QTC_ASSERT(d->m_currentState == AppStopRequested, /**/);
|
||||||
|
break;
|
||||||
|
case AppStopped:
|
||||||
|
QTC_ASSERT(d->m_currentState == AppReadyToStop, /**/);
|
||||||
|
break;
|
||||||
|
case AppKilled:
|
||||||
|
QTC_ASSERT(d->m_currentState == AppRunning, /**/);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qDebug() << tr("Switching to unknown state in %1:%2").arg(QString(__FILE__), QString::number(__LINE__));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->m_currentState = newState;
|
||||||
|
emit stateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerStateManager::setClientRecording(bool recording)
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG_PROFILERSTATE_
|
||||||
|
qDebug() << "Setting client recording flag from" << d->m_serverRecording << "to" << recording;
|
||||||
|
#endif
|
||||||
|
if (d->m_clientRecording != recording) {
|
||||||
|
d->m_clientRecording = recording;
|
||||||
|
emit clientRecordingChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerStateManager::setServerRecording(bool recording)
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG_PROFILERSTATE_
|
||||||
|
qDebug() << "Setting server recording flag from" << d->m_serverRecording << "to" << recording;
|
||||||
|
#endif
|
||||||
|
if (d->m_serverRecording != recording) {
|
||||||
|
d->m_serverRecording = recording;
|
||||||
|
emit serverRecordingChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -30,25 +30,53 @@
|
|||||||
**
|
**
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#ifndef COMMANDLISTENER_H
|
#ifndef QMLPROFILERSTATEMANAGER_H
|
||||||
#define COMMANDLISTENER_H
|
#define QMLPROFILERSTATEMANAGER_H
|
||||||
|
|
||||||
#include <QThread>
|
#include <QObject>
|
||||||
|
|
||||||
class CommandListener : public QThread
|
namespace QmlProfiler {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class QmlProfilerStateManager : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
CommandListener(QObject *parent = 0);
|
enum QmlProfilerState {
|
||||||
|
Idle,
|
||||||
void run();
|
AppStarting,
|
||||||
|
AppRunning,
|
||||||
void requestStop() { m_stopRequested = true; }
|
AppStopRequested,
|
||||||
signals:
|
AppReadyToStop,
|
||||||
void command(const QString &command);
|
AppStopped,
|
||||||
|
AppKilled
|
||||||
private:
|
|
||||||
bool m_stopRequested;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // COMMANDLISTENER_H
|
explicit QmlProfilerStateManager(QObject *parent = 0);
|
||||||
|
~QmlProfilerStateManager();
|
||||||
|
|
||||||
|
QmlProfilerState currentState();
|
||||||
|
bool clientRecording();
|
||||||
|
bool serverRecording();
|
||||||
|
|
||||||
|
QString currentStateAsString();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void stateChanged();
|
||||||
|
void clientRecordingChanged();
|
||||||
|
void serverRecordingChanged();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setCurrentState(QmlProfilerState newState);
|
||||||
|
void setClientRecording(bool recording);
|
||||||
|
void setServerRecording(bool recording);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class QmlProfilerStateManagerPrivate;
|
||||||
|
QmlProfilerStateManagerPrivate *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // QMLPROFILERSTATEMANAGER_H
|
@@ -31,24 +31,20 @@
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "qmlprofilertool.h"
|
#include "qmlprofilertool.h"
|
||||||
|
#include "qmlprofilerstatemanager.h"
|
||||||
#include "qmlprofilerengine.h"
|
#include "qmlprofilerengine.h"
|
||||||
#include "qmlprofilerplugin.h"
|
|
||||||
#include "qmlprofilerconstants.h"
|
#include "qmlprofilerconstants.h"
|
||||||
#include "qmlprofilerattachdialog.h"
|
#include "qmlprofilerattachdialog.h"
|
||||||
#include "qmlprofilereventview.h"
|
#include "qmlprofilerviewmanager.h"
|
||||||
|
#include "qmlprofilerclientmanager.h"
|
||||||
#include "tracewindow.h"
|
#include "qmlprofilerdatamodel.h"
|
||||||
#include "timelineview.h"
|
#include "qmlprofilerdetailsrewriter.h"
|
||||||
|
#include "timelinerenderer.h"
|
||||||
#include <qmljsdebugclient/qmlprofilereventlist.h>
|
|
||||||
#include <qmljsdebugclient/qdeclarativedebugclient.h>
|
|
||||||
|
|
||||||
#include <analyzerbase/analyzermanager.h>
|
#include <analyzerbase/analyzermanager.h>
|
||||||
#include <analyzerbase/analyzerconstants.h>
|
|
||||||
#include <analyzerbase/analyzerruncontrol.h>
|
#include <analyzerbase/analyzerruncontrol.h>
|
||||||
|
|
||||||
#include "canvas/qdeclarativecanvas_p.h"
|
#include "canvas/qdeclarativecontext2d_p.h"
|
||||||
#include "canvas/qdeclarativecanvastimer_p.h"
|
|
||||||
#include "canvas/qmlprofilercanvas.h"
|
#include "canvas/qmlprofilercanvas.h"
|
||||||
|
|
||||||
#include <qmlprojectmanager/qmlprojectrunconfiguration.h>
|
#include <qmlprojectmanager/qmlprojectrunconfiguration.h>
|
||||||
@@ -56,7 +52,6 @@
|
|||||||
#include <utils/fileinprojectfinder.h>
|
#include <utils/fileinprojectfinder.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
|
||||||
#include <projectexplorer/project.h>
|
#include <projectexplorer/project.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
@@ -65,7 +60,6 @@
|
|||||||
#include <remotelinux/remotelinuxrunconfiguration.h>
|
#include <remotelinux/remotelinuxrunconfiguration.h>
|
||||||
#include <remotelinux/linuxdeviceconfiguration.h>
|
#include <remotelinux/linuxdeviceconfiguration.h>
|
||||||
|
|
||||||
#include <texteditor/itexteditor.h>
|
|
||||||
#include <coreplugin/coreconstants.h>
|
#include <coreplugin/coreconstants.h>
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
@@ -82,23 +76,22 @@
|
|||||||
#include <qt4projectmanager/qt-s60/s60devicerunconfiguration.h>
|
#include <qt4projectmanager/qt-s60/s60devicerunconfiguration.h>
|
||||||
#include <qt4projectmanager/qt-s60/s60deployconfiguration.h>
|
#include <qt4projectmanager/qt-s60/s60deployconfiguration.h>
|
||||||
|
|
||||||
#include <QFile>
|
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QTabWidget>
|
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QDockWidget>
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QTime>
|
||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace Core::Constants;
|
using namespace Core::Constants;
|
||||||
using namespace Analyzer;
|
using namespace Analyzer;
|
||||||
using namespace Analyzer::Constants;
|
using namespace Analyzer::Constants;
|
||||||
using namespace QmlProfiler::Internal;
|
using namespace QmlProfiler::Internal;
|
||||||
|
using namespace QmlProfiler::Constants;
|
||||||
using namespace QmlJsDebugClient;
|
using namespace QmlJsDebugClient;
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
using namespace QmlProjectManager;
|
using namespace QmlProjectManager;
|
||||||
@@ -112,59 +105,67 @@ public:
|
|||||||
|
|
||||||
QmlProfilerTool *q;
|
QmlProfilerTool *q;
|
||||||
|
|
||||||
QDeclarativeDebugConnection *m_client;
|
QmlProfilerStateManager *m_profilerState;
|
||||||
QTimer m_connectionTimer;
|
QmlProfilerClientManager *m_profilerConnections;
|
||||||
int m_connectionAttempts;
|
QmlProfilerDataModel *m_profilerDataModel;
|
||||||
TraceWindow *m_traceWindow;
|
QmlProfilerDetailsRewriter *m_detailsRewriter;
|
||||||
QmlProfilerEventsWidget *m_eventsView;
|
|
||||||
QmlProfilerEventsWidget *m_v8profilerView;
|
QmlProfilerViewManager *m_viewContainer;
|
||||||
Utils::FileInProjectFinder m_projectFinder;
|
Utils::FileInProjectFinder m_projectFinder;
|
||||||
RunConfiguration *m_runConfiguration;
|
RunConfiguration *m_runConfiguration;
|
||||||
bool m_isAttached;
|
|
||||||
QToolButton *m_recordButton;
|
QToolButton *m_recordButton;
|
||||||
QToolButton *m_clearButton;
|
QToolButton *m_clearButton;
|
||||||
bool m_recordingEnabled;
|
|
||||||
bool m_appIsRunning;
|
|
||||||
bool m_qmlActive;
|
|
||||||
bool m_v8Active;
|
|
||||||
QTime m_appTimer;
|
|
||||||
qint64 m_appRunningTime;
|
|
||||||
|
|
||||||
enum ConnectMode {
|
// elapsed time display
|
||||||
TcpConnection, OstConnection
|
QTimer m_recordingTimer;
|
||||||
};
|
QTime m_recordingElapsedTime;
|
||||||
|
QLabel *m_timeLabel;
|
||||||
|
|
||||||
ConnectMode m_connectMode;
|
// save and load actions
|
||||||
QString m_tcpHost;
|
|
||||||
quint16 m_tcpPort;
|
|
||||||
QString m_ostDevice;
|
|
||||||
QString m_sysroot;
|
|
||||||
QAction *m_saveQmlTrace;
|
QAction *m_saveQmlTrace;
|
||||||
|
QAction *m_loadQmlTrace;
|
||||||
};
|
};
|
||||||
|
|
||||||
QmlProfilerTool::QmlProfilerTool(QObject *parent)
|
QmlProfilerTool::QmlProfilerTool(QObject *parent)
|
||||||
: IAnalyzerTool(parent), d(new QmlProfilerToolPrivate(this))
|
: IAnalyzerTool(parent), d(new QmlProfilerToolPrivate(this))
|
||||||
{
|
{
|
||||||
setObjectName("QmlProfilerTool");
|
setObjectName("QmlProfilerTool");
|
||||||
d->m_client = 0;
|
|
||||||
d->m_connectionAttempts = 0;
|
d->m_profilerState = 0;
|
||||||
d->m_traceWindow = 0;
|
d->m_viewContainer = 0;
|
||||||
d->m_runConfiguration = 0;
|
d->m_runConfiguration = 0;
|
||||||
d->m_isAttached = false;
|
|
||||||
d->m_recordingEnabled = true;
|
|
||||||
d->m_appIsRunning = false;
|
|
||||||
d->m_appTimer.start();
|
|
||||||
d->m_appRunningTime = 0;
|
|
||||||
|
|
||||||
d->m_connectionTimer.setInterval(200);
|
|
||||||
connect(&d->m_connectionTimer, SIGNAL(timeout()), SLOT(tryToConnect()));
|
|
||||||
|
|
||||||
qmlRegisterType<Canvas>("Monitor", 1, 0, "Canvas");
|
|
||||||
qmlRegisterType<QmlProfilerCanvas>("Monitor", 1, 0, "Canvas2D");
|
qmlRegisterType<QmlProfilerCanvas>("Monitor", 1, 0, "Canvas2D");
|
||||||
qmlRegisterType<Context2D>();
|
qmlRegisterType<Context2D>();
|
||||||
qmlRegisterType<CanvasImage>();
|
|
||||||
qmlRegisterType<CanvasGradient>();
|
qmlRegisterType<CanvasGradient>();
|
||||||
qmlRegisterType<TimelineView>("Monitor", 1, 0,"TimelineView");
|
qmlRegisterType<TimelineRenderer>("Monitor", 1, 0,"TimelineRenderer");
|
||||||
|
|
||||||
|
d->m_profilerState = new QmlProfilerStateManager(this);
|
||||||
|
connect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged()));
|
||||||
|
connect(d->m_profilerState, SIGNAL(clientRecordingChanged()), this, SLOT(clientRecordingChanged()));
|
||||||
|
connect(d->m_profilerState, SIGNAL(serverRecordingChanged()), this, SLOT(serverRecordingChanged()));
|
||||||
|
|
||||||
|
d->m_profilerConnections = new QmlProfilerClientManager(this);
|
||||||
|
d->m_profilerConnections->registerProfilerStateManager(d->m_profilerState);
|
||||||
|
|
||||||
|
d->m_profilerDataModel = new QmlProfilerDataModel(this);
|
||||||
|
connect(d->m_profilerDataModel, SIGNAL(stateChanged()), this, SLOT(profilerDataModelStateChanged()));
|
||||||
|
connect(d->m_profilerDataModel, SIGNAL(error(QString)), this, SLOT(showErrorDialog(QString)));
|
||||||
|
connect(d->m_profilerConnections, SIGNAL(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)), d->m_profilerDataModel, SLOT(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
|
||||||
|
connect(d->m_profilerConnections, SIGNAL(addV8Event(int,QString,QString,int,double,double)), d->m_profilerDataModel, SLOT(addV8Event(int,QString,QString,int,double,double)));
|
||||||
|
connect(d->m_profilerConnections, SIGNAL(addFrameEvent(qint64,int,int)), d->m_profilerDataModel, SLOT(addFrameEvent(qint64,int,int)));
|
||||||
|
connect(d->m_profilerConnections, SIGNAL(traceStarted(qint64)), d->m_profilerDataModel, SLOT(setTraceStartTime(qint64)));
|
||||||
|
connect(d->m_profilerConnections, SIGNAL(traceFinished(qint64)), d->m_profilerDataModel, SLOT(setTraceEndTime(qint64)));
|
||||||
|
connect(d->m_profilerConnections, SIGNAL(dataReadyForProcessing()), d->m_profilerDataModel, SLOT(complete()));
|
||||||
|
|
||||||
|
|
||||||
|
d->m_detailsRewriter = new QmlProfilerDetailsRewriter(this);
|
||||||
|
connect(d->m_profilerDataModel, SIGNAL(requestDetailsForLocation(int,QmlJsDebugClient::QmlEventLocation)),
|
||||||
|
d->m_detailsRewriter, SLOT(requestDetailsForLocation(int,QmlJsDebugClient::QmlEventLocation)));
|
||||||
|
connect(d->m_detailsRewriter, SIGNAL(rewriteDetailsString(int,QmlJsDebugClient::QmlEventLocation,QString)),
|
||||||
|
d->m_profilerDataModel, SLOT(rewriteDetailsString(int,QmlJsDebugClient::QmlEventLocation,QString)));
|
||||||
|
connect(d->m_detailsRewriter, SIGNAL(eventDetailsChanged()), d->m_profilerDataModel, SLOT(finishedRewritingDetails()));
|
||||||
|
connect(d->m_profilerDataModel, SIGNAL(reloadDocumentsForDetails()), d->m_detailsRewriter, SLOT(reloadDocuments()));
|
||||||
|
|
||||||
Command *command = 0;
|
Command *command = 0;
|
||||||
const Context globalContext(C_GLOBAL);
|
const Context globalContext(C_GLOBAL);
|
||||||
@@ -176,7 +177,7 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
|
|||||||
menu->addMenu(options, G_ANALYZER_OPTIONS);
|
menu->addMenu(options, G_ANALYZER_OPTIONS);
|
||||||
options->menu()->setEnabled(true);
|
options->menu()->setEnabled(true);
|
||||||
|
|
||||||
QAction *act = new QAction(tr("Load QML Trace"), options);
|
QAction *act = d->m_loadQmlTrace = new QAction(tr("Load QML Trace"), options);
|
||||||
command = am->registerAction(act, "Analyzer.Menu.StartAnalyzer.QMLProfilerOptions.LoadQMLTrace", globalContext);
|
command = am->registerAction(act, "Analyzer.Menu.StartAnalyzer.QMLProfilerOptions.LoadQMLTrace", globalContext);
|
||||||
connect(act, SIGNAL(triggered()), this, SLOT(showLoadDialog()));
|
connect(act, SIGNAL(triggered()), this, SLOT(showLoadDialog()));
|
||||||
options->addAction(command);
|
options->addAction(command);
|
||||||
@@ -186,11 +187,13 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
|
|||||||
command = am->registerAction(act, "Analyzer.Menu.StartAnalyzer.QMLProfilerOptions.SaveQMLTrace", globalContext);
|
command = am->registerAction(act, "Analyzer.Menu.StartAnalyzer.QMLProfilerOptions.SaveQMLTrace", globalContext);
|
||||||
connect(act, SIGNAL(triggered()), this, SLOT(showSaveDialog()));
|
connect(act, SIGNAL(triggered()), this, SLOT(showSaveDialog()));
|
||||||
options->addAction(command);
|
options->addAction(command);
|
||||||
|
|
||||||
|
d->m_recordingTimer.setInterval(100);
|
||||||
|
connect(&d->m_recordingTimer, SIGNAL(timeout()), this, SLOT(updateTimeDisplay()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlProfilerTool::~QmlProfilerTool()
|
QmlProfilerTool::~QmlProfilerTool()
|
||||||
{
|
{
|
||||||
delete d->m_client;
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,86 +223,14 @@ IAnalyzerTool::ToolMode QmlProfilerTool::toolMode() const
|
|||||||
return AnyMode;
|
return AnyMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerTool::showContextMenu(const QPoint &position)
|
|
||||||
{
|
|
||||||
QmlProfilerEventsWidget *eventView = qobject_cast<QmlProfilerEventsWidget *>(sender());
|
|
||||||
TraceWindow *traceView = qobject_cast<TraceWindow *>(sender());
|
|
||||||
|
|
||||||
QMenu menu;
|
|
||||||
QAction *loadAction = menu.addAction(tr("Load QML Trace"));
|
|
||||||
QAction *saveAction = menu.addAction(tr("Save QML Trace"));
|
|
||||||
QAction *copyRowAction = 0;
|
|
||||||
QAction *copyTableAction = 0;
|
|
||||||
QAction *showExtendedStatsAction = 0;
|
|
||||||
QAction *viewAllAction = 0;
|
|
||||||
QAction *getLocalStatsAction = 0;
|
|
||||||
QAction *getGlobalStatsAction = 0;
|
|
||||||
|
|
||||||
if (eventView && eventView->mouseOnTable(position)) {
|
|
||||||
menu.addSeparator();
|
|
||||||
if (eventView->selectedItem().isValid())
|
|
||||||
copyRowAction = menu.addAction(tr("Copy Row"));
|
|
||||||
copyTableAction = menu.addAction(tr("Copy Table"));
|
|
||||||
|
|
||||||
if (eventView == d->m_eventsView) {
|
|
||||||
// only for qml events view, not for v8
|
|
||||||
showExtendedStatsAction = menu.addAction(tr("Extended Event Statistics"));
|
|
||||||
showExtendedStatsAction->setCheckable(true);
|
|
||||||
showExtendedStatsAction->setChecked(eventView->showExtendedStatistics());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sender() == d->m_traceWindow || sender() == d->m_eventsView) {
|
|
||||||
menu.addSeparator();
|
|
||||||
getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range"));
|
|
||||||
if (!d->m_traceWindow->hasValidSelection())
|
|
||||||
getLocalStatsAction->setEnabled(false);
|
|
||||||
getGlobalStatsAction = menu.addAction(tr("Reset Events Pane"));
|
|
||||||
if (d->m_eventsView->hasGlobalStats())
|
|
||||||
getGlobalStatsAction->setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (traceView) {
|
|
||||||
if (traceView->getEventList()->count() > 0) {
|
|
||||||
menu.addSeparator();
|
|
||||||
viewAllAction = menu.addAction(tr("Reset Zoom"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction *selectedAction = menu.exec(position);
|
|
||||||
|
|
||||||
if (selectedAction) {
|
|
||||||
if (selectedAction == loadAction)
|
|
||||||
showLoadDialog();
|
|
||||||
if (selectedAction == saveAction)
|
|
||||||
showSaveDialog();
|
|
||||||
if (selectedAction == copyRowAction)
|
|
||||||
eventView->copyRowToClipboard();
|
|
||||||
if (selectedAction == copyTableAction)
|
|
||||||
eventView->copyTableToClipboard();
|
|
||||||
if (selectedAction == viewAllAction)
|
|
||||||
traceView->viewAll();
|
|
||||||
if (selectedAction == getLocalStatsAction) {
|
|
||||||
d->m_eventsView->getStatisticsInRange(
|
|
||||||
d->m_traceWindow->selectionStart(),
|
|
||||||
d->m_traceWindow->selectionEnd());
|
|
||||||
}
|
|
||||||
if (selectedAction == getGlobalStatsAction) {
|
|
||||||
d->m_eventsView->getStatisticsInRange(
|
|
||||||
d->m_traceWindow->getEventList()->traceStartTime(),
|
|
||||||
d->m_traceWindow->getEventList()->traceEndTime());
|
|
||||||
}
|
|
||||||
if (selectedAction == showExtendedStatsAction)
|
|
||||||
eventView->setShowExtendedStatistics(!eventView->showExtendedStatistics());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp,
|
IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp,
|
||||||
RunConfiguration *runConfiguration)
|
RunConfiguration *runConfiguration)
|
||||||
{
|
{
|
||||||
QmlProfilerEngine *engine = new QmlProfilerEngine(this, sp, runConfiguration);
|
QmlProfilerEngine *engine = new QmlProfilerEngine(this, sp, runConfiguration);
|
||||||
|
|
||||||
d->m_connectMode = QmlProfilerToolPrivate::TcpConnection;
|
engine->registerProfilerStateManager(d->m_profilerState);
|
||||||
|
|
||||||
|
bool isTcpConnection = true;
|
||||||
|
|
||||||
if (runConfiguration) {
|
if (runConfiguration) {
|
||||||
// Check minimum Qt Version. We cannot really be sure what the Qt version
|
// Check minimum Qt Version. We cannot really be sure what the Qt version
|
||||||
@@ -324,16 +255,15 @@ IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp
|
|||||||
runConfiguration->target()->activeDeployConfiguration())) {
|
runConfiguration->target()->activeDeployConfiguration())) {
|
||||||
if (deployConfig->communicationChannel()
|
if (deployConfig->communicationChannel()
|
||||||
== Qt4ProjectManager::S60DeployConfiguration::CommunicationCodaSerialConnection) {
|
== Qt4ProjectManager::S60DeployConfiguration::CommunicationCodaSerialConnection) {
|
||||||
d->m_connectMode = QmlProfilerToolPrivate::OstConnection;
|
d->m_profilerConnections->setOstConnection(deployConfig->serialPortName());
|
||||||
d->m_ostDevice = deployConfig->serialPortName();
|
isTcpConnection = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Check that there's something sensible in sp.connParams
|
// FIXME: Check that there's something sensible in sp.connParams
|
||||||
if (d->m_connectMode == QmlProfilerToolPrivate::TcpConnection) {
|
if (isTcpConnection) {
|
||||||
d->m_tcpHost = sp.connParams.host;
|
d->m_profilerConnections->setTcpConnection(sp.connParams.host, sp.connParams.port);
|
||||||
d->m_tcpPort = sp.connParams.port;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
d->m_runConfiguration = runConfiguration;
|
d->m_runConfiguration = runConfiguration;
|
||||||
@@ -364,20 +294,9 @@ IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp
|
|||||||
d->m_projectFinder.setProjectFiles(sourceFiles);
|
d->m_projectFinder.setProjectFiles(sourceFiles);
|
||||||
d->m_projectFinder.setSysroot(sp.sysroot);
|
d->m_projectFinder.setSysroot(sp.sysroot);
|
||||||
|
|
||||||
connect(engine, SIGNAL(processRunning(quint16)), this, SLOT(connectClient(quint16)));
|
connect(engine, SIGNAL(processRunning(quint16)), d->m_profilerConnections, SLOT(connectClient(quint16)));
|
||||||
connect(engine, SIGNAL(finished()), this, SLOT(disconnectClient()));
|
connect(engine, SIGNAL(finished()), d->m_profilerConnections, SLOT(disconnectClient()));
|
||||||
connect(engine, SIGNAL(finished()), this, SLOT(updateTimers()));
|
connect(d->m_profilerConnections, SIGNAL(connectionFailed()), engine, SLOT(cancelProcess()));
|
||||||
connect(engine, SIGNAL(stopRecording()), this, SLOT(stopRecording()));
|
|
||||||
connect(engine, SIGNAL(recordingChanged(bool)), this, SLOT(setRecording(bool)));
|
|
||||||
connect(engine, SIGNAL(timeUpdate()), this, SLOT(updateTimers()));
|
|
||||||
connect(d->m_traceWindow, SIGNAL(viewUpdated()), engine, SLOT(dataReceived()));
|
|
||||||
connect(this, SIGNAL(connectionFailed()), engine, SLOT(finishProcess()));
|
|
||||||
connect(this, SIGNAL(fetchingData(bool)), engine, SLOT(setFetchingData(bool)));
|
|
||||||
connect(engine, SIGNAL(starting(const Analyzer::IAnalyzerEngine*)), this, SLOT(setAppIsRunning()));
|
|
||||||
connect(engine, SIGNAL(finished()), this, SLOT(setAppIsStopped()));
|
|
||||||
connect(this, SIGNAL(cancelRun()), engine, SLOT(finishProcess()));
|
|
||||||
connect(engine, SIGNAL(applicationDied()), d->m_traceWindow, SLOT(applicationDied()));
|
|
||||||
emit fetchingData(d->m_recordButton->isChecked());
|
|
||||||
|
|
||||||
return engine;
|
return engine;
|
||||||
}
|
}
|
||||||
@@ -444,53 +363,15 @@ AnalyzerStartParameters QmlProfilerTool::createStartParameters(RunConfiguration
|
|||||||
|
|
||||||
QWidget *QmlProfilerTool::createWidgets()
|
QWidget *QmlProfilerTool::createWidgets()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!d->m_traceWindow, return 0);
|
QTC_ASSERT(!d->m_viewContainer, return 0);
|
||||||
|
|
||||||
//
|
|
||||||
// DockWidgets
|
|
||||||
//
|
|
||||||
|
|
||||||
Utils::FancyMainWindow *mw = AnalyzerManager::mainWindow();
|
d->m_viewContainer = new QmlProfilerViewManager(this,
|
||||||
|
this,
|
||||||
d->m_traceWindow = new TraceWindow(mw);
|
d->m_profilerDataModel,
|
||||||
d->m_traceWindow->reset(d->m_client);
|
d->m_profilerState);
|
||||||
|
connect(d->m_viewContainer, SIGNAL(gotoSourceLocation(QString,int,int)),
|
||||||
connect(d->m_traceWindow, SIGNAL(clearViewsFromTool()), this, SLOT(clearDisplay()));
|
this, SLOT(gotoSourceLocation(QString,int,int)));
|
||||||
connect(d->m_traceWindow, SIGNAL(gotoSourceLocation(QString,int,int)),this, SLOT(gotoSourceLocation(QString,int,int)));
|
|
||||||
connect(d->m_traceWindow, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
|
||||||
connect(d->m_traceWindow->getEventList(), SIGNAL(error(QString)), this, SLOT(showErrorDialog(QString)));
|
|
||||||
connect(d->m_traceWindow->getEventList(), SIGNAL(stateChanged()), this, SLOT(eventListStateChanged()));
|
|
||||||
connect(d->m_traceWindow, SIGNAL(profilerStateChanged(bool,bool)), this, SLOT(profilerStateChanged(bool,bool)));
|
|
||||||
connect(d->m_traceWindow, SIGNAL(recordingChanged(bool)), this, SLOT(setRecording(bool)));
|
|
||||||
|
|
||||||
d->m_eventsView = new QmlProfilerEventsWidget(d->m_traceWindow->getEventList(), mw);
|
|
||||||
connect(d->m_eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), this, SLOT(gotoSourceLocation(QString,int,int)));
|
|
||||||
connect(d->m_eventsView, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
|
||||||
connect(d->m_eventsView, SIGNAL(showEventInTimeline(int)), d->m_traceWindow, SLOT(selectNextEvent(int)));
|
|
||||||
connect(d->m_traceWindow, SIGNAL(selectedEventIdChanged(int)), d->m_eventsView, SLOT(updateSelectedEvent(int)));
|
|
||||||
|
|
||||||
d->m_v8profilerView = new QmlProfilerEventsWidget(d->m_traceWindow->getEventList(), mw);
|
|
||||||
d->m_v8profilerView->switchToV8View();
|
|
||||||
connect(d->m_v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)), this, SLOT(gotoSourceLocation(QString,int,int)));
|
|
||||||
connect(d->m_v8profilerView, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
|
||||||
|
|
||||||
connect(d->m_v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)), d->m_eventsView, SLOT(selectBySourceLocation(QString,int,int)));
|
|
||||||
connect(d->m_eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), d->m_v8profilerView, SLOT(selectBySourceLocation(QString,int,int)));
|
|
||||||
|
|
||||||
QDockWidget *eventsDock = AnalyzerManager::createDockWidget
|
|
||||||
(this, tr("Events"), d->m_eventsView, Qt::BottomDockWidgetArea);
|
|
||||||
QDockWidget *timelineDock = AnalyzerManager::createDockWidget
|
|
||||||
(this, tr("Timeline"), d->m_traceWindow, Qt::BottomDockWidgetArea);
|
|
||||||
QDockWidget *v8profilerDock = AnalyzerManager::createDockWidget
|
|
||||||
(this, tr("JavaScript"), d->m_v8profilerView, Qt::BottomDockWidgetArea);
|
|
||||||
|
|
||||||
eventsDock->show();
|
|
||||||
timelineDock->show();
|
|
||||||
v8profilerDock->show();
|
|
||||||
|
|
||||||
mw->splitDockWidget(mw->toolBarDockWidget(), eventsDock, Qt::Vertical);
|
|
||||||
mw->tabifyDockWidget(eventsDock, timelineDock);
|
|
||||||
mw->tabifyDockWidget(timelineDock, v8profilerDock);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Toolbar
|
// Toolbar
|
||||||
@@ -507,118 +388,53 @@ QWidget *QmlProfilerTool::createWidgets()
|
|||||||
|
|
||||||
connect(d->m_recordButton,SIGNAL(clicked(bool)), this, SLOT(recordingButtonChanged(bool)));
|
connect(d->m_recordButton,SIGNAL(clicked(bool)), this, SLOT(recordingButtonChanged(bool)));
|
||||||
d->m_recordButton->setChecked(true);
|
d->m_recordButton->setChecked(true);
|
||||||
setRecording(d->m_recordingEnabled);
|
setRecording(d->m_profilerState->clientRecording());
|
||||||
layout->addWidget(d->m_recordButton);
|
layout->addWidget(d->m_recordButton);
|
||||||
|
|
||||||
d->m_clearButton = new QToolButton(toolbarWidget);
|
d->m_clearButton = new QToolButton(toolbarWidget);
|
||||||
d->m_clearButton->setIcon(QIcon(QLatin1String(":/qmlprofiler/clean_pane_small.png")));
|
d->m_clearButton->setIcon(QIcon(QLatin1String(":/qmlprofiler/clean_pane_small.png")));
|
||||||
d->m_clearButton->setToolTip(tr("Discard data"));
|
d->m_clearButton->setToolTip(tr("Discard data"));
|
||||||
connect(d->m_clearButton,SIGNAL(clicked()), this, SLOT(clearDisplay()));
|
|
||||||
|
connect(d->m_clearButton,SIGNAL(clicked()), this, SLOT(clearData()));
|
||||||
|
|
||||||
layout->addWidget(d->m_clearButton);
|
layout->addWidget(d->m_clearButton);
|
||||||
|
|
||||||
QLabel *timeLabel = new QLabel();
|
d->m_timeLabel = new QLabel();
|
||||||
QPalette palette = timeLabel->palette();
|
QPalette palette = d->m_timeLabel->palette();
|
||||||
palette.setColor(QPalette::WindowText, Qt::white);
|
palette.setColor(QPalette::WindowText, Qt::white);
|
||||||
timeLabel->setPalette(palette);
|
d->m_timeLabel->setPalette(palette);
|
||||||
timeLabel->setIndent(10);
|
d->m_timeLabel->setIndent(10);
|
||||||
connect(d->m_traceWindow, SIGNAL(viewUpdated()), this, SLOT(updateTimers()));
|
updateTimeDisplay();
|
||||||
connect(this, SIGNAL(setTimeLabel(QString)), timeLabel, SLOT(setText(QString)));
|
layout->addWidget(d->m_timeLabel);
|
||||||
updateTimers();
|
|
||||||
layout->addWidget(timeLabel);
|
|
||||||
|
|
||||||
toolbarWidget->setLayout(layout);
|
toolbarWidget->setLayout(layout);
|
||||||
|
|
||||||
return toolbarWidget;
|
return toolbarWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerTool::connectClient(quint16 port)
|
|
||||||
{
|
|
||||||
if (d->m_client)
|
|
||||||
delete d->m_client;
|
|
||||||
d->m_client = new QDeclarativeDebugConnection;
|
|
||||||
d->m_traceWindow->reset(d->m_client);
|
|
||||||
connect(d->m_client, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
|
|
||||||
this, SLOT(connectionStateChanged()));
|
|
||||||
d->m_connectionTimer.start();
|
|
||||||
d->m_appTimer.start();
|
|
||||||
d->m_tcpPort = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerTool::connectToClient()
|
|
||||||
{
|
|
||||||
if (!d->m_client || d->m_client->state() != QAbstractSocket::UnconnectedState)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (d->m_connectMode == QmlProfilerToolPrivate::TcpConnection) {
|
|
||||||
logStatus(QString("QML Profiler: Connecting to %1:%2...").arg(d->m_tcpHost, QString::number(d->m_tcpPort)));
|
|
||||||
d->m_client->connectToHost(d->m_tcpHost, d->m_tcpPort);
|
|
||||||
} else {
|
|
||||||
logStatus(QString("QML Profiler: Connecting to %1...").arg(d->m_tcpHost));
|
|
||||||
d->m_client->connectToOst(d->m_ostDevice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerTool::disconnectClient()
|
|
||||||
{
|
|
||||||
// this might be actually be called indirectly by QDDConnectionPrivate::readyRead(), therefore allow
|
|
||||||
// method to complete before deleting object
|
|
||||||
if (d->m_client) {
|
|
||||||
d->m_client->deleteLater();
|
|
||||||
d->m_client = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerTool::startRecording()
|
|
||||||
{
|
|
||||||
if (d->m_client && d->m_client->isConnected()) {
|
|
||||||
clearDisplay();
|
|
||||||
d->m_traceWindow->setRecording(true);
|
|
||||||
}
|
|
||||||
emit fetchingData(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerTool::stopRecording()
|
|
||||||
{
|
|
||||||
d->m_traceWindow->setRecording(false);
|
|
||||||
emit fetchingData(false);
|
|
||||||
|
|
||||||
// manage early stop
|
|
||||||
if (d->m_client && !d->m_client->isConnected() && d->m_appIsRunning)
|
|
||||||
emit cancelRun();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerTool::recordingButtonChanged(bool recording)
|
void QmlProfilerTool::recordingButtonChanged(bool recording)
|
||||||
{
|
{
|
||||||
if (recording)
|
d->m_profilerState->setClientRecording(recording);
|
||||||
startRecording();
|
|
||||||
else
|
|
||||||
stopRecording();
|
|
||||||
|
|
||||||
setRecording(recording);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerTool::setRecording(bool recording)
|
void QmlProfilerTool::setRecording(bool recording)
|
||||||
{
|
{
|
||||||
// update record button
|
// update display
|
||||||
d->m_recordingEnabled = recording;
|
|
||||||
d->m_recordButton->setToolTip( recording ? tr("Disable profiling") : tr("Enable profiling"));
|
d->m_recordButton->setToolTip( recording ? tr("Disable profiling") : tr("Enable profiling"));
|
||||||
d->m_recordButton->setIcon(QIcon(recording ? QLatin1String(":/qmlprofiler/recordOn.png") :
|
d->m_recordButton->setIcon(QIcon(recording ? QLatin1String(":/qmlprofiler/recordOn.png") :
|
||||||
QLatin1String(":/qmlprofiler/recordOff.png")));
|
QLatin1String(":/qmlprofiler/recordOff.png")));
|
||||||
|
|
||||||
d->m_recordButton->setChecked(recording);
|
d->m_recordButton->setChecked(recording);
|
||||||
updateTimers();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerTool::setAppIsRunning()
|
// manage timer
|
||||||
{
|
if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) {
|
||||||
d->m_appIsRunning = true;
|
if (recording) {
|
||||||
updateTimers();
|
d->m_recordingTimer.start();
|
||||||
|
d->m_recordingElapsedTime.start();
|
||||||
|
} else {
|
||||||
|
d->m_recordingTimer.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerTool::setAppIsStopped()
|
|
||||||
{
|
|
||||||
d->m_appIsRunning = false;
|
|
||||||
updateTimers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerTool::gotoSourceLocation(const QString &fileUrl, int lineNumber, int columnNumber)
|
void QmlProfilerTool::gotoSourceLocation(const QString &fileUrl, int lineNumber, int columnNumber)
|
||||||
@@ -643,33 +459,30 @@ void QmlProfilerTool::gotoSourceLocation(const QString &fileUrl, int lineNumber,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QString stringifyTime(double seconds)
|
void QmlProfilerTool::updateTimeDisplay()
|
||||||
{
|
{
|
||||||
|
double seconds = 0;
|
||||||
|
if (d->m_profilerState->serverRecording() &&
|
||||||
|
d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) {
|
||||||
|
seconds = d->m_recordingElapsedTime.elapsed() / 1000.0;
|
||||||
|
} else if (d->m_profilerDataModel->currentState() != QmlProfilerDataModel::Empty ) {
|
||||||
|
seconds = (d->m_profilerDataModel->traceEndTime() - d->m_profilerDataModel->traceStartTime()) / 1.0e9;
|
||||||
|
}
|
||||||
QString timeString = QString::number(seconds,'f',1);
|
QString timeString = QString::number(seconds,'f',1);
|
||||||
return QmlProfilerTool::tr("%1 s").arg(timeString, 6);
|
QString profilerTimeStr = QmlProfilerTool::tr("%1 s").arg(timeString, 6);
|
||||||
|
d->m_timeLabel->setText(tr("Elapsed: %1").arg(profilerTimeStr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerTool::updateTimers()
|
void QmlProfilerTool::clearData()
|
||||||
{
|
{
|
||||||
// prof time
|
d->m_profilerDataModel->clear();
|
||||||
QString profilerTimeStr = stringifyTime(d->m_traceWindow->profiledTime());
|
|
||||||
emit setTimeLabel(tr("Elapsed: %1").arg(profilerTimeStr));
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerTool::profilerStateChanged(bool qmlActive, bool v8active)
|
|
||||||
{
|
|
||||||
d->m_v8Active = v8active;
|
|
||||||
d->m_qmlActive = qmlActive;
|
|
||||||
updateTimers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerTool::clearDisplay()
|
void QmlProfilerTool::clearDisplay()
|
||||||
{
|
{
|
||||||
d->m_appRunningTime = 0;
|
d->m_profilerConnections->clearBufferedData();
|
||||||
d->m_traceWindow->clearDisplay();
|
d->m_viewContainer->clear();
|
||||||
d->m_eventsView->clear();
|
updateTimeDisplay();
|
||||||
d->m_v8profilerView->clear();
|
|
||||||
updateTimers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void startRemoteTool(IAnalyzerTool *tool, StartMode mode)
|
static void startRemoteTool(IAnalyzerTool *tool, StartMode mode)
|
||||||
@@ -718,84 +531,6 @@ static void startRemoteTool(IAnalyzerTool *tool, StartMode mode)
|
|||||||
ProjectExplorerPlugin::instance()->startRunControl(rc, tool->runMode());
|
ProjectExplorerPlugin::instance()->startRunControl(rc, tool->runMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerTool::tryToConnect()
|
|
||||||
{
|
|
||||||
++d->m_connectionAttempts;
|
|
||||||
|
|
||||||
if (d->m_client && d->m_client->isConnected()) {
|
|
||||||
d->m_connectionTimer.stop();
|
|
||||||
d->m_connectionAttempts = 0;
|
|
||||||
} else if (d->m_connectionAttempts == 50) {
|
|
||||||
d->m_connectionTimer.stop();
|
|
||||||
d->m_connectionAttempts = 0;
|
|
||||||
|
|
||||||
QMessageBox *infoBox = new QMessageBox(Core::ICore::mainWindow());
|
|
||||||
infoBox->setIcon(QMessageBox::Critical);
|
|
||||||
infoBox->setWindowTitle(tr("Qt Creator"));
|
|
||||||
infoBox->setText(tr("Could not connect to the in-process QML profiler.\n"
|
|
||||||
"Do you want to retry?"));
|
|
||||||
infoBox->setStandardButtons(QMessageBox::Retry | QMessageBox::Cancel | QMessageBox::Help);
|
|
||||||
infoBox->setDefaultButton(QMessageBox::Retry);
|
|
||||||
infoBox->setModal(true);
|
|
||||||
|
|
||||||
connect(infoBox, SIGNAL(finished(int)),
|
|
||||||
this, SLOT(retryMessageBoxFinished(int)));
|
|
||||||
|
|
||||||
infoBox->show();
|
|
||||||
} else {
|
|
||||||
connectToClient();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerTool::connectionStateChanged()
|
|
||||||
{
|
|
||||||
if (!d->m_client)
|
|
||||||
return;
|
|
||||||
switch (d->m_client->state()) {
|
|
||||||
case QAbstractSocket::UnconnectedState:
|
|
||||||
{
|
|
||||||
if (QmlProfilerPlugin::debugOutput)
|
|
||||||
qWarning("QML Profiler: disconnected");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case QAbstractSocket::HostLookupState:
|
|
||||||
break;
|
|
||||||
case QAbstractSocket::ConnectingState: {
|
|
||||||
if (QmlProfilerPlugin::debugOutput)
|
|
||||||
qWarning("QML Profiler: Connecting to debug server ...");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case QAbstractSocket::ConnectedState:
|
|
||||||
{
|
|
||||||
if (QmlProfilerPlugin::debugOutput)
|
|
||||||
qWarning("QML Profiler: connected and running");
|
|
||||||
updateRecordingState();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case QAbstractSocket::ClosingState:
|
|
||||||
if (QmlProfilerPlugin::debugOutput)
|
|
||||||
qWarning("QML Profiler: closing ...");
|
|
||||||
break;
|
|
||||||
case QAbstractSocket::BoundState:
|
|
||||||
case QAbstractSocket::ListeningState:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerTool::updateRecordingState()
|
|
||||||
{
|
|
||||||
if (d->m_client->isConnected()) {
|
|
||||||
d->m_traceWindow->setRecording(d->m_recordingEnabled);
|
|
||||||
} else {
|
|
||||||
d->m_traceWindow->setRecording(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d->m_traceWindow->isRecording())
|
|
||||||
clearDisplay();
|
|
||||||
|
|
||||||
updateTimers();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerTool::startTool(StartMode mode)
|
void QmlProfilerTool::startTool(StartMode mode)
|
||||||
{
|
{
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
@@ -821,14 +556,25 @@ void QmlProfilerTool::logStatus(const QString &msg)
|
|||||||
|
|
||||||
void QmlProfilerTool::logError(const QString &msg)
|
void QmlProfilerTool::logError(const QString &msg)
|
||||||
{
|
{
|
||||||
// TODO: Rather show errors in the application ouput
|
|
||||||
MessageManager *messageManager = MessageManager::instance();
|
MessageManager *messageManager = MessageManager::instance();
|
||||||
messageManager->printToOutputPane(msg, true);
|
messageManager->printToOutputPane(msg, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTool::showErrorDialog(const QString &error)
|
||||||
|
{
|
||||||
|
QMessageBox *errorDialog = new QMessageBox(Core::ICore::mainWindow());
|
||||||
|
errorDialog->setIcon(QMessageBox::Warning);
|
||||||
|
errorDialog->setWindowTitle(tr("QML Profiler"));
|
||||||
|
errorDialog->setText(error);
|
||||||
|
errorDialog->setStandardButtons(QMessageBox::Ok);
|
||||||
|
errorDialog->setDefaultButton(QMessageBox::Ok);
|
||||||
|
errorDialog->setModal(false);
|
||||||
|
errorDialog->show();
|
||||||
|
}
|
||||||
|
|
||||||
void QmlProfilerTool::showSaveOption()
|
void QmlProfilerTool::showSaveOption()
|
||||||
{
|
{
|
||||||
d->m_saveQmlTrace->setEnabled(d->m_traceWindow->getEventList()->count());
|
d->m_saveQmlTrace->setEnabled(!d->m_profilerDataModel->isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerTool::showSaveDialog()
|
void QmlProfilerTool::showSaveDialog()
|
||||||
@@ -837,7 +583,7 @@ void QmlProfilerTool::showSaveDialog()
|
|||||||
if (!filename.isEmpty()) {
|
if (!filename.isEmpty()) {
|
||||||
if (!filename.endsWith(QLatin1String(TraceFileExtension)))
|
if (!filename.endsWith(QLatin1String(TraceFileExtension)))
|
||||||
filename += QLatin1String(TraceFileExtension);
|
filename += QLatin1String(TraceFileExtension);
|
||||||
d->m_traceWindow->getEventList()->save(filename);
|
d->m_profilerDataModel->save(filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -853,53 +599,98 @@ void QmlProfilerTool::showLoadDialog()
|
|||||||
|
|
||||||
if (!filename.isEmpty()) {
|
if (!filename.isEmpty()) {
|
||||||
// delayed load (prevent graphical artifacts due to long load time)
|
// delayed load (prevent graphical artifacts due to long load time)
|
||||||
d->m_traceWindow->getEventList()->setFilename(filename);
|
d->m_profilerDataModel->setFilename(filename);
|
||||||
QTimer::singleShot(100, d->m_traceWindow->getEventList(), SLOT(load()));
|
QTimer::singleShot(100, d->m_profilerDataModel, SLOT(load()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerTool::showErrorDialog(const QString &error)
|
void QmlProfilerTool::profilerDataModelStateChanged()
|
||||||
{
|
{
|
||||||
QMessageBox *errorDialog = new QMessageBox(Core::ICore::mainWindow());
|
switch (d->m_profilerDataModel->currentState()) {
|
||||||
errorDialog->setIcon(QMessageBox::Warning);
|
case QmlProfilerDataModel::Empty :
|
||||||
errorDialog->setWindowTitle(tr("QML Profiler"));
|
clearDisplay();
|
||||||
errorDialog->setText(error);
|
|
||||||
errorDialog->setStandardButtons(QMessageBox::Ok);
|
|
||||||
errorDialog->setDefaultButton(QMessageBox::Ok);
|
|
||||||
errorDialog->setModal(false);
|
|
||||||
errorDialog->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerTool::retryMessageBoxFinished(int result)
|
|
||||||
{
|
|
||||||
switch (result) {
|
|
||||||
case QMessageBox::Retry: {
|
|
||||||
d->m_connectionAttempts = 0;
|
|
||||||
d->m_connectionTimer.start();
|
|
||||||
break;
|
break;
|
||||||
}
|
case QmlProfilerDataModel::AcquiringData :
|
||||||
case QMessageBox::Help: {
|
case QmlProfilerDataModel::ProcessingData :
|
||||||
HelpManager *helpManager = HelpManager::instance();
|
// nothing to be done for these two
|
||||||
helpManager->handleHelpRequest("qthelp://com.nokia.qtcreator/doc/creator-debugging-qml.html");
|
|
||||||
// fall through
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
if (d->m_client) {
|
|
||||||
logStatus("QML Profiler: Failed to connect! " + d->m_client->errorString());
|
|
||||||
} else {
|
|
||||||
logStatus("QML Profiler: Failed to connect!");
|
|
||||||
}
|
|
||||||
|
|
||||||
emit connectionFailed();
|
|
||||||
break;
|
break;
|
||||||
}
|
case QmlProfilerDataModel::Done :
|
||||||
}
|
if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppStopRequested)
|
||||||
}
|
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppReadyToStop);
|
||||||
|
|
||||||
void QmlProfilerTool::eventListStateChanged()
|
|
||||||
{
|
|
||||||
if (d->m_traceWindow->getEventList()->currentState() == QmlProfilerEventList::Done) {
|
|
||||||
showSaveOption();
|
showSaveOption();
|
||||||
updateTimers();
|
updateTimeDisplay();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList <QAction *> QmlProfilerTool::profilerContextMenuActions() const
|
||||||
|
{
|
||||||
|
QList <QAction *> commonActions;
|
||||||
|
commonActions << d->m_loadQmlTrace << d->m_saveQmlTrace;
|
||||||
|
return commonActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTool::showNonmodalWarning(const QString &warningMsg)
|
||||||
|
{
|
||||||
|
QMessageBox *noExecWarning = new QMessageBox(Core::ICore::mainWindow());
|
||||||
|
noExecWarning->setIcon(QMessageBox::Warning);
|
||||||
|
noExecWarning->setWindowTitle(tr("QML Profiler"));
|
||||||
|
noExecWarning->setText(warningMsg);
|
||||||
|
noExecWarning->setStandardButtons(QMessageBox::Ok);
|
||||||
|
noExecWarning->setDefaultButton(QMessageBox::Ok);
|
||||||
|
noExecWarning->setModal(false);
|
||||||
|
noExecWarning->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox *QmlProfilerTool::requestMessageBox()
|
||||||
|
{
|
||||||
|
return new QMessageBox(Core::ICore::mainWindow());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTool::handleHelpRequest(const QString &link)
|
||||||
|
{
|
||||||
|
HelpManager *helpManager = HelpManager::instance();
|
||||||
|
helpManager->handleHelpRequest(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTool::profilerStateChanged()
|
||||||
|
{
|
||||||
|
switch (d->m_profilerState->currentState()) {
|
||||||
|
case QmlProfilerStateManager::AppKilled : {
|
||||||
|
if (d->m_profilerDataModel->currentState() == QmlProfilerDataModel::AcquiringData) {
|
||||||
|
showNonmodalWarning(tr("Application finished before loading profiled data.\n Please use the stop button instead."));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QmlProfilerStateManager::Idle :
|
||||||
|
// when the app finishes, set recording display to client status
|
||||||
|
setRecording(d->m_profilerState->clientRecording());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// no special action needed for other states
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTool::clientRecordingChanged()
|
||||||
|
{
|
||||||
|
// if application is running, display server record changes
|
||||||
|
// if application is stopped, display client record changes
|
||||||
|
if (d->m_profilerState->currentState() != QmlProfilerStateManager::AppRunning) {
|
||||||
|
setRecording(d->m_profilerState->clientRecording());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTool::serverRecordingChanged()
|
||||||
|
{
|
||||||
|
if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) {
|
||||||
|
setRecording(d->m_profilerState->serverRecording());
|
||||||
|
// clear the old data each time we start a new profiling session
|
||||||
|
if (d->m_profilerState->serverRecording()) {
|
||||||
|
clearData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -36,13 +36,11 @@
|
|||||||
#include <analyzerbase/ianalyzertool.h>
|
#include <analyzerbase/ianalyzertool.h>
|
||||||
#include <analyzerbase/ianalyzerengine.h>
|
#include <analyzerbase/ianalyzerengine.h>
|
||||||
|
|
||||||
#include <QPoint>
|
class QMessageBox;
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
#define TraceFileExtension ".qtd"
|
|
||||||
|
|
||||||
class QmlProfilerTool : public Analyzer::IAnalyzerTool
|
class QmlProfilerTool : public Analyzer::IAnalyzerTool
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -72,49 +70,37 @@ public:
|
|||||||
QWidget *createWidgets();
|
QWidget *createWidgets();
|
||||||
void startTool(Analyzer::StartMode mode);
|
void startTool(Analyzer::StartMode mode);
|
||||||
|
|
||||||
public slots:
|
QList <QAction *> profilerContextMenuActions() const;
|
||||||
void connectClient(quint16 port);
|
|
||||||
void disconnectClient();
|
// display dialogs / log output
|
||||||
|
static QMessageBox *requestMessageBox();
|
||||||
|
static void handleHelpRequest(const QString &link);
|
||||||
|
static void logStatus(const QString &msg);
|
||||||
|
static void logError(const QString &msg);
|
||||||
|
static void showNonmodalWarning(const QString &warningMsg);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void profilerStateChanged();
|
||||||
|
void clientRecordingChanged();
|
||||||
|
void serverRecordingChanged();
|
||||||
|
|
||||||
void startRecording();
|
|
||||||
void stopRecording();
|
|
||||||
void recordingButtonChanged(bool recording);
|
void recordingButtonChanged(bool recording);
|
||||||
void setRecording(bool recording);
|
void setRecording(bool recording);
|
||||||
|
|
||||||
void setAppIsRunning();
|
|
||||||
void setAppIsStopped();
|
|
||||||
|
|
||||||
void gotoSourceLocation(const QString &fileUrl, int lineNumber, int columnNumber);
|
void gotoSourceLocation(const QString &fileUrl, int lineNumber, int columnNumber);
|
||||||
void updateTimers();
|
|
||||||
void profilerStateChanged(bool qmlActive, bool v8active);
|
|
||||||
|
|
||||||
void clearDisplay();
|
|
||||||
|
|
||||||
void showContextMenu(const QPoint &position);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void setTimeLabel(const QString &);
|
|
||||||
void setStatusLabel(const QString &);
|
|
||||||
void fetchingData(bool);
|
|
||||||
void connectionFailed();
|
|
||||||
void cancelRun();
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void tryToConnect();
|
void clearData();
|
||||||
void connectionStateChanged();
|
void showErrorDialog(const QString &error);
|
||||||
|
void profilerDataModelStateChanged();
|
||||||
|
void updateTimeDisplay();
|
||||||
|
|
||||||
void showSaveOption();
|
void showSaveOption();
|
||||||
void showSaveDialog();
|
void showSaveDialog();
|
||||||
void showLoadDialog();
|
void showLoadDialog();
|
||||||
void showErrorDialog(const QString &error);
|
|
||||||
void retryMessageBoxFinished(int result);
|
|
||||||
void eventListStateChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void connectToClient();
|
void clearDisplay();
|
||||||
void updateRecordingState();
|
|
||||||
void ensureWidgets();
|
|
||||||
void logStatus(const QString &msg);
|
|
||||||
void logError(const QString &msg);
|
|
||||||
|
|
||||||
class QmlProfilerToolPrivate;
|
class QmlProfilerToolPrivate;
|
||||||
QmlProfilerToolPrivate *d;
|
QmlProfilerToolPrivate *d;
|
||||||
|
601
src/plugins/qmlprofiler/qmlprofilertraceview.cpp
Normal file
601
src/plugins/qmlprofiler/qmlprofilertraceview.cpp
Normal file
@@ -0,0 +1,601 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "qmlprofilertraceview.h"
|
||||||
|
#include "qmlprofilertool.h"
|
||||||
|
#include "qmlprofilerstatemanager.h"
|
||||||
|
#include "qmlprofilerdatamodel.h"
|
||||||
|
|
||||||
|
// Needed for the load&save actions in the context menu
|
||||||
|
#include <analyzerbase/ianalyzertool.h>
|
||||||
|
|
||||||
|
// Comunication with the other views (limit events to range)
|
||||||
|
#include "qmlprofilerviewmanager.h"
|
||||||
|
|
||||||
|
#include <utils/styledbar.h>
|
||||||
|
|
||||||
|
#include <QDeclarativeContext>
|
||||||
|
#include <QToolButton>
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QGraphicsObject>
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QSlider>
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
using namespace QmlJsDebugClient;
|
||||||
|
|
||||||
|
namespace QmlProfiler {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
const int sliderTicks = 10000;
|
||||||
|
const qreal sliderExp = 3;
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
bool MouseWheelResizer::eventFilter(QObject *obj, QEvent *event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::Wheel) {
|
||||||
|
QWheelEvent *ev = static_cast<QWheelEvent *>(event);
|
||||||
|
if (ev->modifiers() & Qt::ControlModifier) {
|
||||||
|
emit mouseWheelMoved(ev->pos().x(), ev->pos().y(), ev->delta());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QObject::eventFilter(obj, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
void ZoomControl::setRange(qint64 startTime, qint64 endTime)
|
||||||
|
{
|
||||||
|
if (m_startTime != startTime || m_endTime != endTime) {
|
||||||
|
m_startTime = startTime;
|
||||||
|
m_endTime = endTime;
|
||||||
|
emit rangeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
ScrollableDeclarativeView::ScrollableDeclarativeView(QWidget *parent)
|
||||||
|
: QDeclarativeView(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollableDeclarativeView::~ScrollableDeclarativeView()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollableDeclarativeView::scrollContentsBy(int dx, int dy)
|
||||||
|
{
|
||||||
|
// special workaround to track the scrollbar
|
||||||
|
if (rootObject()) {
|
||||||
|
int scrollY = rootObject()->property("scrollY").toInt();
|
||||||
|
rootObject()->setProperty("scrollY", QVariant(scrollY - dy));
|
||||||
|
}
|
||||||
|
QDeclarativeView::scrollContentsBy(dx,dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
class QmlProfilerTraceView::QmlProfilerTraceViewPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QmlProfilerTraceViewPrivate(QmlProfilerTraceView *qq) : q(qq) {}
|
||||||
|
QmlProfilerTraceView *q;
|
||||||
|
|
||||||
|
QmlProfilerStateManager *m_profilerState;
|
||||||
|
Analyzer::IAnalyzerTool *m_profilerTool;
|
||||||
|
QmlProfilerViewManager *m_viewContainer;
|
||||||
|
|
||||||
|
QSize m_sizeHint;
|
||||||
|
|
||||||
|
ScrollableDeclarativeView *m_mainView;
|
||||||
|
QDeclarativeView *m_timebar;
|
||||||
|
QDeclarativeView *m_overview;
|
||||||
|
QmlProfilerDataModel *m_profilerDataModel;
|
||||||
|
|
||||||
|
ZoomControl *m_zoomControl;
|
||||||
|
|
||||||
|
QToolButton *m_buttonRange;
|
||||||
|
QToolButton *m_buttonLock;
|
||||||
|
QWidget *m_zoomToolbar;
|
||||||
|
int m_currentZoomLevel;
|
||||||
|
};
|
||||||
|
|
||||||
|
QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerTool *profilerTool, QmlProfilerViewManager *container, QmlProfilerDataModel *model, QmlProfilerStateManager *profilerState)
|
||||||
|
: QWidget(parent), d(new QmlProfilerTraceViewPrivate(this))
|
||||||
|
{
|
||||||
|
setObjectName("QML Profiler");
|
||||||
|
|
||||||
|
d->m_zoomControl = new ZoomControl(this);
|
||||||
|
connect(d->m_zoomControl, SIGNAL(rangeChanged()), this, SLOT(updateRange()));
|
||||||
|
|
||||||
|
QVBoxLayout *groupLayout = new QVBoxLayout;
|
||||||
|
groupLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
groupLayout->setSpacing(0);
|
||||||
|
|
||||||
|
d->m_mainView = new ScrollableDeclarativeView(this);
|
||||||
|
d->m_mainView->setResizeMode(QDeclarativeView::SizeViewToRootObject);
|
||||||
|
d->m_mainView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||||
|
d->m_mainView->setBackgroundBrush(QBrush(Qt::white));
|
||||||
|
d->m_mainView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||||
|
d->m_mainView->setFocus();
|
||||||
|
|
||||||
|
MouseWheelResizer *resizer = new MouseWheelResizer(this);
|
||||||
|
connect(resizer,SIGNAL(mouseWheelMoved(int,int,int)), this, SLOT(mouseWheelMoved(int,int,int)));
|
||||||
|
d->m_mainView->viewport()->installEventFilter(resizer);
|
||||||
|
|
||||||
|
QHBoxLayout *toolsLayout = new QHBoxLayout;
|
||||||
|
|
||||||
|
d->m_timebar = new QDeclarativeView(this);
|
||||||
|
d->m_timebar->setResizeMode(QDeclarativeView::SizeRootObjectToView);
|
||||||
|
d->m_timebar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
|
d->m_timebar->setFixedHeight(24);
|
||||||
|
|
||||||
|
d->m_overview = new QDeclarativeView(this);
|
||||||
|
d->m_overview->setResizeMode(QDeclarativeView::SizeRootObjectToView);
|
||||||
|
d->m_overview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
|
d->m_overview->setMaximumHeight(50);
|
||||||
|
|
||||||
|
d->m_zoomToolbar = createZoomToolbar();
|
||||||
|
d->m_zoomToolbar->move(0, d->m_timebar->height());
|
||||||
|
d->m_zoomToolbar->setVisible(false);
|
||||||
|
|
||||||
|
toolsLayout->addWidget(createToolbar());
|
||||||
|
toolsLayout->addWidget(d->m_timebar);
|
||||||
|
emit enableToolbar(false);
|
||||||
|
|
||||||
|
groupLayout->addLayout(toolsLayout);
|
||||||
|
groupLayout->addWidget(d->m_mainView);
|
||||||
|
groupLayout->addWidget(d->m_overview);
|
||||||
|
|
||||||
|
setLayout(groupLayout);
|
||||||
|
|
||||||
|
d->m_profilerTool = profilerTool;
|
||||||
|
d->m_viewContainer = container;
|
||||||
|
d->m_profilerDataModel = model;
|
||||||
|
connect(d->m_profilerDataModel, SIGNAL(stateChanged()),
|
||||||
|
this, SLOT(profilerDataModelStateChanged()));
|
||||||
|
d->m_mainView->rootContext()->setContextProperty("qmlProfilerDataModel",
|
||||||
|
d->m_profilerDataModel);
|
||||||
|
d->m_overview->rootContext()->setContextProperty("qmlProfilerDataModel",
|
||||||
|
d->m_profilerDataModel);
|
||||||
|
|
||||||
|
d->m_profilerState = profilerState;
|
||||||
|
connect(d->m_profilerState, SIGNAL(stateChanged()),
|
||||||
|
this, SLOT(profilerStateChanged()));
|
||||||
|
connect(d->m_profilerState, SIGNAL(clientRecordingChanged()),
|
||||||
|
this, SLOT(clientRecordingChanged()));
|
||||||
|
connect(d->m_profilerState, SIGNAL(serverRecordingChanged()),
|
||||||
|
this, SLOT(serverRecordingChanged()));
|
||||||
|
|
||||||
|
// Minimum height: 5 rows of 20 pixels + scrollbar of 50 pixels + 20 pixels margin
|
||||||
|
setMinimumHeight(170);
|
||||||
|
d->m_currentZoomLevel = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlProfilerTraceView::~QmlProfilerTraceView()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
// Initialize widgets
|
||||||
|
void QmlProfilerTraceView::reset()
|
||||||
|
{
|
||||||
|
d->m_mainView->rootContext()->setContextProperty("zoomControl", d->m_zoomControl);
|
||||||
|
d->m_timebar->rootContext()->setContextProperty("zoomControl", d->m_zoomControl);
|
||||||
|
d->m_overview->rootContext()->setContextProperty("zoomControl", d->m_zoomControl);
|
||||||
|
|
||||||
|
d->m_timebar->setSource(QUrl("qrc:/qmlprofiler/TimeDisplay.qml"));
|
||||||
|
d->m_overview->setSource(QUrl("qrc:/qmlprofiler/Overview.qml"));
|
||||||
|
|
||||||
|
d->m_mainView->setSource(QUrl("qrc:/qmlprofiler/MainView.qml"));
|
||||||
|
d->m_mainView->rootObject()->setProperty("width", QVariant(width()));
|
||||||
|
d->m_mainView->rootObject()->setProperty("candidateHeight", QVariant(height() - d->m_timebar->height() - d->m_overview->height()));
|
||||||
|
|
||||||
|
connect(d->m_mainView->rootObject(), SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition()));
|
||||||
|
connect(d->m_mainView->rootObject(), SIGNAL(updateRangeButton()), this, SLOT(updateRangeButton()));
|
||||||
|
connect(d->m_mainView->rootObject(), SIGNAL(updateLockButton()), this, SLOT(updateLockButton()));
|
||||||
|
connect(this, SIGNAL(jumpToPrev()), d->m_mainView->rootObject(), SLOT(prevEvent()));
|
||||||
|
connect(this, SIGNAL(jumpToNext()), d->m_mainView->rootObject(), SLOT(nextEvent()));
|
||||||
|
connect(d->m_mainView->rootObject(), SIGNAL(selectedEventChanged(int)), this, SIGNAL(selectedEventChanged(int)));
|
||||||
|
connect(d->m_mainView->rootObject(), SIGNAL(changeToolTip(QString)), this, SLOT(updateToolTip(QString)));
|
||||||
|
connect(d->m_mainView->rootObject(), SIGNAL(updateVerticalScroll(int)), this, SLOT(updateVerticalScroll(int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *QmlProfilerTraceView::createToolbar()
|
||||||
|
{
|
||||||
|
Utils::StyledBar *bar = new Utils::StyledBar(this);
|
||||||
|
bar->setSingleRow(true);
|
||||||
|
bar->setFixedWidth(150);
|
||||||
|
bar->setFixedHeight(24);
|
||||||
|
|
||||||
|
QHBoxLayout *toolBarLayout = new QHBoxLayout(bar);
|
||||||
|
toolBarLayout->setMargin(0);
|
||||||
|
toolBarLayout->setSpacing(0);
|
||||||
|
|
||||||
|
QToolButton *buttonPrev= new QToolButton;
|
||||||
|
buttonPrev->setIcon(QIcon(":/qmlprofiler/ico_prev.png"));
|
||||||
|
buttonPrev->setToolTip(tr("Jump to previous event"));
|
||||||
|
connect(buttonPrev, SIGNAL(clicked()), this, SIGNAL(jumpToPrev()));
|
||||||
|
connect(this, SIGNAL(enableToolbar(bool)), buttonPrev, SLOT(setEnabled(bool)));
|
||||||
|
|
||||||
|
QToolButton *buttonNext= new QToolButton;
|
||||||
|
buttonNext->setIcon(QIcon(":/qmlprofiler/ico_next.png"));
|
||||||
|
buttonNext->setToolTip(tr("Jump to next event"));
|
||||||
|
connect(buttonNext, SIGNAL(clicked()), this, SIGNAL(jumpToNext()));
|
||||||
|
connect(this, SIGNAL(enableToolbar(bool)), buttonNext, SLOT(setEnabled(bool)));
|
||||||
|
|
||||||
|
QToolButton *buttonZoomControls = new QToolButton;
|
||||||
|
buttonZoomControls->setIcon(QIcon(":/qmlprofiler/ico_zoom.png"));
|
||||||
|
buttonZoomControls->setToolTip(tr("Show zoom slider"));
|
||||||
|
buttonZoomControls->setCheckable(true);
|
||||||
|
buttonZoomControls->setChecked(false);
|
||||||
|
connect(buttonZoomControls, SIGNAL(toggled(bool)), d->m_zoomToolbar, SLOT(setVisible(bool)));
|
||||||
|
connect(this, SIGNAL(enableToolbar(bool)), buttonZoomControls, SLOT(setEnabled(bool)));
|
||||||
|
|
||||||
|
d->m_buttonRange = new QToolButton;
|
||||||
|
d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png"));
|
||||||
|
d->m_buttonRange->setToolTip(tr("Select range"));
|
||||||
|
d->m_buttonRange->setCheckable(true);
|
||||||
|
d->m_buttonRange->setChecked(false);
|
||||||
|
connect(d->m_buttonRange, SIGNAL(clicked(bool)), this, SLOT(toggleRangeMode(bool)));
|
||||||
|
connect(this, SIGNAL(enableToolbar(bool)), d->m_buttonRange, SLOT(setEnabled(bool)));
|
||||||
|
connect(this, SIGNAL(rangeModeChanged(bool)), d->m_buttonRange, SLOT(setChecked(bool)));
|
||||||
|
|
||||||
|
d->m_buttonLock = new QToolButton;
|
||||||
|
d->m_buttonLock->setIcon(QIcon(":/qmlprofiler/ico_selectionmode.png"));
|
||||||
|
d->m_buttonLock->setToolTip(tr("View event information on mouseover"));
|
||||||
|
d->m_buttonLock->setCheckable(true);
|
||||||
|
d->m_buttonLock->setChecked(false);
|
||||||
|
connect(d->m_buttonLock, SIGNAL(clicked(bool)), this, SLOT(toggleLockMode(bool)));
|
||||||
|
connect(this, SIGNAL(enableToolbar(bool)), d->m_buttonLock, SLOT(setEnabled(bool)));
|
||||||
|
connect(this, SIGNAL(lockModeChanged(bool)), d->m_buttonLock, SLOT(setChecked(bool)));
|
||||||
|
|
||||||
|
toolBarLayout->addWidget(buttonPrev);
|
||||||
|
toolBarLayout->addWidget(buttonNext);
|
||||||
|
toolBarLayout->addWidget(new Utils::StyledSeparator());
|
||||||
|
toolBarLayout->addWidget(buttonZoomControls);
|
||||||
|
toolBarLayout->addWidget(new Utils::StyledSeparator());
|
||||||
|
toolBarLayout->addWidget(d->m_buttonRange);
|
||||||
|
toolBarLayout->addWidget(d->m_buttonLock);
|
||||||
|
|
||||||
|
return bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QWidget *QmlProfilerTraceView::createZoomToolbar()
|
||||||
|
{
|
||||||
|
Utils::StyledBar *bar = new Utils::StyledBar(this);
|
||||||
|
bar->setSingleRow(true);
|
||||||
|
bar->setFixedWidth(150);
|
||||||
|
bar->setFixedHeight(24);
|
||||||
|
|
||||||
|
QHBoxLayout *toolBarLayout = new QHBoxLayout(bar);
|
||||||
|
toolBarLayout->setMargin(0);
|
||||||
|
toolBarLayout->setSpacing(0);
|
||||||
|
|
||||||
|
QSlider *zoomSlider = new QSlider(Qt::Horizontal);
|
||||||
|
zoomSlider->setFocusPolicy(Qt::NoFocus);
|
||||||
|
zoomSlider->setRange(1, sliderTicks);
|
||||||
|
zoomSlider->setInvertedAppearance(true);
|
||||||
|
zoomSlider->setPageStep(sliderTicks/100);
|
||||||
|
connect(this, SIGNAL(enableToolbar(bool)), zoomSlider, SLOT(setEnabled(bool)));
|
||||||
|
connect(zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setZoomLevel(int)));
|
||||||
|
connect(this, SIGNAL(zoomLevelChanged(int)), zoomSlider, SLOT(setValue(int)));
|
||||||
|
zoomSlider->setStyleSheet("\
|
||||||
|
QSlider:horizontal {\
|
||||||
|
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #444444, stop: 1 #5a5a5a);\
|
||||||
|
border: 1px #313131;\
|
||||||
|
height: 20px;\
|
||||||
|
margin: 0px 0px 0px 0px;\
|
||||||
|
}\
|
||||||
|
QSlider::add-page:horizontal {\
|
||||||
|
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\
|
||||||
|
border: 1px #313131;\
|
||||||
|
}\
|
||||||
|
QSlider::sub-page:horizontal {\
|
||||||
|
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\
|
||||||
|
border: 1px #313131;\
|
||||||
|
}\
|
||||||
|
");
|
||||||
|
|
||||||
|
toolBarLayout->addWidget(zoomSlider);
|
||||||
|
|
||||||
|
return bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
bool QmlProfilerTraceView::hasValidSelection() const
|
||||||
|
{
|
||||||
|
if (d->m_mainView->rootObject()) {
|
||||||
|
return d->m_mainView->rootObject()->property("selectionRangeReady").toBool();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 QmlProfilerTraceView::selectionStart() const
|
||||||
|
{
|
||||||
|
if (d->m_mainView->rootObject()) {
|
||||||
|
return d->m_mainView->rootObject()->property("selectionRangeStart").toLongLong();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 QmlProfilerTraceView::selectionEnd() const
|
||||||
|
{
|
||||||
|
if (d->m_mainView->rootObject()) {
|
||||||
|
return d->m_mainView->rootObject()->property("selectionRangeEnd").toLongLong();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTraceView::clearDisplay()
|
||||||
|
{
|
||||||
|
d->m_zoomControl->setRange(0,0);
|
||||||
|
|
||||||
|
updateVerticalScroll(0);
|
||||||
|
d->m_mainView->rootObject()->setProperty("scrollY", QVariant(0));
|
||||||
|
|
||||||
|
QMetaObject::invokeMethod(d->m_mainView->rootObject(), "clearAll");
|
||||||
|
QMetaObject::invokeMethod(d->m_overview->rootObject(), "clearDisplay");
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTraceView::selectNextEventWithId(int eventId)
|
||||||
|
{
|
||||||
|
if (d->m_mainView->rootObject())
|
||||||
|
QMetaObject::invokeMethod(d->m_mainView->rootObject(), "selectNextWithId",
|
||||||
|
Q_ARG(QVariant,QVariant(eventId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
// Goto source location
|
||||||
|
void QmlProfilerTraceView::updateCursorPosition()
|
||||||
|
{
|
||||||
|
emit gotoSourceLocation(d->m_mainView->rootObject()->property("fileName").toString(),
|
||||||
|
d->m_mainView->rootObject()->property("lineNumber").toInt(),
|
||||||
|
d->m_mainView->rootObject()->property("columnNumber").toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
// Toolbar buttons
|
||||||
|
void QmlProfilerTraceView::toggleRangeMode(bool active)
|
||||||
|
{
|
||||||
|
bool rangeMode = d->m_mainView->rootObject()->property("selectionRangeMode").toBool();
|
||||||
|
if (active != rangeMode) {
|
||||||
|
if (active)
|
||||||
|
d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselected.png"));
|
||||||
|
else
|
||||||
|
d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png"));
|
||||||
|
d->m_mainView->rootObject()->setProperty("selectionRangeMode", QVariant(active));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTraceView::updateRangeButton()
|
||||||
|
{
|
||||||
|
bool rangeMode = d->m_mainView->rootObject()->property("selectionRangeMode").toBool();
|
||||||
|
if (rangeMode)
|
||||||
|
d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselected.png"));
|
||||||
|
else
|
||||||
|
d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png"));
|
||||||
|
emit rangeModeChanged(rangeMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTraceView::toggleLockMode(bool active)
|
||||||
|
{
|
||||||
|
bool lockMode = !d->m_mainView->rootObject()->property("selectionLocked").toBool();
|
||||||
|
if (active != lockMode) {
|
||||||
|
d->m_mainView->rootObject()->setProperty("selectionLocked", QVariant(!active));
|
||||||
|
d->m_mainView->rootObject()->setProperty("selectedItem", QVariant(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTraceView::updateLockButton()
|
||||||
|
{
|
||||||
|
bool lockMode = !d->m_mainView->rootObject()->property("selectionLocked").toBool();
|
||||||
|
emit lockModeChanged(lockMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
// Zoom control
|
||||||
|
void QmlProfilerTraceView::setZoomLevel(int zoomLevel)
|
||||||
|
{
|
||||||
|
if (d->m_currentZoomLevel != zoomLevel && d->m_mainView->rootObject()) {
|
||||||
|
QVariant newFactor = pow(qreal(zoomLevel) / qreal(sliderTicks), sliderExp);
|
||||||
|
d->m_currentZoomLevel = zoomLevel;
|
||||||
|
QMetaObject::invokeMethod(d->m_mainView->rootObject(), "updateWindowLength", Q_ARG(QVariant, newFactor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTraceView::updateRange()
|
||||||
|
{
|
||||||
|
if (!d->m_profilerDataModel)
|
||||||
|
return;
|
||||||
|
qreal duration = d->m_zoomControl->endTime() - d->m_zoomControl->startTime();
|
||||||
|
if (duration <= 0)
|
||||||
|
return;
|
||||||
|
if (d->m_profilerDataModel->traceDuration() <= 0)
|
||||||
|
return;
|
||||||
|
int newLevel = pow(duration / d->m_profilerDataModel->traceDuration(), 1/sliderExp) * sliderTicks;
|
||||||
|
if (d->m_currentZoomLevel != newLevel) {
|
||||||
|
d->m_currentZoomLevel = newLevel;
|
||||||
|
emit zoomLevelChanged(newLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTraceView::mouseWheelMoved(int mouseX, int mouseY, int wheelDelta)
|
||||||
|
{
|
||||||
|
Q_UNUSED(mouseY);
|
||||||
|
if (d->m_mainView->rootObject()) {
|
||||||
|
QMetaObject::invokeMethod(d->m_mainView->rootObject(), "wheelZoom",
|
||||||
|
Q_ARG(QVariant, QVariant(mouseX)),
|
||||||
|
Q_ARG(QVariant, QVariant(wheelDelta)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
void QmlProfilerTraceView::updateToolTip(const QString &text)
|
||||||
|
{
|
||||||
|
setToolTip(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTraceView::updateVerticalScroll(int newPosition)
|
||||||
|
{
|
||||||
|
d->m_mainView->verticalScrollBar()->setValue(newPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTraceView::resizeEvent(QResizeEvent *event)
|
||||||
|
{
|
||||||
|
if (d->m_mainView->rootObject()) {
|
||||||
|
d->m_mainView->rootObject()->setProperty("width", QVariant(event->size().width()));
|
||||||
|
int newHeight = event->size().height() - d->m_timebar->height() - d->m_overview->height();
|
||||||
|
d->m_mainView->rootObject()->setProperty("candidateHeight", QVariant(newHeight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// Context menu
|
||||||
|
void QmlProfilerTraceView::contextMenuEvent(QContextMenuEvent *ev)
|
||||||
|
{
|
||||||
|
QMenu menu;
|
||||||
|
QAction *viewAllAction = 0;
|
||||||
|
QAction *getLocalStatsAction = 0;
|
||||||
|
QAction *getGlobalStatsAction = 0;
|
||||||
|
|
||||||
|
QmlProfilerTool *profilerTool = qobject_cast<QmlProfilerTool *>(d->m_profilerTool);
|
||||||
|
QPoint position = ev->globalPos();
|
||||||
|
|
||||||
|
if (profilerTool) {
|
||||||
|
QList <QAction *> commonActions = profilerTool->profilerContextMenuActions();
|
||||||
|
foreach (QAction *act, commonActions) {
|
||||||
|
menu.addAction(act);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.addSeparator();
|
||||||
|
getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range"));
|
||||||
|
if (!d->m_viewContainer->hasValidSelection())
|
||||||
|
getLocalStatsAction->setEnabled(false);
|
||||||
|
getGlobalStatsAction = menu.addAction(tr("Reset Events Pane"));
|
||||||
|
if (d->m_viewContainer->hasGlobalStats())
|
||||||
|
getGlobalStatsAction->setEnabled(false);
|
||||||
|
|
||||||
|
|
||||||
|
if (d->m_profilerDataModel->count() > 0) {
|
||||||
|
menu.addSeparator();
|
||||||
|
viewAllAction = menu.addAction(tr("Reset Zoom"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QAction *selectedAction = menu.exec(position);
|
||||||
|
|
||||||
|
if (selectedAction) {
|
||||||
|
if (selectedAction == viewAllAction) {
|
||||||
|
d->m_zoomControl->setRange(
|
||||||
|
d->m_profilerDataModel->traceStartTime(),
|
||||||
|
d->m_profilerDataModel->traceEndTime());
|
||||||
|
}
|
||||||
|
if (selectedAction == getLocalStatsAction) {
|
||||||
|
d->m_viewContainer->getStatisticsInRange(
|
||||||
|
d->m_viewContainer->selectionStart(),
|
||||||
|
d->m_viewContainer->selectionEnd());
|
||||||
|
}
|
||||||
|
if (selectedAction == getGlobalStatsAction) {
|
||||||
|
d->m_viewContainer->getStatisticsInRange(
|
||||||
|
d->m_profilerDataModel->traceStartTime(),
|
||||||
|
d->m_profilerDataModel->traceEndTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////
|
||||||
|
// Tell QML the state of the profiler
|
||||||
|
void QmlProfilerTraceView::setRecording(bool recording)
|
||||||
|
{
|
||||||
|
if (d->m_mainView->rootObject())
|
||||||
|
d->m_mainView->rootObject()->setProperty("recordingEnabled", QVariant(recording));
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTraceView::setAppKilled()
|
||||||
|
{
|
||||||
|
if (d->m_mainView->rootObject())
|
||||||
|
d->m_mainView->rootObject()->setProperty("appKilled",QVariant(true));
|
||||||
|
}
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// Profiler State
|
||||||
|
void QmlProfilerTraceView::profilerDataModelStateChanged()
|
||||||
|
{
|
||||||
|
switch (d->m_profilerDataModel->currentState()) {
|
||||||
|
case QmlProfilerDataModel::Empty :
|
||||||
|
emit enableToolbar(false);
|
||||||
|
break;
|
||||||
|
case QmlProfilerDataModel::AcquiringData :
|
||||||
|
// nothing to be done
|
||||||
|
break;
|
||||||
|
case QmlProfilerDataModel::ProcessingData :
|
||||||
|
// nothing to be done
|
||||||
|
break;
|
||||||
|
case QmlProfilerDataModel::Done :
|
||||||
|
emit enableToolbar(true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTraceView::profilerStateChanged()
|
||||||
|
{
|
||||||
|
switch (d->m_profilerState->currentState()) {
|
||||||
|
case QmlProfilerStateManager::AppKilled : {
|
||||||
|
if (d->m_profilerDataModel->currentState() == QmlProfilerDataModel::AcquiringData)
|
||||||
|
setAppKilled();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// no special action needed for other states
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTraceView::clientRecordingChanged()
|
||||||
|
{
|
||||||
|
// nothing yet
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTraceView::serverRecordingChanged()
|
||||||
|
{
|
||||||
|
setRecording(d->m_profilerState->serverRecording());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace QmlProfiler
|
@@ -30,24 +30,23 @@
|
|||||||
**
|
**
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#ifndef TRACEWINDOW_H
|
#ifndef QMLPROFILERTRACEVIEW_H
|
||||||
#define TRACEWINDOW_H
|
#define QMLPROFILERTRACEVIEW_H
|
||||||
|
|
||||||
#include <qmljsdebugclient/qmlprofilertraceclient.h>
|
|
||||||
#include <qmljsdebugclient/qmlprofilereventlist.h>
|
|
||||||
#include "qmlprofilerdetailsrewriter.h"
|
|
||||||
#include <qmljsdebugclient/qv8profilerclient.h>
|
|
||||||
|
|
||||||
#include <QPointer>
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QToolButton>
|
|
||||||
|
|
||||||
#include <QEvent>
|
|
||||||
#include <QDeclarativeView>
|
#include <QDeclarativeView>
|
||||||
|
|
||||||
|
namespace Analyzer {
|
||||||
|
class IAnalyzerTool;
|
||||||
|
}
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
class QmlProfilerStateManager;
|
||||||
|
class QmlProfilerViewManager;
|
||||||
|
class QmlProfilerDataModel;
|
||||||
|
|
||||||
|
// capture mouse wheel events
|
||||||
class MouseWheelResizer : public QObject {
|
class MouseWheelResizer : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -87,117 +86,73 @@ protected:
|
|||||||
void scrollContentsBy(int dx, int dy);
|
void scrollContentsBy(int dx, int dy);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TraceWindow : public QWidget
|
class QmlProfilerTraceView : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TraceWindow(QWidget *parent = 0);
|
explicit QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerTool *profilerTool, QmlProfilerViewManager *container, QmlProfilerDataModel *model, QmlProfilerStateManager *profilerState);
|
||||||
~TraceWindow();
|
~QmlProfilerTraceView();
|
||||||
|
|
||||||
void reset(QmlJsDebugClient::QDeclarativeDebugConnection *conn);
|
void reset();
|
||||||
|
|
||||||
QmlJsDebugClient::QmlProfilerEventList *getEventList() const;
|
|
||||||
ZoomControl *rangeTimes() const;
|
|
||||||
|
|
||||||
void setRecording(bool recording);
|
|
||||||
bool isRecording() const;
|
|
||||||
void viewAll();
|
|
||||||
|
|
||||||
bool hasValidSelection() const;
|
bool hasValidSelection() const;
|
||||||
qint64 selectionStart() const;
|
qint64 selectionStart() const;
|
||||||
qint64 selectionEnd() const;
|
qint64 selectionEnd() const;
|
||||||
double profiledTime() const;
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void clearDisplay();
|
void clearDisplay();
|
||||||
void selectNextEvent(int eventId);
|
void selectNextEventWithId(int eventId);
|
||||||
void applicationDied();
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void updateCursorPosition();
|
void updateCursorPosition();
|
||||||
void updateTimer();
|
|
||||||
void updateToolbar();
|
|
||||||
void toggleRangeMode(bool);
|
void toggleRangeMode(bool);
|
||||||
void toggleLockMode(bool);
|
|
||||||
void updateRangeButton();
|
void updateRangeButton();
|
||||||
|
void toggleLockMode(bool);
|
||||||
void updateLockButton();
|
void updateLockButton();
|
||||||
|
|
||||||
void setZoomLevel(int zoomLevel);
|
void setZoomLevel(int zoomLevel);
|
||||||
void updateRange();
|
void updateRange();
|
||||||
void mouseWheelMoved(int x, int y, int delta);
|
void mouseWheelMoved(int mouseX, int mouseY, int wheelDelta);
|
||||||
|
|
||||||
void qmlComplete();
|
|
||||||
void v8Complete();
|
|
||||||
void updateProfilerState();
|
|
||||||
void updateToolTip(const QString &text);
|
void updateToolTip(const QString &text);
|
||||||
void updateVerticalScroll(int newPosition);
|
void updateVerticalScroll(int newPosition);
|
||||||
void eventListStateChanged();
|
void profilerDataModelStateChanged();
|
||||||
void manageTraceStart(qint64 traceStart);
|
|
||||||
void firstDataReceived();
|
protected:
|
||||||
void correctTimer();
|
virtual void resizeEvent(QResizeEvent *event);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void profilerStateChanged();
|
||||||
|
void clientRecordingChanged();
|
||||||
|
void serverRecordingChanged();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void viewUpdated();
|
|
||||||
void profilerStateChanged(bool qmlActive, bool v8active);
|
|
||||||
void gotoSourceLocation(const QString &fileUrl, int lineNumber, int columNumber);
|
void gotoSourceLocation(const QString &fileUrl, int lineNumber, int columNumber);
|
||||||
void range(int type, qint64 startTime, qint64 length, const QStringList &data, const QmlJsDebugClient::QmlEventLocation &location);
|
void selectedEventChanged(int eventId);
|
||||||
void v8range(int depth,const QString &function,const QString &filename,
|
|
||||||
int lineNumber, double totalTime, double selfTime);
|
|
||||||
void traceFinished(qint64);
|
|
||||||
void traceStarted(qint64);
|
|
||||||
void frameEvent(qint64, int, int);
|
|
||||||
void recordingChanged(bool);
|
|
||||||
|
|
||||||
void internalClearDisplay();
|
|
||||||
void clearViewsFromTool();
|
|
||||||
void jumpToPrev();
|
void jumpToPrev();
|
||||||
void jumpToNext();
|
void jumpToNext();
|
||||||
void rangeModeChanged(bool);
|
void rangeModeChanged(bool);
|
||||||
void lockModeChanged(bool);
|
void lockModeChanged(bool);
|
||||||
void enableToolbar(bool);
|
void enableToolbar(bool);
|
||||||
void zoomLevelChanged(int);
|
void zoomLevelChanged(int);
|
||||||
void updateViewZoom(QVariant zoomLevel);
|
|
||||||
void wheelZoom(QVariant wheelCenter, QVariant wheelDelta);
|
|
||||||
void globalZoom();
|
|
||||||
|
|
||||||
void contextMenuRequested(const QPoint& position);
|
|
||||||
void selectNextEventInDisplay(QVariant eventId);
|
|
||||||
void selectedEventIdChanged(int eventId);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void contextMenuEvent(QContextMenuEvent *);
|
void contextMenuEvent(QContextMenuEvent *);
|
||||||
QWidget *createToolbar();
|
QWidget *createToolbar();
|
||||||
QWidget *createZoomToolbar();
|
QWidget *createZoomToolbar();
|
||||||
void connectClientSignals();
|
|
||||||
void disconnectClientSignals();
|
|
||||||
|
|
||||||
protected:
|
void setRecording(bool recording);
|
||||||
virtual void resizeEvent(QResizeEvent *event);
|
void setAppKilled();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWeakPointer<QmlJsDebugClient::QmlProfilerTraceClient> m_plugin;
|
class QmlProfilerTraceViewPrivate;
|
||||||
QWeakPointer<QmlJsDebugClient::QV8ProfilerClient> m_v8plugin;
|
QmlProfilerTraceViewPrivate *d;
|
||||||
QSize m_sizeHint;
|
|
||||||
|
|
||||||
ScrollableDeclarativeView *m_mainView;
|
|
||||||
QDeclarativeView *m_timebar;
|
|
||||||
QDeclarativeView *m_overview;
|
|
||||||
QmlJsDebugClient::QmlProfilerEventList *m_eventList;
|
|
||||||
QmlProfilerDetailsRewriter *m_rewriter;
|
|
||||||
bool m_qmlDataReady;
|
|
||||||
bool m_v8DataReady;
|
|
||||||
double m_profiledTime;
|
|
||||||
|
|
||||||
QWeakPointer<ZoomControl> m_zoomControl;
|
|
||||||
|
|
||||||
QToolButton *m_buttonRange;
|
|
||||||
QToolButton *m_buttonLock;
|
|
||||||
QWidget *m_zoomToolbar;
|
|
||||||
int m_currentZoomLevel;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace QmlProfiler
|
} // namespace QmlProfiler
|
||||||
|
|
||||||
#endif // TRACEWINDOW_H
|
#endif // QMLPROFILERTRACEVIEW_H
|
||||||
|
|
172
src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp
Normal file
172
src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "qmlprofilerviewmanager.h"
|
||||||
|
|
||||||
|
#include "qmlprofilertraceview.h"
|
||||||
|
#include "qmlprofilereventview.h"
|
||||||
|
#include "qmlprofilertool.h"
|
||||||
|
#include "qmlprofilerstatemanager.h"
|
||||||
|
#include "qmlprofilerdatamodel.h"
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/fancymainwindow.h>
|
||||||
|
#include <analyzerbase/analyzermanager.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <QDockWidget>
|
||||||
|
|
||||||
|
using namespace Analyzer;
|
||||||
|
|
||||||
|
namespace QmlProfiler {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class QmlProfilerViewManager::QmlProfilerViewManagerPrivate {
|
||||||
|
public:
|
||||||
|
QmlProfilerViewManagerPrivate(QmlProfilerViewManager *qq) { Q_UNUSED(qq); }
|
||||||
|
|
||||||
|
QmlProfilerTraceView *traceView;
|
||||||
|
QmlProfilerEventsWidget *eventsView;
|
||||||
|
QmlProfilerEventsWidget *v8profilerView;
|
||||||
|
QmlProfilerStateManager *profilerState;
|
||||||
|
QmlProfilerDataModel *profilerDataModel;
|
||||||
|
QmlProfilerTool *profilerTool;
|
||||||
|
};
|
||||||
|
|
||||||
|
QmlProfilerViewManager::QmlProfilerViewManager(QObject *parent,
|
||||||
|
QmlProfilerTool *profilerTool,
|
||||||
|
QmlProfilerDataModel *model,
|
||||||
|
QmlProfilerStateManager *profilerState)
|
||||||
|
: QObject(parent), d(new QmlProfilerViewManagerPrivate(this))
|
||||||
|
{
|
||||||
|
setObjectName("QML Profiler View Manager");
|
||||||
|
d->traceView = 0;
|
||||||
|
d->eventsView = 0;
|
||||||
|
d->v8profilerView = 0;
|
||||||
|
d->profilerState = profilerState;
|
||||||
|
d->profilerDataModel = model;
|
||||||
|
d->profilerTool = profilerTool;
|
||||||
|
createViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlProfilerViewManager::~QmlProfilerViewManager()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Views
|
||||||
|
void QmlProfilerViewManager::createViews()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(d->profilerDataModel, return);
|
||||||
|
QTC_ASSERT(d->profilerState, return);
|
||||||
|
|
||||||
|
Utils::FancyMainWindow *mw = AnalyzerManager::mainWindow();
|
||||||
|
|
||||||
|
d->traceView = new QmlProfilerTraceView(mw,
|
||||||
|
d->profilerTool,
|
||||||
|
this,
|
||||||
|
d->profilerDataModel,
|
||||||
|
d->profilerState);
|
||||||
|
connect(d->traceView, SIGNAL(gotoSourceLocation(QString,int,int)),
|
||||||
|
this, SIGNAL(gotoSourceLocation(QString,int,int)));
|
||||||
|
|
||||||
|
d->traceView->reset();
|
||||||
|
|
||||||
|
d->eventsView = new QmlProfilerEventsWidget(mw, d->profilerTool, this, d->profilerDataModel);
|
||||||
|
connect(d->eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), this,
|
||||||
|
SIGNAL(gotoSourceLocation(QString,int,int)));
|
||||||
|
connect(d->eventsView, SIGNAL(showEventInTimeline(int)), d->traceView,
|
||||||
|
SLOT(selectNextEventWithId(int)));
|
||||||
|
connect(d->traceView, SIGNAL(selectedEventChanged(int)), d->eventsView,
|
||||||
|
SLOT(updateSelectedEvent(int)));
|
||||||
|
|
||||||
|
d->v8profilerView = new QmlProfilerEventsWidget(mw, d->profilerTool,
|
||||||
|
this, d->profilerDataModel);
|
||||||
|
d->v8profilerView->switchToV8View();
|
||||||
|
connect(d->v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)),
|
||||||
|
this, SIGNAL(gotoSourceLocation(QString,int,int)));
|
||||||
|
connect(d->v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)),
|
||||||
|
d->eventsView, SLOT(selectBySourceLocation(QString,int,int)));
|
||||||
|
connect(d->eventsView, SIGNAL(gotoSourceLocation(QString,int,int)),
|
||||||
|
d->v8profilerView, SLOT(selectBySourceLocation(QString,int,int)));
|
||||||
|
|
||||||
|
QDockWidget *eventsDock = AnalyzerManager::createDockWidget
|
||||||
|
(d->profilerTool, tr("Events"), d->eventsView, Qt::BottomDockWidgetArea);
|
||||||
|
QDockWidget *timelineDock = AnalyzerManager::createDockWidget
|
||||||
|
(d->profilerTool, tr("Timeline"), d->traceView, Qt::BottomDockWidgetArea);
|
||||||
|
QDockWidget *v8profilerDock = AnalyzerManager::createDockWidget
|
||||||
|
(d->profilerTool, tr("JavaScript"), d->v8profilerView, Qt::BottomDockWidgetArea);
|
||||||
|
|
||||||
|
eventsDock->show();
|
||||||
|
timelineDock->show();
|
||||||
|
v8profilerDock->show();
|
||||||
|
|
||||||
|
mw->splitDockWidget(mw->toolBarDockWidget(), eventsDock, Qt::Vertical);
|
||||||
|
mw->tabifyDockWidget(eventsDock, timelineDock);
|
||||||
|
mw->tabifyDockWidget(timelineDock, v8profilerDock);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlProfilerViewManager::hasValidSelection() const
|
||||||
|
{
|
||||||
|
return d->traceView->hasValidSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 QmlProfilerViewManager::selectionStart() const
|
||||||
|
{
|
||||||
|
return d->traceView->selectionStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 QmlProfilerViewManager::selectionEnd() const
|
||||||
|
{
|
||||||
|
return d->traceView->selectionEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlProfilerViewManager::hasGlobalStats() const
|
||||||
|
{
|
||||||
|
return d->eventsView->hasGlobalStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerViewManager::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd)
|
||||||
|
{
|
||||||
|
d->eventsView->getStatisticsInRange(rangeStart, rangeEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerViewManager::clear()
|
||||||
|
{
|
||||||
|
d->traceView->clearDisplay();
|
||||||
|
d->eventsView->clear();
|
||||||
|
d->v8profilerView->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace QmlProfiler
|
@@ -30,26 +30,50 @@
|
|||||||
**
|
**
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "qmlprofilerapplication.h"
|
#ifndef QMLPROFILERVIEWMANAGER_H
|
||||||
#include "commandlistener.h"
|
#define QMLPROFILERVIEWMANAGER_H
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace QmlProfiler {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class QmlProfilerTool;
|
||||||
|
class QmlProfilerDataModel;
|
||||||
|
class QmlProfilerStateManager;
|
||||||
|
|
||||||
|
class QmlProfilerViewManager : public QObject
|
||||||
{
|
{
|
||||||
QmlProfilerApplication app(argc, argv);
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit QmlProfilerViewManager(QObject *parent,
|
||||||
|
QmlProfilerTool *profilerTool,
|
||||||
|
QmlProfilerDataModel *model,
|
||||||
|
QmlProfilerStateManager *profilerState);
|
||||||
|
~QmlProfilerViewManager();
|
||||||
|
|
||||||
if (!app.parseArguments()) {
|
void createViews();
|
||||||
app.printUsage();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandListener listener;
|
// used by the options "limit events to range"
|
||||||
QObject::connect(&listener, SIGNAL(command(QString)), &app, SLOT(userCommand(QString)));
|
bool hasValidSelection() const;
|
||||||
listener.start();
|
qint64 selectionStart() const;
|
||||||
|
qint64 selectionEnd() const;
|
||||||
|
bool hasGlobalStats() const;
|
||||||
|
void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd);
|
||||||
|
|
||||||
int exitValue = app.exec();
|
public slots:
|
||||||
// wait for listener to exit
|
void clear();
|
||||||
listener.wait();
|
|
||||||
|
signals:
|
||||||
|
void gotoSourceLocation(QString,int,int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class QmlProfilerViewManagerPrivate;
|
||||||
|
QmlProfilerViewManagerPrivate *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
return exitValue;
|
} // namespace Internal
|
||||||
}
|
} // namespace QmlProfiler
|
||||||
|
|
||||||
|
#endif // QMLPROFILERVIEWMANAGER_H
|
445
src/plugins/qmlprofiler/qv8profilerdatamodel.cpp
Normal file
445
src/plugins/qmlprofiler/qv8profilerdatamodel.cpp
Normal file
@@ -0,0 +1,445 @@
|
|||||||
|
#include "qv8profilerdatamodel.h"
|
||||||
|
#include "qmlprofilerdatamodel.h"
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
using namespace QmlJsDebugClient;
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QV8EventData, Q_MOVABLE_TYPE);
|
||||||
|
Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QV8EventSub, Q_MOVABLE_TYPE);
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace QmlProfiler {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
QV8EventData &QV8EventData::operator=(const QV8EventData &ref)
|
||||||
|
{
|
||||||
|
if (this == &ref)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
displayName = ref.displayName;
|
||||||
|
eventHashStr = ref.eventHashStr;
|
||||||
|
filename = ref.filename;
|
||||||
|
functionName = ref.functionName;
|
||||||
|
line = ref.line;
|
||||||
|
totalTime = ref.totalTime;
|
||||||
|
totalPercent = ref.totalPercent;
|
||||||
|
selfTime = ref.selfTime;
|
||||||
|
selfPercent = ref.selfPercent;
|
||||||
|
eventId = ref.eventId;
|
||||||
|
|
||||||
|
qDeleteAll(parentHash.values());
|
||||||
|
parentHash.clear();
|
||||||
|
foreach (const QString &key, ref.parentHash.keys()) {
|
||||||
|
parentHash.insert(key, new QV8EventSub(ref.parentHash.value(key)));
|
||||||
|
}
|
||||||
|
|
||||||
|
qDeleteAll(childrenHash.values());
|
||||||
|
childrenHash.clear();
|
||||||
|
foreach (const QString &key, ref.childrenHash.keys()) {
|
||||||
|
childrenHash.insert(key, new QV8EventSub(ref.childrenHash.value(key)));
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
QV8EventData::QV8EventData()
|
||||||
|
{
|
||||||
|
line = -1;
|
||||||
|
eventId = -1;
|
||||||
|
totalTime = 0;
|
||||||
|
selfTime = 0;
|
||||||
|
totalPercent = 0;
|
||||||
|
selfPercent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QV8EventData::~QV8EventData()
|
||||||
|
{
|
||||||
|
qDeleteAll(parentHash.values());
|
||||||
|
parentHash.clear();
|
||||||
|
qDeleteAll(childrenHash.values());
|
||||||
|
childrenHash.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
class QV8ProfilerDataModel::QV8ProfilerDataModelPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QV8ProfilerDataModelPrivate(QV8ProfilerDataModel *qq) {Q_UNUSED(qq);}
|
||||||
|
|
||||||
|
QmlProfilerDataModel *qmlProfilerDataModel;
|
||||||
|
|
||||||
|
void clearV8RootEvent();
|
||||||
|
void collectV8Statistics();
|
||||||
|
|
||||||
|
QHash<QString, QV8EventData *> v8EventHash;
|
||||||
|
QHash<int, QV8EventData *> v8parents;
|
||||||
|
QV8EventData v8RootEvent;
|
||||||
|
qint64 v8MeasuredTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
QV8ProfilerDataModel::QV8ProfilerDataModel(QObject *parent,
|
||||||
|
QmlProfilerDataModel *profilerDataModel)
|
||||||
|
: QObject(parent), d(new QV8ProfilerDataModelPrivate(this))
|
||||||
|
{
|
||||||
|
d->v8MeasuredTime = 0;
|
||||||
|
d->clearV8RootEvent();
|
||||||
|
d->qmlProfilerDataModel = profilerDataModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
QV8ProfilerDataModel::~QV8ProfilerDataModel()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QV8ProfilerDataModel::clear()
|
||||||
|
{
|
||||||
|
qDeleteAll(d->v8EventHash.values());
|
||||||
|
d->v8EventHash.clear();
|
||||||
|
d->v8parents.clear();
|
||||||
|
d->clearV8RootEvent();
|
||||||
|
d->v8MeasuredTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QV8ProfilerDataModel::isEmpty() const
|
||||||
|
{
|
||||||
|
return d->v8EventHash.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
QV8EventData *QV8ProfilerDataModel::v8EventDescription(int eventId) const
|
||||||
|
{
|
||||||
|
foreach (QV8EventData *event, d->v8EventHash.values()) {
|
||||||
|
if (event->eventId == eventId)
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 QV8ProfilerDataModel::v8MeasuredTime() const
|
||||||
|
{
|
||||||
|
return d->v8MeasuredTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QV8EventData *> QV8ProfilerDataModel::getV8Events() const
|
||||||
|
{
|
||||||
|
return d->v8EventHash.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QV8ProfilerDataModel::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 = QmlProfilerDataModel::getHashStringForV8Event(displayName, function);
|
||||||
|
|
||||||
|
d->qmlProfilerDataModel->setState(QmlProfilerDataModel::AcquiringData);
|
||||||
|
|
||||||
|
// time is given in milliseconds, but internally we store it in microseconds
|
||||||
|
totalTime *= 1e6;
|
||||||
|
selfTime *= 1e6;
|
||||||
|
|
||||||
|
// accumulate information
|
||||||
|
QV8EventData *eventData = d->v8EventHash[hashStr];
|
||||||
|
if (!eventData) {
|
||||||
|
eventData = new QV8EventData;
|
||||||
|
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;
|
||||||
|
|
||||||
|
QV8EventData *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 (!eventData->parentHash.contains(parentEvent->eventHashStr)) {
|
||||||
|
QV8EventSub *newParentSub = new QV8EventSub(parentEvent);
|
||||||
|
newParentSub->totalTime = totalTime;
|
||||||
|
|
||||||
|
eventData->parentHash.insert(parentEvent->eventHashStr, newParentSub);
|
||||||
|
} else {
|
||||||
|
QV8EventSub *newParentSub = eventData->parentHash.value(parentEvent->eventHashStr);
|
||||||
|
newParentSub->totalTime += totalTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parentEvent->childrenHash.contains(eventData->eventHashStr)) {
|
||||||
|
QV8EventSub *newChildSub = new QV8EventSub(eventData);
|
||||||
|
newChildSub->totalTime = totalTime;
|
||||||
|
|
||||||
|
parentEvent->childrenHash.insert(eventData->eventHashStr, newChildSub);
|
||||||
|
} else {
|
||||||
|
QV8EventSub *newChildSub = parentEvent->childrenHash.value(eventData->eventHashStr);
|
||||||
|
newChildSub->totalTime += totalTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QV8ProfilerDataModel::collectV8Statistics()
|
||||||
|
{
|
||||||
|
d->collectV8Statistics();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QV8ProfilerDataModel::QV8ProfilerDataModelPrivate::collectV8Statistics()
|
||||||
|
{
|
||||||
|
if (!v8EventHash.isEmpty()) {
|
||||||
|
double totalTimes = v8MeasuredTime;
|
||||||
|
double selfTimes = 0;
|
||||||
|
foreach (QV8EventData *v8event, v8EventHash.values()) {
|
||||||
|
selfTimes += v8event->selfTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prevent divisions by 0
|
||||||
|
if (totalTimes == 0)
|
||||||
|
totalTimes = 1;
|
||||||
|
if (selfTimes == 0)
|
||||||
|
selfTimes = 1;
|
||||||
|
|
||||||
|
// insert root event in eventlist
|
||||||
|
// the +1 ns is to get it on top of the sorted list
|
||||||
|
v8RootEvent.totalTime = v8MeasuredTime + 1;
|
||||||
|
v8RootEvent.selfTime = 0;
|
||||||
|
|
||||||
|
QString rootEventHash = QmlProfilerDataModel::getHashStringForV8Event(
|
||||||
|
QmlProfilerDataModel::rootEventName(),
|
||||||
|
QmlProfilerDataModel::rootEventDescription());
|
||||||
|
QV8EventData *v8RootEventPointer = v8EventHash[rootEventHash];
|
||||||
|
if (v8RootEventPointer) {
|
||||||
|
v8RootEvent = *v8RootEventPointer;
|
||||||
|
} else {
|
||||||
|
v8EventHash[rootEventHash] = new QV8EventData;
|
||||||
|
*v8EventHash[rootEventHash] = v8RootEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (QV8EventData *v8event, v8EventHash.values()) {
|
||||||
|
v8event->totalPercent = v8event->totalTime * 100.0 / totalTimes;
|
||||||
|
v8event->selfPercent = v8event->selfTime * 100.0 / selfTimes;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
foreach (QV8EventData *v8event, v8EventHash.values()) {
|
||||||
|
v8event->eventId = index++;
|
||||||
|
}
|
||||||
|
v8RootEvent.eventId = v8EventHash[rootEventHash]->eventId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QV8ProfilerDataModel::QV8ProfilerDataModelPrivate::clearV8RootEvent()
|
||||||
|
{
|
||||||
|
v8RootEvent.displayName = QmlProfilerDataModel::rootEventName();
|
||||||
|
v8RootEvent.eventHashStr = QmlProfilerDataModel::rootEventName();
|
||||||
|
v8RootEvent.functionName = QmlProfilerDataModel::rootEventDescription();
|
||||||
|
v8RootEvent.line = -1;
|
||||||
|
v8RootEvent.totalTime = 0;
|
||||||
|
v8RootEvent.totalPercent = 0;
|
||||||
|
v8RootEvent.selfTime = 0;
|
||||||
|
v8RootEvent.selfPercent = 0;
|
||||||
|
v8RootEvent.eventId = -1;
|
||||||
|
|
||||||
|
qDeleteAll(v8RootEvent.parentHash.values());
|
||||||
|
qDeleteAll(v8RootEvent.childrenHash.values());
|
||||||
|
v8RootEvent.parentHash.clear();
|
||||||
|
v8RootEvent.childrenHash.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QV8ProfilerDataModel::save(QXmlStreamWriter &stream)
|
||||||
|
{
|
||||||
|
stream.writeStartElement("v8profile"); // v8 profiler output
|
||||||
|
stream.writeAttribute("totalTime", QString::number(d->v8MeasuredTime));
|
||||||
|
foreach (QV8EventData *v8event, d->v8EventHash.values()) {
|
||||||
|
stream.writeStartElement("event");
|
||||||
|
stream.writeAttribute("index",
|
||||||
|
QString::number(
|
||||||
|
d->v8EventHash.keys().indexOf(
|
||||||
|
v8event->eventHashStr)));
|
||||||
|
stream.writeTextElement("displayname", v8event->displayName);
|
||||||
|
stream.writeTextElement("functionname", v8event->functionName);
|
||||||
|
if (!v8event->filename.isEmpty()) {
|
||||||
|
stream.writeTextElement("filename", v8event->filename);
|
||||||
|
stream.writeTextElement("line", QString::number(v8event->line));
|
||||||
|
}
|
||||||
|
stream.writeTextElement("totalTime", QString::number(v8event->totalTime));
|
||||||
|
stream.writeTextElement("selfTime", QString::number(v8event->selfTime));
|
||||||
|
if (!v8event->childrenHash.isEmpty()) {
|
||||||
|
stream.writeStartElement("childrenEvents");
|
||||||
|
QStringList childrenIndexes;
|
||||||
|
QStringList childrenTimes;
|
||||||
|
QStringList parentTimes;
|
||||||
|
foreach (QV8EventSub *v8child, v8event->childrenHash.values()) {
|
||||||
|
childrenIndexes << QString::number(v8child->reference->eventId);
|
||||||
|
childrenTimes << QString::number(v8child->totalTime);
|
||||||
|
parentTimes << QString::number(v8child->totalTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.writeAttribute("list", childrenIndexes.join(QString(", ")));
|
||||||
|
stream.writeAttribute("childrenTimes", childrenTimes.join(QString(", ")));
|
||||||
|
stream.writeAttribute("parentTimes", parentTimes.join(QString(", ")));
|
||||||
|
stream.writeEndElement();
|
||||||
|
}
|
||||||
|
stream.writeEndElement();
|
||||||
|
}
|
||||||
|
stream.writeEndElement(); // v8 profiler output
|
||||||
|
}
|
||||||
|
|
||||||
|
void QV8ProfilerDataModel::load(QXmlStreamReader &stream)
|
||||||
|
{
|
||||||
|
QHash <int, QV8EventData *> v8eventBuffer;
|
||||||
|
QHash <int, QString> childrenIndexes;
|
||||||
|
QHash <int, QString> childrenTimes;
|
||||||
|
QHash <int, QString> parentTimes;
|
||||||
|
QV8EventData *v8event = 0;
|
||||||
|
|
||||||
|
// time computation
|
||||||
|
d->v8MeasuredTime = 0;
|
||||||
|
double cumulatedV8Time = 0;
|
||||||
|
|
||||||
|
// get the v8 time
|
||||||
|
QXmlStreamAttributes attributes = stream.attributes();
|
||||||
|
if (attributes.hasAttribute("totalTime"))
|
||||||
|
d->v8MeasuredTime = attributes.value("totalTime").toString().toDouble();
|
||||||
|
|
||||||
|
while (!stream.atEnd() && !stream.hasError()) {
|
||||||
|
QXmlStreamReader::TokenType token = stream.readNext();
|
||||||
|
QString elementName = stream.name().toString();
|
||||||
|
switch (token) {
|
||||||
|
case QXmlStreamReader::StartDocument : continue;
|
||||||
|
case QXmlStreamReader::StartElement : {
|
||||||
|
if (elementName == "event") {
|
||||||
|
QXmlStreamAttributes attributes = stream.attributes();
|
||||||
|
if (attributes.hasAttribute("index")) {
|
||||||
|
int ndx = attributes.value("index").toString().toInt();
|
||||||
|
if (!v8eventBuffer.value(ndx))
|
||||||
|
v8eventBuffer[ndx] = new QV8EventData;
|
||||||
|
v8event = v8eventBuffer[ndx];
|
||||||
|
} else {
|
||||||
|
v8event = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!v8event)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (elementName == "childrenEvents") {
|
||||||
|
QXmlStreamAttributes attributes = stream.attributes();
|
||||||
|
int eventIndex = v8eventBuffer.key(v8event);
|
||||||
|
if (attributes.hasAttribute("list")) {
|
||||||
|
// store for later parsing (we haven't read all the events yet)
|
||||||
|
childrenIndexes[eventIndex] = attributes.value("list").toString();
|
||||||
|
}
|
||||||
|
if (attributes.hasAttribute("childrenTimes")) {
|
||||||
|
childrenTimes[eventIndex] =
|
||||||
|
attributes.value("childrenTimes").toString();
|
||||||
|
}
|
||||||
|
if (attributes.hasAttribute("parentTimes")) {
|
||||||
|
parentTimes[eventIndex] = attributes.value("parentTimes").toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.readNext();
|
||||||
|
if (stream.tokenType() != QXmlStreamReader::Characters)
|
||||||
|
break;
|
||||||
|
QString readData = stream.text().toString();
|
||||||
|
|
||||||
|
if (elementName == "displayname") {
|
||||||
|
v8event->displayName = readData;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elementName == "functionname") {
|
||||||
|
v8event->functionName = readData;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elementName == "filename") {
|
||||||
|
v8event->filename = readData;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elementName == "line") {
|
||||||
|
v8event->line = readData.toInt();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elementName == "totalTime") {
|
||||||
|
v8event->totalTime = readData.toDouble();
|
||||||
|
cumulatedV8Time += v8event->totalTime;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elementName == "selfTime") {
|
||||||
|
v8event->selfTime = readData.toDouble();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QXmlStreamReader::EndElement : {
|
||||||
|
if (elementName == "v8profile") {
|
||||||
|
// done reading the v8 profile data
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// backwards compatibility
|
||||||
|
if (d->v8MeasuredTime == 0)
|
||||||
|
d->v8MeasuredTime = cumulatedV8Time;
|
||||||
|
|
||||||
|
// find v8events' children and parents
|
||||||
|
foreach (int parentIndex, childrenIndexes.keys()) {
|
||||||
|
QStringList childrenStrings = childrenIndexes.value(parentIndex).split(",");
|
||||||
|
QStringList childrenTimesStrings = childrenTimes.value(parentIndex).split(", ");
|
||||||
|
QStringList parentTimesStrings = parentTimes.value(parentIndex).split(", ");
|
||||||
|
for (int ndx = 0; ndx < childrenStrings.count(); ndx++) {
|
||||||
|
int childIndex = childrenStrings[ndx].toInt();
|
||||||
|
if (v8eventBuffer.value(childIndex)) {
|
||||||
|
QV8EventSub *newChild = new QV8EventSub(v8eventBuffer[childIndex]);
|
||||||
|
QV8EventSub *newParent = new QV8EventSub(v8eventBuffer[parentIndex]);
|
||||||
|
if (childrenTimesStrings.count() > ndx) {
|
||||||
|
newChild->totalTime = childrenTimesStrings[ndx].toDouble();
|
||||||
|
}
|
||||||
|
if (parentTimesStrings.count() > ndx) {
|
||||||
|
newParent->totalTime = parentTimesStrings[ndx].toDouble();
|
||||||
|
}
|
||||||
|
v8eventBuffer[parentIndex]->childrenHash.insert(
|
||||||
|
newChild->reference->displayName,
|
||||||
|
newChild);
|
||||||
|
v8eventBuffer[childIndex]->parentHash.insert(
|
||||||
|
newParent->reference->displayName,
|
||||||
|
newParent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// store v8 events
|
||||||
|
foreach (QV8EventData *storedV8Event, v8eventBuffer.values()) {
|
||||||
|
storedV8Event->eventHashStr =
|
||||||
|
QmlProfilerDataModel::getHashStringForV8Event(
|
||||||
|
storedV8Event->displayName, storedV8Event->functionName);
|
||||||
|
d->v8EventHash[storedV8Event->eventHashStr] = storedV8Event;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->collectV8Statistics();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace QmlProfiler
|
79
src/plugins/qmlprofiler/qv8profilerdatamodel.h
Normal file
79
src/plugins/qmlprofiler/qv8profilerdatamodel.h
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#ifndef QV8PROFILERDATAMODEL_H
|
||||||
|
#define QV8PROFILERDATAMODEL_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
#include <QXmlStreamWriter>
|
||||||
|
|
||||||
|
namespace QmlProfiler {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class QmlProfilerDataModel;
|
||||||
|
struct QV8EventSub;
|
||||||
|
|
||||||
|
struct QV8EventData
|
||||||
|
{
|
||||||
|
QV8EventData();
|
||||||
|
~QV8EventData();
|
||||||
|
|
||||||
|
QString displayName;
|
||||||
|
QString eventHashStr;
|
||||||
|
QString filename;
|
||||||
|
QString functionName;
|
||||||
|
int line;
|
||||||
|
double totalTime; // given in milliseconds
|
||||||
|
double totalPercent;
|
||||||
|
double selfTime;
|
||||||
|
double selfPercent;
|
||||||
|
QHash <QString, QV8EventSub *> parentHash;
|
||||||
|
QHash <QString, QV8EventSub *> childrenHash;
|
||||||
|
int eventId;
|
||||||
|
|
||||||
|
QV8EventData &operator=(const QV8EventData &ref);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QV8EventSub {
|
||||||
|
QV8EventSub(QV8EventData *from) : reference(from), totalTime(0) {}
|
||||||
|
QV8EventSub(QV8EventSub *from) : reference(from->reference), totalTime(from->totalTime) {}
|
||||||
|
|
||||||
|
QV8EventData *reference;
|
||||||
|
qint64 totalTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QV8ProfilerDataModel : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit QV8ProfilerDataModel(QObject *parent, QmlProfilerDataModel *profilerDataModel);
|
||||||
|
~QV8ProfilerDataModel();
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
bool isEmpty() const;
|
||||||
|
QList<QV8EventData *> getV8Events() const;
|
||||||
|
QV8EventData *v8EventDescription(int eventId) const;
|
||||||
|
|
||||||
|
qint64 v8MeasuredTime() const;
|
||||||
|
void collectV8Statistics();
|
||||||
|
|
||||||
|
void save(QXmlStreamWriter &stream);
|
||||||
|
void load(QXmlStreamReader &stream);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void addV8Event(int depth,
|
||||||
|
const QString &function,
|
||||||
|
const QString &filename,
|
||||||
|
int lineNumber,
|
||||||
|
double totalTime,
|
||||||
|
double selfTime);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class QV8ProfilerDataModelPrivate;
|
||||||
|
QV8ProfilerDataModelPrivate *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace QmlProfiler
|
||||||
|
|
||||||
|
#endif // QV8PROFILERDATAMODEL_H
|
@@ -30,7 +30,7 @@
|
|||||||
**
|
**
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "timelineview.h"
|
#include "timelinerenderer.h"
|
||||||
|
|
||||||
#include <qdeclarativecontext.h>
|
#include <qdeclarativecontext.h>
|
||||||
#include <qdeclarativeproperty.h>
|
#include <qdeclarativeproperty.h>
|
||||||
@@ -45,9 +45,9 @@ using namespace QmlProfiler::Internal;
|
|||||||
|
|
||||||
const int DefaultRowHeight = 30;
|
const int DefaultRowHeight = 30;
|
||||||
|
|
||||||
TimelineView::TimelineView(QDeclarativeItem *parent) :
|
TimelineRenderer::TimelineRenderer(QDeclarativeItem *parent) :
|
||||||
QDeclarativeItem(parent), m_startTime(0), m_endTime(0), m_spacing(0),
|
QDeclarativeItem(parent), m_startTime(0), m_endTime(0), m_spacing(0),
|
||||||
m_lastStartTime(0), m_lastEndTime(0), m_eventList(0)
|
m_lastStartTime(0), m_lastEndTime(0), m_profilerDataModel(0)
|
||||||
{
|
{
|
||||||
clearData();
|
clearData();
|
||||||
setFlag(QGraphicsItem::ItemHasNoContents, false);
|
setFlag(QGraphicsItem::ItemHasNoContents, false);
|
||||||
@@ -57,12 +57,12 @@ TimelineView::TimelineView(QDeclarativeItem *parent) :
|
|||||||
m_rowsExpanded << false;
|
m_rowsExpanded << false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::componentComplete()
|
void TimelineRenderer::componentComplete()
|
||||||
{
|
{
|
||||||
const QMetaObject *metaObject = this->metaObject();
|
const QMetaObject *metaObject = this->metaObject();
|
||||||
int propertyCount = metaObject->propertyCount();
|
int propertyCount = metaObject->propertyCount();
|
||||||
int requestPaintMethod = metaObject->indexOfMethod("requestPaint()");
|
int requestPaintMethod = metaObject->indexOfMethod("requestPaint()");
|
||||||
for (int ii = TimelineView::staticMetaObject.propertyCount(); ii < propertyCount; ++ii) {
|
for (int ii = TimelineRenderer::staticMetaObject.propertyCount(); ii < propertyCount; ++ii) {
|
||||||
QMetaProperty p = metaObject->property(ii);
|
QMetaProperty p = metaObject->property(ii);
|
||||||
if (p.hasNotifySignal())
|
if (p.hasNotifySignal())
|
||||||
QMetaObject::connect(this, p.notifySignalIndex(), this, requestPaintMethod, 0, 0);
|
QMetaObject::connect(this, p.notifySignalIndex(), this, requestPaintMethod, 0, 0);
|
||||||
@@ -70,12 +70,12 @@ void TimelineView::componentComplete()
|
|||||||
QDeclarativeItem::componentComplete();
|
QDeclarativeItem::componentComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::requestPaint()
|
void TimelineRenderer::requestPaint()
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
|
void TimelineRenderer::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
|
||||||
{
|
{
|
||||||
qint64 windowDuration = m_endTime - m_startTime;
|
qint64 windowDuration = m_endTime - m_startTime;
|
||||||
if (windowDuration <= 0)
|
if (windowDuration <= 0)
|
||||||
@@ -86,7 +86,8 @@ void TimelineView::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget
|
|||||||
m_rowWidths.clear();
|
m_rowWidths.clear();
|
||||||
// The "1+" is because the reference screenshot features an empty row per type, in order to leave space for the title
|
// The "1+" is because the reference screenshot features an empty row per type, in order to leave space for the title
|
||||||
for (int i=0; i<QmlJsDebugClient::MaximumQmlEventType; i++) {
|
for (int i=0; i<QmlJsDebugClient::MaximumQmlEventType; i++) {
|
||||||
m_rowWidths << 1 + (m_rowsExpanded[i] ? m_eventList->uniqueEventsOfType(i) : m_eventList->maxNestingForType(i));
|
m_rowWidths << 1 + (m_rowsExpanded[i] ? m_profilerDataModel->uniqueEventsOfType(i) :
|
||||||
|
m_profilerDataModel->maxNestingForType(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// event rows
|
// event rows
|
||||||
@@ -105,8 +106,8 @@ void TimelineView::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget
|
|||||||
for (int j=0; j<m_rowWidths[i]; j++)
|
for (int j=0; j<m_rowWidths[i]; j++)
|
||||||
m_rowLastX << -m_startTime * m_spacing;
|
m_rowLastX << -m_startTime * m_spacing;
|
||||||
|
|
||||||
int firstIndex = m_eventList->findFirstIndex(m_startTime);
|
int firstIndex = m_profilerDataModel->findFirstIndex(m_startTime);
|
||||||
int lastIndex = m_eventList->findLastIndex(m_endTime);
|
int lastIndex = m_profilerDataModel->findLastIndex(m_endTime);
|
||||||
|
|
||||||
drawItemsToPainter(p, firstIndex, lastIndex);
|
drawItemsToPainter(p, firstIndex, lastIndex);
|
||||||
drawSelectionBoxes(p, firstIndex, lastIndex);
|
drawSelectionBoxes(p, firstIndex, lastIndex);
|
||||||
@@ -116,25 +117,27 @@ void TimelineView::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget
|
|||||||
m_lastEndTime = m_endTime;
|
m_lastEndTime = m_endTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor TimelineView::colorForItem(int itemIndex)
|
QColor TimelineRenderer::colorForItem(int itemIndex)
|
||||||
{
|
{
|
||||||
int ndx = m_eventList->getEventId(itemIndex);
|
int ndx = m_profilerDataModel->getEventId(itemIndex);
|
||||||
return QColor::fromHsl((ndx*25)%360, 76, 166);
|
return QColor::fromHsl((ndx*25)%360, 76, 166);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex)
|
void TimelineRenderer::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex)
|
||||||
{
|
{
|
||||||
int x, y, width, height, rowNumber, eventType;
|
int x, y, width, height, rowNumber, eventType;
|
||||||
for (int i = fromIndex; i <= toIndex; i++) {
|
for (int i = fromIndex; i <= toIndex; i++) {
|
||||||
x = (m_eventList->getStartTime(i) - m_startTime) * m_spacing;
|
x = (m_profilerDataModel->getStartTime(i) - m_startTime) * m_spacing;
|
||||||
|
|
||||||
eventType = m_eventList->getType(i);
|
eventType = m_profilerDataModel->getType(i);
|
||||||
if (m_rowsExpanded[eventType])
|
if (m_rowsExpanded[eventType])
|
||||||
y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->eventPosInType(i) + 1);
|
y = m_rowStarts[eventType] + DefaultRowHeight *
|
||||||
|
(m_profilerDataModel->eventPosInType(i) + 1);
|
||||||
else
|
else
|
||||||
y = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->getNestingLevel(i);
|
y = m_rowStarts[eventType] + DefaultRowHeight *
|
||||||
|
m_profilerDataModel->getNestingLevel(i);
|
||||||
|
|
||||||
width = m_eventList->getDuration(i)*m_spacing;
|
width = m_profilerDataModel->getDuration(i)*m_spacing;
|
||||||
if (width<1)
|
if (width<1)
|
||||||
width = 1;
|
width = 1;
|
||||||
|
|
||||||
@@ -144,17 +147,19 @@ void TimelineView::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex)
|
|||||||
m_rowLastX[rowNumber] = x+width;
|
m_rowLastX[rowNumber] = x+width;
|
||||||
|
|
||||||
// special: animations
|
// special: animations
|
||||||
if (eventType == 0 && m_eventList->getAnimationCount(i) >= 0) {
|
if (eventType == 0 && m_profilerDataModel->getAnimationCount(i) >= 0) {
|
||||||
double scale = m_eventList->getMaximumAnimationCount() - m_eventList->getMinimumAnimationCount();
|
double scale = m_profilerDataModel->getMaximumAnimationCount() -
|
||||||
|
m_profilerDataModel->getMinimumAnimationCount();
|
||||||
double fraction;
|
double fraction;
|
||||||
if (scale > 1)
|
if (scale > 1)
|
||||||
fraction = (double)(m_eventList->getAnimationCount(i) - m_eventList->getMinimumAnimationCount()) / scale;
|
fraction = (double)(m_profilerDataModel->getAnimationCount(i) -
|
||||||
|
m_profilerDataModel->getMinimumAnimationCount()) / scale;
|
||||||
else
|
else
|
||||||
fraction = 1.0;
|
fraction = 1.0;
|
||||||
height = DefaultRowHeight * (fraction * 0.85 + 0.15);
|
height = DefaultRowHeight * (fraction * 0.85 + 0.15);
|
||||||
y += DefaultRowHeight - height;
|
y += DefaultRowHeight - height;
|
||||||
|
|
||||||
double fpsFraction = m_eventList->getFramerate(i) / 60.0;
|
double fpsFraction = m_profilerDataModel->getFramerate(i) / 60.0;
|
||||||
if (fpsFraction > 1.0)
|
if (fpsFraction > 1.0)
|
||||||
fpsFraction = 1.0;
|
fpsFraction = 1.0;
|
||||||
p->setBrush(QColor::fromHsl((fpsFraction*96)+10, 76, 166));
|
p->setBrush(QColor::fromHsl((fpsFraction*96)+10, 76, 166));
|
||||||
@@ -167,12 +172,12 @@ void TimelineView::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex)
|
void TimelineRenderer::drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex)
|
||||||
{
|
{
|
||||||
if (m_selectedItem == -1)
|
if (m_selectedItem == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int id = m_eventList->getEventId(m_selectedItem);
|
int id = m_profilerDataModel->getEventId(m_selectedItem);
|
||||||
|
|
||||||
p->setBrush(Qt::transparent);
|
p->setBrush(Qt::transparent);
|
||||||
QColor selectionColor = Qt::blue;
|
QColor selectionColor = Qt::blue;
|
||||||
@@ -188,17 +193,19 @@ void TimelineView::drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex)
|
|||||||
|
|
||||||
QRect selectedItemRect(0,0,0,0);
|
QRect selectedItemRect(0,0,0,0);
|
||||||
for (int i = fromIndex; i <= toIndex; i++) {
|
for (int i = fromIndex; i <= toIndex; i++) {
|
||||||
if (m_eventList->getEventId(i) != id)
|
if (m_profilerDataModel->getEventId(i) != id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
x = (m_eventList->getStartTime(i) - m_startTime) * m_spacing;
|
x = (m_profilerDataModel->getStartTime(i) - m_startTime) * m_spacing;
|
||||||
eventType = m_eventList->getType(i);
|
eventType = m_profilerDataModel->getType(i);
|
||||||
if (m_rowsExpanded[eventType])
|
if (m_rowsExpanded[eventType])
|
||||||
y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->eventPosInType(i) + 1);
|
y = m_rowStarts[eventType] + DefaultRowHeight *
|
||||||
|
(m_profilerDataModel->eventPosInType(i) + 1);
|
||||||
else
|
else
|
||||||
y = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->getNestingLevel(i);
|
y = m_rowStarts[eventType] + DefaultRowHeight *
|
||||||
|
m_profilerDataModel->getNestingLevel(i);
|
||||||
|
|
||||||
width = m_eventList->getDuration(i)*m_spacing;
|
width = m_profilerDataModel->getDuration(i)*m_spacing;
|
||||||
if (width<1)
|
if (width<1)
|
||||||
width = 1;
|
width = 1;
|
||||||
|
|
||||||
@@ -215,7 +222,7 @@ void TimelineView::drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::drawBindingLoopMarkers(QPainter *p, int fromIndex, int toIndex)
|
void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int fromIndex, int toIndex)
|
||||||
{
|
{
|
||||||
int destindex;
|
int destindex;
|
||||||
int xfrom, xto, eventType;
|
int xfrom, xto, eventType;
|
||||||
@@ -228,35 +235,38 @@ void TimelineView::drawBindingLoopMarkers(QPainter *p, int fromIndex, int toInde
|
|||||||
|
|
||||||
p->save();
|
p->save();
|
||||||
for (int i = fromIndex; i <= toIndex; i++) {
|
for (int i = fromIndex; i <= toIndex; i++) {
|
||||||
destindex = m_eventList->getBindingLoopDest(i);
|
destindex = m_profilerDataModel->getBindingLoopDest(i);
|
||||||
if (destindex >= 0) {
|
if (destindex >= 0) {
|
||||||
// from
|
// from
|
||||||
xfrom = (m_eventList->getStartTime(i) + m_eventList->getDuration(i)/2 -
|
xfrom = (m_profilerDataModel->getStartTime(i) +
|
||||||
|
m_profilerDataModel->getDuration(i)/2 -
|
||||||
m_startTime) * m_spacing;
|
m_startTime) * m_spacing;
|
||||||
eventType = m_eventList->getType(i);
|
eventType = m_profilerDataModel->getType(i);
|
||||||
if (m_rowsExpanded[eventType])
|
if (m_rowsExpanded[eventType])
|
||||||
yfrom = m_rowStarts[eventType] + DefaultRowHeight*
|
yfrom = m_rowStarts[eventType] + DefaultRowHeight*
|
||||||
(m_eventList->eventPosInType(i) + 1);
|
(m_profilerDataModel->eventPosInType(i) + 1);
|
||||||
else
|
else
|
||||||
yfrom = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->getNestingLevel(i);
|
yfrom = m_rowStarts[eventType] + DefaultRowHeight *
|
||||||
|
m_profilerDataModel->getNestingLevel(i);
|
||||||
|
|
||||||
yfrom += DefaultRowHeight / 2;
|
yfrom += DefaultRowHeight / 2;
|
||||||
|
|
||||||
// to
|
// to
|
||||||
xto = (m_eventList->getStartTime(destindex) + m_eventList->getDuration(destindex)/2 -
|
xto = (m_profilerDataModel->getStartTime(destindex) +
|
||||||
|
m_profilerDataModel->getDuration(destindex)/2 -
|
||||||
m_startTime) * m_spacing;
|
m_startTime) * m_spacing;
|
||||||
eventType = m_eventList->getType(destindex);
|
eventType = m_profilerDataModel->getType(destindex);
|
||||||
if (m_rowsExpanded[eventType])
|
if (m_rowsExpanded[eventType])
|
||||||
yto = m_rowStarts[eventType] + DefaultRowHeight *
|
yto = m_rowStarts[eventType] + DefaultRowHeight *
|
||||||
(m_eventList->eventPosInType(destindex) + 1);
|
(m_profilerDataModel->eventPosInType(destindex) + 1);
|
||||||
else
|
else
|
||||||
yto = m_rowStarts[eventType] + DefaultRowHeight *
|
yto = m_rowStarts[eventType] + DefaultRowHeight *
|
||||||
m_eventList->getNestingLevel(destindex);
|
m_profilerDataModel->getNestingLevel(destindex);
|
||||||
|
|
||||||
yto += DefaultRowHeight / 2;
|
yto += DefaultRowHeight / 2;
|
||||||
|
|
||||||
// radius
|
// radius
|
||||||
int eventWidth = m_eventList->getDuration(i) * m_spacing;
|
int eventWidth = m_profilerDataModel->getDuration(i) * m_spacing;
|
||||||
radius = 5;
|
radius = 5;
|
||||||
if (radius * 2 > eventWidth)
|
if (radius * 2 > eventWidth)
|
||||||
radius = eventWidth / 2;
|
radius = eventWidth / 2;
|
||||||
@@ -283,7 +293,7 @@ void TimelineView::drawBindingLoopMarkers(QPainter *p, int fromIndex, int toInde
|
|||||||
p->restore();
|
p->restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
void TimelineRenderer::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
// special case: if there is a drag area below me, don't accept the
|
// special case: if there is a drag area below me, don't accept the
|
||||||
// events unless I'm actually clicking inside an item
|
// events unless I'm actually clicking inside an item
|
||||||
@@ -294,19 +304,19 @@ void TimelineView::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
void TimelineRenderer::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
manageClicked();
|
manageClicked();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
void TimelineRenderer::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
event->setAccepted(false);
|
event->setAccepted(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TimelineView::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
|
void TimelineRenderer::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
|
||||||
{
|
{
|
||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
manageHovered(event->pos().x(), event->pos().y());
|
manageHovered(event->pos().x(), event->pos().y());
|
||||||
@@ -314,7 +324,7 @@ void TimelineView::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
|
|||||||
event->setAccepted(false);
|
event->setAccepted(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::manageClicked()
|
void TimelineRenderer::manageClicked()
|
||||||
{
|
{
|
||||||
if (m_currentSelection.eventIndex != -1) {
|
if (m_currentSelection.eventIndex != -1) {
|
||||||
if (m_currentSelection.eventIndex == m_selectedItem)
|
if (m_currentSelection.eventIndex == m_selectedItem)
|
||||||
@@ -328,7 +338,7 @@ void TimelineView::manageClicked()
|
|||||||
setSelectedItem(m_currentSelection.eventIndex);
|
setSelectedItem(m_currentSelection.eventIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::manageHovered(int x, int y)
|
void TimelineRenderer::manageHovered(int x, int y)
|
||||||
{
|
{
|
||||||
if (m_endTime - m_startTime <=0 || m_lastEndTime - m_lastStartTime <= 0)
|
if (m_endTime - m_startTime <=0 || m_lastEndTime - m_lastStartTime <= 0)
|
||||||
return;
|
return;
|
||||||
@@ -337,13 +347,16 @@ void TimelineView::manageHovered(int x, int y)
|
|||||||
int row = y / DefaultRowHeight;
|
int row = y / DefaultRowHeight;
|
||||||
|
|
||||||
// already covered? nothing to do
|
// already covered? nothing to do
|
||||||
if (m_currentSelection.eventIndex != -1 && time >= m_currentSelection.startTime && time <= m_currentSelection.endTime && row == m_currentSelection.row) {
|
if (m_currentSelection.eventIndex != -1 &&
|
||||||
|
time >= m_currentSelection.startTime &&
|
||||||
|
time <= m_currentSelection.endTime &&
|
||||||
|
row == m_currentSelection.row) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find if there's items in the time range
|
// find if there's items in the time range
|
||||||
int eventFrom = m_eventList->findFirstIndex(time);
|
int eventFrom = m_profilerDataModel->findFirstIndex(time);
|
||||||
int eventTo = m_eventList->findLastIndex(time);
|
int eventTo = m_profilerDataModel->findLastIndex(time);
|
||||||
if (eventTo < eventFrom) {
|
if (eventTo < eventFrom) {
|
||||||
m_currentSelection.eventIndex = -1;
|
m_currentSelection.eventIndex = -1;
|
||||||
return;
|
return;
|
||||||
@@ -352,19 +365,21 @@ void TimelineView::manageHovered(int x, int y)
|
|||||||
// find if we are in the right column
|
// find if we are in the right column
|
||||||
int itemRow, eventType;
|
int itemRow, eventType;
|
||||||
for (int i=eventTo; i>=eventFrom; --i) {
|
for (int i=eventTo; i>=eventFrom; --i) {
|
||||||
if (ceil(m_eventList->getEndTime(i)*m_spacing) < floor(time*m_spacing))
|
if (ceil(m_profilerDataModel->getEndTime(i)*m_spacing) < floor(time*m_spacing))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
eventType = m_eventList->getType(i);
|
eventType = m_profilerDataModel->getType(i);
|
||||||
if (m_rowsExpanded[eventType])
|
if (m_rowsExpanded[eventType])
|
||||||
itemRow = m_rowStarts[eventType]/DefaultRowHeight + m_eventList->eventPosInType(i) + 1;
|
itemRow = m_rowStarts[eventType]/DefaultRowHeight +
|
||||||
|
m_profilerDataModel->eventPosInType(i) + 1;
|
||||||
else
|
else
|
||||||
itemRow = m_rowStarts[eventType]/DefaultRowHeight + m_eventList->getNestingLevel(i);
|
itemRow = m_rowStarts[eventType]/DefaultRowHeight +
|
||||||
|
m_profilerDataModel->getNestingLevel(i);
|
||||||
if (itemRow == row) {
|
if (itemRow == row) {
|
||||||
// match
|
// match
|
||||||
m_currentSelection.eventIndex = i;
|
m_currentSelection.eventIndex = i;
|
||||||
m_currentSelection.startTime = m_eventList->getStartTime(i);
|
m_currentSelection.startTime = m_profilerDataModel->getStartTime(i);
|
||||||
m_currentSelection.endTime = m_eventList->getEndTime(i);
|
m_currentSelection.endTime = m_profilerDataModel->getEndTime(i);
|
||||||
m_currentSelection.row = row;
|
m_currentSelection.row = row;
|
||||||
if (!m_selectionLocked)
|
if (!m_selectionLocked)
|
||||||
setSelectedItem(i);
|
setSelectedItem(i);
|
||||||
@@ -376,7 +391,7 @@ void TimelineView::manageHovered(int x, int y)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::clearData()
|
void TimelineRenderer::clearData()
|
||||||
{
|
{
|
||||||
m_startTime = 0;
|
m_startTime = 0;
|
||||||
m_endTime = 0;
|
m_endTime = 0;
|
||||||
@@ -390,122 +405,125 @@ void TimelineView::clearData()
|
|||||||
m_selectionLocked = true;
|
m_selectionLocked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 TimelineView::getDuration(int index) const
|
qint64 TimelineRenderer::getDuration(int index) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_eventList);
|
Q_ASSERT(m_profilerDataModel);
|
||||||
return m_eventList->getEndTime(index) - m_eventList->getStartTime(index);
|
return m_profilerDataModel->getEndTime(index) -
|
||||||
|
m_profilerDataModel->getStartTime(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TimelineView::getFilename(int index) const
|
QString TimelineRenderer::getFilename(int index) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_eventList);
|
Q_ASSERT(m_profilerDataModel);
|
||||||
return m_eventList->getFilename(index);
|
return m_profilerDataModel->getFilename(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TimelineView::getLine(int index) const
|
int TimelineRenderer::getLine(int index) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_eventList);
|
Q_ASSERT(m_profilerDataModel);
|
||||||
return m_eventList->getLine(index);
|
return m_profilerDataModel->getLine(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TimelineView::getDetails(int index) const
|
QString TimelineRenderer::getDetails(int index) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_eventList);
|
Q_ASSERT(m_profilerDataModel);
|
||||||
return m_eventList->getDetails(index);
|
return m_profilerDataModel->getDetails(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TimelineView::getYPosition(int index) const
|
int TimelineRenderer::getYPosition(int index) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_eventList);
|
Q_ASSERT(m_profilerDataModel);
|
||||||
if (index >= m_eventList->count() || m_rowStarts.isEmpty())
|
if (index >= m_profilerDataModel->count() || m_rowStarts.isEmpty())
|
||||||
return 0;
|
return 0;
|
||||||
int y, eventType = m_eventList->getType(index);
|
int y, eventType = m_profilerDataModel->getType(index);
|
||||||
if (m_rowsExpanded[eventType])
|
if (m_rowsExpanded[eventType])
|
||||||
y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->eventPosInType(index) + 1);
|
y = m_rowStarts[eventType] + DefaultRowHeight *
|
||||||
|
(m_profilerDataModel->eventPosInType(index) + 1);
|
||||||
else
|
else
|
||||||
y = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->getNestingLevel(index);
|
y = m_rowStarts[eventType] + DefaultRowHeight *
|
||||||
|
m_profilerDataModel->getNestingLevel(index);
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::setRowExpanded(int rowIndex, bool expanded)
|
void TimelineRenderer::setRowExpanded(int rowIndex, bool expanded)
|
||||||
{
|
{
|
||||||
m_rowsExpanded[rowIndex] = expanded;
|
m_rowsExpanded[rowIndex] = expanded;
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::selectNext()
|
void TimelineRenderer::selectNext()
|
||||||
{
|
{
|
||||||
if (m_eventList->count() == 0)
|
if (m_profilerDataModel->count() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// select next in view or after
|
// select next in view or after
|
||||||
int newIndex = m_selectedItem+1;
|
int newIndex = m_selectedItem+1;
|
||||||
if (newIndex >= m_eventList->count())
|
if (newIndex >= m_profilerDataModel->count())
|
||||||
newIndex = 0;
|
newIndex = 0;
|
||||||
if (m_eventList->getEndTime(newIndex) < m_startTime)
|
if (m_profilerDataModel->getEndTime(newIndex) < m_startTime)
|
||||||
newIndex = m_eventList->findFirstIndexNoParents(m_startTime);
|
newIndex = m_profilerDataModel->findFirstIndexNoParents(m_startTime);
|
||||||
setSelectedItem(newIndex);
|
setSelectedItem(newIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::selectPrev()
|
void TimelineRenderer::selectPrev()
|
||||||
{
|
{
|
||||||
if (m_eventList->count() == 0)
|
if (m_profilerDataModel->count() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// select last in view or before
|
// select last in view or before
|
||||||
int newIndex = m_selectedItem-1;
|
int newIndex = m_selectedItem-1;
|
||||||
if (newIndex < 0)
|
if (newIndex < 0)
|
||||||
newIndex = m_eventList->count()-1;
|
newIndex = m_profilerDataModel->count()-1;
|
||||||
if (m_eventList->getStartTime(newIndex) > m_endTime)
|
if (m_profilerDataModel->getStartTime(newIndex) > m_endTime)
|
||||||
newIndex = m_eventList->findLastIndex(m_endTime);
|
newIndex = m_profilerDataModel->findLastIndex(m_endTime);
|
||||||
setSelectedItem(newIndex);
|
setSelectedItem(newIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TimelineView::nextItemFromId(int eventId) const
|
int TimelineRenderer::nextItemFromId(int eventId) const
|
||||||
{
|
{
|
||||||
int ndx = -1;
|
int ndx = -1;
|
||||||
if (m_selectedItem == -1)
|
if (m_selectedItem == -1)
|
||||||
ndx = m_eventList->findFirstIndexNoParents(m_startTime);
|
ndx = m_profilerDataModel->findFirstIndexNoParents(m_startTime);
|
||||||
else
|
else
|
||||||
ndx = m_selectedItem + 1;
|
ndx = m_selectedItem + 1;
|
||||||
if (ndx >= m_eventList->count())
|
if (ndx >= m_profilerDataModel->count())
|
||||||
ndx = 0;
|
ndx = 0;
|
||||||
int startIndex = ndx;
|
int startIndex = ndx;
|
||||||
do {
|
do {
|
||||||
if (m_eventList->getEventId(ndx) == eventId)
|
if (m_profilerDataModel->getEventId(ndx) == eventId)
|
||||||
return ndx;
|
return ndx;
|
||||||
ndx = (ndx + 1) % m_eventList->count();
|
ndx = (ndx + 1) % m_profilerDataModel->count();
|
||||||
} while (ndx != startIndex);
|
} while (ndx != startIndex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TimelineView::prevItemFromId(int eventId) const
|
int TimelineRenderer::prevItemFromId(int eventId) const
|
||||||
{
|
{
|
||||||
int ndx = -1;
|
int ndx = -1;
|
||||||
if (m_selectedItem == -1)
|
if (m_selectedItem == -1)
|
||||||
ndx = m_eventList->findFirstIndexNoParents(m_startTime);
|
ndx = m_profilerDataModel->findFirstIndexNoParents(m_startTime);
|
||||||
else
|
else
|
||||||
ndx = m_selectedItem - 1;
|
ndx = m_selectedItem - 1;
|
||||||
if (ndx < 0)
|
if (ndx < 0)
|
||||||
ndx = m_eventList->count() - 1;
|
ndx = m_profilerDataModel->count() - 1;
|
||||||
int startIndex = ndx;
|
int startIndex = ndx;
|
||||||
do {
|
do {
|
||||||
if (m_eventList->getEventId(ndx) == eventId)
|
if (m_profilerDataModel->getEventId(ndx) == eventId)
|
||||||
return ndx;
|
return ndx;
|
||||||
if (--ndx < 0)
|
if (--ndx < 0)
|
||||||
ndx = m_eventList->count()-1;
|
ndx = m_profilerDataModel->count()-1;
|
||||||
} while (ndx != startIndex);
|
} while (ndx != startIndex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::selectNextFromId(int eventId)
|
void TimelineRenderer::selectNextFromId(int eventId)
|
||||||
{
|
{
|
||||||
int eventIndex = nextItemFromId(eventId);
|
int eventIndex = nextItemFromId(eventId);
|
||||||
if (eventIndex != -1)
|
if (eventIndex != -1)
|
||||||
setSelectedItem(eventIndex);
|
setSelectedItem(eventIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::selectPrevFromId(int eventId)
|
void TimelineRenderer::selectPrevFromId(int eventId)
|
||||||
{
|
{
|
||||||
int eventIndex = prevItemFromId(eventId);
|
int eventIndex = prevItemFromId(eventId);
|
||||||
if (eventIndex != -1)
|
if (eventIndex != -1)
|
@@ -30,29 +30,29 @@
|
|||||||
**
|
**
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#ifndef TIMELINEVIEW_H
|
#ifndef TIMELINERENDERER_H
|
||||||
#define TIMELINEVIEW_H
|
#define TIMELINERENDERER_H
|
||||||
|
|
||||||
#include <QDeclarativeItem>
|
#include <QDeclarativeItem>
|
||||||
#include <QScriptValue>
|
#include <QScriptValue>
|
||||||
#include <qmljsdebugclient/qmlprofilereventlist.h>
|
#include "qmlprofilerdatamodel.h"
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class TimelineView : public QDeclarativeItem
|
class TimelineRenderer : public QDeclarativeItem
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(qint64 startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
|
Q_PROPERTY(qint64 startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
|
||||||
Q_PROPERTY(qint64 endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged)
|
Q_PROPERTY(qint64 endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged)
|
||||||
Q_PROPERTY(QObject* eventList READ eventList WRITE setEventList NOTIFY eventListChanged)
|
Q_PROPERTY(QObject* profilerDataModel READ profilerDataModel WRITE setProfilerDataModel NOTIFY profilerDataModelChanged)
|
||||||
Q_PROPERTY(bool selectionLocked READ selectionLocked WRITE setSelectionLocked NOTIFY selectionLockedChanged)
|
Q_PROPERTY(bool selectionLocked READ selectionLocked WRITE setSelectionLocked NOTIFY selectionLockedChanged)
|
||||||
Q_PROPERTY(int selectedItem READ selectedItem WRITE setSelectedItem NOTIFY selectedItemChanged)
|
Q_PROPERTY(int selectedItem READ selectedItem WRITE setSelectedItem NOTIFY selectedItemChanged)
|
||||||
Q_PROPERTY(int startDragArea READ startDragArea WRITE setStartDragArea NOTIFY startDragAreaChanged)
|
Q_PROPERTY(int startDragArea READ startDragArea WRITE setStartDragArea NOTIFY startDragAreaChanged)
|
||||||
Q_PROPERTY(int endDragArea READ endDragArea WRITE setEndDragArea NOTIFY endDragAreaChanged)
|
Q_PROPERTY(int endDragArea READ endDragArea WRITE setEndDragArea NOTIFY endDragAreaChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TimelineView(QDeclarativeItem *parent = 0);
|
explicit TimelineRenderer(QDeclarativeItem *parent = 0);
|
||||||
|
|
||||||
qint64 startTime() const
|
qint64 startTime() const
|
||||||
{
|
{
|
||||||
@@ -84,11 +84,11 @@ public:
|
|||||||
return m_endDragArea;
|
return m_endDragArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlJsDebugClient::QmlProfilerEventList *eventList() const { return m_eventList; }
|
QmlProfilerDataModel *profilerDataModel() const { return m_profilerDataModel; }
|
||||||
void setEventList(QObject *eventList)
|
void setProfilerDataModel(QObject *profilerDataModel)
|
||||||
{
|
{
|
||||||
m_eventList = qobject_cast<QmlJsDebugClient::QmlProfilerEventList *>(eventList);
|
m_profilerDataModel = qobject_cast<QmlProfilerDataModel *>(profilerDataModel);
|
||||||
emit eventListChanged(m_eventList);
|
emit profilerDataModelChanged(m_profilerDataModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_INVOKABLE qint64 getDuration(int index) const;
|
Q_INVOKABLE qint64 getDuration(int index) const;
|
||||||
@@ -109,7 +109,7 @@ public:
|
|||||||
signals:
|
signals:
|
||||||
void startTimeChanged(qint64 arg);
|
void startTimeChanged(qint64 arg);
|
||||||
void endTimeChanged(qint64 arg);
|
void endTimeChanged(qint64 arg);
|
||||||
void eventListChanged(QmlJsDebugClient::QmlProfilerEventList *list);
|
void profilerDataModelChanged(QmlProfilerDataModel *list);
|
||||||
void selectionLockedChanged(bool locked);
|
void selectionLockedChanged(bool locked);
|
||||||
void selectedItemChanged(int itemIndex);
|
void selectedItemChanged(int itemIndex);
|
||||||
void startDragAreaChanged(int startDragArea);
|
void startDragAreaChanged(int startDragArea);
|
||||||
@@ -195,7 +195,7 @@ private:
|
|||||||
qint64 m_lastStartTime;
|
qint64 m_lastStartTime;
|
||||||
qint64 m_lastEndTime;
|
qint64 m_lastEndTime;
|
||||||
|
|
||||||
QmlJsDebugClient::QmlProfilerEventList *m_eventList;
|
QmlProfilerDataModel *m_profilerDataModel;
|
||||||
|
|
||||||
QList<int> m_rowLastX;
|
QList<int> m_rowLastX;
|
||||||
QList<int> m_rowStarts;
|
QList<int> m_rowStarts;
|
||||||
@@ -218,6 +218,6 @@ private:
|
|||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace QmlProfiler
|
} // namespace QmlProfiler
|
||||||
|
|
||||||
QML_DECLARE_TYPE(QmlProfiler::Internal::TimelineView)
|
QML_DECLARE_TYPE(QmlProfiler::Internal::TimelineRenderer)
|
||||||
|
|
||||||
#endif // TIMELINEVIEW_H
|
#endif // TIMELINERENDERER_H
|
@@ -1,649 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#include "tracewindow.h"
|
|
||||||
|
|
||||||
#include "qmlprofilerplugin.h"
|
|
||||||
|
|
||||||
#include <qmljsdebugclient/qmlprofilereventlist.h>
|
|
||||||
#include <qmljsdebugclient/qmlprofilertraceclient.h>
|
|
||||||
#include <utils/styledbar.h>
|
|
||||||
|
|
||||||
#include <QDeclarativeView>
|
|
||||||
#include <QDeclarativeContext>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QGraphicsObject>
|
|
||||||
#include <QContextMenuEvent>
|
|
||||||
#include <QScrollBar>
|
|
||||||
#include <QSlider>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
using namespace QmlJsDebugClient;
|
|
||||||
|
|
||||||
namespace QmlProfiler {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
const int sliderTicks = 10000;
|
|
||||||
const qreal sliderExp = 3;
|
|
||||||
|
|
||||||
void ZoomControl::setRange(qint64 startTime, qint64 endTime)
|
|
||||||
{
|
|
||||||
if (m_startTime != startTime || m_endTime != endTime) {
|
|
||||||
m_startTime = startTime;
|
|
||||||
m_endTime = endTime;
|
|
||||||
emit rangeChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollableDeclarativeView::ScrollableDeclarativeView(QWidget *parent)
|
|
||||||
: QDeclarativeView(parent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollableDeclarativeView::~ScrollableDeclarativeView()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScrollableDeclarativeView::scrollContentsBy(int dx, int dy)
|
|
||||||
{
|
|
||||||
// special workaround to track the scrollbar
|
|
||||||
if (rootObject()) {
|
|
||||||
int scrollY = rootObject()->property("scrollY").toInt();
|
|
||||||
rootObject()->setProperty("scrollY", QVariant(scrollY - dy));
|
|
||||||
}
|
|
||||||
QDeclarativeView::scrollContentsBy(dx,dy);
|
|
||||||
}
|
|
||||||
|
|
||||||
TraceWindow::TraceWindow(QWidget *parent)
|
|
||||||
: QWidget(parent)
|
|
||||||
{
|
|
||||||
setObjectName("QML Profiler");
|
|
||||||
|
|
||||||
m_zoomControl = new ZoomControl(this);
|
|
||||||
connect(m_zoomControl.data(), SIGNAL(rangeChanged()), this, SLOT(updateRange()));
|
|
||||||
|
|
||||||
QVBoxLayout *groupLayout = new QVBoxLayout;
|
|
||||||
groupLayout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
groupLayout->setSpacing(0);
|
|
||||||
|
|
||||||
m_mainView = new ScrollableDeclarativeView(this);
|
|
||||||
m_mainView->setResizeMode(QDeclarativeView::SizeViewToRootObject);
|
|
||||||
m_mainView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
|
||||||
m_mainView->setBackgroundBrush(QBrush(Qt::white));
|
|
||||||
m_mainView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
|
||||||
m_mainView->setFocus();
|
|
||||||
|
|
||||||
MouseWheelResizer *resizer = new MouseWheelResizer(this);
|
|
||||||
connect(resizer,SIGNAL(mouseWheelMoved(int,int,int)), this, SLOT(mouseWheelMoved(int,int,int)));
|
|
||||||
m_mainView->viewport()->installEventFilter(resizer);
|
|
||||||
|
|
||||||
QHBoxLayout *toolsLayout = new QHBoxLayout;
|
|
||||||
|
|
||||||
m_timebar = new QDeclarativeView(this);
|
|
||||||
m_timebar->setResizeMode(QDeclarativeView::SizeRootObjectToView);
|
|
||||||
m_timebar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
|
||||||
m_timebar->setFixedHeight(24);
|
|
||||||
|
|
||||||
m_overview = new QDeclarativeView(this);
|
|
||||||
m_overview->setResizeMode(QDeclarativeView::SizeRootObjectToView);
|
|
||||||
m_overview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
|
||||||
m_overview->setMaximumHeight(50);
|
|
||||||
|
|
||||||
m_zoomToolbar = createZoomToolbar();
|
|
||||||
m_zoomToolbar->move(0, m_timebar->height());
|
|
||||||
m_zoomToolbar->setVisible(false);
|
|
||||||
|
|
||||||
toolsLayout->addWidget(createToolbar());
|
|
||||||
toolsLayout->addWidget(m_timebar);
|
|
||||||
|
|
||||||
groupLayout->addLayout(toolsLayout);
|
|
||||||
groupLayout->addWidget(m_mainView);
|
|
||||||
groupLayout->addWidget(m_overview);
|
|
||||||
|
|
||||||
setLayout(groupLayout);
|
|
||||||
|
|
||||||
m_eventList = new QmlProfilerEventList(this);
|
|
||||||
connect(this,SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)), m_eventList, SLOT(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
|
|
||||||
connect(this, SIGNAL(traceFinished(qint64)), m_eventList, SLOT(setTraceEndTime(qint64)));
|
|
||||||
connect(this, SIGNAL(traceStarted(qint64)), m_eventList, SLOT(setTraceStartTime(qint64)));
|
|
||||||
connect(this, SIGNAL(frameEvent(qint64,int,int)), m_eventList, SLOT(addFrameEvent(qint64,int,int)));
|
|
||||||
connect(m_eventList, SIGNAL(stateChanged()), this, SLOT(eventListStateChanged()));
|
|
||||||
m_mainView->rootContext()->setContextProperty("qmlEventList", m_eventList);
|
|
||||||
m_overview->rootContext()->setContextProperty("qmlEventList", m_eventList);
|
|
||||||
|
|
||||||
m_rewriter = new QmlProfilerDetailsRewriter(this);
|
|
||||||
connect(m_eventList, SIGNAL(requestDetailsForLocation(int,QmlJsDebugClient::QmlEventLocation)), m_rewriter, SLOT(requestDetailsForLocation(int,QmlJsDebugClient::QmlEventLocation)));
|
|
||||||
connect(m_rewriter, SIGNAL(rewriteDetailsString(int,QmlJsDebugClient::QmlEventLocation,QString)), m_eventList, SLOT(rewriteDetailsString(int,QmlJsDebugClient::QmlEventLocation,QString)));
|
|
||||||
connect(m_rewriter, SIGNAL(eventDetailsChanged()), m_eventList, SLOT(finishedRewritingDetails()));
|
|
||||||
connect(m_eventList, SIGNAL(reloadDocumentsForDetails()), m_rewriter, SLOT(reloadDocuments()));
|
|
||||||
|
|
||||||
connect(this, SIGNAL(v8range(int,QString,QString,int,double,double)), m_eventList, SLOT(addV8Event(int,QString,QString,int,double,double)));
|
|
||||||
|
|
||||||
// Minimum height: 5 rows of 20 pixels + scrollbar of 50 pixels + 20 pixels margin
|
|
||||||
setMinimumHeight(170);
|
|
||||||
m_currentZoomLevel = 0;
|
|
||||||
m_profiledTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TraceWindow::~TraceWindow()
|
|
||||||
{
|
|
||||||
disconnectClientSignals();
|
|
||||||
delete m_plugin.data();
|
|
||||||
delete m_v8plugin.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *TraceWindow::createToolbar()
|
|
||||||
{
|
|
||||||
Utils::StyledBar *bar = new Utils::StyledBar(this);
|
|
||||||
bar->setSingleRow(true);
|
|
||||||
bar->setFixedWidth(150);
|
|
||||||
bar->setFixedHeight(24);
|
|
||||||
|
|
||||||
QHBoxLayout *toolBarLayout = new QHBoxLayout(bar);
|
|
||||||
toolBarLayout->setMargin(0);
|
|
||||||
toolBarLayout->setSpacing(0);
|
|
||||||
|
|
||||||
QToolButton *buttonPrev= new QToolButton;
|
|
||||||
buttonPrev->setIcon(QIcon(":/qmlprofiler/ico_prev.png"));
|
|
||||||
buttonPrev->setToolTip(tr("Jump to previous event"));
|
|
||||||
connect(buttonPrev, SIGNAL(clicked()), this, SIGNAL(jumpToPrev()));
|
|
||||||
connect(this, SIGNAL(enableToolbar(bool)), buttonPrev, SLOT(setEnabled(bool)));
|
|
||||||
|
|
||||||
QToolButton *buttonNext= new QToolButton;
|
|
||||||
buttonNext->setIcon(QIcon(":/qmlprofiler/ico_next.png"));
|
|
||||||
buttonNext->setToolTip(tr("Jump to next event"));
|
|
||||||
connect(buttonNext, SIGNAL(clicked()), this, SIGNAL(jumpToNext()));
|
|
||||||
connect(this, SIGNAL(enableToolbar(bool)), buttonNext, SLOT(setEnabled(bool)));
|
|
||||||
|
|
||||||
QToolButton *buttonZoomControls = new QToolButton;
|
|
||||||
buttonZoomControls->setIcon(QIcon(":/qmlprofiler/ico_zoom.png"));
|
|
||||||
buttonZoomControls->setToolTip(tr("Show zoom slider"));
|
|
||||||
buttonZoomControls->setCheckable(true);
|
|
||||||
buttonZoomControls->setChecked(false);
|
|
||||||
connect(buttonZoomControls, SIGNAL(toggled(bool)), m_zoomToolbar, SLOT(setVisible(bool)));
|
|
||||||
connect(this, SIGNAL(enableToolbar(bool)), buttonZoomControls, SLOT(setEnabled(bool)));
|
|
||||||
|
|
||||||
m_buttonRange = new QToolButton;
|
|
||||||
m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png"));
|
|
||||||
m_buttonRange->setToolTip(tr("Select range"));
|
|
||||||
m_buttonRange->setCheckable(true);
|
|
||||||
m_buttonRange->setChecked(false);
|
|
||||||
connect(m_buttonRange, SIGNAL(clicked(bool)), this, SLOT(toggleRangeMode(bool)));
|
|
||||||
connect(this, SIGNAL(enableToolbar(bool)), m_buttonRange, SLOT(setEnabled(bool)));
|
|
||||||
connect(this, SIGNAL(rangeModeChanged(bool)), m_buttonRange, SLOT(setChecked(bool)));
|
|
||||||
|
|
||||||
m_buttonLock = new QToolButton;
|
|
||||||
m_buttonLock->setIcon(QIcon(":/qmlprofiler/ico_selectionmode.png"));
|
|
||||||
m_buttonLock->setToolTip(tr("View event information on mouseover"));
|
|
||||||
m_buttonLock->setCheckable(true);
|
|
||||||
m_buttonLock->setChecked(false);
|
|
||||||
connect(m_buttonLock, SIGNAL(clicked(bool)), this, SLOT(toggleLockMode(bool)));
|
|
||||||
connect(this, SIGNAL(enableToolbar(bool)), m_buttonLock, SLOT(setEnabled(bool)));
|
|
||||||
connect(this, SIGNAL(lockModeChanged(bool)), m_buttonLock, SLOT(setChecked(bool)));
|
|
||||||
|
|
||||||
toolBarLayout->addWidget(buttonPrev);
|
|
||||||
toolBarLayout->addWidget(buttonNext);
|
|
||||||
toolBarLayout->addWidget(new Utils::StyledSeparator());
|
|
||||||
toolBarLayout->addWidget(buttonZoomControls);
|
|
||||||
toolBarLayout->addWidget(new Utils::StyledSeparator());
|
|
||||||
toolBarLayout->addWidget(m_buttonRange);
|
|
||||||
toolBarLayout->addWidget(m_buttonLock);
|
|
||||||
|
|
||||||
return bar;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QWidget *TraceWindow::createZoomToolbar()
|
|
||||||
{
|
|
||||||
Utils::StyledBar *bar = new Utils::StyledBar(this);
|
|
||||||
bar->setSingleRow(true);
|
|
||||||
bar->setFixedWidth(150);
|
|
||||||
bar->setFixedHeight(24);
|
|
||||||
|
|
||||||
QHBoxLayout *toolBarLayout = new QHBoxLayout(bar);
|
|
||||||
toolBarLayout->setMargin(0);
|
|
||||||
toolBarLayout->setSpacing(0);
|
|
||||||
|
|
||||||
QSlider *zoomSlider = new QSlider(Qt::Horizontal);
|
|
||||||
zoomSlider->setFocusPolicy(Qt::NoFocus);
|
|
||||||
zoomSlider->setRange(1, sliderTicks);
|
|
||||||
zoomSlider->setInvertedAppearance(true);
|
|
||||||
zoomSlider->setPageStep(sliderTicks/100);
|
|
||||||
connect(this, SIGNAL(enableToolbar(bool)), zoomSlider, SLOT(setEnabled(bool)));
|
|
||||||
connect(zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setZoomLevel(int)));
|
|
||||||
connect(this, SIGNAL(zoomLevelChanged(int)), zoomSlider, SLOT(setValue(int)));
|
|
||||||
zoomSlider->setStyleSheet("\
|
|
||||||
QSlider:horizontal {\
|
|
||||||
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #444444, stop: 1 #5a5a5a);\
|
|
||||||
border: 1px #313131;\
|
|
||||||
height: 20px;\
|
|
||||||
margin: 0px 0px 0px 0px;\
|
|
||||||
}\
|
|
||||||
QSlider::add-page:horizontal {\
|
|
||||||
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\
|
|
||||||
border: 1px #313131;\
|
|
||||||
}\
|
|
||||||
QSlider::sub-page:horizontal {\
|
|
||||||
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\
|
|
||||||
border: 1px #313131;\
|
|
||||||
}\
|
|
||||||
");
|
|
||||||
|
|
||||||
toolBarLayout->addWidget(zoomSlider);
|
|
||||||
|
|
||||||
return bar;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::reset(QDeclarativeDebugConnection *conn)
|
|
||||||
{
|
|
||||||
disconnectClientSignals();
|
|
||||||
|
|
||||||
delete m_plugin.data();
|
|
||||||
m_plugin = new QmlProfilerTraceClient(conn);
|
|
||||||
delete m_v8plugin.data();
|
|
||||||
m_v8plugin = new QV8ProfilerClient(conn);
|
|
||||||
|
|
||||||
connectClientSignals();
|
|
||||||
|
|
||||||
m_mainView->rootContext()->setContextProperty("connection", m_plugin.data());
|
|
||||||
m_mainView->rootContext()->setContextProperty("zoomControl", m_zoomControl.data());
|
|
||||||
m_timebar->rootContext()->setContextProperty("zoomControl", m_zoomControl.data());
|
|
||||||
m_overview->rootContext()->setContextProperty("zoomControl", m_zoomControl.data());
|
|
||||||
|
|
||||||
m_timebar->setSource(QUrl("qrc:/qmlprofiler/TimeDisplay.qml"));
|
|
||||||
m_overview->setSource(QUrl("qrc:/qmlprofiler/Overview.qml"));
|
|
||||||
|
|
||||||
m_mainView->setSource(QUrl("qrc:/qmlprofiler/MainView.qml"));
|
|
||||||
m_mainView->rootObject()->setProperty("width", QVariant(width()));
|
|
||||||
m_mainView->rootObject()->setProperty("candidateHeight", QVariant(height() - m_timebar->height() - m_overview->height()));
|
|
||||||
|
|
||||||
updateToolbar();
|
|
||||||
|
|
||||||
connect(m_mainView->rootObject(), SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition()));
|
|
||||||
connect(m_mainView->rootObject(), SIGNAL(updateTimer()), this, SLOT(updateTimer()));
|
|
||||||
connect(m_mainView->rootObject(), SIGNAL(updateRangeButton()), this, SLOT(updateRangeButton()));
|
|
||||||
connect(m_mainView->rootObject(), SIGNAL(updateLockButton()), this, SLOT(updateLockButton()));
|
|
||||||
connect(m_eventList, SIGNAL(countChanged()), this, SLOT(updateToolbar()));
|
|
||||||
connect(this, SIGNAL(jumpToPrev()), m_mainView->rootObject(), SLOT(prevEvent()));
|
|
||||||
connect(this, SIGNAL(jumpToNext()), m_mainView->rootObject(), SLOT(nextEvent()));
|
|
||||||
connect(this, SIGNAL(updateViewZoom(QVariant)), m_mainView->rootObject(), SLOT(updateWindowLength(QVariant)));
|
|
||||||
connect(this, SIGNAL(wheelZoom(QVariant,QVariant)), m_mainView->rootObject(), SLOT(wheelZoom(QVariant,QVariant)));
|
|
||||||
connect(this, SIGNAL(globalZoom()), m_mainView->rootObject(), SLOT(globalZoom()));
|
|
||||||
connect(this, SIGNAL(selectNextEventInDisplay(QVariant)), m_mainView->rootObject(), SLOT(selectNextWithId(QVariant)));
|
|
||||||
connect(m_mainView->rootObject(), SIGNAL(selectedEventIdChanged(int)), this, SIGNAL(selectedEventIdChanged(int)));
|
|
||||||
connect(m_mainView->rootObject(), SIGNAL(changeToolTip(QString)), this, SLOT(updateToolTip(QString)));
|
|
||||||
connect(m_mainView->rootObject(), SIGNAL(updateVerticalScroll(int)), this, SLOT(updateVerticalScroll(int)));
|
|
||||||
|
|
||||||
connect(this, SIGNAL(internalClearDisplay()), m_mainView->rootObject(), SLOT(clearAll()));
|
|
||||||
connect(this,SIGNAL(internalClearDisplay()), m_overview->rootObject(), SLOT(clearDisplay()));
|
|
||||||
|
|
||||||
m_v8DataReady = false;
|
|
||||||
m_qmlDataReady = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::connectClientSignals()
|
|
||||||
{
|
|
||||||
if (m_plugin) {
|
|
||||||
connect(m_plugin.data(), SIGNAL(complete()), this, SLOT(qmlComplete()));
|
|
||||||
connect(m_plugin.data(), SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)),
|
|
||||||
this, SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
|
|
||||||
connect(m_plugin.data(), SIGNAL(traceFinished(qint64)), this, SIGNAL(traceFinished(qint64)));
|
|
||||||
connect(m_plugin.data(), SIGNAL(traceStarted(qint64)), this, SLOT(manageTraceStart(qint64)));
|
|
||||||
connect(m_plugin.data(), SIGNAL(frame(qint64,int,int)), this, SIGNAL(frameEvent(qint64,int,int)));
|
|
||||||
connect(m_plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState()));
|
|
||||||
connect(m_plugin.data(), SIGNAL(enabledChanged()), m_plugin.data(), SLOT(sendRecordingStatus()));
|
|
||||||
connect(m_plugin.data(), SIGNAL(recordingChanged(bool)), this, SIGNAL(recordingChanged(bool)));
|
|
||||||
}
|
|
||||||
if (m_v8plugin) {
|
|
||||||
connect(m_v8plugin.data(), SIGNAL(complete()), this, SLOT(v8Complete()));
|
|
||||||
connect(m_v8plugin.data(), SIGNAL(v8range(int,QString,QString,int,double,double)), this, SIGNAL(v8range(int,QString,QString,int,double,double)));
|
|
||||||
connect(m_v8plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState()));
|
|
||||||
connect(m_v8plugin.data(), SIGNAL(enabledChanged()), m_v8plugin.data(), SLOT(sendRecordingStatus()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::disconnectClientSignals()
|
|
||||||
{
|
|
||||||
if (m_plugin) {
|
|
||||||
disconnect(m_plugin.data(), SIGNAL(complete()), this, SLOT(qmlComplete()));
|
|
||||||
disconnect(m_plugin.data(), SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)),
|
|
||||||
this, SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
|
|
||||||
disconnect(m_plugin.data(), SIGNAL(traceFinished(qint64)), this, SIGNAL(traceFinished(qint64)));
|
|
||||||
disconnect(m_plugin.data(), SIGNAL(traceStarted(qint64)), this, SLOT(manageTraceStart(qint64)));
|
|
||||||
disconnect(m_plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState()));
|
|
||||||
disconnect(m_plugin.data(), SIGNAL(enabledChanged()), m_plugin.data(), SLOT(sendRecordingStatus()));
|
|
||||||
disconnect(m_plugin.data(), SIGNAL(recordingChanged(bool)), this, SIGNAL(recordingChanged(bool)));
|
|
||||||
}
|
|
||||||
if (m_v8plugin) {
|
|
||||||
disconnect(m_v8plugin.data(), SIGNAL(complete()), this, SLOT(v8Complete()));
|
|
||||||
disconnect(m_v8plugin.data(), SIGNAL(v8range(int,QString,QString,int,double,double)), this, SIGNAL(v8range(int,QString,QString,int,double,double)));
|
|
||||||
disconnect(m_v8plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState()));
|
|
||||||
disconnect(m_v8plugin.data(), SIGNAL(enabledChanged()), m_v8plugin.data(), SLOT(sendRecordingStatus()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlProfilerEventList *TraceWindow::getEventList() const
|
|
||||||
{
|
|
||||||
return m_eventList;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZoomControl *TraceWindow::rangeTimes() const
|
|
||||||
{
|
|
||||||
return m_zoomControl.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|
||||||
{
|
|
||||||
emit contextMenuRequested(ev->globalPos());
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::updateCursorPosition()
|
|
||||||
{
|
|
||||||
emit gotoSourceLocation(m_mainView->rootObject()->property("fileName").toString(),
|
|
||||||
m_mainView->rootObject()->property("lineNumber").toInt(),
|
|
||||||
m_mainView->rootObject()->property("columnNumber").toInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::updateTimer()
|
|
||||||
{
|
|
||||||
m_profiledTime = m_mainView->rootObject()->property("elapsedTime").toDouble();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::correctTimer()
|
|
||||||
{
|
|
||||||
// once the data is post-processed, use the eventlist time instead of the qml timer
|
|
||||||
m_profiledTime = (m_eventList->traceEndTime() - m_eventList->traceStartTime()) / 1.0e9;
|
|
||||||
if (m_profiledTime < 0)
|
|
||||||
m_profiledTime = 0;
|
|
||||||
emit viewUpdated();
|
|
||||||
}
|
|
||||||
|
|
||||||
double TraceWindow::profiledTime() const
|
|
||||||
{
|
|
||||||
return m_profiledTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::clearDisplay()
|
|
||||||
{
|
|
||||||
m_eventList->clear();
|
|
||||||
|
|
||||||
if (m_plugin)
|
|
||||||
m_plugin.data()->clearData();
|
|
||||||
if (m_v8plugin)
|
|
||||||
m_v8plugin.data()->clearData();
|
|
||||||
|
|
||||||
m_zoomControl.data()->setRange(0,0);
|
|
||||||
m_profiledTime = 0;
|
|
||||||
|
|
||||||
updateVerticalScroll(0);
|
|
||||||
m_mainView->rootObject()->setProperty("scrollY", QVariant(0));
|
|
||||||
|
|
||||||
emit internalClearDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::updateToolbar()
|
|
||||||
{
|
|
||||||
emit enableToolbar(m_eventList && m_eventList->count()>0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::toggleRangeMode(bool active)
|
|
||||||
{
|
|
||||||
bool rangeMode = m_mainView->rootObject()->property("selectionRangeMode").toBool();
|
|
||||||
if (active != rangeMode) {
|
|
||||||
if (active)
|
|
||||||
m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselected.png"));
|
|
||||||
else
|
|
||||||
m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png"));
|
|
||||||
m_mainView->rootObject()->setProperty("selectionRangeMode", QVariant(active));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::updateRangeButton()
|
|
||||||
{
|
|
||||||
bool rangeMode = m_mainView->rootObject()->property("selectionRangeMode").toBool();
|
|
||||||
if (rangeMode)
|
|
||||||
m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselected.png"));
|
|
||||||
else
|
|
||||||
m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png"));
|
|
||||||
emit rangeModeChanged(rangeMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::toggleLockMode(bool active)
|
|
||||||
{
|
|
||||||
bool lockMode = !m_mainView->rootObject()->property("selectionLocked").toBool();
|
|
||||||
if (active != lockMode) {
|
|
||||||
m_mainView->rootObject()->setProperty("selectionLocked", QVariant(!active));
|
|
||||||
m_mainView->rootObject()->setProperty("selectedItem", QVariant(-1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::updateLockButton()
|
|
||||||
{
|
|
||||||
bool lockMode = !m_mainView->rootObject()->property("selectionLocked").toBool();
|
|
||||||
emit lockModeChanged(lockMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::setRecording(bool recording)
|
|
||||||
{
|
|
||||||
if (recording) {
|
|
||||||
m_v8DataReady = false;
|
|
||||||
m_qmlDataReady = false;
|
|
||||||
}
|
|
||||||
if (m_plugin)
|
|
||||||
m_plugin.data()->setRecording(recording);
|
|
||||||
if (m_v8plugin)
|
|
||||||
m_v8plugin.data()->setRecording(recording);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TraceWindow::isRecording() const
|
|
||||||
{
|
|
||||||
return m_plugin.data()->isRecording();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::qmlComplete()
|
|
||||||
{
|
|
||||||
m_qmlDataReady = true;
|
|
||||||
if (!m_v8plugin || m_v8plugin.data()->status() != QDeclarativeDebugClient::Enabled || m_v8DataReady) {
|
|
||||||
m_eventList->complete();
|
|
||||||
// once complete is sent, reset the flags
|
|
||||||
m_qmlDataReady = false;
|
|
||||||
m_v8DataReady = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::v8Complete()
|
|
||||||
{
|
|
||||||
m_v8DataReady = true;
|
|
||||||
if (!m_plugin || m_plugin.data()->status() != QDeclarativeDebugClient::Enabled || m_qmlDataReady) {
|
|
||||||
m_eventList->complete();
|
|
||||||
// once complete is sent, reset the flags
|
|
||||||
m_v8DataReady = false;
|
|
||||||
m_qmlDataReady = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::resizeEvent(QResizeEvent *event)
|
|
||||||
{
|
|
||||||
if (m_mainView->rootObject()) {
|
|
||||||
m_mainView->rootObject()->setProperty("width", QVariant(event->size().width()));
|
|
||||||
int newHeight = event->size().height() - m_timebar->height() - m_overview->height();
|
|
||||||
m_mainView->rootObject()->setProperty("candidateHeight", QVariant(newHeight));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MouseWheelResizer::eventFilter(QObject *obj, QEvent *event)
|
|
||||||
{
|
|
||||||
if (event->type() == QEvent::Wheel) {
|
|
||||||
QWheelEvent *ev = static_cast<QWheelEvent *>(event);
|
|
||||||
if (ev->modifiers() & Qt::ControlModifier) {
|
|
||||||
emit mouseWheelMoved(ev->pos().x(), ev->pos().y(), ev->delta());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QObject::eventFilter(obj, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::mouseWheelMoved(int x, int y, int delta)
|
|
||||||
{
|
|
||||||
Q_UNUSED(y);
|
|
||||||
if (m_mainView->rootObject()) {
|
|
||||||
emit wheelZoom(QVariant(x), QVariant(delta));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::viewAll()
|
|
||||||
{
|
|
||||||
emit globalZoom();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TraceWindow::hasValidSelection() const
|
|
||||||
{
|
|
||||||
if (m_mainView->rootObject()) {
|
|
||||||
return m_mainView->rootObject()->property("selectionRangeReady").toBool();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 TraceWindow::selectionStart() const
|
|
||||||
{
|
|
||||||
if (m_mainView->rootObject()) {
|
|
||||||
return m_mainView->rootObject()->property("selectionRangeStart").toLongLong();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 TraceWindow::selectionEnd() const
|
|
||||||
{
|
|
||||||
if (m_mainView->rootObject()) {
|
|
||||||
return m_mainView->rootObject()->property("selectionRangeEnd").toLongLong();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::setZoomLevel(int zoomLevel)
|
|
||||||
{
|
|
||||||
if (m_currentZoomLevel != zoomLevel && m_mainView->rootObject()) {
|
|
||||||
qreal newFactor = pow(qreal(zoomLevel) / qreal(sliderTicks), sliderExp);
|
|
||||||
m_currentZoomLevel = zoomLevel;
|
|
||||||
emit updateViewZoom(QVariant(newFactor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::updateRange()
|
|
||||||
{
|
|
||||||
if (!m_eventList)
|
|
||||||
return;
|
|
||||||
qreal duration = m_zoomControl.data()->endTime() - m_zoomControl.data()->startTime();
|
|
||||||
if (duration <= 0)
|
|
||||||
return;
|
|
||||||
if (m_eventList->traceDuration() <= 0)
|
|
||||||
return;
|
|
||||||
int newLevel = pow(duration / m_eventList->traceDuration(), 1/sliderExp) * sliderTicks;
|
|
||||||
if (m_currentZoomLevel != newLevel) {
|
|
||||||
m_currentZoomLevel = newLevel;
|
|
||||||
emit zoomLevelChanged(newLevel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::selectNextEvent(int eventId)
|
|
||||||
{
|
|
||||||
emit selectNextEventInDisplay(QVariant(eventId));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::updateProfilerState()
|
|
||||||
{
|
|
||||||
bool qmlActive = false;
|
|
||||||
bool v8Active = false;
|
|
||||||
if (m_plugin)
|
|
||||||
qmlActive = m_plugin.data()->isEnabled();
|
|
||||||
if (m_v8plugin)
|
|
||||||
v8Active = m_v8plugin.data()->isEnabled();
|
|
||||||
|
|
||||||
emit profilerStateChanged(qmlActive, v8Active);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::updateToolTip(const QString &text)
|
|
||||||
{
|
|
||||||
setToolTip(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::updateVerticalScroll(int newPosition)
|
|
||||||
{
|
|
||||||
m_mainView->verticalScrollBar()->setValue(newPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::eventListStateChanged()
|
|
||||||
{
|
|
||||||
switch (m_eventList->currentState()) {
|
|
||||||
case QmlProfilerEventList::Empty :
|
|
||||||
clearDisplay();
|
|
||||||
break;
|
|
||||||
case QmlProfilerEventList::AcquiringData :
|
|
||||||
firstDataReceived();
|
|
||||||
break;
|
|
||||||
case QmlProfilerEventList::ProcessingData :
|
|
||||||
// nothing to be done
|
|
||||||
break;
|
|
||||||
case QmlProfilerEventList::Done :
|
|
||||||
correctTimer();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::manageTraceStart(qint64 traceStart)
|
|
||||||
{
|
|
||||||
// new trace started
|
|
||||||
emit clearViewsFromTool();
|
|
||||||
|
|
||||||
emit traceStarted(traceStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::firstDataReceived()
|
|
||||||
{
|
|
||||||
if (m_plugin && m_plugin.data()->isRecording()) {
|
|
||||||
// serverside recording disabled
|
|
||||||
m_plugin.data()->setRecordingFromServer(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraceWindow::applicationDied()
|
|
||||||
{
|
|
||||||
if (m_mainView->rootObject())
|
|
||||||
m_mainView->rootObject()->setProperty("applicationDied",QVariant(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace QmlProfiler
|
|
@@ -1,57 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#include "commandlistener.h"
|
|
||||||
#include "constants.h"
|
|
||||||
#include <QTextStream>
|
|
||||||
|
|
||||||
CommandListener::CommandListener(QObject *parent)
|
|
||||||
: QThread(parent)
|
|
||||||
, m_stopRequested(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CommandListener::run()
|
|
||||||
{
|
|
||||||
QString line;
|
|
||||||
QTextStream in(stdin, QIODevice::ReadOnly);
|
|
||||||
do {
|
|
||||||
line = in.readLine();
|
|
||||||
line = line.trimmed();
|
|
||||||
if (!line.isEmpty()) {
|
|
||||||
emit command(line);
|
|
||||||
if (line == QLatin1String(Constants::CMD_QUIT)
|
|
||||||
|| line == QLatin1String(Constants::CMD_QUIT2))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} while (!m_stopRequested && !line.isNull());
|
|
||||||
}
|
|
@@ -1,50 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#ifndef CONSTANTS_H
|
|
||||||
#define CONSTANTS_H
|
|
||||||
|
|
||||||
namespace Constants {
|
|
||||||
|
|
||||||
const char CMD_HELP[] ="help";
|
|
||||||
const char CMD_HELP2[] = "h";
|
|
||||||
const char CMD_HELP3[] = "?";
|
|
||||||
|
|
||||||
const char CMD_RECORD[] ="record";
|
|
||||||
const char CMD_RECORD2[] ="r";
|
|
||||||
|
|
||||||
const char CMD_QUIT[] ="quit";
|
|
||||||
const char CMD_QUIT2[] = "q";
|
|
||||||
|
|
||||||
} // Contants
|
|
||||||
|
|
||||||
#endif // CONSTANTS_H
|
|
@@ -1,113 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
||||||
** Please review the following information to ensure the GNU Lesser General
|
|
||||||
** Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QMLPROFILERAPPLICATION_H
|
|
||||||
#define QMLPROFILERAPPLICATION_H
|
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QStringList>
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
#include <qdeclarativedebugclient.h>
|
|
||||||
#include <qmlprofilertraceclient.h>
|
|
||||||
#include <qmlprofilereventlist.h>
|
|
||||||
#include <qv8profilerclient.h>
|
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QProcess)
|
|
||||||
|
|
||||||
class QmlProfilerApplication : public QCoreApplication
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
QmlProfilerApplication(int &argc, char **argv);
|
|
||||||
~QmlProfilerApplication();
|
|
||||||
|
|
||||||
bool parseArguments();
|
|
||||||
void printUsage();
|
|
||||||
int exec();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void userCommand(const QString &command);
|
|
||||||
|
|
||||||
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 traceFinished();
|
|
||||||
void recordingChanged();
|
|
||||||
|
|
||||||
void print(const QString &line);
|
|
||||||
void logError(const QString &error);
|
|
||||||
void logStatus(const QString &status);
|
|
||||||
|
|
||||||
void qmlComplete();
|
|
||||||
void v8Complete();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void printCommands();
|
|
||||||
QString traceFileName() const;
|
|
||||||
|
|
||||||
enum ApplicationMode {
|
|
||||||
LaunchMode,
|
|
||||||
AttachMode
|
|
||||||
} m_runMode;
|
|
||||||
|
|
||||||
// LaunchMode
|
|
||||||
QString m_programPath;
|
|
||||||
QStringList m_programArguments;
|
|
||||||
QProcess *m_process;
|
|
||||||
QString m_tracePrefix;
|
|
||||||
|
|
||||||
QString m_hostName;
|
|
||||||
quint16 m_port;
|
|
||||||
bool m_verbose;
|
|
||||||
bool m_quitAfterSave;
|
|
||||||
|
|
||||||
QmlJsDebugClient::QDeclarativeDebugConnection m_connection;
|
|
||||||
QmlJsDebugClient::QmlProfilerTraceClient m_qmlProfilerClient;
|
|
||||||
QmlJsDebugClient::QV8ProfilerClient m_v8profilerClient;
|
|
||||||
QmlJsDebugClient::QmlProfilerEventList m_eventList;
|
|
||||||
QTimer m_connectTimer;
|
|
||||||
uint m_connectionAttempts;
|
|
||||||
|
|
||||||
bool m_qmlDataReady;
|
|
||||||
bool m_v8DataReady;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // QMLPROFILERAPPLICATION_H
|
|
@@ -1,28 +0,0 @@
|
|||||||
QT = core
|
|
||||||
include(../../../qtcreator.pri)
|
|
||||||
include(../../rpath.pri)
|
|
||||||
|
|
||||||
TEMPLATE = app
|
|
||||||
TARGET = qmlprofiler
|
|
||||||
DESTDIR = $$IDE_BIN_PATH
|
|
||||||
|
|
||||||
CONFIG += console
|
|
||||||
CONFIG -= app_bundle
|
|
||||||
|
|
||||||
include(../../shared/symbianutils/symbianutils.pri)
|
|
||||||
include(../../libs/qmljsdebugclient/qmljsdebugclient-lib.pri)
|
|
||||||
|
|
||||||
INCLUDEPATH += ../../libs/qmljsdebugclient
|
|
||||||
|
|
||||||
SOURCES += main.cpp \
|
|
||||||
qmlprofilerapplication.cpp \
|
|
||||||
commandlistener.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
qmlprofilerapplication.h \
|
|
||||||
commandlistener.h \
|
|
||||||
constants.h
|
|
||||||
|
|
||||||
target.path=/bin
|
|
||||||
INSTALLS+=target
|
|
||||||
|
|
@@ -1,7 +1,6 @@
|
|||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
|
|
||||||
SUBDIRS = qtpromaker \
|
SUBDIRS = qtpromaker \
|
||||||
qmlprofilertool \
|
|
||||||
qmlpuppet
|
qmlpuppet
|
||||||
|
|
||||||
win32 {
|
win32 {
|
||||||
|
Reference in New Issue
Block a user