#include "containers_view.h" #include #include #include #include enum ColumnContainers { ccType, ccItemSize, ccCount, ccBytesAllocated, ccBytesUsed, ccColumnCount, }; ContainersModel::ContainersModel() { mode_changes = false; ls_column = 0; ls_order = Qt::AscendingOrder; all.resize(columnCount(), 0L); prev_all.resize(all.size(), 0L); } void ContainersModel::update(const PIVector & t) { prev_data.clear(); all.fill(0U); for (const auto & i: cur_data) { prev_data[i.id] = i; } for (const auto & i: t) { all[ccCount] += i.count; #if PIP_VERSION >= PIP_MAKE_VERSION(2, 35, 0) all[ccBytesAllocated] += i.allocated_bytes; all[ccBytesUsed] += i.used_bytes; #else all[ccBytesAllocated] += i.allocated; all[ccBytesUsed] += i.used; #endif } int pts = cur_data.size_s(); cur_data = t; if (t.size_s() > pts) { beginInsertRows(QModelIndex(), pts, t.size_s() - 1); endInsertRows(); } if (t.size_s() < pts) { beginRemoveRows(QModelIndex(), t.size_s(), pts - 1); endRemoveRows(); } sort(ls_column, ls_order); emit headerDataChanged(Qt::Horizontal, ccCount, columnCount()); } void ContainersModel::clear() { beginRemoveRows(QModelIndex(), 0, cur_data.size_s() - 1); cur_data.clear(); prev_data.clear(); all.fill(0L); endRemoveRows(); } int ContainersModel::rowCount(const QModelIndex & parent) const { return cur_data.size_s(); } int ContainersModel::columnCount(const QModelIndex & parent) const { return ccColumnCount; } QModelIndex ContainersModel::index(int row, int column, const QModelIndex & parent) const { if (row >= cur_data.size_s() || row >= cur_data.size_s()) return QModelIndex(); return createIndex(row, column, cur_data[row].id); } 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 ccItemSize: return tr("Item size"); 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()); const PIIntrospectionContainers::TypeInfo & t(cur_data[index.row()]); llong v = 0L; if (role == Qt::DisplayRole || role == Qt::UserRole) { switch (index.column()) { case ccType: return PI2QString(t.name); case ccItemSize: if (role == Qt::UserRole) return t.item_size; #if PIP_VERSION >= PIP_MAKE_VERSION(2, 35, 0) return PI2QString(t.item_size_str); #else return PI2QString(PIString::readableSize(t.item_size)); #endif default: break; } if (mode_changes) { switch (index.column()) { case ccCount: return int(t.count) - int(prev_data.value(id).count); case ccBytesAllocated: #if PIP_VERSION >= PIP_MAKE_VERSION(2, 35, 0) v = t.allocated_bytes; v -= prev_data.value(id).allocated_bytes; #else v = t.allocated; v -= prev_data.value(id).allocated; #endif if (role == Qt::UserRole) return piAbs(v); return PI2QString(PIString::readableSize(v)); case ccBytesUsed: #if PIP_VERSION >= PIP_MAKE_VERSION(2, 35, 0) v = t.used_bytes; v -= prev_data.value(id).used_bytes; #else v = t.used; v -= prev_data.value(id).used; #endif if (role == Qt::UserRole) return piAbs(v); return PI2QString(PIString::readableSize(v)); } } else { switch (index.column()) { case ccCount: return t.count; case ccBytesAllocated: #if PIP_VERSION >= PIP_MAKE_VERSION(2, 35, 0) if (role == Qt::UserRole) return t.allocated_bytes; return PI2QString(t.allocated_str); case ccBytesUsed: if (role == Qt::UserRole) return t.used_bytes; return PI2QString(t.used_str); #else if (role == Qt::UserRole) return t.allocated; return PI2QString(PIString::readableSize(t.allocated)); case ccBytesUsed: if (role == Qt::UserRole) return t.used; return PI2QString(PIString::readableSize(t.used)); #endif } } } if (role == (Qt::UserRole + 1) && (index.column() == ccCount)) { return t.count; } return QVariant(); } Qt::ItemFlags ContainersModel::flags(const QModelIndex & index) const { return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } // bool cmp(const PIIntrospectionContainers::TypeInfo & a, const PIIntrospectionContainers::TypeInfo & b); #if PIP_VERSION >= PIP_MAKE_VERSION(2, 35, 0) bool cmp_func_name_a(const PIIntrospectionContainers::TypeInfo & t0, const PIIntrospectionContainers::TypeInfo & t1) { return QString::localeAwareCompare(PI2QString(t0.name), PI2QString(t1.name)) < 0; } bool cmp_func_name_d(const PIIntrospectionContainers::TypeInfo & t0, const PIIntrospectionContainers::TypeInfo & t1) { return !cmp_func_name_a(t0, t1); } # define CMP_FUNC(field) \ bool cmp_func_##field##_a(const PIIntrospectionContainers::TypeInfo & t0, const PIIntrospectionContainers::TypeInfo & t1) { \ return t0.field < t1.field; \ } \ bool cmp_func_##field##_d(const PIIntrospectionContainers::TypeInfo & t0, const PIIntrospectionContainers::TypeInfo & t1) { \ return t0.field > t1.field; \ } #else int cmp_func_name_a(const PIIntrospectionContainers::TypeInfo * t0, const PIIntrospectionContainers::TypeInfo * t1) { return QString::localeAwareCompare(PI2QString(t0->name), PI2QString(t1->name)); } int cmp_func_name_d(const PIIntrospectionContainers::TypeInfo * t0, const PIIntrospectionContainers::TypeInfo * t1) { return -cmp_func_name_a(t0, t1); } # define CMP_FUNC(field) \ int cmp_func_##field##_a(const PIIntrospectionContainers::TypeInfo * t0, const PIIntrospectionContainers::TypeInfo * t1) { \ return (t0->field) <= (t1->field) ? -1 : ((t0->field) == (t1->field) ? 0 : 1); \ } \ int cmp_func_##field##_d(const PIIntrospectionContainers::TypeInfo * t0, const PIIntrospectionContainers::TypeInfo * t1) { \ return -cmp_func_##field##_a(t0, t1); \ } #endif CMP_FUNC(item_size) CMP_FUNC(count) #if PIP_VERSION >= PIP_MAKE_VERSION(2, 35, 0) CMP_FUNC(allocated_bytes) CMP_FUNC(used_bytes) #else CMP_FUNC(allocated) CMP_FUNC(used) #endif #undef CMP_FUNC void ContainersModel::sort(int column, Qt::SortOrder order) { ls_column = column; ls_order = order; if (cur_data.isEmpty()) return; PIVector::CompareFunc cf = nullptr; #if PIP_VERSION >= PIP_MAKE_VERSION(2, 35, 0) switch (column) { case ccType: cf = order == Qt::AscendingOrder ? cmp_func_name_a : cmp_func_name_d; break; case ccItemSize: cf = order == Qt::AscendingOrder ? cmp_func_item_size_a : cmp_func_item_size_d; break; case ccCount: cf = order == Qt::AscendingOrder ? cmp_func_count_a : cmp_func_count_d; break; case ccBytesAllocated: cf = order == Qt::AscendingOrder ? cmp_func_allocated_bytes_a : cmp_func_allocated_bytes_d; break; case ccBytesUsed: cf = order == Qt::AscendingOrder ? cmp_func_used_bytes_a : cmp_func_used_bytes_d; break; default: break; } #else switch (column) { case ccType: cf = order == Qt::AscendingOrder ? cmp_func_name_a : cmp_func_name_d; break; case ccItemSize: cf = order == Qt::AscendingOrder ? cmp_func_item_size_a : cmp_func_item_size_d; break; case ccCount: cf = order == Qt::AscendingOrder ? cmp_func_count_a : cmp_func_count_d; break; case ccBytesAllocated: cf = order == Qt::AscendingOrder ? cmp_func_allocated_a : cmp_func_allocated_d; break; case ccBytesUsed: cf = order == Qt::AscendingOrder ? cmp_func_used_a : cmp_func_used_d; break; default: break; } #endif if (cf) cur_data.sort(cf); // qDebug() << "sort" << column << order; dataChanged(index(0, 0), index(cur_data.size_s() - 1, columnCount())); } void ContainersModel::setChangesMode(bool yes) { mode_changes = yes; if (cur_data.isEmpty()) return; sort(ls_column, ls_order); 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 PIVector & t) { model->update(t); } void ContainersView::clear() { model->clear(); }