File indexing completed on 2024-04-28 17:02:22

0001 /*
0002    This file is part of Massif Visualizer
0003 
0004    Copyright 2010 Milian Wolff <mail@milianw.de>
0005 
0006    This library is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU Lesser General Public
0008    License as published by the Free Software Foundation; either
0009    version 2.1 of the License, or (at your option) version 3, or any
0010    later version accepted by the membership of KDE e.V. (or its
0011    successor approved by the membership of KDE e.V.), which shall
0012    act as a proxy defined in Section 6 of version 3 of the license.
0013 
0014    This library is distributed in the hope that it will be useful,
0015    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017    Lesser General Public License for more details.
0018 
0019    You should have received a copy of the GNU Lesser General Public
0020    License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0021 */
0022 
0023 #include "totalcostmodel.h"
0024 
0025 #include "massifdata/filedata.h"
0026 #include "massifdata/snapshotitem.h"
0027 #include "massifdata/treeleafitem.h"
0028 #include "massifdata/util.h"
0029 
0030 #include "KChartGlobal"
0031 #include "KChartLineAttributes"
0032 
0033 #include <QtGui/QPen>
0034 
0035 #include <KLocalizedString>
0036 
0037 using namespace Massif;
0038 
0039 TotalCostModel::TotalCostModel(QObject* parent): QAbstractTableModel(parent), m_data(0)
0040 {
0041 }
0042 
0043 TotalCostModel::~TotalCostModel()
0044 {
0045 }
0046 
0047 void TotalCostModel::setSource(const FileData* data)
0048 {
0049     if (m_data) {
0050         beginRemoveRows(QModelIndex(), 0, rowCount() - 1);
0051         m_data = 0;
0052         endRemoveRows();
0053     }
0054     if (data) {
0055         beginInsertRows(QModelIndex(), 0, data->snapshots().size() - 1);
0056         m_data = data;
0057         endInsertRows();
0058     }
0059 }
0060 
0061 QModelIndex TotalCostModel::peak() const
0062 {
0063     Q_ASSERT(m_data);
0064     if (!m_data->peak()) {
0065         return QModelIndex();
0066     }
0067     return index(m_data->snapshots().indexOf(m_data->peak()), 0);
0068 }
0069 
0070 QVariant TotalCostModel::headerData(int section, Qt::Orientation orientation, int role) const
0071 {
0072     Q_ASSERT(orientation != Qt::Horizontal || section < columnCount());
0073     if (section == 0 && orientation == Qt::Horizontal) {
0074         if ( role == KChart::DatasetPenRole ) {
0075             return QPen(Qt::red);
0076         } else if ( role == KChart::DatasetBrushRole ) {
0077             return QBrush(Qt::red);
0078         } else if ( role == Qt::DisplayRole ) {
0079             return i18n("Total Memory Heap Consumption");
0080         }
0081     }
0082     return QAbstractItemModel::headerData(section, orientation, role);
0083 }
0084 
0085 QVariant TotalCostModel::data(const QModelIndex& index, int role) const
0086 {
0087     // FIXME kdchart queries (-1, -1) for empty models
0088     if ( index.row() == -1 || index.column() == -1 ) {
0089 //         qWarning() << "TotalCostModel::data: FIXME fix kdchart views to not query model data for invalid indices!";
0090         return QVariant();
0091     }
0092 
0093     Q_ASSERT(index.row() >= 0 && index.row() < rowCount(index.parent()));
0094     Q_ASSERT(index.column() >= 0 && index.column() < columnCount(index.parent()));
0095     Q_ASSERT(m_data);
0096     Q_ASSERT(!index.parent().isValid());
0097 
0098     if ( role == KChart::LineAttributesRole ) {
0099         static KChart::LineAttributes attributes;
0100         attributes.setDisplayArea(true);
0101         if (index == m_selection) {
0102             attributes.setTransparency(255);
0103         } else {
0104             attributes.setTransparency(50);
0105         }
0106         return QVariant::fromValue(attributes);
0107     }
0108     if ( role == KChart::DatasetPenRole ) {
0109         return QPen(Qt::red);
0110     } else if ( role == KChart::DatasetBrushRole ) {
0111         return QBrush(Qt::red);
0112     }
0113 
0114     if ( role != Qt::DisplayRole && role != Qt::ToolTipRole ) {
0115         return QVariant();
0116     }
0117 
0118     if ( role == Qt::ToolTipRole ) {
0119         // hack: the ToolTip will only be queried by KDChart and that one uses the
0120         // left index, but we want it to query the right one. but we also need to
0121         // take the very last data set into account to prevent an overflow there
0122         const SnapshotItem* snapshot = m_data->snapshots().at(qMin(index.row() + 1, m_data->snapshots().size() - 1));
0123         return i18n("Snapshot #%1:\n"
0124                     "Heap cost of %2\n"
0125                     "Extra heap cost of %3\n"
0126                     "Stack cost of %4",
0127                     snapshot->number(), prettyCost(snapshot->memHeap()), prettyCost(snapshot->memHeapExtra()),
0128                     prettyCost(snapshot->memStacks()));
0129     }
0130 
0131     const SnapshotItem* snapshot = m_data->snapshots().at(index.row());
0132     if (index.column() == 0) {
0133         return snapshot->time();
0134     } else {
0135         Q_ASSERT(index.column() == 1);
0136         return snapshot->cost();
0137     }
0138 }
0139 
0140 int TotalCostModel::columnCount(const QModelIndex&) const
0141 {
0142     return 2;
0143 }
0144 
0145 int TotalCostModel::rowCount(const QModelIndex& parent) const
0146 {
0147     if (!m_data) {
0148         return 0;
0149     }
0150 
0151     if (parent.isValid()) {
0152         return 0;
0153     } else {
0154         // snapshot item
0155         return m_data->snapshots().count();
0156     }
0157 }
0158 
0159 QModelIndex TotalCostModel::indexForSnapshot(const SnapshotItem* snapshot) const
0160 {
0161     int row = m_data->snapshots().indexOf(const_cast<SnapshotItem*>(snapshot));
0162     if (row == -1) {
0163         return QModelIndex();
0164     }
0165     return index(row, 0);
0166 }
0167 
0168 QModelIndex TotalCostModel::indexForTreeLeaf(const TreeLeafItem* node) const
0169 {
0170     Q_UNUSED(node)
0171     return QModelIndex();
0172 }
0173 
0174 ModelItem TotalCostModel::itemForIndex(const QModelIndex& idx) const
0175 {
0176     if (!idx.isValid() || idx.parent().isValid() || idx.row() > rowCount() || idx.column() > columnCount()) {
0177         return ModelItem(0, 0);
0178     }
0179     const SnapshotItem* snapshot = m_data->snapshots().at(idx.row());
0180     return ModelItem(0, snapshot);
0181 }
0182 
0183 QModelIndex TotalCostModel::indexForItem(const ModelItem& item) const
0184 {
0185     if ((!item.first && !item.second) || item.first) {
0186         return QModelIndex();
0187     }
0188     return indexForSnapshot(item.second);
0189 }
0190 
0191 void TotalCostModel::setSelection(const QModelIndex& index)
0192 {
0193     m_selection = index;
0194 }