#include "containers_view.h" #include #include #include #include #include const QString demangle(const char * name) { int status = -4; char * res = abi::__cxa_demangle(name, NULL, NULL, &status); QString ret((status == 0) ? res : name); free(res); return ret; } enum ColumnContainers { ccType, ccCount, ccBytesAllocated, ccBytesUsed, ccColumnCount, }; ContainersModel::ContainersModel() { mode_changes = false; all.resize(columnCount(), 0L); prev_all.resize(all.size(), 0L); } void ContainersModel::update(const PIMap & td, const PIMap & tn) { prev_typedata = typedata; typedata = td; typenames = tn; PIVector ntypeids = tn.keys(); for (int i = 0; i < ntypeids.size_s(); ++i) { if (typeids.size_s() > i) if (typeids[i] == ntypeids[i]) continue; beginInsertRows(QModelIndex(), i, i); typeids.insert(i, ntypeids[i]); endInsertRows(); } prev_all = all; all.fill(0U); for (auto i = td.constBegin(); i != td.constEnd(); ++i) { all[ccCount] += i.value().count; all[ccBytesAllocated] += i.value().bytes_allocated; all[ccBytesUsed] += i.value().bytes_used; } dataChanged(index(0, ccCount), index(typeids.size_s() - 1, columnCount())); emit headerDataChanged(Qt::Horizontal, ccCount, columnCount()); } void ContainersModel::clear() { beginRemoveRows(QModelIndex(), 0, typeids.size_s() - 1); typedata.clear(); prev_typedata.clear(); typenames.clear(); typeids.clear(); all.fill(0L); endRemoveRows(); } int ContainersModel::rowCount(const QModelIndex & parent) const { return typeids.size_s(); } int ContainersModel::columnCount(const QModelIndex & parent) const { return ccColumnCount; } QModelIndex ContainersModel::index(int row, int column, const QModelIndex & parent) const { if (row >= typenames.size_s() || row >= typedata.size_s()) return QModelIndex(); return createIndex(row, column, typeids[row]); } bool ContainersModel::hasChildren(const QModelIndex & parent) const { if (!parent.isValid()) return true; return false; } QVariant ContainersModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation != Qt::Horizontal || role != Qt::DisplayRole) return QVariant(); PIVector ret = all; if (mode_changes) { for (int i = 0; i < all.size_s(); ++i) ret[i] -= prev_all[i]; } switch (section) { case ccType : return tr("Type"); case ccCount : return tr("Count (%1)").arg(ret[ccCount]); case ccBytesAllocated: return tr("Allocated (%1)").arg(PI2QString(PIString::readableSize(ret[ccBytesAllocated]))); case ccBytesUsed : return tr("Used (%1)").arg(PI2QString(PIString::readableSize(ret[ccBytesUsed]))); default: break; } return QVariant(); } QVariant ContainersModel::data(const QModelIndex & index, int role) const { if (role != Qt::DisplayRole && role != Qt::UserRole && role != (Qt::UserRole+1)) return QVariant(); uint id = uint(index.internalId()); llong v = 0L; if (role == Qt::DisplayRole || role == Qt::UserRole) { if (mode_changes) { switch (index.column()) { case ccType: return demangle(typenames.value(id).dataAscii()); case ccCount: return int(typedata.value(id).count) - int(prev_typedata.value(id).count); case ccBytesAllocated: v = typedata.value(id).bytes_allocated; v -= prev_typedata.value(id).bytes_allocated; if (role == Qt::UserRole) return piAbs(v); return PI2QString(PIString::readableSize(v)); case ccBytesUsed: v = typedata.value(id).bytes_used; v -= prev_typedata.value(id).bytes_used; if (role == Qt::UserRole) return piAbs(v); return PI2QString(PIString::readableSize(v)); } } else { switch (index.column()) { case ccType: return demangle(typenames.value(id).dataAscii()); case ccCount: return typedata.value(id).count; case ccBytesAllocated: v = typedata.value(id).bytes_allocated; if (role == Qt::UserRole) return v; return PI2QString(PIString::readableSize(v)); case ccBytesUsed: v = typedata.value(id).bytes_used; if (role == Qt::UserRole) return v; return PI2QString(PIString::readableSize(v)); } } } if (role == (Qt::UserRole+1) && (index.column() == ccCount)) { return typedata.value(id).count; } return QVariant(); } Qt::ItemFlags ContainersModel::flags(const QModelIndex & index) const { return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } void ContainersModel::setChangesMode(bool yes) { mode_changes = yes; if (typeids.isEmpty()) return; dataChanged(index(0, ccCount), index(typeids.size_s() - 1, columnCount())); emit headerDataChanged(Qt::Horizontal, ccCount, columnCount()); } void ContainersDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { QStyledItemDelegate::paint(painter, option, index); if (model->index(index.row(), ccCount).data(Qt::UserRole+1).toInt() == 0) { QColor col; if (option.state == QStyle::State_Enabled || option.state == QStyle::State_HasFocus) col = option.palette.color(QPalette::Active, QPalette::WindowText); else col = option.palette.color(QPalette::Disabled, QPalette::WindowText); col.setAlphaF(0.5); int y = option.rect.center().y() + (option.fontMetrics.height() / 2.5) - option.fontMetrics.strikeOutPos(); painter->setPen(QPen(col, lineThickness())); painter->drawLine(QPoint(option.rect.left(), y), QPoint(option.rect.right(), y)); } } ContainersView::ContainersView(QWidget * parent): QWidget(parent) { setupUi(this); model = new ContainersModel(); connect(radioChanges, SIGNAL(toggled(bool)), model, SLOT(setChangesMode(bool))); QSortFilterProxyModel * proxy = new QSortFilterProxyModel(); proxy->setSourceModel(model); proxy->setSortRole(Qt::UserRole); proxy->setDynamicSortFilter(false); treeContainers->setModel(model); treeContainers->setItemDelegate(new ContainersDelegate(model)); } ContainersView::~ContainersView() { } void ContainersView::changeEvent(QEvent * e) { QWidget::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: retranslateUi(this); break; default: break; } } void ContainersView::showContainers(const PIMap & data, const PIMap & typenames) { model->update(data, typenames); } void ContainersView::clear() { model->clear(); }