235 lines
6.3 KiB
C++
235 lines
6.3 KiB
C++
#include "threads_view.h"
|
|
#include <QTreeView>
|
|
#include <QPainter>
|
|
#include <QStyle>
|
|
#include <QSortFilterProxyModel>
|
|
#include "ccm_piintrospector.h"
|
|
|
|
|
|
enum ColumnThreads {
|
|
ctClassname,
|
|
ctName,
|
|
ctID,
|
|
ctDelay,
|
|
ctState,
|
|
ctLoad,
|
|
ctRunCost,
|
|
ctRunCount,
|
|
ctColumnCount,
|
|
};
|
|
|
|
|
|
|
|
|
|
ThreadsModel::ThreadsModel() {
|
|
PICodeInfo::EnumInfo * ei = PICodeInfo::enumsInfo->value("PIIntrospectionThreads::ThreadState");
|
|
if (ei) {
|
|
piForeachC (PICodeInfo::EnumeratorInfo & e, ei->members) {
|
|
#if PIP_VERSION >= PIP_MAKE_VERSION(2,39,0)
|
|
state_names[e.value] = PI2QString(e.name.mid(1).toString());
|
|
#else
|
|
state_names[e.value] = PI2QString(e.name.mid(1));
|
|
#endif
|
|
}
|
|
}
|
|
state_colors[PIIntrospectionThreads::sStopped] = QColor(Qt::red).lighter(150);
|
|
state_colors[PIIntrospectionThreads::sStarting] = QColor(Qt::blue).lighter(150);
|
|
state_colors[PIIntrospectionThreads::sRunning] = QColor(Qt::green).lighter(120);
|
|
state_colors[PIIntrospectionThreads::sWaiting] = QColor(Qt::yellow).lighter(110);
|
|
}
|
|
|
|
|
|
void ThreadsModel::update(const PIVector<PIIntrospectionThreads::ThreadInfo> & t) {
|
|
int pts = threads.size_s();
|
|
threads = 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();
|
|
}
|
|
dataChanged(index(0, 0), index(threads.size_s() - 1, columnCount()));
|
|
//emit headerDataChanged(Qt::Horizontal, ccCount, columnCount());
|
|
}
|
|
|
|
|
|
void ThreadsModel::setStat(const PIVector<PISystemMonitor::ThreadStats> & s) {
|
|
stat = s;
|
|
dataChanged(index(0, ctLoad), index(threads.size_s() - 1, ctLoad));
|
|
}
|
|
|
|
|
|
void ThreadsModel::clear() {
|
|
beginRemoveRows(QModelIndex(), 0, threads.size_s() - 1);
|
|
threads.clear();
|
|
endRemoveRows();
|
|
}
|
|
|
|
|
|
int ThreadsModel::rowCount(const QModelIndex & parent) const {
|
|
return threads.size_s();
|
|
}
|
|
|
|
|
|
int ThreadsModel::columnCount(const QModelIndex & parent) const {
|
|
return ctColumnCount;
|
|
}
|
|
|
|
|
|
QModelIndex ThreadsModel::index(int row, int column, const QModelIndex & parent) const {
|
|
if (row >= threads.size_s() || row >= threads.size_s()) return QModelIndex();
|
|
return createIndex(row, column, quintptr(0));
|
|
}
|
|
|
|
|
|
bool ThreadsModel::hasChildren(const QModelIndex & parent) const {
|
|
if (!parent.isValid()) return true;
|
|
return false;
|
|
}
|
|
|
|
|
|
QVariant ThreadsModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
|
if (orientation != Qt::Horizontal || role != Qt::DisplayRole) return QVariant();
|
|
switch (section) {
|
|
case ctClassname: return tr("Classname");
|
|
case ctName : return tr("Name");
|
|
case ctID : return tr("pID (pri)");
|
|
case ctDelay : return tr("Delay, ms");
|
|
case ctState : return tr("State");
|
|
case ctLoad : return tr("CPU, %");
|
|
case ctRunCost : return tr("Run cost, avg");
|
|
case ctRunCount : return tr("Run counts");
|
|
default: break;
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
|
|
QVariant ThreadsModel::data(const QModelIndex & index, int role) const {
|
|
if (role != Qt::DisplayRole && role != Qt::DecorationRole && role != Qt::UserRole) return QVariant();
|
|
const PIIntrospectionThreads::ThreadInfo & ti(threads[index.row()]);
|
|
if (role == Qt::DisplayRole) {
|
|
switch (index.column()) {
|
|
case ctClassname: return PI2QString(ti.classname);
|
|
case ctName : return PI2QString(ti.name);
|
|
case ctID : return QString("%1 (%2)").arg(ti.id).arg(ti.priority);
|
|
case ctDelay : return QString::number(ti.delay);
|
|
case ctState : return state_names.value(ti.state);
|
|
case ctLoad : {
|
|
piForeachC (PISystemMonitor::ThreadStats & s, stat) {
|
|
if (s.id == llong(ti.id)) {
|
|
return QString::number(s.cpu_load_kernel + s.cpu_load_user, 'f', 2) + " %";
|
|
}
|
|
}
|
|
return "-";
|
|
}
|
|
case ctRunCost : {
|
|
double v = ti.run_us;
|
|
QByteArray suff = " us";
|
|
if (v > 1000.) {v /= 1000.; suff = " ms";}
|
|
if (v > 1000.) {v /= 1000.; suff = " s";}
|
|
return QString::number(v, 'f', 1) + suff;
|
|
}
|
|
case ctRunCount : return QString::number(ti.run_count);
|
|
}
|
|
}
|
|
if (index.column() == ctState) {
|
|
if (role == Qt::DecorationRole) {
|
|
return state_colors.value(ti.state);
|
|
}
|
|
if (role == Qt::UserRole) {
|
|
return int(ti.state);
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
|
|
Qt::ItemFlags ThreadsModel::flags(const QModelIndex & index) const {
|
|
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
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));
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
|
|
ThreadsView::ThreadsView(QWidget * parent): QWidget(parent) {
|
|
setupUi(this);
|
|
model = new ThreadsModel();
|
|
QSortFilterProxyModel * proxy = new QSortFilterProxyModel();
|
|
proxy->setSourceModel(model);
|
|
proxy->setSortRole(Qt::UserRole);
|
|
proxy->setDynamicSortFilter(false);
|
|
treeThreads->setModel(model);
|
|
connect(checkHideStopped, SIGNAL(toggled(bool)), this, SLOT(updateHidden()));
|
|
//treeContainers->setItemDelegate(new ContainersDelegate(model));
|
|
}
|
|
|
|
|
|
ThreadsView::~ThreadsView() {
|
|
}
|
|
|
|
|
|
void ThreadsView::setStat(const PIVector<PISystemMonitor::ThreadStats> & stat) {
|
|
model->setStat(stat);
|
|
}
|
|
|
|
|
|
void ThreadsView::changeEvent(QEvent * e) {
|
|
QWidget::changeEvent(e);
|
|
switch (e->type()) {
|
|
case QEvent::LanguageChange:
|
|
retranslateUi(this);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void ThreadsView::updateHidden() {
|
|
bool hide_stopped = checkHideStopped->isChecked();
|
|
QModelIndex root = treeThreads->rootIndex();
|
|
for (int i = 0; i < model->rowCount(); ++i) {
|
|
if (!hide_stopped) treeThreads->setRowHidden(i, root, false);
|
|
else {
|
|
if (model->index(i, ctState).data(Qt::UserRole).toInt() == PIIntrospectionThreads::sStopped)
|
|
treeThreads->setRowHidden(i, root, true);
|
|
else
|
|
treeThreads->setRowHidden(i, root, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ThreadsView::showThreads(const PIVector<PIIntrospectionThreads::ThreadInfo> & threads) {
|
|
model->update(threads);
|
|
updateHidden();
|
|
}
|
|
|
|
|
|
void ThreadsView::clear() {
|
|
model->clear();
|
|
}
|