#include <QPen>
#include <QBrush>
+#include <QDebug>
#include "modeltest.h"
+namespace {
+QColor colorForColumn(int column, int columnCount)
+{
+ return QColor::fromHsv((1. - double(column + 1) / columnCount) * 255, 255, 255);
+}
+}
+
ChartModel::ChartModel(QObject* parent)
: QAbstractTableModel(parent)
{
QVariant ChartModel::headerData(int section, Qt::Orientation orientation, int role) const
{
Q_ASSERT(orientation != Qt::Horizontal || section < columnCount());
- if (section == 0 && orientation == Qt::Horizontal) {
- if ( role == KChart::DatasetPenRole ) {
- return QPen(Qt::red);
- } else if ( role == KChart::DatasetBrushRole ) {
- return QBrush(Qt::red);
+ if (orientation == Qt::Horizontal) {
+ if (role == KChart::DatasetPenRole) {
+ return QVariant::fromValue(QPen(colorForColumn(section, columnCount())));
+ } else if (role == KChart::DatasetBrushRole) {
+ return QVariant::fromValue(QBrush(colorForColumn(section, columnCount())));
}
}
return {};
// }
return QVariant::fromValue(attributes);
}
+
+ const auto idx = index.column() / 4;
+ const auto column = index.column() % 4;
+
if ( role == KChart::DatasetPenRole ) {
- static const auto pen = QVariant::fromValue(QPen(Qt::red));
- return pen;
+ return QVariant::fromValue(QPen(colorForColumn(index.column(), columnCount())));
} else if ( role == KChart::DatasetBrushRole ) {
- static const auto brush = QVariant::fromValue(QBrush(Qt::red));
- return brush;
+ return QVariant::fromValue(QBrush(colorForColumn(index.column(), columnCount())));
}
if ( role != Qt::DisplayRole && role != Qt::ToolTipRole ) {
}
if ( role == Qt::ToolTipRole ) {
+ // TODO
return {};
}
- const auto& data= m_data.at(index.row());
- if (index.column() == 0) {
+ const auto& data = m_data.at(index.row());
+ if (column == TimeStampColumn) {
return data.timeStamp;
- } else if (index.column() == 1) {
- return data.leaked;
- } else if (index.column() == 2) {
- return data.allocations;
+ }
+
+ if (column == LeakedColumn) {
+ return idx < data.leaked.size() ? data.leaked[idx].cost : 0;
+ } else if (column == AllocationsColumn) {
+ return idx < data.allocations.size() ? data.allocations[idx].cost : 0;
} else {
- return data.allocated;
+ return idx < data.allocated.size() ? data.allocated[idx].cost : 0;
}
}
int ChartModel::columnCount(const QModelIndex& /*parent*/) const
{
- return 4;
+ return m_data.isEmpty() ? 0 : NUM_COLUMNS * m_data.last().allocated.size();
}
int ChartModel::rowCount(const QModelIndex& parent) const
struct ChartRow
{
+ QString function;
+ quint64 cost;
+};
+Q_DECLARE_TYPEINFO(ChartRow, Q_MOVABLE_TYPE);
+
+struct ChartRows
+{
quint64 timeStamp;
- quint64 leaked;
- quint64 allocations;
- quint64 allocated;
+ QVector<ChartRow> leaked;
+ QVector<ChartRow> allocations;
+ QVector<ChartRow> allocated;
};
+Q_DECLARE_TYPEINFO(ChartRows, Q_MOVABLE_TYPE);
-Q_DECLARE_TYPEINFO(ChartRow, Q_MOVABLE_TYPE);
-using ChartData = QVector<ChartRow>;
+using ChartData = QVector<ChartRows>;
Q_DECLARE_METATYPE(ChartData)
class ChartModel : public QAbstractTableModel
explicit ChartModel(QObject* parent = nullptr);
virtual ~ChartModel();
+ enum Columns {
+ TimeStampColumn,
+ LeakedColumn,
+ AllocationsColumn,
+ AllocatedColumn,
+ NUM_COLUMNS
+ };
+
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
*/
#include "chartproxy.h"
+#include "chartmodel.h"
ChartProxy::ChartProxy(const QString& label, int column, QObject* parent)
: QSortFilterProxyModel(parent)
bool ChartProxy::filterAcceptsColumn(int sourceColumn, const QModelIndex& /*sourceParent*/) const
{
- return sourceColumn == 0 || sourceColumn == m_column;
+ const auto column = sourceColumn % 4;
+ return column == ChartModel::TimeStampColumn || column == m_column;
}
setLayout(layout);
m_plotter->setAntiAliasing(true);
+ m_plotter->setType(KChart::Plotter::Stacked);
KColorScheme scheme(QPalette::Active, KColorScheme::Window);
QPen foreground(scheme.foreground().color());
m_ui->loadingProgress->setMinimum(0);
m_ui->loadingProgress->setMaximum(0);
- auto leakedProxy = new ChartProxy(i18n("Memory Leaked"), 1, this);
+ auto leakedProxy = new ChartProxy(i18n("Memory Leaked"), ChartModel::LeakedColumn, this);
leakedProxy->setSourceModel(m_chartModel);
m_ui->leakedTab->setModel(leakedProxy);
- auto allocationsProxy = new ChartProxy(i18n("Memory Allocations"), 2, this);
+ auto allocationsProxy = new ChartProxy(i18n("Memory Allocations"), ChartModel::AllocationsColumn, this);
allocationsProxy->setSourceModel(m_chartModel);
m_ui->allocationsTab->setModel(allocationsProxy);
- auto allocatedProxy = new ChartProxy(i18n("Memory Allocated"), 3, this);
+ auto allocatedProxy = new ChartProxy(i18n("Memory Allocated"), ChartModel::AllocatedColumn, this);
allocatedProxy->setSourceModel(m_chartModel);
m_ui->allocatedTab->setModel(allocatedProxy);
{
ParserData()
{
- chartData.push_back({0, 0, 0, 0});
+ chartData.push_back({0, {{i18n("total"), 0}}, {{i18n("total"), 0}}, {{i18n("total"), 0}}});
}
void handleTimeStamp(uint64_t /*newStamp*/, uint64_t oldStamp)
{
maxLeakedSinceLastTimeStamp = max(maxLeakedSinceLastTimeStamp, leaked);
- chartData.push_back({oldStamp, maxLeakedSinceLastTimeStamp, totalAllocations, totalAllocated});
+ ChartRows data;
+ data.timeStamp = oldStamp;
+ data.leaked.push_back({i18n("total"), maxLeakedSinceLastTimeStamp});
+ data.allocations.push_back({i18n("total"), totalAllocations});
+ data.allocated.push_back({i18n("total"), totalAllocated});
+
+ auto allocs = allocations;
+ sort(allocs.begin(), allocs.end(), [] (const Allocation& left, const Allocation& right) {
+ return left.leaked < right.leaked;
+ });
+ for (size_t i = 0; i < min(size_t(10), allocs.size()); ++i) {
+ QString function;
+ data.leaked.push_back({function, allocs[i].leaked});
+ }
+ sort(allocs.begin(), allocs.end(), [] (const Allocation& left, const Allocation& right) {
+ return left.allocations < right.allocations;
+ });
+ for (size_t i = 0; i < min(size_t(10), allocs.size()); ++i) {
+ QString function;
+ data.allocations.push_back({function, allocs[i].allocations});
+ }
+ sort(allocs.begin(), allocs.end(), [] (const Allocation& left, const Allocation& right) {
+ return left.allocated < right.allocated;
+ });
+ for (size_t i = 0; i < min(size_t(10), allocs.size()); ++i) {
+ QString function;
+ data.allocated.push_back({function, allocs[i].allocated});
+ }
+ chartData.push_back(data);
maxLeakedSinceLastTimeStamp = 0;
}