forked from qt-creator/qt-creator
QmlProfiler: Eliminate QStandardItemModel from statistics
This resolves the data duplication between model manager and statistics models, that gets in the way of updating the details strings on the fly. Task-number: QTCREATORBUG-20106 Change-Id: I1c4881f903402dff936267de03b84d05ab7c39ca Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
@@ -33,7 +33,6 @@
|
||||
|
||||
#include <QUrl>
|
||||
#include <QHash>
|
||||
#include <QStandardItem>
|
||||
#include <QHeaderView>
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
@@ -41,6 +40,7 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QMenu>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
#include <functional>
|
||||
|
||||
@@ -49,64 +49,6 @@ namespace Internal {
|
||||
|
||||
const int DEFAULT_SORT_COLUMN = MainTimeInPercent;
|
||||
|
||||
struct SortPreserver {
|
||||
SortPreserver(Utils::TreeView *view) : view(view)
|
||||
{
|
||||
const QHeaderView *header = view->header();
|
||||
column = header->sortIndicatorSection();
|
||||
order = header->sortIndicatorOrder();
|
||||
view->setSortingEnabled(false);
|
||||
}
|
||||
|
||||
~SortPreserver()
|
||||
{
|
||||
view->setSortingEnabled(true);
|
||||
view->sortByColumn(column, order);
|
||||
}
|
||||
|
||||
int column = DEFAULT_SORT_COLUMN;
|
||||
Qt::SortOrder order = Qt::DescendingOrder;
|
||||
Utils::TreeView *view = nullptr;
|
||||
};
|
||||
|
||||
struct Colors {
|
||||
QColor noteBackground = QColor("orange");
|
||||
QColor defaultBackground = QColor("white");
|
||||
};
|
||||
|
||||
struct RootEventType : public QmlEventType {
|
||||
RootEventType() : QmlEventType(MaximumMessage, MaximumRangeType, -1,
|
||||
QmlEventLocation("<program>", 1, 1),
|
||||
QmlProfilerStatisticsMainView::tr("Main Program"),
|
||||
QmlProfilerStatisticsMainView::tr("<program>"))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(Colors, colors)
|
||||
Q_GLOBAL_STATIC(RootEventType, rootEventType)
|
||||
|
||||
class StatisticsViewItem : public QStandardItem
|
||||
{
|
||||
public:
|
||||
StatisticsViewItem(const QString &text, const QVariant &sort) : QStandardItem(text)
|
||||
{
|
||||
setData(sort, SortRole);
|
||||
}
|
||||
|
||||
virtual bool operator<(const QStandardItem &other) const
|
||||
{
|
||||
if (data(SortRole).type() == QVariant::String) {
|
||||
// Strings should be case-insensitive compared
|
||||
return data(SortRole).toString().compare(other.data(SortRole).toString(),
|
||||
Qt::CaseInsensitive) < 0;
|
||||
} else {
|
||||
// For everything else the standard comparison should be OK
|
||||
return QStandardItem::operator<(other);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void setViewDefaults(Utils::TreeView *view)
|
||||
{
|
||||
view->setFrameStyle(QFrame::NoFrame);
|
||||
@@ -116,68 +58,12 @@ static void setViewDefaults(Utils::TreeView *view)
|
||||
header->setMinimumSectionSize(50);
|
||||
}
|
||||
|
||||
static QString displayHeader(MainField header)
|
||||
{
|
||||
switch (header) {
|
||||
case MainCallCount:
|
||||
return QmlProfilerStatisticsMainView::tr("Calls");
|
||||
case MainDetails:
|
||||
return QmlProfilerStatisticsMainView::tr("Details");
|
||||
case MainLocation:
|
||||
return QmlProfilerStatisticsMainView::tr("Location");
|
||||
case MainMaxTime:
|
||||
return QmlProfilerStatisticsMainView::tr("Longest Time");
|
||||
case MainTimePerCall:
|
||||
return QmlProfilerStatisticsMainView::tr("Mean Time");
|
||||
case MainSelfTime:
|
||||
return QmlProfilerStatisticsMainView::tr("Self Time");
|
||||
case MainSelfTimeInPercent:
|
||||
return QmlProfilerStatisticsMainView::tr("Self Time in Percent");
|
||||
case MainMinTime:
|
||||
return QmlProfilerStatisticsMainView::tr("Shortest Time");
|
||||
case MainTimeInPercent:
|
||||
return QmlProfilerStatisticsMainView::tr("Time in Percent");
|
||||
case MainTotalTime:
|
||||
return QmlProfilerStatisticsMainView::tr("Total Time");
|
||||
case MainType:
|
||||
return QmlProfilerStatisticsMainView::tr("Type");
|
||||
case MainMedianTime:
|
||||
return QmlProfilerStatisticsMainView::tr("Median Time");
|
||||
case MaxMainField:
|
||||
QTC_ASSERT(false, break);
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
static QString displayHeader(RelativeField header, QmlProfilerStatisticsRelation relation)
|
||||
{
|
||||
switch (header) {
|
||||
case RelativeLocation:
|
||||
return relation == QmlProfilerStatisticsCallees
|
||||
? QmlProfilerStatisticsMainView::tr("Callee")
|
||||
: QmlProfilerStatisticsMainView::tr("Caller");
|
||||
case RelativeType:
|
||||
return displayHeader(MainType);
|
||||
case RelativeTotalTime:
|
||||
return displayHeader(MainTotalTime);
|
||||
case RelativeCallCount:
|
||||
return displayHeader(MainCallCount);
|
||||
case RelativeDetails:
|
||||
return relation == QmlProfilerStatisticsCallees
|
||||
? QmlProfilerStatisticsMainView::tr("Callee Description")
|
||||
: QmlProfilerStatisticsMainView::tr("Caller Description");
|
||||
case MaxRelativeField:
|
||||
QTC_ASSERT(false, break);
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
static void getSourceLocation(QStandardItem *infoItem,
|
||||
static void getSourceLocation(const QModelIndex &index,
|
||||
std::function<void (const QString &, int, int)> receiver)
|
||||
{
|
||||
int line = infoItem->data(LineRole).toInt();
|
||||
int column = infoItem->data(ColumnRole).toInt();
|
||||
QString fileName = infoItem->data(FilenameRole).toString();
|
||||
const int line = index.data(LineRole).toInt();
|
||||
const int column = index.data(ColumnRole).toInt();
|
||||
const QString fileName = index.data(FilenameRole).toString();
|
||||
if (line != -1 && !fileName.isEmpty())
|
||||
receiver(fileName, line, column);
|
||||
}
|
||||
@@ -234,13 +120,6 @@ QmlProfilerStatisticsView::QmlProfilerStatisticsView(QmlProfilerModelManager *pr
|
||||
setLayout(groupLayout);
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsView::clear()
|
||||
{
|
||||
m_mainView->clear();
|
||||
m_calleesView->clear();
|
||||
m_callersView->clear();
|
||||
}
|
||||
|
||||
QString QmlProfilerStatisticsView::summary(const QVector<int> &typeIds) const
|
||||
{
|
||||
return m_mainView->summary(typeIds);
|
||||
@@ -344,33 +223,30 @@ QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainView(QmlProfilerStatisti
|
||||
setViewDefaults(this);
|
||||
setObjectName(QLatin1String("QmlProfilerEventsTable"));
|
||||
|
||||
m_standardItemModel.reset(new QStandardItemModel);
|
||||
m_standardItemModel->setSortRole(SortRole);
|
||||
setModel(m_standardItemModel.get());
|
||||
connect(this, &QAbstractItemView::activated, this, &QmlProfilerStatisticsMainView::jumpToItem);
|
||||
auto sortModel = new QSortFilterProxyModel(this);
|
||||
sortModel->setSourceModel(model);
|
||||
sortModel->setSortRole(SortRole);
|
||||
sortModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
sortModel->setFilterRole(FilterRole);
|
||||
sortModel->setFilterKeyColumn(MainType);
|
||||
sortModel->setFilterFixedString("+");
|
||||
|
||||
connect(m_model.get(), &QmlProfilerStatisticsModel::dataAvailable,
|
||||
this, &QmlProfilerStatisticsMainView::buildModel);
|
||||
connect(m_model.get(), &QmlProfilerStatisticsModel::notesAvailable,
|
||||
this, &QmlProfilerStatisticsMainView::updateNotes);
|
||||
setModel(sortModel);
|
||||
|
||||
connect(this, &QAbstractItemView::activated, this, &QmlProfilerStatisticsMainView::jumpToItem);
|
||||
|
||||
setSortingEnabled(true);
|
||||
sortByColumn(DEFAULT_SORT_COLUMN, Qt::DescendingOrder);
|
||||
|
||||
buildModel();
|
||||
setShowExtendedStatistics(m_showExtendedStatistics);
|
||||
setRootIsDecorated(false);
|
||||
|
||||
resizeColumnToContents(MainLocation);
|
||||
resizeColumnToContents(MainType);
|
||||
}
|
||||
|
||||
QmlProfilerStatisticsMainView::~QmlProfilerStatisticsMainView()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsMainView::setHeaderLabels()
|
||||
{
|
||||
for (int i = 0; i < MaxMainField; ++i) {
|
||||
m_standardItemModel->setHeaderData(i, Qt::Horizontal,
|
||||
displayHeader(static_cast<MainField>(i)));
|
||||
}
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsMainView::setShowExtendedStatistics(bool show)
|
||||
@@ -393,59 +269,6 @@ bool QmlProfilerStatisticsMainView::showExtendedStatistics() const
|
||||
return m_showExtendedStatistics;
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsMainView::clear()
|
||||
{
|
||||
SortPreserver sorter(this);
|
||||
m_standardItemModel->clear();
|
||||
m_standardItemModel->setColumnCount(MaxMainField);
|
||||
setHeaderLabels();
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsMainView::buildModel()
|
||||
{
|
||||
clear();
|
||||
|
||||
{
|
||||
SortPreserver sorter(this);
|
||||
parseModel();
|
||||
setShowExtendedStatistics(m_showExtendedStatistics);
|
||||
setRootIsDecorated(false);
|
||||
}
|
||||
|
||||
resizeColumnToContents(MainLocation);
|
||||
resizeColumnToContents(MainType);
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsMainView::updateNotes(int typeIndex)
|
||||
{
|
||||
const QVector<QmlProfilerStatisticsModel::QmlEventStats> &eventList = m_model->getData();
|
||||
const QHash<int, QString> ¬eList = m_model->getNotes();
|
||||
QStandardItem *rootItem = m_standardItemModel->invisibleRootItem();
|
||||
|
||||
for (int rowIndex = 0; rowIndex < rootItem->rowCount(); ++rowIndex) {
|
||||
int rowType = rootItem->child(rowIndex)->data(TypeIdRole).toInt();
|
||||
if (rowType == -1 || (rowType != typeIndex && typeIndex != -1))
|
||||
continue;
|
||||
const QmlProfilerStatisticsModel::QmlEventStats &stats = eventList[rowType];
|
||||
|
||||
for (int columnIndex = 0; columnIndex < rootItem->columnCount(); ++columnIndex) {
|
||||
QStandardItem *item = rootItem->child(rowIndex, columnIndex);
|
||||
QHash<int, QString>::ConstIterator it = noteList.find(rowType);
|
||||
if (it != noteList.end()) {
|
||||
item->setBackground(colors()->noteBackground);
|
||||
item->setToolTip(it.value());
|
||||
} else if (stats.recursive > 0) {
|
||||
item->setBackground(colors()->noteBackground);
|
||||
item->setToolTip(tr("+%1 in recursive calls")
|
||||
.arg(Timeline::formatTime(stats.recursive)));
|
||||
} else if (!item->toolTip().isEmpty()){
|
||||
item->setBackground(colors()->defaultBackground);
|
||||
item->setToolTip(QString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsMainView::restrictToFeatures(quint64 features)
|
||||
{
|
||||
m_model->restrictToFeatures(features);
|
||||
@@ -466,132 +289,40 @@ QStringList QmlProfilerStatisticsMainView::details(int typeId) const
|
||||
return m_model->details(typeId);
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsMainView::parseModel()
|
||||
{
|
||||
const QVector<QmlProfilerStatisticsModel::QmlEventStats> &eventList = m_model->getData();
|
||||
const QVector<QmlEventType> &typeList = m_model->getTypes();
|
||||
|
||||
QmlProfilerStatisticsModel::QmlEventStats rootEventStats;
|
||||
rootEventStats.total = rootEventStats.maximum = rootEventStats.minimum = rootEventStats.median
|
||||
= m_model->rootDuration();
|
||||
rootEventStats.calls = rootEventStats.total > 0 ? 1 : 0;
|
||||
|
||||
for (int typeIndex = -1; typeIndex < eventList.size(); ++typeIndex) {
|
||||
const QmlProfilerStatisticsModel::QmlEventStats &stats = typeIndex >= 0
|
||||
? eventList[typeIndex] : rootEventStats;
|
||||
if (stats.calls == 0)
|
||||
continue;
|
||||
|
||||
const QmlEventType &type = typeIndex >= 0 ? typeList[typeIndex] : *rootEventType();
|
||||
QStandardItem *rootItem = m_standardItemModel->invisibleRootItem();
|
||||
QList<QStandardItem *> newRow;
|
||||
|
||||
newRow << new StatisticsViewItem(
|
||||
type.displayName().isEmpty() ? tr("<bytecode>") : type.displayName(),
|
||||
type.displayName());
|
||||
|
||||
QString typeString = QmlProfilerStatisticsModel::nameForType(type.rangeType());
|
||||
newRow << new StatisticsViewItem(typeString, typeString);
|
||||
|
||||
const double percent = m_model->durationPercent(typeIndex);
|
||||
newRow << new StatisticsViewItem(QString::number(percent, 'f', 2)
|
||||
+ QLatin1String(" %"), percent);
|
||||
|
||||
newRow << new StatisticsViewItem(
|
||||
Timeline::formatTime(stats.totalNonRecursive()),
|
||||
stats.totalNonRecursive());
|
||||
|
||||
const double percentSelf = m_model->durationSelfPercent(typeIndex);
|
||||
newRow << new StatisticsViewItem(QString::number(percentSelf, 'f', 2)
|
||||
+ QLatin1String(" %"), percentSelf);
|
||||
|
||||
newRow << new StatisticsViewItem(Timeline::formatTime(stats.self),
|
||||
stats.self);
|
||||
|
||||
newRow << new StatisticsViewItem(QString::number(stats.calls), stats.calls);
|
||||
|
||||
const qint64 timePerCall = stats.average();
|
||||
newRow << new StatisticsViewItem(Timeline::formatTime(timePerCall),
|
||||
timePerCall);
|
||||
|
||||
newRow << new StatisticsViewItem(Timeline::formatTime(stats.median),
|
||||
stats.median);
|
||||
|
||||
newRow << new StatisticsViewItem(Timeline::formatTime(stats.maximum),
|
||||
stats.maximum);
|
||||
|
||||
newRow << new StatisticsViewItem(Timeline::formatTime(stats.minimum),
|
||||
stats.minimum);
|
||||
|
||||
newRow << new StatisticsViewItem(type.data().isEmpty() ? tr("Source code not available")
|
||||
: type.data(), type.data());
|
||||
|
||||
// no edit
|
||||
foreach (QStandardItem *item, newRow)
|
||||
item->setEditable(false);
|
||||
|
||||
// metadata
|
||||
QStandardItem *first = newRow.at(MainLocation);
|
||||
first->setData(typeIndex, TypeIdRole);
|
||||
const QmlEventLocation location(type.location());
|
||||
first->setData(location.filename(), FilenameRole);
|
||||
first->setData(location.line(), LineRole);
|
||||
first->setData(location.column(), ColumnRole);
|
||||
|
||||
// append
|
||||
rootItem->appendRow(newRow);
|
||||
}
|
||||
}
|
||||
|
||||
QStandardItem *QmlProfilerStatisticsMainView::itemFromIndex(const QModelIndex &index) const
|
||||
{
|
||||
QStandardItem *indexItem = m_standardItemModel->itemFromIndex(index);
|
||||
if (indexItem->parent())
|
||||
return indexItem->parent()->child(indexItem->row());
|
||||
else
|
||||
return m_standardItemModel->item(index.row());
|
||||
}
|
||||
|
||||
int QmlProfilerStatisticsMainView::selectedTypeId() const
|
||||
{
|
||||
QModelIndex index = selectedModelIndex();
|
||||
if (!index.isValid())
|
||||
return -1;
|
||||
QStandardItem *item = m_standardItemModel->item(index.row());
|
||||
return item->data(TypeIdRole).toInt();
|
||||
return model()->data(selectedModelIndex(), TypeIdRole).toInt();
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsMainView::jumpToItem(const QModelIndex &index)
|
||||
{
|
||||
QStandardItem *infoItem = itemFromIndex(index);
|
||||
|
||||
// show in editor
|
||||
getSourceLocation(infoItem, [this](const QString &fileName, int line, int column) {
|
||||
getSourceLocation(index, [this](const QString &fileName, int line, int column) {
|
||||
emit gotoSourceLocation(fileName, line, column);
|
||||
});
|
||||
|
||||
// show in callers/callees subwindow
|
||||
emit typeSelected(infoItem->data(TypeIdRole).toInt());
|
||||
emit typeSelected(model()->data(index, TypeIdRole).toInt());
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsMainView::selectItem(const QStandardItem *item)
|
||||
void QmlProfilerStatisticsMainView::selectItem(const QModelIndex &index)
|
||||
{
|
||||
// If the same item is already selected, don't reselect it.
|
||||
QModelIndex index = m_standardItemModel->indexFromItem(item);
|
||||
if (index != currentIndex()) {
|
||||
setCurrentIndex(index);
|
||||
|
||||
// show in callers/callees subwindow
|
||||
emit typeSelected(itemFromIndex(index)->data(TypeIdRole).toInt());
|
||||
emit typeSelected(index.data(TypeIdRole).toInt());
|
||||
}
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsMainView::selectType(int typeIndex)
|
||||
{
|
||||
for (int i = 0; i < m_standardItemModel->rowCount(); i++) {
|
||||
QStandardItem *infoItem = m_standardItemModel->item(i);
|
||||
if (infoItem->data(TypeIdRole).toInt() == typeIndex) {
|
||||
selectItem(infoItem);
|
||||
QAbstractItemModel *itemModel = model();
|
||||
for (int i = 0; i < itemModel->rowCount(); i++) {
|
||||
QModelIndex index = itemModel->index(i, MainLocation);
|
||||
if (itemModel->data(index, TypeIdRole).toInt() == typeIndex) {
|
||||
selectItem(index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -606,16 +337,15 @@ QModelIndex QmlProfilerStatisticsMainView::selectedModelIndex() const
|
||||
return sel.first();
|
||||
}
|
||||
|
||||
QString QmlProfilerStatisticsMainView::textForItem(QStandardItem *item) const
|
||||
QString QmlProfilerStatisticsMainView::textForItem(const QModelIndex &index) const
|
||||
{
|
||||
QString str;
|
||||
|
||||
// item's data
|
||||
int colCount = m_standardItemModel->columnCount();
|
||||
const int colCount = model()->columnCount();
|
||||
for (int j = 0; j < colCount; ++j) {
|
||||
QStandardItem *colItem = item->parent() ? item->parent()->child(item->row(),j) :
|
||||
m_standardItemModel->item(item->row(),j);
|
||||
str += colItem->data(Qt::DisplayRole).toString();
|
||||
const QModelIndex cellIndex = model()->index(index.row(), j);
|
||||
str += cellIndex.data(Qt::DisplayRole).toString();
|
||||
if (j < colCount-1) str += QLatin1Char('\t');
|
||||
}
|
||||
str += QLatin1Char('\n');
|
||||
@@ -626,20 +356,24 @@ QString QmlProfilerStatisticsMainView::textForItem(QStandardItem *item) const
|
||||
void QmlProfilerStatisticsMainView::copyTableToClipboard() const
|
||||
{
|
||||
QString str;
|
||||
|
||||
const QAbstractItemModel *itemModel = model();
|
||||
|
||||
// headers
|
||||
int columnCount = m_standardItemModel->columnCount();
|
||||
const int columnCount = itemModel->columnCount();
|
||||
for (int i = 0; i < columnCount; ++i) {
|
||||
str += m_standardItemModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString();
|
||||
str += itemModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString();
|
||||
if (i < columnCount - 1)
|
||||
str += QLatin1Char('\t');
|
||||
else
|
||||
str += QLatin1Char('\n');
|
||||
}
|
||||
|
||||
// data
|
||||
int rowCount = m_standardItemModel->rowCount();
|
||||
for (int i = 0; i != rowCount; ++i) {
|
||||
str += textForItem(m_standardItemModel->item(i));
|
||||
}
|
||||
const int rowCount = itemModel->rowCount();
|
||||
for (int i = 0; i != rowCount; ++i)
|
||||
str += textForItem(itemModel->index(i, 0));
|
||||
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
clipboard->setText(str, QClipboard::Selection);
|
||||
clipboard->setText(str, QClipboard::Clipboard);
|
||||
@@ -647,7 +381,7 @@ void QmlProfilerStatisticsMainView::copyTableToClipboard() const
|
||||
|
||||
void QmlProfilerStatisticsMainView::copyRowToClipboard() const
|
||||
{
|
||||
QString str = textForItem(m_standardItemModel->itemFromIndex(selectedModelIndex()));
|
||||
QString str = textForItem(selectedModelIndex());
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
clipboard->setText(str, QClipboard::Selection);
|
||||
clipboard->setText(str, QClipboard::Clipboard);
|
||||
@@ -658,21 +392,18 @@ QmlProfilerStatisticsRelativesView::QmlProfilerStatisticsRelativesView(
|
||||
m_model(model)
|
||||
{
|
||||
setViewDefaults(this);
|
||||
QStandardItemModel *itemModel = new QStandardItemModel(this);
|
||||
itemModel->setSortRole(SortRole);
|
||||
setModel(itemModel);
|
||||
auto sortModel = new QSortFilterProxyModel(this);
|
||||
sortModel->setSourceModel(model);
|
||||
sortModel->setSortRole(SortRole);
|
||||
sortModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
setModel(sortModel);
|
||||
setRootIsDecorated(false);
|
||||
updateHeader();
|
||||
|
||||
setSortingEnabled(true);
|
||||
sortByColumn(DEFAULT_SORT_COLUMN, Qt::DescendingOrder);
|
||||
|
||||
connect(this, &QAbstractItemView::activated,
|
||||
this, &QmlProfilerStatisticsRelativesView::jumpToItem);
|
||||
|
||||
// Clear when new data available as the selection may be invalid now.
|
||||
connect(m_model.get(), &QmlProfilerStatisticsRelativesModel::dataAvailable,
|
||||
this, &QmlProfilerStatisticsRelativesView::clear);
|
||||
}
|
||||
|
||||
QmlProfilerStatisticsRelativesView::~QmlProfilerStatisticsRelativesView()
|
||||
@@ -681,100 +412,18 @@ QmlProfilerStatisticsRelativesView::~QmlProfilerStatisticsRelativesView()
|
||||
|
||||
void QmlProfilerStatisticsRelativesView::displayType(int typeIndex)
|
||||
{
|
||||
SortPreserver sorter(this);
|
||||
rebuildTree(m_model->getData(typeIndex));
|
||||
|
||||
updateHeader();
|
||||
model()->setData(QModelIndex(), typeIndex, TypeIdRole);
|
||||
resizeColumnToContents(RelativeLocation);
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsRelativesView::rebuildTree(
|
||||
const QVector<QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesData> &data)
|
||||
{
|
||||
Q_ASSERT(treeModel());
|
||||
treeModel()->clear();
|
||||
|
||||
QStandardItem *topLevelItem = treeModel()->invisibleRootItem();
|
||||
const QVector<QmlEventType> &typeList = m_model->getTypes();
|
||||
|
||||
for (auto it = data.constBegin(); it != data.constEnd(); ++it) {
|
||||
const QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesData &stats = *it;
|
||||
const QmlEventType &type = stats.typeIndex != -1 ? typeList[stats.typeIndex]
|
||||
: *rootEventType();
|
||||
QList<QStandardItem *> newRow;
|
||||
|
||||
// ToDo: here we were going to search for the data in the other model
|
||||
// maybe we should store the data in this model and get it here
|
||||
// no indirections at this level of abstraction!
|
||||
newRow << new StatisticsViewItem(
|
||||
type.displayName().isEmpty() ? tr("<bytecode>") : type.displayName(),
|
||||
type.displayName());
|
||||
const QString typeName = QmlProfilerStatisticsModel::nameForType(type.rangeType());
|
||||
newRow << new StatisticsViewItem(typeName, typeName);
|
||||
newRow << new StatisticsViewItem(Timeline::formatTime(stats.duration),
|
||||
stats.duration);
|
||||
newRow << new StatisticsViewItem(QString::number(stats.calls), stats.calls);
|
||||
newRow << new StatisticsViewItem(type.data().isEmpty() ? tr("Source code not available") :
|
||||
type.data(), type.data());
|
||||
|
||||
QStandardItem *first = newRow.at(RelativeLocation);
|
||||
first->setData(stats.typeIndex, TypeIdRole);
|
||||
const QmlEventLocation location(type.location());
|
||||
first->setData(location.filename(), FilenameRole);
|
||||
first->setData(location.line(), LineRole);
|
||||
first->setData(location.column(), ColumnRole);
|
||||
|
||||
if (stats.isRecursive) {
|
||||
foreach (QStandardItem *item, newRow) {
|
||||
item->setBackground(colors()->noteBackground);
|
||||
item->setToolTip(tr("called recursively"));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (QStandardItem *item, newRow)
|
||||
item->setEditable(false);
|
||||
|
||||
topLevelItem->appendRow(newRow);
|
||||
}
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsRelativesView::clear()
|
||||
{
|
||||
if (treeModel()) {
|
||||
SortPreserver sorter(this);
|
||||
treeModel()->clear();
|
||||
updateHeader();
|
||||
}
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsRelativesView::updateHeader()
|
||||
{
|
||||
const QmlProfilerStatisticsRelation relation = m_model->relation();
|
||||
if (QStandardItemModel *model = treeModel()) {
|
||||
model->setColumnCount(MaxRelativeField);
|
||||
for (int i = 0; i < MaxRelativeField; ++i) {
|
||||
model->setHeaderData(i, Qt::Horizontal,
|
||||
displayHeader(static_cast<RelativeField>(i), relation));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QStandardItemModel *QmlProfilerStatisticsRelativesView::treeModel()
|
||||
{
|
||||
return qobject_cast<QStandardItemModel *>(model());
|
||||
}
|
||||
|
||||
void QmlProfilerStatisticsRelativesView::jumpToItem(const QModelIndex &index)
|
||||
{
|
||||
if (treeModel()) {
|
||||
QStandardItem *infoItem = treeModel()->item(index.row());
|
||||
// show in editor
|
||||
getSourceLocation(infoItem, [this](const QString &fileName, int line, int column) {
|
||||
emit gotoSourceLocation(fileName, line, column);
|
||||
});
|
||||
// show in editor
|
||||
getSourceLocation(index, [this](const QString &fileName, int line, int column) {
|
||||
emit gotoSourceLocation(fileName, line, column);
|
||||
});
|
||||
|
||||
emit typeClicked(infoItem->data(TypeIdRole).toInt());
|
||||
}
|
||||
emit typeClicked(index.data(TypeIdRole).toInt());
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
Reference in New Issue
Block a user