Commit 0a3b20f5 authored by Christiaan Janssen's avatar Christiaan Janssen
Browse files

QmlProfiler: reworked



Change-Id: I66a236a024d76e7bef6edfb91ae30b5dd098b76b
Reviewed-by: default avatarKai Koehne <kai.koehne@digia.com>
parent 7764f351
......@@ -6,6 +6,7 @@ QtcLibrary {
cpp.defines: base.concat("QMLDEBUG_LIB")
Depends { name: "cpp" }
Depends { name: "Qt"; submodules: ["gui", "network"] }
files: [
......
......@@ -38,6 +38,8 @@ enum QmlEventType {
Creating,
Binding,
HandlingSignal,
PixmapCacheEvent,
SceneGraphFrameEvent,
MaximumQmlEventType
};
......@@ -46,6 +48,8 @@ enum BindingType {
QmlBinding,
V8Binding,
OptimizedBinding,
QPainterEvent,
AnimationFrame,
MaximumBindingType
};
......
......@@ -170,7 +170,8 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
} else if (event == AnimationFrame) {
int frameRate, animationCount;
stream >> frameRate >> animationCount;
emit this->frame(time, frameRate, animationCount);
emit rangedEvent(QmlDebug::Painting, QmlDebug::AnimationFrame, time, 0,
QStringList(), QmlDebug::QmlEventLocation(), frameRate, animationCount, 0,0,0);
d->maximumTime = qMax(time, d->maximumTime);
} else if (event == StartTrace) {
emit this->traceStarted(time);
......@@ -181,6 +182,32 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
}
} else if (messageType == Complete) {
emit complete();
} else if (messageType == SceneGraphFrame) {
int sgEventType;
int count = 0;
qint64 params[5];
stream >> sgEventType;
while (!stream.atEnd()) {
stream >> params[count++];
}
while (count<5)
params[count++] = 0;
emit rangedEvent(SceneGraphFrameEvent, sgEventType,time, 0, QStringList(),
QmlDebug::QmlEventLocation(), params[0], params[1], params[2], params[3], params[4]);
} else if (messageType == PixmapCacheEvent) {
int pixEvTy, width = 0, height = 0, refcount = 0;
QString pixUrl;
stream >> pixEvTy >> pixUrl;
if (pixEvTy == (int)PixmapReferenceCountChanged || pixEvTy == (int)PixmapCacheCountChanged) {
stream >> refcount;
} else if (pixEvTy == (int)PixmapSizeKnown) {
stream >> width >> height;
refcount = 1;
}
emit rangedEvent(QmlDebug::PixmapCacheEvent, pixEvTy, time, 0, QStringList(),
QmlDebug::QmlEventLocation(pixUrl,0,0), width, height, refcount, 0, 0);
d->maximumTime = qMax(time, d->maximumTime);
} else {
int range;
stream >> range;
......@@ -240,7 +267,10 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
BindingType bindingType = QmlBinding;
if ((QmlEventType)range == Binding)
bindingType = d->bindingTypes.pop();
emit this->range((QmlEventType)range, bindingType, startTime, time - startTime, data, location);
if ((QmlEventType)range == Painting)
bindingType = QPainterEvent;
emit rangedEvent((QmlEventType)range, bindingType, startTime, time - startTime, data,
location, 0, 0, 0, 0, 0);
if (d->rangeCount[range] == 0) {
int count = d->rangeDatas[range].count() +
d->rangeStartTimes[range].count() +
......
......@@ -71,10 +71,23 @@ public:
RangeLocation,
RangeEnd,
Complete,
PixmapCacheEvent,
SceneGraphFrame,
MaximumMessage
};
enum PixmapEventType {
PixmapSizeKnown,
PixmapReferenceCountChanged,
PixmapCacheCountChanged,
PixmapLoadingStarted,
PixmapLoadingFinished,
PixmapLoadingError,
MaximumPixmapEventType
};
bool isEnabled() const;
bool isRecording() const;
void setRecording(bool);
......@@ -89,10 +102,9 @@ signals:
void event(int event, qint64 time);
void traceFinished( qint64 time );
void traceStarted( qint64 time );
void range(int type, int bindingType, qint64 startTime, qint64 length,
const QStringList &data, const QmlDebug::QmlEventLocation &location);
void frame(qint64 time, int frameRate, int animationCount);
void rangedEvent(int type, int bindingType, qint64 startTime, qint64 length,
const QStringList &data, const QmlDebug::QmlEventLocation &location,
qint64 param1, qint64 param2, qint64 param3, qint64 param4, qint64 param5);
void recordingChanged(bool arg);
void enabledChanged();
......
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 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, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "abstracttimelinemodel.h"
namespace QmlProfiler {
AbstractTimelineModel::AbstractTimelineModel(QObject *parent) : QObject(parent), m_modelManager(0)
{}
AbstractTimelineModel::~AbstractTimelineModel()
{}
void AbstractTimelineModel::setModelManager(QmlProfilerModelManager *modelManager)
{
m_modelManager = modelManager;
connect(modelManager->simpleModel(),SIGNAL(changed()),this,SLOT(dataChanged()));
m_modelId = modelManager->registerModelProxy();
}
qint64 AbstractTimelineModel::traceStartTime() const
{
return m_modelManager->traceTime()->startTime();
}
qint64 AbstractTimelineModel::traceEndTime() const
{
return m_modelManager->traceTime()->endTime();
}
qint64 AbstractTimelineModel::traceDuration() const
{
return m_modelManager->traceTime()->duration();
}
int AbstractTimelineModel::getState() const
{
return (int)m_modelManager->state();
}
int AbstractTimelineModel::rowCount() const
{
int count = 0;
for (int i=0; i<categoryCount(); i++)
count += categoryDepth(i);
return count;
}
int AbstractTimelineModel::getBindingLoopDest(int index) const
{
Q_UNUSED(index);
return -1;
}
}
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 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, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef ABSTRACTTIMELINEMODEL_H
#define ABSTRACTTIMELINEMODEL_H
#include "qmlprofiler_global.h"
#include "qmlprofilermodelmanager.h"
#include "qmlprofilersimplemodel.h"
#include <QObject>
#include <QVariant>
#include <QColor>
namespace QmlProfiler {
class QMLPROFILER_EXPORT AbstractTimelineModel : public QObject
{
Q_OBJECT
public:
explicit AbstractTimelineModel(QObject *parent = 0);
~AbstractTimelineModel();
void setModelManager(QmlProfilerModelManager *modelManager);
virtual int categories() const = 0;
virtual QStringList categoryTitles() const = 0;
virtual QString name() const = 0;
virtual int count() const = 0;
virtual bool isEmpty() const = 0;
virtual bool eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const = 0;
Q_INVOKABLE virtual qint64 lastTimeMark() const = 0;
Q_INVOKABLE qint64 traceStartTime() const;
Q_INVOKABLE qint64 traceEndTime() const;
Q_INVOKABLE qint64 traceDuration() const;
Q_INVOKABLE int getState() const;
Q_INVOKABLE virtual bool expanded(int category) const = 0;
Q_INVOKABLE virtual void setExpanded(int category, bool expanded) = 0;
Q_INVOKABLE virtual int categoryDepth(int categoryIndex) const = 0;
Q_INVOKABLE virtual int categoryCount() const = 0;
Q_INVOKABLE virtual int rowCount() const;
Q_INVOKABLE virtual const QString categoryLabel(int categoryIndex) const = 0;
virtual int findFirstIndex(qint64 startTime) const = 0;
virtual int findFirstIndexNoParents(qint64 startTime) const = 0;
virtual int findLastIndex(qint64 endTime) const = 0;
virtual int getEventType(int index) const = 0;
virtual int getEventCategory(int index) const = 0;
virtual int getEventRow(int index) const = 0;
Q_INVOKABLE virtual qint64 getDuration(int index) const = 0;
Q_INVOKABLE virtual qint64 getStartTime(int index) const = 0;
Q_INVOKABLE virtual qint64 getEndTime(int index) const = 0;
Q_INVOKABLE virtual int getEventId(int index) const = 0;
Q_INVOKABLE virtual int getBindingLoopDest(int index) const;
Q_INVOKABLE virtual QColor getColor(int index) const = 0;
Q_INVOKABLE virtual float getHeight(int index) const = 0;
Q_INVOKABLE virtual const QVariantList getLabelsForCategory(int category) const = 0;
Q_INVOKABLE virtual const QVariantList getEventDetails(int index) const = 0;
// returned map should contain "file", "line", "column" properties, or be empty
Q_INVOKABLE virtual const QVariantMap getEventLocation(int index) const = 0;
Q_INVOKABLE virtual int getEventIdForHash(const QString &eventHash) const = 0;
Q_INVOKABLE virtual int getEventIdForLocation(const QString &filename, int line, int column) const = 0;
signals:
void countChanged();
void dataAvailable();
void stateChanged();
void emptyChanged();
void expandedChanged();
protected:
QmlProfilerModelManager *m_modelManager;
int m_modelId;
};
}
#endif // ABSTRACTTIMELINEMODEL_H
......@@ -34,7 +34,6 @@ Item {
id: detail
property string label
property string content
signal linkActivated(string url)
height: childrenRect.height+2
width: childrenRect.width
......@@ -55,7 +54,6 @@ Item {
font.pixelSize: 12
anchors.baseline: lbl.baseline
anchors.left: guideline.right
onLinkActivated: detail.linkActivated(link)
textFormat: Text.PlainText
}
}
......@@ -31,23 +31,24 @@ import QtQuick 1.0
Item {
id: labelContainer
property alias text: txt.text
property string text: qmlProfilerModelProxy.categoryLabel(modelIndex, categoryIndex)
property bool expanded: false
property int typeIndex: index
property int categoryIndex: qmlProfilerModelProxy.correctedCategoryIndexForModel(modelIndex, index)
property int modelIndex: qmlProfilerModelProxy.modelIndexForCategory(index);
property variant descriptions: []
property variant extdescriptions: []
property variant eventIds: []
visible: qmlProfilerModelProxy.categoryDepth(modelIndex, categoryIndex) > 0;
height: root.singleRowHeight
width: 150
onExpandedChanged: {
var rE = labels.rowExpanded;
rE[typeIndex] = expanded;
labels.rowExpanded = rE;
qmlProfilerModelProxy.setExpanded(modelIndex, categoryIndex, expanded);
backgroundMarks.requestRedraw();
view.setRowExpanded(typeIndex, expanded);
getDescriptions();
updateHeight();
}
......@@ -56,20 +57,24 @@ Item {
}
function updateHeight() {
height = root.singleRowHeight * (1 +
(expanded ? qmlProfilerDataModel.uniqueEventsOfType(typeIndex) :
qmlProfilerDataModel.maxNestingForType(typeIndex)));
if (expanded != qmlProfilerModelProxy.expanded(modelIndex, categoryIndex))
expanded = qmlProfilerModelProxy.expanded(modelIndex, categoryIndex);
height = root.singleRowHeight * qmlProfilerModelProxy.categoryDepth(modelIndex, categoryIndex);
}
function getDescriptions() {
visible = qmlProfilerModelProxy.categoryDepth(modelIndex, categoryIndex) > 0;
if (!visible)
return;
var desc=[];
var ids=[];
var extdesc=[];
for (var i=0; i<qmlProfilerDataModel.uniqueEventsOfType(typeIndex); i++) {
desc[i] = qmlProfilerDataModel.eventTextForType(typeIndex, i);
ids[i] = qmlProfilerDataModel.eventIdForType(typeIndex, i);
extdesc[i] = qmlProfilerDataModel.eventDisplayNameForType(typeIndex, i) +
" : " + desc[i];
var labelList = qmlProfilerModelProxy.getLabelsForCategory(modelIndex, categoryIndex);
for (var i = 0; i < labelList.length; i++ ) {
desc[i] = labelList[i].description;
ids[i] = labelList[i].id;
extdesc[i] = labelList[i].displayName + ":" + labelList[i].description;
}
descriptions = desc;
eventIds = ids;
......@@ -78,20 +83,13 @@ Item {
}
Connections {
target: qmlProfilerDataModel
onReloadDetailLabels: getDescriptions();
target: qmlProfilerModelProxy
onExpandedChanged: {
updateHeight();
}
onStateChanged: {
// Empty
if (qmlProfilerDataModel.getCurrentStateFromQml() == 0) {
descriptions = [];
eventIds = [];
extdescriptions = [];
updateHeight();
} else
// Done
if (qmlProfilerDataModel.getCurrentStateFromQml() == 3) {
getDescriptions();
}
getDescriptions();
}
}
......@@ -99,6 +97,7 @@ Item {
id: txt
x: 5
font.pixelSize: 12
text: labelContainer.text
color: "#232323"
height: root.singleRowHeight
width: 140
......@@ -140,9 +139,9 @@ Item {
onExited: changeToolTip("");
onClicked: {
if (mouse.modifiers & Qt.ShiftModifier)
view.selectPrevFromId(eventIds[index]);
view.selectPrevFromId(modelIndex,eventIds[index]);
else
view.selectNextFromId(eventIds[index]);
view.selectNextFromId(modelIndex,eventIds[index]);
}
}
}
......@@ -150,7 +149,6 @@ Item {
}
Image {
visible: descriptions.length > 0
source: expanded ? "arrow_down.png" : "arrow_right.png"
x: parent.width - 12
y: root.singleRowHeight / 2 - height / 2
......
......@@ -51,14 +51,6 @@ Rectangle {
signal selectedEventChanged(int eventId)
property bool lockItemSelection : false
property variant names: [ qsTr("Painting"),
qsTr("Compiling"),
qsTr("Creating"),
qsTr("Binding"),
qsTr("Handling Signal")]
property variant colors : [ "#99CCB3", "#99CCCC", "#99B3CC",
"#9999CC", "#CC99B3", "#CC99CC", "#CCCC99", "#CCB399" ]
property variant mainviewTimePerPixel : 0
signal updateCursorPosition
......@@ -95,7 +87,7 @@ Rectangle {
backgroundMarks.updateMarks(startTime, endTime);
view.updateFlickRange(startTime, endTime);
if (duration > 0) {
var candidateWidth = qmlProfilerDataModel.traceDuration() *
var candidateWidth = qmlProfilerModelProxy.traceDuration() *
flick.width / duration;
if (flick.contentWidth !== candidateWidth)
flick.contentWidth = candidateWidth;
......@@ -104,22 +96,23 @@ Rectangle {
}
}
Connections {
target: qmlProfilerDataModel
target: qmlProfilerModelProxy
onCountChanged: {
eventCount = qmlProfilerDataModel.count();
eventCount = qmlProfilerModelProxy.count();
if (eventCount === 0)
root.clearAll();
if (eventCount > 1) {
root.progress = Math.min(1.0,
(qmlProfilerDataModel.lastTimeMark() -
qmlProfilerDataModel.traceStartTime()) / root.elapsedTime * 1e-9 );
(qmlProfilerModelProxy.lastTimeMark() -
qmlProfilerModelProxy.traceStartTime()) / root.elapsedTime * 1e-9 );
} else {
root.progress = 0;
}
}
onStateChanged: {
switch (qmlProfilerDataModel.getCurrentStateFromQml()) {
switch (qmlProfilerModelProxy.getState()) {
case 0: {
root.clearAll();
break;
......@@ -132,27 +125,30 @@ Rectangle {
root.progress = 0.9; // jump to 90%
break;
}
case 3: {
view.clearData();
progress = 1.0;
dataAvailable = true;
view.visible = true;
view.requestPaint();
zoomControl.setRange(qmlProfilerDataModel.traceStartTime(),
qmlProfilerDataModel.traceStartTime() +
qmlProfilerDataModel.traceDuration()/10);
break;
}
}
}
onDataAvailable: {
view.clearData();
zoomControl.setRange(0,0);
progress = 1.0;
dataAvailable = true;
view.visible = true;
view.requestPaint();
zoomControl.setRange(qmlProfilerModelProxy.traceStartTime(),
qmlProfilerModelProxy.traceStartTime() +
qmlProfilerModelProxy.traceDuration()/10);
}
}
// ***** functions
function gotoSourceLocation(file,line,column) {
root.fileName = file;
root.lineNumber = line;
root.columnNumber = column;
root.updateCursorPosition();
if (file !== undefined) {
root.fileName = file;
root.lineNumber = line;
root.columnNumber = column;
root.updateCursorPosition();
}
}
function clearData() {
......@@ -186,10 +182,10 @@ Rectangle {
function updateWindowLength(absoluteFactor) {
var windowLength = view.endTime - view.startTime;
if (qmlProfilerDataModel.traceEndTime() <= qmlProfilerDataModel.traceStartTime() ||
if (qmlProfilerModelProxy.traceEndTime() <= qmlProfilerModelProxy.traceStartTime() ||
windowLength <= 0)
return;
var currentFactor = windowLength / qmlProfilerDataModel.traceDuration();
var currentFactor = windowLength / qmlProfilerModelProxy.traceDuration();
updateZoom(absoluteFactor / currentFactor);
}
......@@ -200,8 +196,8 @@ Rectangle {
windowLength = min_length;
var newWindowLength = windowLength * relativeFactor;
if (newWindowLength > qmlProfilerDataModel.traceDuration()) {
newWindowLength = qmlProfilerDataModel.traceDuration();
if (newWindowLength > qmlProfilerModelProxy.traceDuration()) {
newWindowLength = qmlProfilerModelProxy.traceDuration();
relativeFactor = newWindowLength / windowLength;
}
if (newWindowLength < min_length) {
......@@ -210,13 +206,15 @@ Rectangle {
}
var fixedPoint = (view.startTime + view.endTime) / 2;
if (view.selectedItem !== -1) {
// center on selected item if it's inside the current screen
var newFixedPoint = qmlProfilerDataModel.getStartTime(view.selectedItem);
var newFixedPoint = qmlProfilerModelProxy.getStartTime(view.selectedModel, view.selectedItem);
if (newFixedPoint >= view.startTime && newFixedPoint < view.endTime)
fixedPoint = newFixedPoint;
}
var startTime = fixedPoint - relativeFactor*(fixedPoint - view.startTime);
zoomControl.setRange(startTime, startTime + newWindowLength);
}
......@@ -229,8 +227,8 @@ Rectangle {
windowLength = min_length;
var newWindowLength = windowLength * relativeFactor;