Files
qad/utils/piintrospector/containers_view.cpp
2022-12-14 14:14:33 +03:00

309 lines
11 KiB
C++

#include "containers_view.h"
#include <QPainter>
#include <QSortFilterProxyModel>
#include <QStyle>
#include <QTreeView>
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<PIIntrospectionContainers::TypeInfo> & t) {
prev_data.clear();
all.fill(0U);
piForeachC(PIIntrospectionContainers::TypeInfo & i, cur_data) {
prev_data[i.id] = i;
}
piForeachC(PIIntrospectionContainers::TypeInfo & 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<llong> 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<PIIntrospectionContainers::TypeInfo>::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<PIIntrospectionContainers::TypeInfo> & t) {
model->update(t);
}
void ContainersView::clear() {
model->clear();
}