forked from qt-creator/qt-creator
QmlProfiler: Un-pimpl statistics classes
They aren't part of any public API and the pimpl pattern just gets in the way here. Also, initialize members inline where possible, remove redundant deletes, prefer explicit ownership over parenting, and use std::unique_ptr for owned objects and QPointer for non-owned QObjects. Change-Id: Ibe1e1f88d0e38b6ca26544fccb1db6b809d1556b Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
@@ -32,58 +32,35 @@
|
|||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QPointer>
|
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
|
|
||||||
class QmlProfilerStatisticsModel::QmlProfilerStatisticsModelPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QHash<int, QmlProfilerStatisticsModel::QmlEventStats> data;
|
|
||||||
|
|
||||||
QPointer<QmlProfilerStatisticsRelativesModel> childrenModel;
|
|
||||||
QPointer<QmlProfilerStatisticsRelativesModel> parentsModel;
|
|
||||||
|
|
||||||
QmlProfilerModelManager *modelManager;
|
|
||||||
|
|
||||||
int modelId;
|
|
||||||
|
|
||||||
QList<RangeType> acceptedTypes;
|
|
||||||
QHash<int, QString> notes;
|
|
||||||
|
|
||||||
QStack<QmlEvent> callStack;
|
|
||||||
QStack<QmlEvent> compileStack;
|
|
||||||
QHash <int, QVector<qint64> > durations;
|
|
||||||
};
|
|
||||||
|
|
||||||
double QmlProfilerStatisticsModel::durationPercent(int typeId) const
|
double QmlProfilerStatisticsModel::durationPercent(int typeId) const
|
||||||
{
|
{
|
||||||
const QmlEventStats &global = d->data[-1];
|
const QmlEventStats &global = m_data[-1];
|
||||||
const QmlEventStats &stats = d->data[typeId];
|
const QmlEventStats &stats = m_data[typeId];
|
||||||
return double(stats.duration - stats.durationRecursive) / double(global.duration) * 100l;
|
return double(stats.duration - stats.durationRecursive) / double(global.duration) * 100l;
|
||||||
}
|
}
|
||||||
|
|
||||||
double QmlProfilerStatisticsModel::durationSelfPercent(int typeId) const
|
double QmlProfilerStatisticsModel::durationSelfPercent(int typeId) const
|
||||||
{
|
{
|
||||||
const QmlEventStats &global = d->data[-1];
|
const QmlEventStats &global = m_data[-1];
|
||||||
const QmlEventStats &stats = d->data[typeId];
|
const QmlEventStats &stats = m_data[typeId];
|
||||||
return double(stats.durationSelf) / double(global.duration) * 100l;
|
return double(stats.durationSelf) / double(global.duration) * 100l;
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlProfilerStatisticsModel::QmlProfilerStatisticsModel(QmlProfilerModelManager *modelManager,
|
QmlProfilerStatisticsModel::QmlProfilerStatisticsModel(QmlProfilerModelManager *modelManager)
|
||||||
QObject *parent) :
|
: m_modelManager(modelManager)
|
||||||
QObject(parent), d(new QmlProfilerStatisticsModelPrivate)
|
|
||||||
{
|
{
|
||||||
d->modelManager = modelManager;
|
|
||||||
connect(modelManager, &QmlProfilerModelManager::stateChanged,
|
connect(modelManager, &QmlProfilerModelManager::stateChanged,
|
||||||
this, &QmlProfilerStatisticsModel::dataChanged);
|
this, &QmlProfilerStatisticsModel::dataChanged);
|
||||||
connect(modelManager->notesModel(), &Timeline::TimelineNotesModel::changed,
|
connect(modelManager->notesModel(), &Timeline::TimelineNotesModel::changed,
|
||||||
this, &QmlProfilerStatisticsModel::notesChanged);
|
this, &QmlProfilerStatisticsModel::notesChanged);
|
||||||
d->modelId = modelManager->registerModelProxy();
|
modelManager->registerModelProxy();
|
||||||
|
|
||||||
d->acceptedTypes << Compiling << Creating << Binding << HandlingSignal << Javascript;
|
m_acceptedTypes << Compiling << Creating << Binding << HandlingSignal << Javascript;
|
||||||
|
|
||||||
modelManager->announceFeatures(Constants::QML_JS_RANGE_FEATURES,
|
modelManager->announceFeatures(Constants::QML_JS_RANGE_FEATURES,
|
||||||
[this](const QmlEvent &event, const QmlEventType &type) {
|
[this](const QmlEvent &event, const QmlEventType &type) {
|
||||||
@@ -93,11 +70,6 @@ QmlProfilerStatisticsModel::QmlProfilerStatisticsModel(QmlProfilerModelManager *
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlProfilerStatisticsModel::~QmlProfilerStatisticsModel()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerStatisticsModel::restrictToFeatures(quint64 features)
|
void QmlProfilerStatisticsModel::restrictToFeatures(quint64 features)
|
||||||
{
|
{
|
||||||
bool didChange = false;
|
bool didChange = false;
|
||||||
@@ -106,25 +78,25 @@ void QmlProfilerStatisticsModel::restrictToFeatures(quint64 features)
|
|||||||
quint64 featureFlag = 1ULL << featureFromRangeType(type);
|
quint64 featureFlag = 1ULL << featureFromRangeType(type);
|
||||||
if (Constants::QML_JS_RANGE_FEATURES & featureFlag) {
|
if (Constants::QML_JS_RANGE_FEATURES & featureFlag) {
|
||||||
bool accepted = features & featureFlag;
|
bool accepted = features & featureFlag;
|
||||||
if (accepted && !d->acceptedTypes.contains(type)) {
|
if (accepted && !m_acceptedTypes.contains(type)) {
|
||||||
d->acceptedTypes << type;
|
m_acceptedTypes << type;
|
||||||
didChange = true;
|
didChange = true;
|
||||||
} else if (!accepted && d->acceptedTypes.contains(type)) {
|
} else if (!accepted && m_acceptedTypes.contains(type)) {
|
||||||
d->acceptedTypes.removeOne(type);
|
m_acceptedTypes.removeOne(type);
|
||||||
didChange = true;
|
didChange = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!didChange || d->modelManager->state() != QmlProfilerModelManager::Done)
|
if (!didChange || m_modelManager->state() != QmlProfilerModelManager::Done)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
if (!d->modelManager->replayEvents(d->modelManager->traceTime()->startTime(),
|
if (!m_modelManager->replayEvents(m_modelManager->traceTime()->startTime(),
|
||||||
d->modelManager->traceTime()->endTime(),
|
m_modelManager->traceTime()->endTime(),
|
||||||
std::bind(&QmlProfilerStatisticsModel::loadEvent,
|
std::bind(&QmlProfilerStatisticsModel::loadEvent,
|
||||||
this, std::placeholders::_1,
|
this, std::placeholders::_1,
|
||||||
std::placeholders::_2))) {
|
std::placeholders::_2))) {
|
||||||
emit d->modelManager->error(tr("Could not re-read events from temporary trace file."));
|
emit m_modelManager->error(tr("Could not re-read events from temporary trace file."));
|
||||||
clear();
|
clear();
|
||||||
} else {
|
} else {
|
||||||
finalize();
|
finalize();
|
||||||
@@ -132,63 +104,68 @@ void QmlProfilerStatisticsModel::restrictToFeatures(quint64 features)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QmlProfilerStatisticsModel::isRestrictedToRange() const
|
||||||
|
{
|
||||||
|
return m_modelManager->isRestrictedToRange();
|
||||||
|
}
|
||||||
|
|
||||||
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &QmlProfilerStatisticsModel::getData() const
|
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &QmlProfilerStatisticsModel::getData() const
|
||||||
{
|
{
|
||||||
return d->data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QVector<QmlEventType> &QmlProfilerStatisticsModel::getTypes() const
|
const QVector<QmlEventType> &QmlProfilerStatisticsModel::getTypes() const
|
||||||
{
|
{
|
||||||
return d->modelManager->eventTypes();
|
return m_modelManager->eventTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QHash<int, QString> &QmlProfilerStatisticsModel::getNotes() const
|
const QHash<int, QString> &QmlProfilerStatisticsModel::getNotes() const
|
||||||
{
|
{
|
||||||
return d->notes;
|
return m_notes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsModel::clear()
|
void QmlProfilerStatisticsModel::clear()
|
||||||
{
|
{
|
||||||
d->data.clear();
|
m_data.clear();
|
||||||
d->notes.clear();
|
m_notes.clear();
|
||||||
d->callStack.clear();
|
m_callStack.clear();
|
||||||
d->compileStack.clear();
|
m_compileStack.clear();
|
||||||
d->durations.clear();
|
m_durations.clear();
|
||||||
if (!d->childrenModel.isNull())
|
if (!m_calleesModel.isNull())
|
||||||
d->childrenModel->clear();
|
m_calleesModel->clear();
|
||||||
if (!d->parentsModel.isNull())
|
if (!m_callersModel.isNull())
|
||||||
d->parentsModel->clear();
|
m_callersModel->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsModel::setRelativesModel(QmlProfilerStatisticsRelativesModel *relative,
|
void QmlProfilerStatisticsModel::setRelativesModel(QmlProfilerStatisticsRelativesModel *relative,
|
||||||
QmlProfilerStatisticsRelation relation)
|
QmlProfilerStatisticsRelation relation)
|
||||||
{
|
{
|
||||||
if (relation == QmlProfilerStatisticsParents)
|
if (relation == QmlProfilerStatisticsParents)
|
||||||
d->parentsModel = relative;
|
m_callersModel = relative;
|
||||||
else
|
else
|
||||||
d->childrenModel = relative;
|
m_calleesModel = relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlProfilerModelManager *QmlProfilerStatisticsModel::modelManager() const
|
QmlProfilerModelManager *QmlProfilerStatisticsModel::modelManager() const
|
||||||
{
|
{
|
||||||
return d->modelManager;
|
return m_modelManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsModel::dataChanged()
|
void QmlProfilerStatisticsModel::dataChanged()
|
||||||
{
|
{
|
||||||
if (d->modelManager->state() == QmlProfilerModelManager::ClearingData)
|
if (m_modelManager->state() == QmlProfilerModelManager::ClearingData)
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsModel::notesChanged(int typeIndex)
|
void QmlProfilerStatisticsModel::notesChanged(int typeIndex)
|
||||||
{
|
{
|
||||||
const QmlProfilerNotesModel *notesModel = d->modelManager->notesModel();
|
const QmlProfilerNotesModel *notesModel = m_modelManager->notesModel();
|
||||||
if (typeIndex == -1) {
|
if (typeIndex == -1) {
|
||||||
d->notes.clear();
|
m_notes.clear();
|
||||||
for (int noteId = 0; noteId < notesModel->count(); ++noteId) {
|
for (int noteId = 0; noteId < notesModel->count(); ++noteId) {
|
||||||
int noteType = notesModel->typeId(noteId);
|
int noteType = notesModel->typeId(noteId);
|
||||||
if (noteType != -1) {
|
if (noteType != -1) {
|
||||||
QString ¬e = d->notes[noteType];
|
QString ¬e = m_notes[noteType];
|
||||||
if (note.isEmpty()) {
|
if (note.isEmpty()) {
|
||||||
note = notesModel->text(noteId);
|
note = notesModel->text(noteId);
|
||||||
} else {
|
} else {
|
||||||
@@ -197,7 +174,7 @@ void QmlProfilerStatisticsModel::notesChanged(int typeIndex)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
d->notes.remove(typeIndex);
|
m_notes.remove(typeIndex);
|
||||||
const QVariantList changedNotes = notesModel->byTypeId(typeIndex);
|
const QVariantList changedNotes = notesModel->byTypeId(typeIndex);
|
||||||
if (!changedNotes.isEmpty()) {
|
if (!changedNotes.isEmpty()) {
|
||||||
QStringList newNotes;
|
QStringList newNotes;
|
||||||
@@ -205,7 +182,7 @@ void QmlProfilerStatisticsModel::notesChanged(int typeIndex)
|
|||||||
++it) {
|
++it) {
|
||||||
newNotes << notesModel->text(it->toInt());
|
newNotes << notesModel->text(it->toInt());
|
||||||
}
|
}
|
||||||
d->notes[typeIndex] = newNotes.join(QStringLiteral("\n"));
|
m_notes[typeIndex] = newNotes.join(QStringLiteral("\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,11 +191,11 @@ void QmlProfilerStatisticsModel::notesChanged(int typeIndex)
|
|||||||
|
|
||||||
void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
|
void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
|
||||||
{
|
{
|
||||||
if (!d->acceptedTypes.contains(type.rangeType()))
|
if (!m_acceptedTypes.contains(type.rangeType()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool isRecursive = false;
|
bool isRecursive = false;
|
||||||
QStack<QmlEvent> &stack = type.rangeType() == Compiling ? d->compileStack : d->callStack;
|
QStack<QmlEvent> &stack = type.rangeType() == Compiling ? m_compileStack : m_callStack;
|
||||||
switch (event.rangeStage()) {
|
switch (event.rangeStage()) {
|
||||||
case RangeStart:
|
case RangeStart:
|
||||||
stack.push(event);
|
stack.push(event);
|
||||||
@@ -227,7 +204,7 @@ void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEvent
|
|||||||
// update stats
|
// update stats
|
||||||
QTC_ASSERT(!stack.isEmpty(), return);
|
QTC_ASSERT(!stack.isEmpty(), return);
|
||||||
QTC_ASSERT(stack.top().typeIndex() == event.typeIndex(), return);
|
QTC_ASSERT(stack.top().typeIndex() == event.typeIndex(), return);
|
||||||
QmlEventStats *stats = &d->data[event.typeIndex()];
|
QmlEventStats *stats = &m_data[event.typeIndex()];
|
||||||
qint64 duration = event.timestamp() - stack.top().timestamp();
|
qint64 duration = event.timestamp() - stack.top().timestamp();
|
||||||
stats->duration += duration;
|
stats->duration += duration;
|
||||||
stats->durationSelf += duration;
|
stats->durationSelf += duration;
|
||||||
@@ -237,7 +214,7 @@ void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEvent
|
|||||||
stats->maxTime = duration;
|
stats->maxTime = duration;
|
||||||
stats->calls++;
|
stats->calls++;
|
||||||
// for median computing
|
// for median computing
|
||||||
d->durations[event.typeIndex()].append(duration);
|
m_durations[event.typeIndex()].append(duration);
|
||||||
stack.pop();
|
stack.pop();
|
||||||
|
|
||||||
// recursion detection: check whether event was already in stack
|
// recursion detection: check whether event was already in stack
|
||||||
@@ -250,27 +227,27 @@ void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!stack.isEmpty())
|
if (!stack.isEmpty())
|
||||||
d->data[stack.top().typeIndex()].durationSelf -= duration;
|
m_data[stack.top().typeIndex()].durationSelf -= duration;
|
||||||
else
|
else
|
||||||
d->data[-1].duration += duration;
|
m_data[-1].duration += duration;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!d->childrenModel.isNull())
|
if (!m_calleesModel.isNull())
|
||||||
d->childrenModel->loadEvent(type.rangeType(), event, isRecursive);
|
m_calleesModel->loadEvent(type.rangeType(), event, isRecursive);
|
||||||
if (!d->parentsModel.isNull())
|
if (!m_callersModel.isNull())
|
||||||
d->parentsModel->loadEvent(type.rangeType(), event, isRecursive);
|
m_callersModel->loadEvent(type.rangeType(), event, isRecursive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void QmlProfilerStatisticsModel::finalize()
|
void QmlProfilerStatisticsModel::finalize()
|
||||||
{
|
{
|
||||||
// post-process: calc mean time, median time, percentoftime
|
// post-process: calc mean time, median time, percentoftime
|
||||||
for (QHash<int, QmlEventStats>::iterator it = d->data.begin(); it != d->data.end(); ++it) {
|
for (QHash<int, QmlEventStats>::iterator it = m_data.begin(); it != m_data.end(); ++it) {
|
||||||
QVector<qint64> eventDurations = d->durations[it.key()];
|
QVector<qint64> eventDurations = m_durations[it.key()];
|
||||||
if (!eventDurations.isEmpty()) {
|
if (!eventDurations.isEmpty()) {
|
||||||
Utils::sort(eventDurations);
|
Utils::sort(eventDurations);
|
||||||
it->medianTime = eventDurations.at(eventDurations.count()/2);
|
it->medianTime = eventDurations.at(eventDurations.count()/2);
|
||||||
@@ -278,7 +255,7 @@ void QmlProfilerStatisticsModel::finalize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert root event
|
// insert root event
|
||||||
QmlEventStats &rootEvent = d->data[-1];
|
QmlEventStats &rootEvent = m_data[-1];
|
||||||
rootEvent.minTime = rootEvent.maxTime = rootEvent.medianTime = rootEvent.duration;
|
rootEvent.minTime = rootEvent.maxTime = rootEvent.medianTime = rootEvent.duration;
|
||||||
rootEvent.durationSelf = 0;
|
rootEvent.durationSelf = 0;
|
||||||
rootEvent.calls = 1;
|
rootEvent.calls = 1;
|
||||||
@@ -288,17 +265,16 @@ void QmlProfilerStatisticsModel::finalize()
|
|||||||
|
|
||||||
int QmlProfilerStatisticsModel::count() const
|
int QmlProfilerStatisticsModel::count() const
|
||||||
{
|
{
|
||||||
return d->data.count();
|
return m_data.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlProfilerStatisticsRelativesModel::QmlProfilerStatisticsRelativesModel(
|
QmlProfilerStatisticsRelativesModel::QmlProfilerStatisticsRelativesModel(
|
||||||
QmlProfilerModelManager *modelManager, QmlProfilerStatisticsModel *statisticsModel,
|
QmlProfilerModelManager *modelManager,
|
||||||
QmlProfilerStatisticsRelation relation, QObject *parent) :
|
QmlProfilerStatisticsModel *statisticsModel,
|
||||||
QObject(parent), m_relation(relation)
|
QmlProfilerStatisticsRelation relation) :
|
||||||
|
m_modelManager(modelManager), m_relation(relation)
|
||||||
{
|
{
|
||||||
QTC_CHECK(modelManager);
|
QTC_CHECK(modelManager);
|
||||||
m_modelManager = modelManager;
|
|
||||||
|
|
||||||
QTC_CHECK(statisticsModel);
|
QTC_CHECK(statisticsModel);
|
||||||
statisticsModel->setRelativesModel(this, relation);
|
statisticsModel->setRelativesModel(this, relation);
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#include <QStack>
|
#include <QStack>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
class QmlProfilerModelManager;
|
class QmlProfilerModelManager;
|
||||||
@@ -49,24 +50,23 @@ class QmlProfilerStatisticsModel : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
struct QmlEventStats {
|
struct QmlEventStats {
|
||||||
QmlEventStats() : duration(0), durationSelf(0), durationRecursive(0), calls(0),
|
qint64 duration = 0;
|
||||||
minTime(std::numeric_limits<qint64>::max()), maxTime(0), medianTime(0) {}
|
qint64 durationSelf = 0;
|
||||||
qint64 duration;
|
qint64 durationRecursive = 0;
|
||||||
qint64 durationSelf;
|
qint64 calls = 0;
|
||||||
qint64 durationRecursive;
|
qint64 minTime = std::numeric_limits<qint64>::max();
|
||||||
qint64 calls;
|
qint64 maxTime = 0;
|
||||||
qint64 minTime;
|
qint64 medianTime = 0;
|
||||||
qint64 maxTime;
|
|
||||||
qint64 medianTime;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
double durationPercent(int typeId) const;
|
double durationPercent(int typeId) const;
|
||||||
double durationSelfPercent(int typeId) const;
|
double durationSelfPercent(int typeId) const;
|
||||||
|
|
||||||
QmlProfilerStatisticsModel(QmlProfilerModelManager *modelManager, QObject *parent = 0);
|
QmlProfilerStatisticsModel(QmlProfilerModelManager *modelManager);
|
||||||
~QmlProfilerStatisticsModel();
|
~QmlProfilerStatisticsModel() override = default;
|
||||||
|
|
||||||
void restrictToFeatures(quint64 features);
|
void restrictToFeatures(quint64 features);
|
||||||
|
bool isRestrictedToRange() const;
|
||||||
|
|
||||||
const QHash<int, QmlEventStats> &getData() const;
|
const QHash<int, QmlEventStats> &getData() const;
|
||||||
const QVector<QmlEventType> &getTypes() const;
|
const QVector<QmlEventType> &getTypes() const;
|
||||||
@@ -90,8 +90,18 @@ private:
|
|||||||
void dataChanged();
|
void dataChanged();
|
||||||
void notesChanged(int typeIndex);
|
void notesChanged(int typeIndex);
|
||||||
|
|
||||||
class QmlProfilerStatisticsModelPrivate;
|
QHash<int, QmlEventStats> m_data;
|
||||||
QmlProfilerStatisticsModelPrivate *d;
|
|
||||||
|
QPointer<QmlProfilerStatisticsRelativesModel> m_calleesModel;
|
||||||
|
QPointer<QmlProfilerStatisticsRelativesModel> m_callersModel;
|
||||||
|
QPointer<QmlProfilerModelManager> m_modelManager;
|
||||||
|
|
||||||
|
QList<RangeType> m_acceptedTypes;
|
||||||
|
QHash<int, QString> m_notes;
|
||||||
|
|
||||||
|
QStack<QmlEvent> m_callStack;
|
||||||
|
QStack<QmlEvent> m_compileStack;
|
||||||
|
QHash<int, QVector<qint64>> m_durations;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QmlProfilerStatisticsRelativesModel : public QObject
|
class QmlProfilerStatisticsRelativesModel : public QObject
|
||||||
@@ -100,16 +110,15 @@ class QmlProfilerStatisticsRelativesModel : public QObject
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
struct QmlStatisticsRelativesData {
|
struct QmlStatisticsRelativesData {
|
||||||
qint64 duration;
|
qint64 duration = 0;
|
||||||
qint64 calls;
|
qint64 calls = 0;
|
||||||
bool isRecursive;
|
bool isRecursive = false;
|
||||||
};
|
};
|
||||||
typedef QHash <int, QmlStatisticsRelativesData> QmlStatisticsRelativesMap;
|
typedef QHash <int, QmlStatisticsRelativesData> QmlStatisticsRelativesMap;
|
||||||
|
|
||||||
QmlProfilerStatisticsRelativesModel(QmlProfilerModelManager *modelManager,
|
QmlProfilerStatisticsRelativesModel(QmlProfilerModelManager *modelManager,
|
||||||
QmlProfilerStatisticsModel *statisticsModel,
|
QmlProfilerStatisticsModel *statisticsModel,
|
||||||
QmlProfilerStatisticsRelation relation,
|
QmlProfilerStatisticsRelation relation);
|
||||||
QObject *parent = 0);
|
|
||||||
|
|
||||||
int count() const;
|
int count() const;
|
||||||
void clear();
|
void clear();
|
||||||
@@ -125,12 +134,12 @@ signals:
|
|||||||
void dataAvailable();
|
void dataAvailable();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash <int, QmlStatisticsRelativesMap> m_data;
|
QHash<int, QmlStatisticsRelativesMap> m_data;
|
||||||
QmlProfilerModelManager *m_modelManager;
|
QPointer<QmlProfilerModelManager> m_modelManager;
|
||||||
|
|
||||||
struct Frame {
|
struct Frame {
|
||||||
qint64 startTime;
|
qint64 startTime = 0;
|
||||||
int typeId;
|
int typeId = -1;
|
||||||
};
|
};
|
||||||
QStack<Frame> m_callStack;
|
QStack<Frame> m_callStack;
|
||||||
QStack<Frame> m_compileStack;
|
QStack<Frame> m_compileStack;
|
||||||
|
|||||||
@@ -64,15 +64,14 @@ struct SortPreserver {
|
|||||||
view->sortByColumn(column, order);
|
view->sortByColumn(column, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
int column;
|
int column = DEFAULT_SORT_COLUMN;
|
||||||
Qt::SortOrder order;
|
Qt::SortOrder order = Qt::DescendingOrder;
|
||||||
Utils::TreeView *view;
|
Utils::TreeView *view = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Colors {
|
struct Colors {
|
||||||
Colors () : noteBackground(QColor("orange")), defaultBackground(QColor("white")) {}
|
QColor noteBackground = QColor("orange");
|
||||||
QColor noteBackground;
|
QColor defaultBackground = QColor("white");
|
||||||
QColor defaultBackground;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RootEventType : public QmlEventType {
|
struct RootEventType : public QmlEventType {
|
||||||
@@ -108,16 +107,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class QmlProfilerStatisticsView::QmlProfilerStatisticsViewPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QmlProfilerStatisticsMainView *m_statsTree;
|
|
||||||
QmlProfilerStatisticsRelativesView *m_statsChildren;
|
|
||||||
QmlProfilerStatisticsRelativesView *m_statsParents;
|
|
||||||
|
|
||||||
QmlProfilerStatisticsModel *model;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void setViewDefaults(Utils::TreeView *view)
|
static void setViewDefaults(Utils::TreeView *view)
|
||||||
{
|
{
|
||||||
view->setFrameStyle(QFrame::NoFrame);
|
view->setFrameStyle(QFrame::NoFrame);
|
||||||
@@ -195,38 +184,35 @@ static void getSourceLocation(QStandardItem *infoItem,
|
|||||||
|
|
||||||
QmlProfilerStatisticsView::QmlProfilerStatisticsView(QmlProfilerModelManager *profilerModelManager,
|
QmlProfilerStatisticsView::QmlProfilerStatisticsView(QmlProfilerModelManager *profilerModelManager,
|
||||||
QWidget *parent)
|
QWidget *parent)
|
||||||
: QmlProfilerEventsView(parent), d(new QmlProfilerStatisticsViewPrivate)
|
: QmlProfilerEventsView(parent)
|
||||||
{
|
{
|
||||||
setObjectName(QLatin1String("QmlProfiler.Statistics.Dock"));
|
setObjectName(QLatin1String("QmlProfiler.Statistics.Dock"));
|
||||||
setWindowTitle(tr("Statistics"));
|
setWindowTitle(tr("Statistics"));
|
||||||
|
|
||||||
d->model = new QmlProfilerStatisticsModel(profilerModelManager, this);
|
QmlProfilerStatisticsModel *model = new QmlProfilerStatisticsModel(profilerModelManager);
|
||||||
|
m_mainView.reset(new QmlProfilerStatisticsMainView(model));
|
||||||
d->m_statsTree = new QmlProfilerStatisticsMainView(this, d->model);
|
connect(m_mainView.get(), &QmlProfilerStatisticsMainView::gotoSourceLocation,
|
||||||
connect(d->m_statsTree, &QmlProfilerStatisticsMainView::gotoSourceLocation,
|
|
||||||
this, &QmlProfilerStatisticsView::gotoSourceLocation);
|
this, &QmlProfilerStatisticsView::gotoSourceLocation);
|
||||||
connect(d->m_statsTree, &QmlProfilerStatisticsMainView::typeSelected,
|
connect(m_mainView.get(), &QmlProfilerStatisticsMainView::typeSelected,
|
||||||
this, &QmlProfilerStatisticsView::typeSelected);
|
this, &QmlProfilerStatisticsView::typeSelected);
|
||||||
|
|
||||||
d->m_statsChildren = new QmlProfilerStatisticsRelativesView(
|
m_calleesView.reset(new QmlProfilerStatisticsRelativesView(
|
||||||
new QmlProfilerStatisticsRelativesModel(profilerModelManager, d->model,
|
new QmlProfilerStatisticsRelativesModel(profilerModelManager, model,
|
||||||
QmlProfilerStatisticsChilden, this),
|
QmlProfilerStatisticsChilden)));
|
||||||
this);
|
m_callersView.reset(new QmlProfilerStatisticsRelativesView(
|
||||||
d->m_statsParents = new QmlProfilerStatisticsRelativesView(
|
new QmlProfilerStatisticsRelativesModel(profilerModelManager, model,
|
||||||
new QmlProfilerStatisticsRelativesModel(profilerModelManager, d->model,
|
QmlProfilerStatisticsParents)));
|
||||||
QmlProfilerStatisticsParents, this),
|
connect(m_mainView.get(), &QmlProfilerStatisticsMainView::typeSelected,
|
||||||
this);
|
m_calleesView.get(), &QmlProfilerStatisticsRelativesView::displayType);
|
||||||
connect(d->m_statsTree, &QmlProfilerStatisticsMainView::typeSelected,
|
connect(m_mainView.get(), &QmlProfilerStatisticsMainView::typeSelected,
|
||||||
d->m_statsChildren, &QmlProfilerStatisticsRelativesView::displayType);
|
m_callersView.get(), &QmlProfilerStatisticsRelativesView::displayType);
|
||||||
connect(d->m_statsTree, &QmlProfilerStatisticsMainView::typeSelected,
|
connect(m_calleesView.get(), &QmlProfilerStatisticsRelativesView::typeClicked,
|
||||||
d->m_statsParents, &QmlProfilerStatisticsRelativesView::displayType);
|
m_mainView.get(), &QmlProfilerStatisticsMainView::selectType);
|
||||||
connect(d->m_statsChildren, &QmlProfilerStatisticsRelativesView::typeClicked,
|
connect(m_callersView.get(), &QmlProfilerStatisticsRelativesView::typeClicked,
|
||||||
d->m_statsTree, &QmlProfilerStatisticsMainView::selectType);
|
m_mainView.get(), &QmlProfilerStatisticsMainView::selectType);
|
||||||
connect(d->m_statsParents, &QmlProfilerStatisticsRelativesView::typeClicked,
|
connect(m_calleesView.get(), &QmlProfilerStatisticsRelativesView::gotoSourceLocation,
|
||||||
d->m_statsTree, &QmlProfilerStatisticsMainView::selectType);
|
|
||||||
connect(d->m_statsChildren, &QmlProfilerStatisticsRelativesView::gotoSourceLocation,
|
|
||||||
this, &QmlProfilerStatisticsView::gotoSourceLocation);
|
this, &QmlProfilerStatisticsView::gotoSourceLocation);
|
||||||
connect(d->m_statsParents, &QmlProfilerStatisticsRelativesView::gotoSourceLocation,
|
connect(m_callersView.get(), &QmlProfilerStatisticsRelativesView::gotoSourceLocation,
|
||||||
this, &QmlProfilerStatisticsView::gotoSourceLocation);
|
this, &QmlProfilerStatisticsView::gotoSourceLocation);
|
||||||
|
|
||||||
// widget arrangement
|
// widget arrangement
|
||||||
@@ -235,10 +221,10 @@ QmlProfilerStatisticsView::QmlProfilerStatisticsView(QmlProfilerModelManager *pr
|
|||||||
groupLayout->setSpacing(0);
|
groupLayout->setSpacing(0);
|
||||||
|
|
||||||
Core::MiniSplitter *splitterVertical = new Core::MiniSplitter;
|
Core::MiniSplitter *splitterVertical = new Core::MiniSplitter;
|
||||||
splitterVertical->addWidget(d->m_statsTree);
|
splitterVertical->addWidget(m_mainView.get());
|
||||||
Core::MiniSplitter *splitterHorizontal = new Core::MiniSplitter;
|
Core::MiniSplitter *splitterHorizontal = new Core::MiniSplitter;
|
||||||
splitterHorizontal->addWidget(d->m_statsParents);
|
splitterHorizontal->addWidget(m_callersView.get());
|
||||||
splitterHorizontal->addWidget(d->m_statsChildren);
|
splitterHorizontal->addWidget(m_calleesView.get());
|
||||||
splitterHorizontal->setOrientation(Qt::Horizontal);
|
splitterHorizontal->setOrientation(Qt::Horizontal);
|
||||||
splitterVertical->addWidget(splitterHorizontal);
|
splitterVertical->addWidget(splitterHorizontal);
|
||||||
splitterVertical->setOrientation(Qt::Vertical);
|
splitterVertical->setOrientation(Qt::Vertical);
|
||||||
@@ -248,17 +234,11 @@ QmlProfilerStatisticsView::QmlProfilerStatisticsView(QmlProfilerModelManager *pr
|
|||||||
setLayout(groupLayout);
|
setLayout(groupLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlProfilerStatisticsView::~QmlProfilerStatisticsView()
|
|
||||||
{
|
|
||||||
delete d->model;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerStatisticsView::clear()
|
void QmlProfilerStatisticsView::clear()
|
||||||
{
|
{
|
||||||
d->m_statsTree->clear();
|
m_mainView->clear();
|
||||||
d->m_statsChildren->clear();
|
m_calleesView->clear();
|
||||||
d->m_statsParents->clear();
|
m_callersView->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlProfilerStatisticsView::summary(const QVector<int> &typeIds) const
|
QString QmlProfilerStatisticsView::summary(const QVector<int> &typeIds) const
|
||||||
@@ -269,7 +249,7 @@ QString QmlProfilerStatisticsView::summary(const QVector<int> &typeIds) const
|
|||||||
double sum = 0;
|
double sum = 0;
|
||||||
|
|
||||||
for (int typeId : typeIds) {
|
for (int typeId : typeIds) {
|
||||||
const double percentage = d->model->durationPercent(typeId);
|
const double percentage = m_mainView->durationPercent(typeId);
|
||||||
if (percentage > maximum)
|
if (percentage > maximum)
|
||||||
maximum = percentage;
|
maximum = percentage;
|
||||||
sum += percentage;
|
sum += percentage;
|
||||||
@@ -292,7 +272,7 @@ QString QmlProfilerStatisticsView::summary(const QVector<int> &typeIds) const
|
|||||||
|
|
||||||
QStringList QmlProfilerStatisticsView::details(int typeId) const
|
QStringList QmlProfilerStatisticsView::details(int typeId) const
|
||||||
{
|
{
|
||||||
const QmlEventType &type = d->model->getTypes()[typeId];
|
const QmlEventType &type = m_mainView->getType(typeId);
|
||||||
|
|
||||||
const QChar ellipsisChar(0x2026);
|
const QChar ellipsisChar(0x2026);
|
||||||
const int maxColumnWidth = 32;
|
const int maxColumnWidth = 32;
|
||||||
@@ -304,13 +284,13 @@ QStringList QmlProfilerStatisticsView::details(int typeId) const
|
|||||||
return QStringList({
|
return QStringList({
|
||||||
QmlProfilerStatisticsMainView::nameForType(type.rangeType()),
|
QmlProfilerStatisticsMainView::nameForType(type.rangeType()),
|
||||||
data,
|
data,
|
||||||
QString::number(d->model->durationPercent(typeId), 'f', 2) + QLatin1Char('%')
|
QString::number(m_mainView->durationPercent(typeId), 'f', 2) + QLatin1Char('%')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex QmlProfilerStatisticsView::selectedModelIndex() const
|
QModelIndex QmlProfilerStatisticsView::selectedModelIndex() const
|
||||||
{
|
{
|
||||||
return d->m_statsTree->selectedModelIndex();
|
return m_mainView->selectedModelIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsView::contextMenuEvent(QContextMenuEvent *ev)
|
void QmlProfilerStatisticsView::contextMenuEvent(QContextMenuEvent *ev)
|
||||||
@@ -340,7 +320,7 @@ void QmlProfilerStatisticsView::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
|
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
getGlobalStatsAction = menu.addAction(tr("Show Full Range"));
|
getGlobalStatsAction = menu.addAction(tr("Show Full Range"));
|
||||||
if (!d->model->modelManager()->isRestrictedToRange())
|
if (!m_mainView->isRestrictedToRange())
|
||||||
getGlobalStatsAction->setEnabled(false);
|
getGlobalStatsAction->setEnabled(false);
|
||||||
|
|
||||||
QAction *selectedAction = menu.exec(position);
|
QAction *selectedAction = menu.exec(position);
|
||||||
@@ -359,74 +339,57 @@ void QmlProfilerStatisticsView::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
|
|
||||||
bool QmlProfilerStatisticsView::mouseOnTable(const QPoint &position) const
|
bool QmlProfilerStatisticsView::mouseOnTable(const QPoint &position) const
|
||||||
{
|
{
|
||||||
QPoint tableTopLeft = d->m_statsTree->mapToGlobal(QPoint(0,0));
|
QPoint tableTopLeft = m_mainView->mapToGlobal(QPoint(0,0));
|
||||||
QPoint tableBottomRight = d->m_statsTree->mapToGlobal(QPoint(d->m_statsTree->width(), d->m_statsTree->height()));
|
QPoint tableBottomRight = m_mainView->mapToGlobal(QPoint(m_mainView->width(), m_mainView->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 QmlProfilerStatisticsView::copyTableToClipboard() const
|
void QmlProfilerStatisticsView::copyTableToClipboard() const
|
||||||
{
|
{
|
||||||
d->m_statsTree->copyTableToClipboard();
|
m_mainView->copyTableToClipboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsView::copyRowToClipboard() const
|
void QmlProfilerStatisticsView::copyRowToClipboard() const
|
||||||
{
|
{
|
||||||
d->m_statsTree->copyRowToClipboard();
|
m_mainView->copyRowToClipboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsView::selectByTypeId(int typeIndex)
|
void QmlProfilerStatisticsView::selectByTypeId(int typeIndex)
|
||||||
{
|
{
|
||||||
if (d->m_statsTree->selectedTypeId() != typeIndex)
|
if (m_mainView->selectedTypeId() != typeIndex)
|
||||||
d->m_statsTree->selectType(typeIndex);
|
m_mainView->selectType(typeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsView::onVisibleFeaturesChanged(quint64 features)
|
void QmlProfilerStatisticsView::onVisibleFeaturesChanged(quint64 features)
|
||||||
{
|
{
|
||||||
d->model->restrictToFeatures(features);
|
m_mainView->restrictToFeatures(features);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsView::setShowExtendedStatistics(bool show)
|
void QmlProfilerStatisticsView::setShowExtendedStatistics(bool show)
|
||||||
{
|
{
|
||||||
d->m_statsTree->setShowExtendedStatistics(show);
|
m_mainView->setShowExtendedStatistics(show);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlProfilerStatisticsView::showExtendedStatistics() const
|
bool QmlProfilerStatisticsView::showExtendedStatistics() const
|
||||||
{
|
{
|
||||||
return d->m_statsTree->showExtendedStatistics();
|
return m_mainView->showExtendedStatistics();
|
||||||
}
|
}
|
||||||
|
|
||||||
class QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainViewPrivate
|
QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainView(QmlProfilerStatisticsModel *model) :
|
||||||
{
|
m_model(model)
|
||||||
public:
|
|
||||||
QmlProfilerStatisticsMainViewPrivate(QmlProfilerStatisticsMainView *qq) : q(qq) {}
|
|
||||||
|
|
||||||
QString textForItem(QStandardItem *item) const;
|
|
||||||
|
|
||||||
QmlProfilerStatisticsMainView *q;
|
|
||||||
|
|
||||||
QmlProfilerStatisticsModel *model;
|
|
||||||
QStandardItemModel *m_model;
|
|
||||||
bool m_showExtendedStatistics;
|
|
||||||
};
|
|
||||||
|
|
||||||
QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainView(
|
|
||||||
QWidget *parent, QmlProfilerStatisticsModel *model) :
|
|
||||||
Utils::TreeView(parent), d(new QmlProfilerStatisticsMainViewPrivate(this))
|
|
||||||
{
|
{
|
||||||
setViewDefaults(this);
|
setViewDefaults(this);
|
||||||
setObjectName(QLatin1String("QmlProfilerEventsTable"));
|
setObjectName(QLatin1String("QmlProfilerEventsTable"));
|
||||||
|
|
||||||
d->m_model = new QStandardItemModel(this);
|
m_standardItemModel.reset(new QStandardItemModel);
|
||||||
d->m_model->setSortRole(SortRole);
|
m_standardItemModel->setSortRole(SortRole);
|
||||||
setModel(d->m_model);
|
setModel(m_standardItemModel.get());
|
||||||
connect(this, &QAbstractItemView::activated, this, &QmlProfilerStatisticsMainView::jumpToItem);
|
connect(this, &QAbstractItemView::activated, this, &QmlProfilerStatisticsMainView::jumpToItem);
|
||||||
|
|
||||||
d->model = model;
|
connect(m_model.get(), &QmlProfilerStatisticsModel::dataAvailable,
|
||||||
connect(d->model, &QmlProfilerStatisticsModel::dataAvailable,
|
|
||||||
this, &QmlProfilerStatisticsMainView::buildModel);
|
this, &QmlProfilerStatisticsMainView::buildModel);
|
||||||
connect(d->model, &QmlProfilerStatisticsModel::notesAvailable,
|
connect(m_model.get(), &QmlProfilerStatisticsModel::notesAvailable,
|
||||||
this, &QmlProfilerStatisticsMainView::updateNotes);
|
this, &QmlProfilerStatisticsMainView::updateNotes);
|
||||||
d->m_showExtendedStatistics = false;
|
|
||||||
|
|
||||||
setSortingEnabled(true);
|
setSortingEnabled(true);
|
||||||
sortByColumn(DEFAULT_SORT_COLUMN, Qt::DescendingOrder);
|
sortByColumn(DEFAULT_SORT_COLUMN, Qt::DescendingOrder);
|
||||||
@@ -437,20 +400,20 @@ QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainView(
|
|||||||
QmlProfilerStatisticsMainView::~QmlProfilerStatisticsMainView()
|
QmlProfilerStatisticsMainView::~QmlProfilerStatisticsMainView()
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
delete d->m_model;
|
|
||||||
delete d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsMainView::setHeaderLabels()
|
void QmlProfilerStatisticsMainView::setHeaderLabels()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MaxMainField; ++i)
|
for (int i = 0; i < MaxMainField; ++i) {
|
||||||
d->m_model->setHeaderData(i, Qt::Horizontal, displayHeader(static_cast<MainField>(i)));
|
m_standardItemModel->setHeaderData(i, Qt::Horizontal,
|
||||||
|
displayHeader(static_cast<MainField>(i)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsMainView::setShowExtendedStatistics(bool show)
|
void QmlProfilerStatisticsMainView::setShowExtendedStatistics(bool show)
|
||||||
{
|
{
|
||||||
// Not checking if already set because we don't want the first call to skip
|
// Not checking if already set because we don't want the first call to skip
|
||||||
d->m_showExtendedStatistics = show;
|
m_showExtendedStatistics = show;
|
||||||
if (show) {
|
if (show) {
|
||||||
showColumn(MainMedianTime);
|
showColumn(MainMedianTime);
|
||||||
showColumn(MainMaxTime);
|
showColumn(MainMaxTime);
|
||||||
@@ -464,14 +427,14 @@ void QmlProfilerStatisticsMainView::setShowExtendedStatistics(bool show)
|
|||||||
|
|
||||||
bool QmlProfilerStatisticsMainView::showExtendedStatistics() const
|
bool QmlProfilerStatisticsMainView::showExtendedStatistics() const
|
||||||
{
|
{
|
||||||
return d->m_showExtendedStatistics;
|
return m_showExtendedStatistics;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsMainView::clear()
|
void QmlProfilerStatisticsMainView::clear()
|
||||||
{
|
{
|
||||||
SortPreserver sorter(this);
|
SortPreserver sorter(this);
|
||||||
d->m_model->clear();
|
m_standardItemModel->clear();
|
||||||
d->m_model->setColumnCount(MaxMainField);
|
m_standardItemModel->setColumnCount(MaxMainField);
|
||||||
setHeaderLabels();
|
setHeaderLabels();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +445,7 @@ void QmlProfilerStatisticsMainView::buildModel()
|
|||||||
{
|
{
|
||||||
SortPreserver sorter(this);
|
SortPreserver sorter(this);
|
||||||
parseModel();
|
parseModel();
|
||||||
setShowExtendedStatistics(d->m_showExtendedStatistics);
|
setShowExtendedStatistics(m_showExtendedStatistics);
|
||||||
setRootIsDecorated(false);
|
setRootIsDecorated(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,9 +455,9 @@ void QmlProfilerStatisticsMainView::buildModel()
|
|||||||
|
|
||||||
void QmlProfilerStatisticsMainView::updateNotes(int typeIndex)
|
void QmlProfilerStatisticsMainView::updateNotes(int typeIndex)
|
||||||
{
|
{
|
||||||
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &eventList = d->model->getData();
|
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &eventList = m_model->getData();
|
||||||
const QHash<int, QString> ¬eList = d->model->getNotes();
|
const QHash<int, QString> ¬eList = m_model->getNotes();
|
||||||
QStandardItem *parentItem = d->m_model->invisibleRootItem();
|
QStandardItem *parentItem = m_standardItemModel->invisibleRootItem();
|
||||||
|
|
||||||
for (int rowIndex = 0; rowIndex < parentItem->rowCount(); ++rowIndex) {
|
for (int rowIndex = 0; rowIndex < parentItem->rowCount(); ++rowIndex) {
|
||||||
int rowType = parentItem->child(rowIndex)->data(TypeIdRole).toInt();
|
int rowType = parentItem->child(rowIndex)->data(TypeIdRole).toInt();
|
||||||
@@ -520,17 +483,37 @@ void QmlProfilerStatisticsMainView::updateNotes(int typeIndex)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlProfilerStatisticsMainView::restrictToFeatures(quint64 features)
|
||||||
|
{
|
||||||
|
m_model->restrictToFeatures(features);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlProfilerStatisticsMainView::isRestrictedToRange() const
|
||||||
|
{
|
||||||
|
return m_model->isRestrictedToRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
double QmlProfilerStatisticsMainView::durationPercent(int typeId) const
|
||||||
|
{
|
||||||
|
return m_model->durationPercent(typeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QmlEventType &QmlProfilerStatisticsMainView::getType(int typeId) const
|
||||||
|
{
|
||||||
|
return m_model->getTypes()[typeId];
|
||||||
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsMainView::parseModel()
|
void QmlProfilerStatisticsMainView::parseModel()
|
||||||
{
|
{
|
||||||
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &eventList = d->model->getData();
|
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &eventList = m_model->getData();
|
||||||
const QVector<QmlEventType> &typeList = d->model->getTypes();
|
const QVector<QmlEventType> &typeList = m_model->getTypes();
|
||||||
|
|
||||||
QHash<int, QmlProfilerStatisticsModel::QmlEventStats>::ConstIterator it;
|
QHash<int, QmlProfilerStatisticsModel::QmlEventStats>::ConstIterator it;
|
||||||
for (it = eventList.constBegin(); it != eventList.constEnd(); ++it) {
|
for (it = eventList.constBegin(); it != eventList.constEnd(); ++it) {
|
||||||
int typeIndex = it.key();
|
int typeIndex = it.key();
|
||||||
const QmlProfilerStatisticsModel::QmlEventStats &stats = it.value();
|
const QmlProfilerStatisticsModel::QmlEventStats &stats = it.value();
|
||||||
const QmlEventType &type = (typeIndex != -1 ? typeList[typeIndex] : *rootEventType());
|
const QmlEventType &type = (typeIndex != -1 ? typeList[typeIndex] : *rootEventType());
|
||||||
QStandardItem *parentItem = d->m_model->invisibleRootItem();
|
QStandardItem *parentItem = m_standardItemModel->invisibleRootItem();
|
||||||
QList<QStandardItem *> newRow;
|
QList<QStandardItem *> newRow;
|
||||||
|
|
||||||
newRow << new StatisticsViewItem(
|
newRow << new StatisticsViewItem(
|
||||||
@@ -540,7 +523,7 @@ void QmlProfilerStatisticsMainView::parseModel()
|
|||||||
QString typeString = QmlProfilerStatisticsMainView::nameForType(type.rangeType());
|
QString typeString = QmlProfilerStatisticsMainView::nameForType(type.rangeType());
|
||||||
newRow << new StatisticsViewItem(typeString, typeString);
|
newRow << new StatisticsViewItem(typeString, typeString);
|
||||||
|
|
||||||
const double percent = d->model->durationPercent(typeIndex);
|
const double percent = m_model->durationPercent(typeIndex);
|
||||||
newRow << new StatisticsViewItem(QString::number(percent, 'f', 2)
|
newRow << new StatisticsViewItem(QString::number(percent, 'f', 2)
|
||||||
+ QLatin1String(" %"), percent);
|
+ QLatin1String(" %"), percent);
|
||||||
|
|
||||||
@@ -548,7 +531,7 @@ void QmlProfilerStatisticsMainView::parseModel()
|
|||||||
Timeline::formatTime(stats.duration - stats.durationRecursive),
|
Timeline::formatTime(stats.duration - stats.durationRecursive),
|
||||||
stats.duration - stats.durationRecursive);
|
stats.duration - stats.durationRecursive);
|
||||||
|
|
||||||
const double percentSelf = d->model->durationSelfPercent(typeIndex);
|
const double percentSelf = m_model->durationSelfPercent(typeIndex);
|
||||||
newRow << new StatisticsViewItem(QString::number(percentSelf, 'f', 2)
|
newRow << new StatisticsViewItem(QString::number(percentSelf, 'f', 2)
|
||||||
+ QLatin1String(" %"), percentSelf);
|
+ QLatin1String(" %"), percentSelf);
|
||||||
|
|
||||||
@@ -592,12 +575,11 @@ void QmlProfilerStatisticsMainView::parseModel()
|
|||||||
|
|
||||||
QStandardItem *QmlProfilerStatisticsMainView::itemFromIndex(const QModelIndex &index) const
|
QStandardItem *QmlProfilerStatisticsMainView::itemFromIndex(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
QStandardItem *indexItem = d->m_model->itemFromIndex(index);
|
QStandardItem *indexItem = m_standardItemModel->itemFromIndex(index);
|
||||||
if (indexItem->parent())
|
if (indexItem->parent())
|
||||||
return indexItem->parent()->child(indexItem->row());
|
return indexItem->parent()->child(indexItem->row());
|
||||||
else
|
else
|
||||||
return d->m_model->item(index.row());
|
return m_standardItemModel->item(index.row());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlProfilerStatisticsMainView::nameForType(RangeType typeNumber)
|
QString QmlProfilerStatisticsMainView::nameForType(RangeType typeNumber)
|
||||||
@@ -618,7 +600,7 @@ int QmlProfilerStatisticsMainView::selectedTypeId() const
|
|||||||
QModelIndex index = selectedModelIndex();
|
QModelIndex index = selectedModelIndex();
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return -1;
|
return -1;
|
||||||
QStandardItem *item = d->m_model->item(index.row());
|
QStandardItem *item = m_standardItemModel->item(index.row());
|
||||||
return item->data(TypeIdRole).toInt();
|
return item->data(TypeIdRole).toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,7 +620,7 @@ void QmlProfilerStatisticsMainView::jumpToItem(const QModelIndex &index)
|
|||||||
void QmlProfilerStatisticsMainView::selectItem(const QStandardItem *item)
|
void QmlProfilerStatisticsMainView::selectItem(const QStandardItem *item)
|
||||||
{
|
{
|
||||||
// If the same item is already selected, don't reselect it.
|
// If the same item is already selected, don't reselect it.
|
||||||
QModelIndex index = d->m_model->indexFromItem(item);
|
QModelIndex index = m_standardItemModel->indexFromItem(item);
|
||||||
if (index != currentIndex()) {
|
if (index != currentIndex()) {
|
||||||
setCurrentIndex(index);
|
setCurrentIndex(index);
|
||||||
|
|
||||||
@@ -649,8 +631,8 @@ void QmlProfilerStatisticsMainView::selectItem(const QStandardItem *item)
|
|||||||
|
|
||||||
void QmlProfilerStatisticsMainView::selectType(int typeIndex)
|
void QmlProfilerStatisticsMainView::selectType(int typeIndex)
|
||||||
{
|
{
|
||||||
for (int i=0; i<d->m_model->rowCount(); i++) {
|
for (int i = 0; i < m_standardItemModel->rowCount(); i++) {
|
||||||
QStandardItem *infoItem = d->m_model->item(i);
|
QStandardItem *infoItem = m_standardItemModel->item(i);
|
||||||
if (infoItem->data(TypeIdRole).toInt() == typeIndex) {
|
if (infoItem->data(TypeIdRole).toInt() == typeIndex) {
|
||||||
selectItem(infoItem);
|
selectItem(infoItem);
|
||||||
return;
|
return;
|
||||||
@@ -667,16 +649,15 @@ QModelIndex QmlProfilerStatisticsMainView::selectedModelIndex() const
|
|||||||
return sel.first();
|
return sel.first();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainViewPrivate::textForItem(
|
QString QmlProfilerStatisticsMainView::textForItem(QStandardItem *item) const
|
||||||
QStandardItem *item) const
|
|
||||||
{
|
{
|
||||||
QString str;
|
QString str;
|
||||||
|
|
||||||
// item's data
|
// item's data
|
||||||
int colCount = m_model->columnCount();
|
int colCount = m_standardItemModel->columnCount();
|
||||||
for (int j = 0; j < colCount; ++j) {
|
for (int j = 0; j < colCount; ++j) {
|
||||||
QStandardItem *colItem = item->parent() ? item->parent()->child(item->row(),j) :
|
QStandardItem *colItem = item->parent() ? item->parent()->child(item->row(),j) :
|
||||||
m_model->item(item->row(),j);
|
m_standardItemModel->item(item->row(),j);
|
||||||
str += colItem->data(Qt::DisplayRole).toString();
|
str += colItem->data(Qt::DisplayRole).toString();
|
||||||
if (j < colCount-1) str += QLatin1Char('\t');
|
if (j < colCount-1) str += QLatin1Char('\t');
|
||||||
}
|
}
|
||||||
@@ -689,18 +670,18 @@ void QmlProfilerStatisticsMainView::copyTableToClipboard() const
|
|||||||
{
|
{
|
||||||
QString str;
|
QString str;
|
||||||
// headers
|
// headers
|
||||||
int columnCount = d->m_model->columnCount();
|
int columnCount = m_standardItemModel->columnCount();
|
||||||
for (int i = 0; i < columnCount; ++i) {
|
for (int i = 0; i < columnCount; ++i) {
|
||||||
str += d->m_model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString();
|
str += m_standardItemModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString();
|
||||||
if (i < columnCount - 1)
|
if (i < columnCount - 1)
|
||||||
str += QLatin1Char('\t');
|
str += QLatin1Char('\t');
|
||||||
else
|
else
|
||||||
str += QLatin1Char('\n');
|
str += QLatin1Char('\n');
|
||||||
}
|
}
|
||||||
// data
|
// data
|
||||||
int rowCount = d->m_model->rowCount();
|
int rowCount = m_standardItemModel->rowCount();
|
||||||
for (int i = 0; i != rowCount; ++i) {
|
for (int i = 0; i != rowCount; ++i) {
|
||||||
str += d->textForItem(d->m_model->item(i));
|
str += textForItem(m_standardItemModel->item(i));
|
||||||
}
|
}
|
||||||
QClipboard *clipboard = QApplication::clipboard();
|
QClipboard *clipboard = QApplication::clipboard();
|
||||||
clipboard->setText(str, QClipboard::Selection);
|
clipboard->setText(str, QClipboard::Selection);
|
||||||
@@ -709,29 +690,17 @@ void QmlProfilerStatisticsMainView::copyTableToClipboard() const
|
|||||||
|
|
||||||
void QmlProfilerStatisticsMainView::copyRowToClipboard() const
|
void QmlProfilerStatisticsMainView::copyRowToClipboard() const
|
||||||
{
|
{
|
||||||
QString str = d->textForItem(d->m_model->itemFromIndex(selectedModelIndex()));
|
QString str = textForItem(m_standardItemModel->itemFromIndex(selectedModelIndex()));
|
||||||
QClipboard *clipboard = QApplication::clipboard();
|
QClipboard *clipboard = QApplication::clipboard();
|
||||||
clipboard->setText(str, QClipboard::Selection);
|
clipboard->setText(str, QClipboard::Selection);
|
||||||
clipboard->setText(str, QClipboard::Clipboard);
|
clipboard->setText(str, QClipboard::Clipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
class QmlProfilerStatisticsRelativesView::QmlProfilerStatisticsRelativesViewPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QmlProfilerStatisticsRelativesViewPrivate(QmlProfilerStatisticsRelativesView *qq):q(qq) {}
|
|
||||||
~QmlProfilerStatisticsRelativesViewPrivate() {}
|
|
||||||
|
|
||||||
QmlProfilerStatisticsRelativesModel *model;
|
|
||||||
|
|
||||||
QmlProfilerStatisticsRelativesView *q;
|
|
||||||
};
|
|
||||||
|
|
||||||
QmlProfilerStatisticsRelativesView::QmlProfilerStatisticsRelativesView(
|
QmlProfilerStatisticsRelativesView::QmlProfilerStatisticsRelativesView(
|
||||||
QmlProfilerStatisticsRelativesModel *model, QWidget *parent) :
|
QmlProfilerStatisticsRelativesModel *model) :
|
||||||
Utils::TreeView(parent), d(new QmlProfilerStatisticsRelativesViewPrivate(this))
|
m_model(model)
|
||||||
{
|
{
|
||||||
setViewDefaults(this);
|
setViewDefaults(this);
|
||||||
d->model = model;
|
|
||||||
QStandardItemModel *itemModel = new QStandardItemModel(this);
|
QStandardItemModel *itemModel = new QStandardItemModel(this);
|
||||||
itemModel->setSortRole(SortRole);
|
itemModel->setSortRole(SortRole);
|
||||||
setModel(itemModel);
|
setModel(itemModel);
|
||||||
@@ -745,19 +714,18 @@ QmlProfilerStatisticsRelativesView::QmlProfilerStatisticsRelativesView(
|
|||||||
this, &QmlProfilerStatisticsRelativesView::jumpToItem);
|
this, &QmlProfilerStatisticsRelativesView::jumpToItem);
|
||||||
|
|
||||||
// Clear when new data available as the selection may be invalid now.
|
// Clear when new data available as the selection may be invalid now.
|
||||||
connect(d->model, &QmlProfilerStatisticsRelativesModel::dataAvailable,
|
connect(m_model.get(), &QmlProfilerStatisticsRelativesModel::dataAvailable,
|
||||||
this, &QmlProfilerStatisticsRelativesView::clear);
|
this, &QmlProfilerStatisticsRelativesView::clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlProfilerStatisticsRelativesView::~QmlProfilerStatisticsRelativesView()
|
QmlProfilerStatisticsRelativesView::~QmlProfilerStatisticsRelativesView()
|
||||||
{
|
{
|
||||||
delete d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsRelativesView::displayType(int typeIndex)
|
void QmlProfilerStatisticsRelativesView::displayType(int typeIndex)
|
||||||
{
|
{
|
||||||
SortPreserver sorter(this);
|
SortPreserver sorter(this);
|
||||||
rebuildTree(d->model->getData(typeIndex));
|
rebuildTree(m_model->getData(typeIndex));
|
||||||
|
|
||||||
updateHeader();
|
updateHeader();
|
||||||
resizeColumnToContents(RelativeLocation);
|
resizeColumnToContents(RelativeLocation);
|
||||||
@@ -770,7 +738,7 @@ void QmlProfilerStatisticsRelativesView::rebuildTree(
|
|||||||
treeModel()->clear();
|
treeModel()->clear();
|
||||||
|
|
||||||
QStandardItem *topLevelItem = treeModel()->invisibleRootItem();
|
QStandardItem *topLevelItem = treeModel()->invisibleRootItem();
|
||||||
const QVector<QmlEventType> &typeList = d->model->getTypes();
|
const QVector<QmlEventType> &typeList = m_model->getTypes();
|
||||||
|
|
||||||
QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesMap::const_iterator it;
|
QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesMap::const_iterator it;
|
||||||
for (it = map.constBegin(); it != map.constEnd(); ++it) {
|
for (it = map.constBegin(); it != map.constEnd(); ++it) {
|
||||||
@@ -825,7 +793,7 @@ void QmlProfilerStatisticsRelativesView::clear()
|
|||||||
|
|
||||||
void QmlProfilerStatisticsRelativesView::updateHeader()
|
void QmlProfilerStatisticsRelativesView::updateHeader()
|
||||||
{
|
{
|
||||||
const QmlProfilerStatisticsRelation relation = d->model->relation();
|
const QmlProfilerStatisticsRelation relation = m_model->relation();
|
||||||
if (QStandardItemModel *model = treeModel()) {
|
if (QStandardItemModel *model = treeModel()) {
|
||||||
model->setColumnCount(MaxRelativeField);
|
model->setColumnCount(MaxRelativeField);
|
||||||
for (int i = 0; i < MaxRelativeField; ++i) {
|
for (int i = 0; i < MaxRelativeField; ++i) {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include <debugger/analyzer/analyzermanager.h>
|
#include <debugger/analyzer/analyzermanager.h>
|
||||||
#include <utils/itemviews.h>
|
#include <utils/itemviews.h>
|
||||||
|
|
||||||
|
#include <QPointer>
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
@@ -80,7 +81,7 @@ class QmlProfilerStatisticsView : public QmlProfilerEventsView
|
|||||||
public:
|
public:
|
||||||
explicit QmlProfilerStatisticsView(QmlProfilerModelManager *profilerModelManager,
|
explicit QmlProfilerStatisticsView(QmlProfilerModelManager *profilerModelManager,
|
||||||
QWidget *parent = nullptr);
|
QWidget *parent = nullptr);
|
||||||
~QmlProfilerStatisticsView();
|
~QmlProfilerStatisticsView() override = default;
|
||||||
void clear() override;
|
void clear() override;
|
||||||
|
|
||||||
QString summary(const QVector<int> &typeIds) const;
|
QString summary(const QVector<int> &typeIds) const;
|
||||||
@@ -100,15 +101,16 @@ private:
|
|||||||
void setShowExtendedStatistics(bool show);
|
void setShowExtendedStatistics(bool show);
|
||||||
bool showExtendedStatistics() const;
|
bool showExtendedStatistics() const;
|
||||||
|
|
||||||
class QmlProfilerStatisticsViewPrivate;
|
std::unique_ptr<QmlProfilerStatisticsMainView> m_mainView;
|
||||||
QmlProfilerStatisticsViewPrivate *d;
|
std::unique_ptr<QmlProfilerStatisticsRelativesView> m_calleesView;
|
||||||
|
std::unique_ptr<QmlProfilerStatisticsRelativesView> m_callersView;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QmlProfilerStatisticsMainView : public Utils::TreeView
|
class QmlProfilerStatisticsMainView : public Utils::TreeView
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit QmlProfilerStatisticsMainView(QWidget *parent, QmlProfilerStatisticsModel *model);
|
explicit QmlProfilerStatisticsMainView(QmlProfilerStatisticsModel *model);
|
||||||
~QmlProfilerStatisticsMainView();
|
~QmlProfilerStatisticsMainView();
|
||||||
|
|
||||||
QModelIndex selectedModelIndex() const;
|
QModelIndex selectedModelIndex() const;
|
||||||
@@ -128,6 +130,12 @@ public:
|
|||||||
void buildModel();
|
void buildModel();
|
||||||
void updateNotes(int typeIndex);
|
void updateNotes(int typeIndex);
|
||||||
|
|
||||||
|
void restrictToFeatures(quint64 features);
|
||||||
|
bool isRestrictedToRange() const;
|
||||||
|
double durationPercent(int typeId) const;
|
||||||
|
|
||||||
|
const QmlEventType &getType(int typeId) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
|
void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
|
||||||
void typeSelected(int typeIndex);
|
void typeSelected(int typeIndex);
|
||||||
@@ -137,17 +145,18 @@ private:
|
|||||||
void setHeaderLabels();
|
void setHeaderLabels();
|
||||||
void parseModel();
|
void parseModel();
|
||||||
QStandardItem *itemFromIndex(const QModelIndex &index) const;
|
QStandardItem *itemFromIndex(const QModelIndex &index) const;
|
||||||
|
QString textForItem(QStandardItem *item) const;
|
||||||
|
|
||||||
class QmlProfilerStatisticsMainViewPrivate;
|
std::unique_ptr<QmlProfilerStatisticsModel> m_model;
|
||||||
QmlProfilerStatisticsMainViewPrivate *d;
|
std::unique_ptr<QStandardItemModel> m_standardItemModel;
|
||||||
|
bool m_showExtendedStatistics = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QmlProfilerStatisticsRelativesView : public Utils::TreeView
|
class QmlProfilerStatisticsRelativesView : public Utils::TreeView
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit QmlProfilerStatisticsRelativesView(QmlProfilerStatisticsRelativesModel *model,
|
explicit QmlProfilerStatisticsRelativesView(QmlProfilerStatisticsRelativesModel *model);
|
||||||
QWidget *parent);
|
|
||||||
~QmlProfilerStatisticsRelativesView();
|
~QmlProfilerStatisticsRelativesView();
|
||||||
|
|
||||||
void displayType(int typeIndex);
|
void displayType(int typeIndex);
|
||||||
@@ -163,8 +172,7 @@ private:
|
|||||||
void updateHeader();
|
void updateHeader();
|
||||||
QStandardItemModel *treeModel();
|
QStandardItemModel *treeModel();
|
||||||
|
|
||||||
class QmlProfilerStatisticsRelativesViewPrivate;
|
std::unique_ptr<QmlProfilerStatisticsRelativesModel> m_model;
|
||||||
QmlProfilerStatisticsRelativesViewPrivate *d;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
Reference in New Issue
Block a user