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:
Ulf Hermann
2018-03-23 09:28:57 +01:00
parent 86b78bde5d
commit f94e048c2f
4 changed files with 219 additions and 258 deletions

View File

@@ -32,58 +32,35 @@
#include <QHash>
#include <QSet>
#include <QString>
#include <QPointer>
#include <functional>
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
{
const QmlEventStats &global = d->data[-1];
const QmlEventStats &stats = d->data[typeId];
const QmlEventStats &global = m_data[-1];
const QmlEventStats &stats = m_data[typeId];
return double(stats.duration - stats.durationRecursive) / double(global.duration) * 100l;
}
double QmlProfilerStatisticsModel::durationSelfPercent(int typeId) const
{
const QmlEventStats &global = d->data[-1];
const QmlEventStats &stats = d->data[typeId];
const QmlEventStats &global = m_data[-1];
const QmlEventStats &stats = m_data[typeId];
return double(stats.durationSelf) / double(global.duration) * 100l;
}
QmlProfilerStatisticsModel::QmlProfilerStatisticsModel(QmlProfilerModelManager *modelManager,
QObject *parent) :
QObject(parent), d(new QmlProfilerStatisticsModelPrivate)
QmlProfilerStatisticsModel::QmlProfilerStatisticsModel(QmlProfilerModelManager *modelManager)
: m_modelManager(modelManager)
{
d->modelManager = modelManager;
connect(modelManager, &QmlProfilerModelManager::stateChanged,
this, &QmlProfilerStatisticsModel::dataChanged);
connect(modelManager->notesModel(), &Timeline::TimelineNotesModel::changed,
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,
[this](const QmlEvent &event, const QmlEventType &type) {
@@ -93,11 +70,6 @@ QmlProfilerStatisticsModel::QmlProfilerStatisticsModel(QmlProfilerModelManager *
});
}
QmlProfilerStatisticsModel::~QmlProfilerStatisticsModel()
{
delete d;
}
void QmlProfilerStatisticsModel::restrictToFeatures(quint64 features)
{
bool didChange = false;
@@ -106,25 +78,25 @@ void QmlProfilerStatisticsModel::restrictToFeatures(quint64 features)
quint64 featureFlag = 1ULL << featureFromRangeType(type);
if (Constants::QML_JS_RANGE_FEATURES & featureFlag) {
bool accepted = features & featureFlag;
if (accepted && !d->acceptedTypes.contains(type)) {
d->acceptedTypes << type;
if (accepted && !m_acceptedTypes.contains(type)) {
m_acceptedTypes << type;
didChange = true;
} else if (!accepted && d->acceptedTypes.contains(type)) {
d->acceptedTypes.removeOne(type);
} else if (!accepted && m_acceptedTypes.contains(type)) {
m_acceptedTypes.removeOne(type);
didChange = true;
}
}
}
if (!didChange || d->modelManager->state() != QmlProfilerModelManager::Done)
if (!didChange || m_modelManager->state() != QmlProfilerModelManager::Done)
return;
clear();
if (!d->modelManager->replayEvents(d->modelManager->traceTime()->startTime(),
d->modelManager->traceTime()->endTime(),
if (!m_modelManager->replayEvents(m_modelManager->traceTime()->startTime(),
m_modelManager->traceTime()->endTime(),
std::bind(&QmlProfilerStatisticsModel::loadEvent,
this, std::placeholders::_1,
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();
} else {
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
{
return d->data;
return m_data;
}
const QVector<QmlEventType> &QmlProfilerStatisticsModel::getTypes() const
{
return d->modelManager->eventTypes();
return m_modelManager->eventTypes();
}
const QHash<int, QString> &QmlProfilerStatisticsModel::getNotes() const
{
return d->notes;
return m_notes;
}
void QmlProfilerStatisticsModel::clear()
{
d->data.clear();
d->notes.clear();
d->callStack.clear();
d->compileStack.clear();
d->durations.clear();
if (!d->childrenModel.isNull())
d->childrenModel->clear();
if (!d->parentsModel.isNull())
d->parentsModel->clear();
m_data.clear();
m_notes.clear();
m_callStack.clear();
m_compileStack.clear();
m_durations.clear();
if (!m_calleesModel.isNull())
m_calleesModel->clear();
if (!m_callersModel.isNull())
m_callersModel->clear();
}
void QmlProfilerStatisticsModel::setRelativesModel(QmlProfilerStatisticsRelativesModel *relative,
QmlProfilerStatisticsRelation relation)
{
if (relation == QmlProfilerStatisticsParents)
d->parentsModel = relative;
m_callersModel = relative;
else
d->childrenModel = relative;
m_calleesModel = relative;
}
QmlProfilerModelManager *QmlProfilerStatisticsModel::modelManager() const
{
return d->modelManager;
return m_modelManager;
}
void QmlProfilerStatisticsModel::dataChanged()
{
if (d->modelManager->state() == QmlProfilerModelManager::ClearingData)
if (m_modelManager->state() == QmlProfilerModelManager::ClearingData)
clear();
}
void QmlProfilerStatisticsModel::notesChanged(int typeIndex)
{
const QmlProfilerNotesModel *notesModel = d->modelManager->notesModel();
const QmlProfilerNotesModel *notesModel = m_modelManager->notesModel();
if (typeIndex == -1) {
d->notes.clear();
m_notes.clear();
for (int noteId = 0; noteId < notesModel->count(); ++noteId) {
int noteType = notesModel->typeId(noteId);
if (noteType != -1) {
QString &note = d->notes[noteType];
QString &note = m_notes[noteType];
if (note.isEmpty()) {
note = notesModel->text(noteId);
} else {
@@ -197,7 +174,7 @@ void QmlProfilerStatisticsModel::notesChanged(int typeIndex)
}
}
} else {
d->notes.remove(typeIndex);
m_notes.remove(typeIndex);
const QVariantList changedNotes = notesModel->byTypeId(typeIndex);
if (!changedNotes.isEmpty()) {
QStringList newNotes;
@@ -205,7 +182,7 @@ void QmlProfilerStatisticsModel::notesChanged(int typeIndex)
++it) {
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)
{
if (!d->acceptedTypes.contains(type.rangeType()))
if (!m_acceptedTypes.contains(type.rangeType()))
return;
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()) {
case RangeStart:
stack.push(event);
@@ -227,7 +204,7 @@ void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEvent
// update stats
QTC_ASSERT(!stack.isEmpty(), 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();
stats->duration += duration;
stats->durationSelf += duration;
@@ -237,7 +214,7 @@ void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEvent
stats->maxTime = duration;
stats->calls++;
// for median computing
d->durations[event.typeIndex()].append(duration);
m_durations[event.typeIndex()].append(duration);
stack.pop();
// recursion detection: check whether event was already in stack
@@ -250,27 +227,27 @@ void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEvent
}
if (!stack.isEmpty())
d->data[stack.top().typeIndex()].durationSelf -= duration;
m_data[stack.top().typeIndex()].durationSelf -= duration;
else
d->data[-1].duration += duration;
m_data[-1].duration += duration;
break;
}
default:
return;
}
if (!d->childrenModel.isNull())
d->childrenModel->loadEvent(type.rangeType(), event, isRecursive);
if (!d->parentsModel.isNull())
d->parentsModel->loadEvent(type.rangeType(), event, isRecursive);
if (!m_calleesModel.isNull())
m_calleesModel->loadEvent(type.rangeType(), event, isRecursive);
if (!m_callersModel.isNull())
m_callersModel->loadEvent(type.rangeType(), event, isRecursive);
}
void QmlProfilerStatisticsModel::finalize()
{
// post-process: calc mean time, median time, percentoftime
for (QHash<int, QmlEventStats>::iterator it = d->data.begin(); it != d->data.end(); ++it) {
QVector<qint64> eventDurations = d->durations[it.key()];
for (QHash<int, QmlEventStats>::iterator it = m_data.begin(); it != m_data.end(); ++it) {
QVector<qint64> eventDurations = m_durations[it.key()];
if (!eventDurations.isEmpty()) {
Utils::sort(eventDurations);
it->medianTime = eventDurations.at(eventDurations.count()/2);
@@ -278,7 +255,7 @@ void QmlProfilerStatisticsModel::finalize()
}
// insert root event
QmlEventStats &rootEvent = d->data[-1];
QmlEventStats &rootEvent = m_data[-1];
rootEvent.minTime = rootEvent.maxTime = rootEvent.medianTime = rootEvent.duration;
rootEvent.durationSelf = 0;
rootEvent.calls = 1;
@@ -288,17 +265,16 @@ void QmlProfilerStatisticsModel::finalize()
int QmlProfilerStatisticsModel::count() const
{
return d->data.count();
return m_data.count();
}
QmlProfilerStatisticsRelativesModel::QmlProfilerStatisticsRelativesModel(
QmlProfilerModelManager *modelManager, QmlProfilerStatisticsModel *statisticsModel,
QmlProfilerStatisticsRelation relation, QObject *parent) :
QObject(parent), m_relation(relation)
QmlProfilerModelManager *modelManager,
QmlProfilerStatisticsModel *statisticsModel,
QmlProfilerStatisticsRelation relation) :
m_modelManager(modelManager), m_relation(relation)
{
QTC_CHECK(modelManager);
m_modelManager = modelManager;
QTC_CHECK(statisticsModel);
statisticsModel->setRelativesModel(this, relation);

View File

@@ -34,6 +34,7 @@
#include <QStack>
#include <QVector>
#include <QObject>
#include <QPointer>
namespace QmlProfiler {
class QmlProfilerModelManager;
@@ -49,24 +50,23 @@ class QmlProfilerStatisticsModel : public QObject
Q_OBJECT
public:
struct QmlEventStats {
QmlEventStats() : duration(0), durationSelf(0), durationRecursive(0), calls(0),
minTime(std::numeric_limits<qint64>::max()), maxTime(0), medianTime(0) {}
qint64 duration;
qint64 durationSelf;
qint64 durationRecursive;
qint64 calls;
qint64 minTime;
qint64 maxTime;
qint64 medianTime;
qint64 duration = 0;
qint64 durationSelf = 0;
qint64 durationRecursive = 0;
qint64 calls = 0;
qint64 minTime = std::numeric_limits<qint64>::max();
qint64 maxTime = 0;
qint64 medianTime = 0;
};
double durationPercent(int typeId) const;
double durationSelfPercent(int typeId) const;
QmlProfilerStatisticsModel(QmlProfilerModelManager *modelManager, QObject *parent = 0);
~QmlProfilerStatisticsModel();
QmlProfilerStatisticsModel(QmlProfilerModelManager *modelManager);
~QmlProfilerStatisticsModel() override = default;
void restrictToFeatures(quint64 features);
bool isRestrictedToRange() const;
const QHash<int, QmlEventStats> &getData() const;
const QVector<QmlEventType> &getTypes() const;
@@ -90,8 +90,18 @@ private:
void dataChanged();
void notesChanged(int typeIndex);
class QmlProfilerStatisticsModelPrivate;
QmlProfilerStatisticsModelPrivate *d;
QHash<int, QmlEventStats> m_data;
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
@@ -100,16 +110,15 @@ class QmlProfilerStatisticsRelativesModel : public QObject
public:
struct QmlStatisticsRelativesData {
qint64 duration;
qint64 calls;
bool isRecursive;
qint64 duration = 0;
qint64 calls = 0;
bool isRecursive = false;
};
typedef QHash <int, QmlStatisticsRelativesData> QmlStatisticsRelativesMap;
QmlProfilerStatisticsRelativesModel(QmlProfilerModelManager *modelManager,
QmlProfilerStatisticsModel *statisticsModel,
QmlProfilerStatisticsRelation relation,
QObject *parent = 0);
QmlProfilerStatisticsRelation relation);
int count() const;
void clear();
@@ -125,12 +134,12 @@ signals:
void dataAvailable();
protected:
QHash <int, QmlStatisticsRelativesMap> m_data;
QmlProfilerModelManager *m_modelManager;
QHash<int, QmlStatisticsRelativesMap> m_data;
QPointer<QmlProfilerModelManager> m_modelManager;
struct Frame {
qint64 startTime;
int typeId;
qint64 startTime = 0;
int typeId = -1;
};
QStack<Frame> m_callStack;
QStack<Frame> m_compileStack;

View File

@@ -64,15 +64,14 @@ struct SortPreserver {
view->sortByColumn(column, order);
}
int column;
Qt::SortOrder order;
Utils::TreeView *view;
int column = DEFAULT_SORT_COLUMN;
Qt::SortOrder order = Qt::DescendingOrder;
Utils::TreeView *view = nullptr;
};
struct Colors {
Colors () : noteBackground(QColor("orange")), defaultBackground(QColor("white")) {}
QColor noteBackground;
QColor defaultBackground;
QColor noteBackground = QColor("orange");
QColor defaultBackground = QColor("white");
};
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)
{
view->setFrameStyle(QFrame::NoFrame);
@@ -195,38 +184,35 @@ static void getSourceLocation(QStandardItem *infoItem,
QmlProfilerStatisticsView::QmlProfilerStatisticsView(QmlProfilerModelManager *profilerModelManager,
QWidget *parent)
: QmlProfilerEventsView(parent), d(new QmlProfilerStatisticsViewPrivate)
: QmlProfilerEventsView(parent)
{
setObjectName(QLatin1String("QmlProfiler.Statistics.Dock"));
setWindowTitle(tr("Statistics"));
d->model = new QmlProfilerStatisticsModel(profilerModelManager, this);
d->m_statsTree = new QmlProfilerStatisticsMainView(this, d->model);
connect(d->m_statsTree, &QmlProfilerStatisticsMainView::gotoSourceLocation,
QmlProfilerStatisticsModel *model = new QmlProfilerStatisticsModel(profilerModelManager);
m_mainView.reset(new QmlProfilerStatisticsMainView(model));
connect(m_mainView.get(), &QmlProfilerStatisticsMainView::gotoSourceLocation,
this, &QmlProfilerStatisticsView::gotoSourceLocation);
connect(d->m_statsTree, &QmlProfilerStatisticsMainView::typeSelected,
connect(m_mainView.get(), &QmlProfilerStatisticsMainView::typeSelected,
this, &QmlProfilerStatisticsView::typeSelected);
d->m_statsChildren = new QmlProfilerStatisticsRelativesView(
new QmlProfilerStatisticsRelativesModel(profilerModelManager, d->model,
QmlProfilerStatisticsChilden, this),
this);
d->m_statsParents = new QmlProfilerStatisticsRelativesView(
new QmlProfilerStatisticsRelativesModel(profilerModelManager, d->model,
QmlProfilerStatisticsParents, this),
this);
connect(d->m_statsTree, &QmlProfilerStatisticsMainView::typeSelected,
d->m_statsChildren, &QmlProfilerStatisticsRelativesView::displayType);
connect(d->m_statsTree, &QmlProfilerStatisticsMainView::typeSelected,
d->m_statsParents, &QmlProfilerStatisticsRelativesView::displayType);
connect(d->m_statsChildren, &QmlProfilerStatisticsRelativesView::typeClicked,
d->m_statsTree, &QmlProfilerStatisticsMainView::selectType);
connect(d->m_statsParents, &QmlProfilerStatisticsRelativesView::typeClicked,
d->m_statsTree, &QmlProfilerStatisticsMainView::selectType);
connect(d->m_statsChildren, &QmlProfilerStatisticsRelativesView::gotoSourceLocation,
m_calleesView.reset(new QmlProfilerStatisticsRelativesView(
new QmlProfilerStatisticsRelativesModel(profilerModelManager, model,
QmlProfilerStatisticsChilden)));
m_callersView.reset(new QmlProfilerStatisticsRelativesView(
new QmlProfilerStatisticsRelativesModel(profilerModelManager, model,
QmlProfilerStatisticsParents)));
connect(m_mainView.get(), &QmlProfilerStatisticsMainView::typeSelected,
m_calleesView.get(), &QmlProfilerStatisticsRelativesView::displayType);
connect(m_mainView.get(), &QmlProfilerStatisticsMainView::typeSelected,
m_callersView.get(), &QmlProfilerStatisticsRelativesView::displayType);
connect(m_calleesView.get(), &QmlProfilerStatisticsRelativesView::typeClicked,
m_mainView.get(), &QmlProfilerStatisticsMainView::selectType);
connect(m_callersView.get(), &QmlProfilerStatisticsRelativesView::typeClicked,
m_mainView.get(), &QmlProfilerStatisticsMainView::selectType);
connect(m_calleesView.get(), &QmlProfilerStatisticsRelativesView::gotoSourceLocation,
this, &QmlProfilerStatisticsView::gotoSourceLocation);
connect(d->m_statsParents, &QmlProfilerStatisticsRelativesView::gotoSourceLocation,
connect(m_callersView.get(), &QmlProfilerStatisticsRelativesView::gotoSourceLocation,
this, &QmlProfilerStatisticsView::gotoSourceLocation);
// widget arrangement
@@ -235,10 +221,10 @@ QmlProfilerStatisticsView::QmlProfilerStatisticsView(QmlProfilerModelManager *pr
groupLayout->setSpacing(0);
Core::MiniSplitter *splitterVertical = new Core::MiniSplitter;
splitterVertical->addWidget(d->m_statsTree);
splitterVertical->addWidget(m_mainView.get());
Core::MiniSplitter *splitterHorizontal = new Core::MiniSplitter;
splitterHorizontal->addWidget(d->m_statsParents);
splitterHorizontal->addWidget(d->m_statsChildren);
splitterHorizontal->addWidget(m_callersView.get());
splitterHorizontal->addWidget(m_calleesView.get());
splitterHorizontal->setOrientation(Qt::Horizontal);
splitterVertical->addWidget(splitterHorizontal);
splitterVertical->setOrientation(Qt::Vertical);
@@ -248,17 +234,11 @@ QmlProfilerStatisticsView::QmlProfilerStatisticsView(QmlProfilerModelManager *pr
setLayout(groupLayout);
}
QmlProfilerStatisticsView::~QmlProfilerStatisticsView()
{
delete d->model;
delete d;
}
void QmlProfilerStatisticsView::clear()
{
d->m_statsTree->clear();
d->m_statsChildren->clear();
d->m_statsParents->clear();
m_mainView->clear();
m_calleesView->clear();
m_callersView->clear();
}
QString QmlProfilerStatisticsView::summary(const QVector<int> &typeIds) const
@@ -269,7 +249,7 @@ QString QmlProfilerStatisticsView::summary(const QVector<int> &typeIds) const
double sum = 0;
for (int typeId : typeIds) {
const double percentage = d->model->durationPercent(typeId);
const double percentage = m_mainView->durationPercent(typeId);
if (percentage > maximum)
maximum = percentage;
sum += percentage;
@@ -292,7 +272,7 @@ QString QmlProfilerStatisticsView::summary(const QVector<int> &typeIds) 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 int maxColumnWidth = 32;
@@ -304,13 +284,13 @@ QStringList QmlProfilerStatisticsView::details(int typeId) const
return QStringList({
QmlProfilerStatisticsMainView::nameForType(type.rangeType()),
data,
QString::number(d->model->durationPercent(typeId), 'f', 2) + QLatin1Char('%')
QString::number(m_mainView->durationPercent(typeId), 'f', 2) + QLatin1Char('%')
});
}
QModelIndex QmlProfilerStatisticsView::selectedModelIndex() const
{
return d->m_statsTree->selectedModelIndex();
return m_mainView->selectedModelIndex();
}
void QmlProfilerStatisticsView::contextMenuEvent(QContextMenuEvent *ev)
@@ -340,7 +320,7 @@ void QmlProfilerStatisticsView::contextMenuEvent(QContextMenuEvent *ev)
menu.addSeparator();
getGlobalStatsAction = menu.addAction(tr("Show Full Range"));
if (!d->model->modelManager()->isRestrictedToRange())
if (!m_mainView->isRestrictedToRange())
getGlobalStatsAction->setEnabled(false);
QAction *selectedAction = menu.exec(position);
@@ -359,74 +339,57 @@ void QmlProfilerStatisticsView::contextMenuEvent(QContextMenuEvent *ev)
bool QmlProfilerStatisticsView::mouseOnTable(const QPoint &position) const
{
QPoint tableTopLeft = d->m_statsTree->mapToGlobal(QPoint(0,0));
QPoint tableBottomRight = d->m_statsTree->mapToGlobal(QPoint(d->m_statsTree->width(), d->m_statsTree->height()));
QPoint tableTopLeft = m_mainView->mapToGlobal(QPoint(0,0));
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());
}
void QmlProfilerStatisticsView::copyTableToClipboard() const
{
d->m_statsTree->copyTableToClipboard();
m_mainView->copyTableToClipboard();
}
void QmlProfilerStatisticsView::copyRowToClipboard() const
{
d->m_statsTree->copyRowToClipboard();
m_mainView->copyRowToClipboard();
}
void QmlProfilerStatisticsView::selectByTypeId(int typeIndex)
{
if (d->m_statsTree->selectedTypeId() != typeIndex)
d->m_statsTree->selectType(typeIndex);
if (m_mainView->selectedTypeId() != typeIndex)
m_mainView->selectType(typeIndex);
}
void QmlProfilerStatisticsView::onVisibleFeaturesChanged(quint64 features)
{
d->model->restrictToFeatures(features);
m_mainView->restrictToFeatures(features);
}
void QmlProfilerStatisticsView::setShowExtendedStatistics(bool show)
{
d->m_statsTree->setShowExtendedStatistics(show);
m_mainView->setShowExtendedStatistics(show);
}
bool QmlProfilerStatisticsView::showExtendedStatistics() const
{
return d->m_statsTree->showExtendedStatistics();
return m_mainView->showExtendedStatistics();
}
class QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainViewPrivate
{
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))
QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainView(QmlProfilerStatisticsModel *model) :
m_model(model)
{
setViewDefaults(this);
setObjectName(QLatin1String("QmlProfilerEventsTable"));
d->m_model = new QStandardItemModel(this);
d->m_model->setSortRole(SortRole);
setModel(d->m_model);
m_standardItemModel.reset(new QStandardItemModel);
m_standardItemModel->setSortRole(SortRole);
setModel(m_standardItemModel.get());
connect(this, &QAbstractItemView::activated, this, &QmlProfilerStatisticsMainView::jumpToItem);
d->model = model;
connect(d->model, &QmlProfilerStatisticsModel::dataAvailable,
connect(m_model.get(), &QmlProfilerStatisticsModel::dataAvailable,
this, &QmlProfilerStatisticsMainView::buildModel);
connect(d->model, &QmlProfilerStatisticsModel::notesAvailable,
connect(m_model.get(), &QmlProfilerStatisticsModel::notesAvailable,
this, &QmlProfilerStatisticsMainView::updateNotes);
d->m_showExtendedStatistics = false;
setSortingEnabled(true);
sortByColumn(DEFAULT_SORT_COLUMN, Qt::DescendingOrder);
@@ -437,20 +400,20 @@ QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainView(
QmlProfilerStatisticsMainView::~QmlProfilerStatisticsMainView()
{
clear();
delete d->m_model;
delete d;
}
void QmlProfilerStatisticsMainView::setHeaderLabels()
{
for (int i = 0; i < MaxMainField; ++i)
d->m_model->setHeaderData(i, Qt::Horizontal, displayHeader(static_cast<MainField>(i)));
for (int i = 0; i < MaxMainField; ++i) {
m_standardItemModel->setHeaderData(i, Qt::Horizontal,
displayHeader(static_cast<MainField>(i)));
}
}
void QmlProfilerStatisticsMainView::setShowExtendedStatistics(bool show)
{
// Not checking if already set because we don't want the first call to skip
d->m_showExtendedStatistics = show;
m_showExtendedStatistics = show;
if (show) {
showColumn(MainMedianTime);
showColumn(MainMaxTime);
@@ -464,14 +427,14 @@ void QmlProfilerStatisticsMainView::setShowExtendedStatistics(bool show)
bool QmlProfilerStatisticsMainView::showExtendedStatistics() const
{
return d->m_showExtendedStatistics;
return m_showExtendedStatistics;
}
void QmlProfilerStatisticsMainView::clear()
{
SortPreserver sorter(this);
d->m_model->clear();
d->m_model->setColumnCount(MaxMainField);
m_standardItemModel->clear();
m_standardItemModel->setColumnCount(MaxMainField);
setHeaderLabels();
}
@@ -482,7 +445,7 @@ void QmlProfilerStatisticsMainView::buildModel()
{
SortPreserver sorter(this);
parseModel();
setShowExtendedStatistics(d->m_showExtendedStatistics);
setShowExtendedStatistics(m_showExtendedStatistics);
setRootIsDecorated(false);
}
@@ -492,9 +455,9 @@ void QmlProfilerStatisticsMainView::buildModel()
void QmlProfilerStatisticsMainView::updateNotes(int typeIndex)
{
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &eventList = d->model->getData();
const QHash<int, QString> &noteList = d->model->getNotes();
QStandardItem *parentItem = d->m_model->invisibleRootItem();
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &eventList = m_model->getData();
const QHash<int, QString> &noteList = m_model->getNotes();
QStandardItem *parentItem = m_standardItemModel->invisibleRootItem();
for (int rowIndex = 0; rowIndex < parentItem->rowCount(); ++rowIndex) {
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()
{
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &eventList = d->model->getData();
const QVector<QmlEventType> &typeList = d->model->getTypes();
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &eventList = m_model->getData();
const QVector<QmlEventType> &typeList = m_model->getTypes();
QHash<int, QmlProfilerStatisticsModel::QmlEventStats>::ConstIterator it;
for (it = eventList.constBegin(); it != eventList.constEnd(); ++it) {
int typeIndex = it.key();
const QmlProfilerStatisticsModel::QmlEventStats &stats = it.value();
const QmlEventType &type = (typeIndex != -1 ? typeList[typeIndex] : *rootEventType());
QStandardItem *parentItem = d->m_model->invisibleRootItem();
QStandardItem *parentItem = m_standardItemModel->invisibleRootItem();
QList<QStandardItem *> newRow;
newRow << new StatisticsViewItem(
@@ -540,7 +523,7 @@ void QmlProfilerStatisticsMainView::parseModel()
QString typeString = QmlProfilerStatisticsMainView::nameForType(type.rangeType());
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)
+ QLatin1String(" %"), percent);
@@ -548,7 +531,7 @@ void QmlProfilerStatisticsMainView::parseModel()
Timeline::formatTime(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)
+ QLatin1String(" %"), percentSelf);
@@ -592,12 +575,11 @@ void QmlProfilerStatisticsMainView::parseModel()
QStandardItem *QmlProfilerStatisticsMainView::itemFromIndex(const QModelIndex &index) const
{
QStandardItem *indexItem = d->m_model->itemFromIndex(index);
QStandardItem *indexItem = m_standardItemModel->itemFromIndex(index);
if (indexItem->parent())
return indexItem->parent()->child(indexItem->row());
else
return d->m_model->item(index.row());
return m_standardItemModel->item(index.row());
}
QString QmlProfilerStatisticsMainView::nameForType(RangeType typeNumber)
@@ -618,7 +600,7 @@ int QmlProfilerStatisticsMainView::selectedTypeId() const
QModelIndex index = selectedModelIndex();
if (!index.isValid())
return -1;
QStandardItem *item = d->m_model->item(index.row());
QStandardItem *item = m_standardItemModel->item(index.row());
return item->data(TypeIdRole).toInt();
}
@@ -638,7 +620,7 @@ void QmlProfilerStatisticsMainView::jumpToItem(const QModelIndex &index)
void QmlProfilerStatisticsMainView::selectItem(const QStandardItem *item)
{
// 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()) {
setCurrentIndex(index);
@@ -649,8 +631,8 @@ void QmlProfilerStatisticsMainView::selectItem(const QStandardItem *item)
void QmlProfilerStatisticsMainView::selectType(int typeIndex)
{
for (int i=0; i<d->m_model->rowCount(); i++) {
QStandardItem *infoItem = d->m_model->item(i);
for (int i = 0; i < m_standardItemModel->rowCount(); i++) {
QStandardItem *infoItem = m_standardItemModel->item(i);
if (infoItem->data(TypeIdRole).toInt() == typeIndex) {
selectItem(infoItem);
return;
@@ -667,16 +649,15 @@ QModelIndex QmlProfilerStatisticsMainView::selectedModelIndex() const
return sel.first();
}
QString QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainViewPrivate::textForItem(
QStandardItem *item) const
QString QmlProfilerStatisticsMainView::textForItem(QStandardItem *item) const
{
QString str;
// item's data
int colCount = m_model->columnCount();
int colCount = m_standardItemModel->columnCount();
for (int j = 0; j < colCount; ++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();
if (j < colCount-1) str += QLatin1Char('\t');
}
@@ -689,18 +670,18 @@ void QmlProfilerStatisticsMainView::copyTableToClipboard() const
{
QString str;
// headers
int columnCount = d->m_model->columnCount();
int columnCount = m_standardItemModel->columnCount();
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)
str += QLatin1Char('\t');
else
str += QLatin1Char('\n');
}
// data
int rowCount = d->m_model->rowCount();
int rowCount = m_standardItemModel->rowCount();
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();
clipboard->setText(str, QClipboard::Selection);
@@ -709,29 +690,17 @@ void QmlProfilerStatisticsMainView::copyTableToClipboard() 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();
clipboard->setText(str, QClipboard::Selection);
clipboard->setText(str, QClipboard::Clipboard);
}
class QmlProfilerStatisticsRelativesView::QmlProfilerStatisticsRelativesViewPrivate
{
public:
QmlProfilerStatisticsRelativesViewPrivate(QmlProfilerStatisticsRelativesView *qq):q(qq) {}
~QmlProfilerStatisticsRelativesViewPrivate() {}
QmlProfilerStatisticsRelativesModel *model;
QmlProfilerStatisticsRelativesView *q;
};
QmlProfilerStatisticsRelativesView::QmlProfilerStatisticsRelativesView(
QmlProfilerStatisticsRelativesModel *model, QWidget *parent) :
Utils::TreeView(parent), d(new QmlProfilerStatisticsRelativesViewPrivate(this))
QmlProfilerStatisticsRelativesModel *model) :
m_model(model)
{
setViewDefaults(this);
d->model = model;
QStandardItemModel *itemModel = new QStandardItemModel(this);
itemModel->setSortRole(SortRole);
setModel(itemModel);
@@ -745,19 +714,18 @@ QmlProfilerStatisticsRelativesView::QmlProfilerStatisticsRelativesView(
this, &QmlProfilerStatisticsRelativesView::jumpToItem);
// 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);
}
QmlProfilerStatisticsRelativesView::~QmlProfilerStatisticsRelativesView()
{
delete d;
}
void QmlProfilerStatisticsRelativesView::displayType(int typeIndex)
{
SortPreserver sorter(this);
rebuildTree(d->model->getData(typeIndex));
rebuildTree(m_model->getData(typeIndex));
updateHeader();
resizeColumnToContents(RelativeLocation);
@@ -770,7 +738,7 @@ void QmlProfilerStatisticsRelativesView::rebuildTree(
treeModel()->clear();
QStandardItem *topLevelItem = treeModel()->invisibleRootItem();
const QVector<QmlEventType> &typeList = d->model->getTypes();
const QVector<QmlEventType> &typeList = m_model->getTypes();
QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesMap::const_iterator it;
for (it = map.constBegin(); it != map.constEnd(); ++it) {
@@ -825,7 +793,7 @@ void QmlProfilerStatisticsRelativesView::clear()
void QmlProfilerStatisticsRelativesView::updateHeader()
{
const QmlProfilerStatisticsRelation relation = d->model->relation();
const QmlProfilerStatisticsRelation relation = m_model->relation();
if (QStandardItemModel *model = treeModel()) {
model->setColumnCount(MaxRelativeField);
for (int i = 0; i < MaxRelativeField; ++i) {

View File

@@ -33,6 +33,7 @@
#include <debugger/analyzer/analyzermanager.h>
#include <utils/itemviews.h>
#include <QPointer>
#include <QStandardItemModel>
namespace QmlProfiler {
@@ -80,7 +81,7 @@ class QmlProfilerStatisticsView : public QmlProfilerEventsView
public:
explicit QmlProfilerStatisticsView(QmlProfilerModelManager *profilerModelManager,
QWidget *parent = nullptr);
~QmlProfilerStatisticsView();
~QmlProfilerStatisticsView() override = default;
void clear() override;
QString summary(const QVector<int> &typeIds) const;
@@ -100,15 +101,16 @@ private:
void setShowExtendedStatistics(bool show);
bool showExtendedStatistics() const;
class QmlProfilerStatisticsViewPrivate;
QmlProfilerStatisticsViewPrivate *d;
std::unique_ptr<QmlProfilerStatisticsMainView> m_mainView;
std::unique_ptr<QmlProfilerStatisticsRelativesView> m_calleesView;
std::unique_ptr<QmlProfilerStatisticsRelativesView> m_callersView;
};
class QmlProfilerStatisticsMainView : public Utils::TreeView
{
Q_OBJECT
public:
explicit QmlProfilerStatisticsMainView(QWidget *parent, QmlProfilerStatisticsModel *model);
explicit QmlProfilerStatisticsMainView(QmlProfilerStatisticsModel *model);
~QmlProfilerStatisticsMainView();
QModelIndex selectedModelIndex() const;
@@ -128,6 +130,12 @@ public:
void buildModel();
void updateNotes(int typeIndex);
void restrictToFeatures(quint64 features);
bool isRestrictedToRange() const;
double durationPercent(int typeId) const;
const QmlEventType &getType(int typeId) const;
signals:
void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
void typeSelected(int typeIndex);
@@ -137,17 +145,18 @@ private:
void setHeaderLabels();
void parseModel();
QStandardItem *itemFromIndex(const QModelIndex &index) const;
QString textForItem(QStandardItem *item) const;
class QmlProfilerStatisticsMainViewPrivate;
QmlProfilerStatisticsMainViewPrivate *d;
std::unique_ptr<QmlProfilerStatisticsModel> m_model;
std::unique_ptr<QStandardItemModel> m_standardItemModel;
bool m_showExtendedStatistics = false;
};
class QmlProfilerStatisticsRelativesView : public Utils::TreeView
{
Q_OBJECT
public:
explicit QmlProfilerStatisticsRelativesView(QmlProfilerStatisticsRelativesModel *model,
QWidget *parent);
explicit QmlProfilerStatisticsRelativesView(QmlProfilerStatisticsRelativesModel *model);
~QmlProfilerStatisticsRelativesView();
void displayType(int typeIndex);
@@ -163,8 +172,7 @@ private:
void updateHeader();
QStandardItemModel *treeModel();
class QmlProfilerStatisticsRelativesViewPrivate;
QmlProfilerStatisticsRelativesViewPrivate *d;
std::unique_ptr<QmlProfilerStatisticsRelativesModel> m_model;
};
} // namespace Internal