#include "threads_view.h" #include "ccm_piintrospector.h" #include #include #include #include enum ColumnThreads { ctClassname, ctName, ctID, ctDelay, ctState, ctLoad, ctRunCost, ctRunCount, ctColumnCount, }; ThreadsModel::ThreadsModel() { PICodeInfo::EnumInfo * ei = PICODEINFO::enums().value("PIIntrospectionThreads::ThreadState"); if (ei) { for (const auto & 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 & 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 & 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: { for (const auto & 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 & 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 & threads) { model->update(threads); updateHidden(); } void ThreadsView::clear() { model->clear(); }