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

QmlProfiler: reworked

Change-Id: I66a236a024d76e7bef6edfb91ae30b5dd098b76b
Reviewed-by: default avatarKai Koehne <kai.koehne@digia.com>
parent 7764f351
...@@ -6,6 +6,7 @@ QtcLibrary { ...@@ -6,6 +6,7 @@ QtcLibrary {
cpp.defines: base.concat("QMLDEBUG_LIB") cpp.defines: base.concat("QMLDEBUG_LIB")
Depends { name: "cpp" }
Depends { name: "Qt"; submodules: ["gui", "network"] } Depends { name: "Qt"; submodules: ["gui", "network"] }
files: [ files: [
......
...@@ -38,6 +38,8 @@ enum QmlEventType { ...@@ -38,6 +38,8 @@ enum QmlEventType {
Creating, Creating,
Binding, Binding,
HandlingSignal, HandlingSignal,
PixmapCacheEvent,
SceneGraphFrameEvent,
MaximumQmlEventType MaximumQmlEventType
}; };
...@@ -46,6 +48,8 @@ enum BindingType { ...@@ -46,6 +48,8 @@ enum BindingType {
QmlBinding, QmlBinding,
V8Binding, V8Binding,
OptimizedBinding, OptimizedBinding,
QPainterEvent,
AnimationFrame,
MaximumBindingType MaximumBindingType
}; };
......
...@@ -170,7 +170,8 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data) ...@@ -170,7 +170,8 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
} else if (event == AnimationFrame) { } else if (event == AnimationFrame) {
int frameRate, animationCount; int frameRate, animationCount;
stream >> 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); d->maximumTime = qMax(time, d->maximumTime);
} else if (event == StartTrace) { } else if (event == StartTrace) {
emit this->traceStarted(time); emit this->traceStarted(time);
...@@ -181,6 +182,32 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data) ...@@ -181,6 +182,32 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
} }
} else if (messageType == Complete) { } else if (messageType == Complete) {
emit 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 { } else {
int range; int range;
stream >> range; stream >> range;
...@@ -240,7 +267,10 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data) ...@@ -240,7 +267,10 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
BindingType bindingType = QmlBinding; BindingType bindingType = QmlBinding;
if ((QmlEventType)range == Binding) if ((QmlEventType)range == Binding)
bindingType = d->bindingTypes.pop(); 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) { if (d->rangeCount[range] == 0) {
int count = d->rangeDatas[range].count() + int count = d->rangeDatas[range].count() +
d->rangeStartTimes[range].count() + d->rangeStartTimes[range].count() +
......
...@@ -71,10 +71,23 @@ public: ...@@ -71,10 +71,23 @@ public:
RangeLocation, RangeLocation,
RangeEnd, RangeEnd,
Complete, Complete,
PixmapCacheEvent,
SceneGraphFrame,
MaximumMessage MaximumMessage
}; };
enum PixmapEventType {
PixmapSizeKnown,
PixmapReferenceCountChanged,
PixmapCacheCountChanged,
PixmapLoadingStarted,
PixmapLoadingFinished,
PixmapLoadingError,
MaximumPixmapEventType
};
bool isEnabled() const; bool isEnabled() const;
bool isRecording() const; bool isRecording() const;
void setRecording(bool); void setRecording(bool);
...@@ -89,10 +102,9 @@ signals: ...@@ -89,10 +102,9 @@ signals:
void event(int event, qint64 time); void event(int event, qint64 time);
void traceFinished( qint64 time ); void traceFinished( qint64 time );
void traceStarted( qint64 time ); void traceStarted( qint64 time );
void range(int type, int bindingType, qint64 startTime, qint64 length, void rangedEvent(int type, int bindingType, qint64 startTime, qint64 length,
const QStringList &data, const QmlDebug::QmlEventLocation &location); const QStringList &data, const QmlDebug::QmlEventLocation &location,
void frame(qint64 time, int frameRate, int animationCount); qint64 param1, qint64 param2, qint64 param3, qint64 param4, qint64 param5);
void recordingChanged(bool arg); void recordingChanged(bool arg);
void enabledChanged(); 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 { ...@@ -34,7 +34,6 @@ Item {
id: detail id: detail
property string label property string label
property string content property string content
signal linkActivated(string url)
height: childrenRect.height+2 height: childrenRect.height+2
width: childrenRect.width width: childrenRect.width
...@@ -55,7 +54,6 @@ Item { ...@@ -55,7 +54,6 @@ Item {
font.pixelSize: 12 font.pixelSize: 12
anchors.baseline: lbl.baseline anchors.baseline: lbl.baseline
anchors.left: guideline.right anchors.left: guideline.right
onLinkActivated: detail.linkActivated(link)
textFormat: Text.PlainText textFormat: Text.PlainText
} }
} }
...@@ -31,23 +31,24 @@ import QtQuick 1.0 ...@@ -31,23 +31,24 @@ import QtQuick 1.0
Item { Item {
id: labelContainer id: labelContainer
property alias text: txt.text property string text: qmlProfilerModelProxy.categoryLabel(modelIndex, categoryIndex)
property bool expanded: false 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 descriptions: []
property variant extdescriptions: [] property variant extdescriptions: []
property variant eventIds: [] property variant eventIds: []
visible: qmlProfilerModelProxy.categoryDepth(modelIndex, categoryIndex) > 0;
height: root.singleRowHeight height: root.singleRowHeight
width: 150 width: 150
onExpandedChanged: { onExpandedChanged: {
var rE = labels.rowExpanded; qmlProfilerModelProxy.setExpanded(modelIndex, categoryIndex, expanded);
rE[typeIndex] = expanded;
labels.rowExpanded = rE;
backgroundMarks.requestRedraw(); backgroundMarks.requestRedraw();
view.setRowExpanded(typeIndex, expanded); getDescriptions();
updateHeight(); updateHeight();
} }
...@@ -56,20 +57,24 @@ Item { ...@@ -56,20 +57,24 @@ Item {
} }
function updateHeight() { function updateHeight() {
height = root.singleRowHeight * (1 + if (expanded != qmlProfilerModelProxy.expanded(modelIndex, categoryIndex))
(expanded ? qmlProfilerDataModel.uniqueEventsOfType(typeIndex) : expanded = qmlProfilerModelProxy.expanded(modelIndex, categoryIndex);
qmlProfilerDataModel.maxNestingForType(typeIndex))); height = root.singleRowHeight * qmlProfilerModelProxy.categoryDepth(modelIndex, categoryIndex);
} }
function getDescriptions() { function getDescriptions() {
visible = qmlProfilerModelProxy.categoryDepth(modelIndex, categoryIndex) > 0;
if (!visible)
return;
var desc=[]; var desc=[];
var ids=[]; var ids=[];
var extdesc=[]; var extdesc=[];
for (var i=0; i<qmlProfilerDataModel.uniqueEventsOfType(typeIndex); i++) { var labelList = qmlProfilerModelProxy.getLabelsForCategory(modelIndex, categoryIndex);
desc[i] = qmlProfilerDataModel.eventTextForType(typeIndex, i); for (var i = 0; i < labelList.length; i++ ) {
ids[i] = qmlProfilerDataModel.eventIdForType(typeIndex, i); desc[i] = labelList[i].description;
extdesc[i] = qmlProfilerDataModel.eventDisplayNameForType(typeIndex, i) + ids[i] = labelList[i].id;
" : " + desc[i]; extdesc[i] = labelList[i].displayName + ":" + labelList[i].description;
} }
descriptions = desc; descriptions = desc;
eventIds = ids; eventIds = ids;
...@@ -78,20 +83,13 @@ Item { ...@@ -78,20 +83,13 @@ Item {
} }
Connections { Connections {
target: qmlProfilerDataModel target: qmlProfilerModelProxy
onReloadDetailLabels: getDescriptions(); onExpandedChanged: {
updateHeight();
}
onStateChanged: { onStateChanged: {
// Empty getDescriptions();
if (qmlProfilerDataModel.getCurrentStateFromQml() == 0) {
descriptions = [];
eventIds = [];
extdescriptions = [];
updateHeight();
} else
// Done
if (qmlProfilerDataModel.getCurrentStateFromQml() == 3) {
getDescriptions();
}
} }
} }
...@@ -99,6 +97,7 @@ Item { ...@@ -99,6 +97,7 @@ Item {
id: txt id: txt
x: 5 x: 5
font.pixelSize: 12 font.pixelSize: 12
text: labelContainer.text
color: "#232323" color: "#232323"
height: root.singleRowHeight height: root.singleRowHeight
width: 140 width: 140
...@@ -140,9 +139,9 @@ Item { ...@@ -140,9 +139,9 @@ Item {
onExited: changeToolTip(""); onExited: changeToolTip("");
onClicked: { onClicked: {
if (mouse.modifiers & Qt.ShiftModifier) if (mouse.modifiers & Qt.ShiftModifier)
view.selectPrevFromId(eventIds[index]); view.selectPrevFromId(modelIndex,eventIds[index]);
else else
view.selectNextFromId(eventIds[index]); view.selectNextFromId(modelIndex,eventIds[index]);
} }
} }
} }
...@@ -150,7 +149,6 @@ Item { ...@@ -150,7 +149,6 @@ Item {
} }
Image { Image {
visible: descriptions.length > 0
source: expanded ? "arrow_down.png" : "arrow_right.png" source: expanded ? "arrow_down.png" : "arrow_right.png"
x: parent.width - 12 x: parent.width - 12
y: root.singleRowHeight / 2 - height / 2 y: root.singleRowHeight / 2 - height / 2
......
This diff is collapsed.
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
.pragma library .pragma library
var qmlProfilerDataModel = 0; var qmlProfilerModelProxy = 0;
//draw background of the graph //draw background of the graph
function drawGraph(canvas, ctxt, region) function drawGraph(canvas, ctxt, region)
...@@ -41,89 +41,82 @@ function drawGraph(canvas, ctxt, region) ...@@ -41,89 +41,82 @@ 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 ((!qmlProfilerDataModel) || qmlProfilerDataModel.count() == 0) if ((!qmlProfilerModelProxy) || qmlProfilerModelProxy.count() == 0)
return; return;
var typeCount = 5;
var width = canvas.width; var width = canvas.width;
var bump = 10; var bump = 10;
var height = canvas.height - bump; var height = canvas.height - bump;
var typeCount = qmlProfilerModelProxy.visibleCategories();
var blockHeight = height / typeCount; var blockHeight = height / typeCount;
var spacing = width / qmlProfilerDataModel.traceDuration(); var spacing = width / qmlProfilerModelProxy.traceDuration();
var highest = [0,0,0,0,0]; // note: change if typeCount changes var modelRowStart = 0;
for (var modelIndex = 0; modelIndex < qmlProfilerModelProxy.modelCount(); modelIndex++) {
for (var ii = 0; ii < qmlProfilerDataModel.count(); ++ii) { for (var ii = 0; ii < qmlProfilerModelProxy.count(modelIndex); ++ii) {
var xx = (qmlProfilerDataModel.getStartTime(ii) - var xx = (qmlProfilerModelProxy.getStartTime(modelIndex,ii) -
qmlProfilerDataModel.traceStartTime()) * spacing; qmlProfilerModelProxy.traceStartTime()) * spacing;
if (xx > region.x + region.width) if (xx > region.x + region.width)
continue; continue;
var eventWidth = qmlProfilerDataModel.getDuration(ii) * spacing;