mainwindow.cpp
treemodel.cpp
treeproxy.cpp
+ costdelegate.cpp
chartwidget.cpp
chartmodel.cpp
chartproxy.cpp
--- /dev/null
+/*
+ * Copyright 2016 Milian Wolff <mail@milianw.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "costdelegate.h"
+
+#include "treemodel.h"
+
+#include <QDebug>
+#include <QPainter>
+
+CostDelegate::CostDelegate(QObject* parent)
+ : QStyledItemDelegate(parent)
+{
+}
+
+CostDelegate::~CostDelegate() = default;
+
+void CostDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
+{
+ const uint64_t cost = index.data(TreeModel::SortRole).toULongLong();
+ if (cost == 0) {
+ QStyledItemDelegate::paint(painter, option, index);
+ return;
+ }
+
+ const uint64_t maxCost = index.data(TreeModel::MaxCostRole).toULongLong();
+ // top-down can miscalculate the peak cost
+ const auto fraction = std::min(1.f, float(cost) / maxCost);
+ auto rect = option.rect;
+ rect.setWidth(rect.width() * fraction);
+
+ const auto& brush = painter->brush();
+ const auto& pen = painter->pen();
+
+ painter->setPen(Qt::NoPen);
+
+ if (option.features & QStyleOptionViewItem::Alternate) {
+ // we must handle this ourselves as otherwise the custom background
+ // would get painted over with the alternate background color
+ painter->setBrush(option.palette.alternateBase());
+ painter->drawRect(option.rect);
+ }
+
+ auto color = QColor::fromHsv(120 - fraction * 120, 255, 255,
+ (-((fraction-1) * (fraction-1))) * 120 + 120);
+ painter->setBrush(color);
+ painter->drawRect(rect);
+
+ painter->setBrush(brush);
+ painter->setPen(pen);
+
+ if (option.features & QStyleOptionViewItem::Alternate) {
+ auto o = option;
+ o.features &= ~QStyleOptionViewItem::Alternate;
+ QStyledItemDelegate::paint(painter, o, index);
+ } else {
+ QStyledItemDelegate::paint(painter, option, index);
+ }
+}
+
--- /dev/null
+/*
+ * Copyright 2016 Milian Wolff <mail@milianw.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef COSTDELEGATE_H
+#define COSTDELEGATE_H
+
+#include <QStyledItemDelegate>
+
+class CostDelegate : public QStyledItemDelegate
+{
+ Q_OBJECT
+public:
+ explicit CostDelegate(QObject *parent = nullptr);
+ ~CostDelegate();
+
+ void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const override;
+};
+
+#endif // COSTDELEGATE_H
#include "treemodel.h"
#include "treeproxy.h"
#include "topproxy.h"
+#include "costdelegate.h"
#include "parser.h"
#include "chartmodel.h"
#include "chartproxy.h"
m_ui->tabWidget->setTabEnabled(m_ui->tabWidget->indexOf(m_ui->sizesTab), true);
});
connect(m_parser, &Parser::summaryAvailable,
- this, [this] (const SummaryData& data) {
+ this, [this, bottomUpModel, topDownModel] (const SummaryData& data) {
+ bottomUpModel->setSummary(data);
+ topDownModel->setSummary(data);
KFormat format;
QString textLeft;
QString textCenter;
bottomUpProxy->setSourceModel(bottomUpModel);
bottomUpProxy->setSortRole(TreeModel::SortRole);
m_ui->bottomUpResults->setModel(bottomUpProxy);
+ auto costDelegate = new CostDelegate(this);
+ m_ui->bottomUpResults->setItemDelegateForColumn(TreeModel::PeakColumn, costDelegate);
+ m_ui->bottomUpResults->setItemDelegateForColumn(TreeModel::AllocatedColumn, costDelegate);
+ m_ui->bottomUpResults->setItemDelegateForColumn(TreeModel::LeakedColumn, costDelegate);
+ m_ui->bottomUpResults->setItemDelegateForColumn(TreeModel::AllocationsColumn, costDelegate);
+ m_ui->bottomUpResults->setItemDelegateForColumn(TreeModel::TemporaryColumn, costDelegate);
m_ui->bottomUpResults->hideColumn(TreeModel::FunctionColumn);
m_ui->bottomUpResults->hideColumn(TreeModel::FileColumn);
m_ui->bottomUpResults->hideColumn(TreeModel::LineColumn);
topDownProxy->setSourceModel(topDownModel);
topDownProxy->setSortRole(TreeModel::SortRole);
m_ui->topDownResults->setModel(topDownProxy);
+ m_ui->topDownResults->setItemDelegateForColumn(TreeModel::PeakColumn, costDelegate);
+ m_ui->topDownResults->setItemDelegateForColumn(TreeModel::AllocatedColumn, costDelegate);
+ m_ui->topDownResults->setItemDelegateForColumn(TreeModel::LeakedColumn, costDelegate);
+ m_ui->topDownResults->setItemDelegateForColumn(TreeModel::AllocationsColumn, costDelegate);
+ m_ui->topDownResults->setItemDelegateForColumn(TreeModel::TemporaryColumn, costDelegate);
m_ui->topDownResults->hideColumn(TreeModel::FunctionColumn);
m_ui->topDownResults->hideColumn(TreeModel::FileColumn);
m_ui->topDownResults->hideColumn(TreeModel::LineColumn);
setupStacks();
setupTopView(bottomUpModel, m_ui->topPeak, TopProxy::Peak);
+ m_ui->topPeak->setItemDelegate(costDelegate);
setupTopView(bottomUpModel, m_ui->topLeaked, TopProxy::Leaked);
+ m_ui->topLeaked->setItemDelegate(costDelegate);
setupTopView(bottomUpModel, m_ui->topAllocations, TopProxy::Allocations);
+ m_ui->topAllocations->setItemDelegate(costDelegate);
setupTopView(bottomUpModel, m_ui->topTemporary, TopProxy::Temporary);
+ m_ui->topTemporary->setItemDelegate(costDelegate);
setupTopView(bottomUpModel, m_ui->topAllocated, TopProxy::Allocated);
+ m_ui->topAllocated->setItemDelegate(costDelegate);
setWindowTitle(i18n("Heaptrack"));
}
#include "chartmodel.h"
#include "histogrammodel.h"
-struct SummaryData
-{
- QString debuggee;
- uint64_t totalTime;
- uint64_t peakTime;
- uint64_t peak;
- uint64_t leaked;
- uint64_t allocations;
- uint64_t temporary;
- uint64_t allocated;
- uint64_t peakRSS;
- uint64_t totalSystemMemory;
-};
-Q_DECLARE_METATYPE(SummaryData);
-
class Parser : public QObject
{
Q_OBJECT
if (index.row() < 0 || index.column() < 0 || index.column() > NUM_COLUMNS) {
return {};
}
- const auto row = toRow(index);
- if (role == Qt::DisplayRole || role == SortRole) {
+
+ const auto row = (role == MaxCostRole) ? &m_maxCost : toRow(index);
+
+ if (role == Qt::DisplayRole || role == SortRole || role == MaxCostRole) {
switch (static_cast<Columns>(index.column())) {
case AllocatedColumn:
- if (role == SortRole) {
+ if (role == SortRole || role == MaxCostRole) {
return row->allocated;
} else {
return m_format.formatByteSize(row->allocated);
case TemporaryColumn:
return row->temporary;
case PeakColumn:
- if (role == SortRole) {
+ if (role == SortRole || role == MaxCostRole) {
return row->peak;
} else {
return m_format.formatByteSize(row->peak);
}
case LeakedColumn:
- if (role == SortRole) {
+ if (role == SortRole || role == MaxCostRole) {
return row->leaked;
} else {
return m_format.formatByteSize(row->leaked);
endResetModel();
}
+void TreeModel::setSummary(const SummaryData& data)
+{
+ beginResetModel();
+ m_maxCost.allocated = data.allocated;
+ m_maxCost.leaked = data.leaked;
+ m_maxCost.peak = data.peak;
+ m_maxCost.allocations = data.allocations;
+ m_maxCost.temporary = data.temporary;
+ endResetModel();
+}
+
const RowData* TreeModel::toRow(const QModelIndex& index) const
{
if (!index.isValid()) {
#include <memory>
+struct SummaryData
+{
+ QString debuggee;
+ uint64_t totalTime;
+ uint64_t peakTime;
+ uint64_t peak;
+ uint64_t leaked;
+ uint64_t allocations;
+ uint64_t temporary;
+ uint64_t allocated;
+ uint64_t peakRSS;
+ uint64_t totalSystemMemory;
+};
+Q_DECLARE_METATYPE(SummaryData);
+
struct LocationData
{
QString function;
};
enum Roles {
- SortRole = Qt::UserRole
+ SortRole = Qt::UserRole,
+ MaxCostRole = Qt::UserRole + 1
};
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
public slots:
void resetData(const TreeData& data);
+ void setSummary(const SummaryData& data);
private:
/// @return the row resembled by @p index
int rowOf(const RowData* row) const;
TreeData m_data;
+ RowData m_maxCost;
// TODO: update via global event filter when the locale changes (changeEvent)
KFormat m_format;
};