265 lines
7.9 KiB
C++
265 lines
7.9 KiB
C++
#include "containers_view.h"
|
|
#include <QTreeView>
|
|
#include <QPainter>
|
|
#include <QStyle>
|
|
#include <QSortFilterProxyModel>
|
|
|
|
|
|
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;
|
|
all[ccBytesAllocated] += i.allocated * i.item_size;
|
|
all[ccBytesUsed] += i.used * i.item_size;
|
|
}
|
|
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;
|
|
return PI2QString(PIString::readableSize(t.item_size));
|
|
default: break;
|
|
}
|
|
if (mode_changes) {
|
|
switch (index.column()) {
|
|
case ccCount: return int(t.count) - int(prev_data.value(id).count);
|
|
case ccBytesAllocated:
|
|
v = t.allocated;
|
|
v -= prev_data.value(id).allocated;
|
|
v *= t.item_size;
|
|
if (role == Qt::UserRole) return piAbs(v);
|
|
return PI2QString(PIString::readableSize(v));
|
|
case ccBytesUsed:
|
|
v = t.used;
|
|
v -= prev_data.value(id).used;
|
|
v *= t.item_size;
|
|
if (role == Qt::UserRole) return piAbs(v);
|
|
return PI2QString(PIString::readableSize(v));
|
|
}
|
|
} else {
|
|
switch (index.column()) {
|
|
case ccCount: return t.count;
|
|
case ccBytesAllocated:
|
|
v = t.allocated * t.item_size;
|
|
if (role == Qt::UserRole) return v;
|
|
return PI2QString(PIString::readableSize(v));
|
|
case ccBytesUsed:
|
|
v = t.used * t.item_size;
|
|
if (role == Qt::UserRole) return v;
|
|
return PI2QString(PIString::readableSize(v));
|
|
}
|
|
}
|
|
}
|
|
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);
|
|
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); \
|
|
}
|
|
CMP_FUNC(item_size)
|
|
CMP_FUNC(count)
|
|
CMP_FUNC(allocated)
|
|
CMP_FUNC(used)
|
|
#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 = 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_a : cmp_func_allocated_d; break;
|
|
case ccBytesUsed : cf = order == Qt::AscendingOrder ? cmp_func_used_a : cmp_func_used_d; break;
|
|
default : break;
|
|
}
|
|
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();
|
|
}
|