moved to shstk
This commit is contained in:
13
utils/piintrospector/CMakeLists.txt
Normal file
13
utils/piintrospector/CMakeLists.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
project(piintrospector)
|
||||
if(APPLE)
|
||||
set(APP_ICON "")
|
||||
elseif(WIN32)
|
||||
set(APP_ICON "")
|
||||
else()
|
||||
set(APP_ICON "")
|
||||
endif()
|
||||
set(APP_INFO "PIConnection GUI editor")
|
||||
include(PIPMacros)
|
||||
set(PII_ROOT "${ROOT_DIR}/pip/libs/main/introspection")
|
||||
pip_code_model(CCM "${PII_ROOT}/piintrospection_server_p.h" "${PII_ROOT}/piintrospection_threads_p.h" OPTIONS "-DPIP_EXPORT" "-Es")
|
||||
piqt_application(${PROJECT_NAME} "Gui;Widgets" "qad_utils;qad_widgets;qad_application;piqt_utils" ${CCM})
|
||||
264
utils/piintrospector/containers_view.cpp
Normal file
264
utils/piintrospector/containers_view.cpp
Normal file
@@ -0,0 +1,264 @@
|
||||
#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();
|
||||
}
|
||||
76
utils/piintrospector/containers_view.h
Normal file
76
utils/piintrospector/containers_view.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#ifndef CONTAINERS_VIEW_H
|
||||
#define CONTAINERS_VIEW_H
|
||||
|
||||
#include "ui_containers_view.h"
|
||||
#include <QDebug>
|
||||
#include <QWidget>
|
||||
#include <QAbstractItemModel>
|
||||
#include <QStyledItemDelegate>
|
||||
#include "piqt.h"
|
||||
#include "piintrospection_containers_p.h"
|
||||
|
||||
class ContainersModel: public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ContainersModel();
|
||||
|
||||
void update(const PIVector<PIIntrospectionContainers::TypeInfo> & t);
|
||||
void clear();
|
||||
|
||||
int rowCount(const QModelIndex & parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex & parent = QModelIndex()) const;
|
||||
QModelIndex parent(const QModelIndex & child) const {return QModelIndex();}
|
||||
QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const;
|
||||
bool hasChildren(const QModelIndex & parent = QModelIndex()) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
QVariant data(const QModelIndex & index, int role) const;
|
||||
Qt::ItemFlags flags(const QModelIndex & index) const;
|
||||
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
|
||||
|
||||
protected:
|
||||
PIVector<PIIntrospectionContainers::TypeInfo> cur_data;
|
||||
PIMap<uint, PIIntrospectionContainers::TypeInfo> prev_data;
|
||||
PIVector<llong> all, prev_all;
|
||||
Qt::SortOrder ls_order;
|
||||
int ls_column;
|
||||
bool mode_changes;
|
||||
|
||||
public slots:
|
||||
void setChangesMode(bool yes);
|
||||
|
||||
};
|
||||
|
||||
|
||||
class ContainersDelegate: public QStyledItemDelegate {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ContainersDelegate(QAbstractItemModel * m) {model = m;}
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem & option, const QModelIndex &index) const;
|
||||
QAbstractItemModel * model;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ContainersView: public QWidget, private Ui::ContainersView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ContainersView(QWidget * parent = 0);
|
||||
~ContainersView();
|
||||
void showContainers(const PIVector<PIIntrospectionContainers::TypeInfo> & t);
|
||||
void clear();
|
||||
protected:
|
||||
void changeEvent(QEvent * e);
|
||||
|
||||
ContainersModel * model;
|
||||
|
||||
private slots:
|
||||
void sessionSave(QByteArray * data) {*data = treeContainers->header()->saveState();}
|
||||
void sessionLoad(QByteArray * data) {treeContainers->header()->restoreState(*data);}
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // CONTAINERS_VIEW_H
|
||||
93
utils/piintrospector/containers_view.ui
Normal file
93
utils/piintrospector/containers_view.ui
Normal file
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ContainersView</class>
|
||||
<widget class="QWidget" name="ContainersView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>610</width>
|
||||
<height>406</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioOverall">
|
||||
<property name="text">
|
||||
<string>Overall</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioChanges">
|
||||
<property name="text">
|
||||
<string>Changes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>1</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="treeContainers">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
60
utils/piintrospector/objects_view.cpp
Normal file
60
utils/piintrospector/objects_view.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "objects_view.h"
|
||||
#include <QScrollBar>
|
||||
#include <QTreeWidget>
|
||||
|
||||
|
||||
enum ColumnObjects {
|
||||
coClassName,
|
||||
coName,
|
||||
coParents,
|
||||
coQueuedEvents,
|
||||
};
|
||||
|
||||
|
||||
ObjectsView::ObjectsView(QWidget * parent): QWidget(parent) {
|
||||
setupUi(this);
|
||||
}
|
||||
|
||||
|
||||
ObjectsView::~ObjectsView() {
|
||||
}
|
||||
|
||||
|
||||
void ObjectsView::changeEvent(QEvent * e) {
|
||||
QWidget::changeEvent(e);
|
||||
switch (e->type()) {
|
||||
case QEvent::LanguageChange:
|
||||
retranslateUi(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ObjectsView::showObjects(const PIVector<PIIntrospection::ObjectInfo> & objects) {
|
||||
QHash<QString, int> stat;
|
||||
|
||||
int vpos = treeObjects->verticalScrollBar()->value();
|
||||
treeObjects->clear();
|
||||
piForeachC (PIIntrospection::ObjectInfo & i, objects) {
|
||||
stat[PI2QString(i.classname)]++;
|
||||
QTreeWidgetItem * ti = new QTreeWidgetItem();
|
||||
ti->setText(coClassName, PI2QString(i.classname));
|
||||
ti->setText(coName, PI2QString(i.name));
|
||||
ti->setText(coParents, PI2QString(i.parents.join(":")));
|
||||
ti->setText(coQueuedEvents, QString::number(i.queued_events));
|
||||
treeObjects->addTopLevelItem(ti);
|
||||
}
|
||||
treeObjects->verticalScrollBar()->setValue(vpos);
|
||||
|
||||
vpos = treeObjectsStat->verticalScrollBar()->value();
|
||||
treeObjectsStat->clear();
|
||||
for (QHash<QString, int>::const_iterator i = stat.constBegin(); i != stat.constEnd(); ++i) {
|
||||
QTreeWidgetItem * ti = new QTreeWidgetItem();
|
||||
ti->setText(0, i.key());
|
||||
ti->setText(1, QString::number(i.value()));
|
||||
treeObjectsStat->addTopLevelItem(ti);
|
||||
}
|
||||
treeObjectsStat->verticalScrollBar()->setValue(vpos);
|
||||
}
|
||||
28
utils/piintrospector/objects_view.h
Normal file
28
utils/piintrospector/objects_view.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef OBJECTS_VIEW_H
|
||||
#define OBJECTS_VIEW_H
|
||||
|
||||
#include "ui_objects_view.h"
|
||||
#include <QDebug>
|
||||
#include <QWidget>
|
||||
#include "piqt.h"
|
||||
#include "piintrospection_server_p.h"
|
||||
|
||||
class ObjectsView: public QWidget, private Ui::ObjectsView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ObjectsView(QWidget * parent = 0);
|
||||
~ObjectsView();
|
||||
void showObjects(const PIVector<PIIntrospection::ObjectInfo> & objects);
|
||||
protected:
|
||||
void changeEvent(QEvent * e);
|
||||
|
||||
private slots:
|
||||
void sessionSave(QByteArray * data) {*data = treeObjects->header()->saveState();}
|
||||
void sessionLoad(QByteArray * data) {treeObjects->header()->restoreState(*data);}
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // OBJECTS_VIEW_H
|
||||
101
utils/piintrospector/objects_view.ui
Normal file
101
utils/piintrospector/objects_view.ui
Normal file
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ObjectsView</class>
|
||||
<widget class="QWidget" name="ObjectsView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>614</width>
|
||||
<height>413</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidgetObjects">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab_5">
|
||||
<attribute name="title">
|
||||
<string>List</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="treeObjects">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>class</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>parents</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>queued_events</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_6">
|
||||
<attribute name="title">
|
||||
<string>Statictic</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="treeObjectsStat">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>class</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>count</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
242
utils/piintrospector/piintrospector.cpp
Normal file
242
utils/piintrospector/piintrospector.cpp
Normal file
@@ -0,0 +1,242 @@
|
||||
#include "piintrospector.h"
|
||||
#include <QClipboard>
|
||||
#include <QScrollBar>
|
||||
#include "pifile.h"
|
||||
#include "pitime.h"
|
||||
#include "pidir.h"
|
||||
#include "pichunkstream.h"
|
||||
#include "ccm_piintrospector.h"
|
||||
|
||||
|
||||
QPIIntrospector::QPIIntrospector(QWidget * parent): EMainWindow(parent), peer("__introspection_client__") {
|
||||
setupUi(this);
|
||||
request_timer = 0;
|
||||
session.setFile("qpiintrospector_session.conf");
|
||||
#if QT_VERSION >= 0x050000
|
||||
//treeContainers->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
#else
|
||||
//treeContainers->header()->setResizeMode(QHeaderView::ResizeToContents);
|
||||
#endif
|
||||
CONNECTU_QUEUED(&peer, peerConnectedEvent, this, peersChanged, this);
|
||||
CONNECTU_QUEUED(&peer, peerDisconnectedEvent, this, peersChanged, this);
|
||||
CONNECTU_QUEUED(&peer, dataReceivedEvent, this, peerReceived, this);
|
||||
CONNECTU(&peer, peerConnectedEvent, this, reqProcPIEvents);
|
||||
CONNECTU(&peer, peerDisconnectedEvent, this, reqProcPIEvents);
|
||||
CONNECTU(&peer, dataReceivedEvent, this, reqProcPIEvents);
|
||||
session.addEntry(this);
|
||||
session.addEntry(tabWidgetMain);
|
||||
PICodeInfo::EnumInfo * ei = PICodeInfo::enumsInfo->value("PIIntrospection::InfoTypes");
|
||||
if (ei) {
|
||||
piForeachC (PICodeInfo::EnumeratorInfo & e, ei->members) {
|
||||
QCheckBox * cb = new QCheckBox(PI2QString(e.name.mid(2)));
|
||||
cb->setObjectName(QString("checkRequest%1").arg(e.value));
|
||||
cb->setProperty("__value__", e.value);
|
||||
layoutRequestFlags->addWidget(cb);
|
||||
session.addEntry(cb);
|
||||
}
|
||||
}
|
||||
//startTimer(100);
|
||||
session.load();
|
||||
peer.start();
|
||||
}
|
||||
|
||||
|
||||
QPIIntrospector::~QPIIntrospector() {
|
||||
session.save();
|
||||
peer.stop();
|
||||
}
|
||||
|
||||
|
||||
void QPIIntrospector::changeEvent(QEvent * e) {
|
||||
EMainWindow::changeEvent(e);
|
||||
switch (e->type()) {
|
||||
case QEvent::LanguageChange:
|
||||
retranslateUi(this);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QPIIntrospector::timerEvent(QTimerEvent * e) {
|
||||
if (e->timerId() == request_timer)
|
||||
buttonRequest->click();
|
||||
}
|
||||
|
||||
|
||||
void QPIIntrospector::savingSession(QPIConfig & conf) {
|
||||
conf.setValue("treeStat_header", treeStat->header()->saveState());
|
||||
}
|
||||
|
||||
|
||||
void QPIIntrospector::loadingSession(QPIConfig & conf) {
|
||||
treeStat->header()->restoreState(conf.getValue("treeStat_header").toByteArray());
|
||||
}
|
||||
|
||||
|
||||
void QPIIntrospector::buildTree(QByteArray d) {
|
||||
/*PIVector<PIIntrospectionThreads::ThreadInfo> threads;
|
||||
PIByteArray pd = Q2PIByteArray(d);
|
||||
pd >> threads;
|
||||
treeContainers->clear();
|
||||
piForeachC (PIIntrospectionThreads::ThreadInfo & t, threads) {
|
||||
QTreeWidgetItem * ti = new QTreeWidgetItem();
|
||||
ti->setText(0, QString(PI2QString(t.name) + " (%1)").arg(t.id));
|
||||
treeContainers->addTopLevelItem(ti);
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
void QPIIntrospector::procRequestTimer() {
|
||||
if (request_timer != 0) killTimer(request_timer);
|
||||
request_timer = 0;
|
||||
if (!checkRequestTimer->isChecked()) return;
|
||||
request_timer = startTimer(1000 / spinRequestTimerHz->value());
|
||||
}
|
||||
|
||||
|
||||
void QPIIntrospector::buildDumpSection(QTreeWidgetItem * pi, PIString & str) {
|
||||
}
|
||||
|
||||
|
||||
void QPIIntrospector::showInfo() {
|
||||
PIString s;
|
||||
s << info.execCommand << "\n";
|
||||
s << info.execDateTime.toString() << "\n";
|
||||
s << info.OS_name << "(" << info.OS_version << ", " << info.architecture << ")\n";
|
||||
s << info.user << "\n";
|
||||
s << info.build_options.join(", ") << "\n";
|
||||
s << "\n";
|
||||
s << "load k: " << PIString::fromNumber(stat.proc.cpu_load_system, 'f', 2) << " %\n";
|
||||
s << "load u: " << PIString::fromNumber(stat.proc.cpu_load_user, 'f', 2) << " %\n";
|
||||
s << "threads: " << stat.proc.threads << "\n";
|
||||
s << "memory usage: " << stat.proc.physical_memsize_readable;
|
||||
labelInfo->setText(PI2QString(s));
|
||||
int tlic = treeStat->topLevelItemCount();
|
||||
for (int i = tlic; i < stat.threads.size_s(); ++i)
|
||||
treeStat->addTopLevelItem(new QTreeWidgetItem());
|
||||
for (int i = tlic - 1; i >= stat.threads.size_s(); --i)
|
||||
delete treeStat->topLevelItem(i);
|
||||
tlic = piMini(treeStat->topLevelItemCount(), stat.threads.size_s());
|
||||
for (int i = 0; i < tlic; ++i) {
|
||||
QTreeWidgetItem * ti = treeStat->topLevelItem(i);
|
||||
PISystemMonitor::ThreadStats & ts(stat.threads[i]);
|
||||
ti->setText(0, QString::number(i + 1));
|
||||
ti->setText(1, QString::number(ts.id));
|
||||
ti->setText(2, PI2QString(ts.name));
|
||||
ti->setText(3, durationStr(ts.work_time));
|
||||
ti->setText(4, QString::number(ts.cpu_load_kernel, 'f', 2));
|
||||
ti->setText(5, QString::number(ts.cpu_load_user, 'f', 2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString QPIIntrospector::durationStr(PISystemTime t) {
|
||||
QString ret;
|
||||
double s = t.toSeconds();
|
||||
int d, h, m;
|
||||
d = piFloor(s / (24*60*60));
|
||||
if (d > 0) {
|
||||
ret += QString::number(d) + " d ";
|
||||
s -= d * (24*60*60);
|
||||
}
|
||||
h = piFloor(s / (60*60));
|
||||
if (h > 0) {
|
||||
ret += QString::number(h) + " h ";
|
||||
s -= h * (60*60);
|
||||
}
|
||||
m = piFloor(s / 60);
|
||||
if (m > 0) {
|
||||
ret += QString::number(m).rightJustified(2, '0') + " m ";
|
||||
s -= m * 60;
|
||||
}
|
||||
ret += QString::number(piFloor(s)).rightJustified(2, '0') + " s";
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void QPIIntrospector::on_listApp_currentRowChanged(int r) {
|
||||
PIString cs;
|
||||
if (r < 0) cs.clear();
|
||||
else cs = Q2PIString(listApp->item(r)->text());
|
||||
if (cur_server != cs)
|
||||
widgetContainers->clear();
|
||||
cur_server = cs;
|
||||
}
|
||||
|
||||
|
||||
void QPIIntrospector::peerReceived(const PIString & from, const PIByteArray & data) {
|
||||
if (from != cur_server) return;
|
||||
//piCout << "rec" << data.size();
|
||||
PIByteArray ba(data);
|
||||
if (ba.size_s() < 4) return;
|
||||
uint sign(0); ba >> sign;
|
||||
if (sign != PIIntrospection::sign) return;
|
||||
PIChunkStream cs(ba);
|
||||
PIByteArray pba;
|
||||
while (!cs.atEnd()) {
|
||||
switch (cs.read()) {
|
||||
case PIIntrospection::itInfo: {
|
||||
cs.get(pba);
|
||||
PIIntrospection::unpackInfo(pba, info);
|
||||
} break;
|
||||
case PIIntrospection::itProcStat: {
|
||||
cs.get(pba);
|
||||
PIIntrospection::unpackProcStat(pba, stat);
|
||||
widgetThreads->setStat(stat.threads);
|
||||
//showInfo(info);
|
||||
} break;
|
||||
case PIIntrospection::itContainers: {
|
||||
cs.get(pba);
|
||||
PIVector<PIIntrospectionContainers::TypeInfo> data;
|
||||
PIIntrospection::unpackContainers(pba, data);
|
||||
widgetContainers->showContainers(data);
|
||||
} break;
|
||||
case PIIntrospection::itObjects: {
|
||||
cs.get(pba);
|
||||
PIVector<PIIntrospection::ObjectInfo> objects;
|
||||
PIIntrospection::unpackObjects(pba, objects);
|
||||
widgetObjects->showObjects(objects);
|
||||
} break;
|
||||
case PIIntrospection::itThreads: {
|
||||
cs.get(pba);
|
||||
PIVector<PIIntrospectionThreads::ThreadInfo> threads;
|
||||
PIIntrospection::unpackThreads(pba, threads);
|
||||
widgetThreads->showThreads(threads);
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
showInfo();
|
||||
}
|
||||
|
||||
|
||||
void QPIIntrospector::peersChanged(const PIString & name) {
|
||||
listApp->blockSignals(true);
|
||||
QString cs = listApp->currentItem() ? listApp->currentItem()->text() : "";
|
||||
listApp->clear();
|
||||
peer.lock();
|
||||
piForeachC (PIPeer::PeerInfo & p, peer.allPeers()) {
|
||||
QString pn = PI2QString(p.name);
|
||||
listApp->addItem(pn);
|
||||
if (pn == cs)
|
||||
listApp->setCurrentRow(listApp->count() - 1);
|
||||
}
|
||||
peer.unlock();
|
||||
listApp->blockSignals(false);
|
||||
}
|
||||
|
||||
|
||||
void QPIIntrospector::on_buttonRequest_clicked() {
|
||||
if (cur_server.isEmpty()) return;
|
||||
PIIntrospection::RequiredInfo info;
|
||||
for (int i = 0; i < layoutRequestFlags->count(); ++i) {
|
||||
QCheckBox * cb = qobject_cast<QCheckBox*>(layoutRequestFlags->itemAt(i)->widget());
|
||||
if (!cb) continue;
|
||||
if (!cb->isChecked()) continue;
|
||||
info.types |= cb->property("__value__").toInt();
|
||||
}
|
||||
PIByteArray ba;
|
||||
ba << PIIntrospection::sign << info;
|
||||
peer.send(cur_server, ba);
|
||||
}
|
||||
53
utils/piintrospector/piintrospector.h
Normal file
53
utils/piintrospector/piintrospector.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef PIINTROSPECTOR_H
|
||||
#define PIINTROSPECTOR_H
|
||||
|
||||
#include "ui_piintrospector.h"
|
||||
#include <QImage>
|
||||
#include <QTime>
|
||||
#include <QDesktopWidget>
|
||||
#include <QDebug>
|
||||
#include <emainwindow.h>
|
||||
#include "piqt.h"
|
||||
#include "pipeer.h"
|
||||
#include "piintrospection_server_p.h"
|
||||
|
||||
class QPIIntrospector: public EMainWindow, private Ui::QPIIntrospector, public PIObject
|
||||
{
|
||||
Q_OBJECT
|
||||
PIOBJECT(QPIIntrospector)
|
||||
public:
|
||||
QPIIntrospector(QWidget * parent = 0);
|
||||
~QPIIntrospector();
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent * e);
|
||||
void timerEvent(QTimerEvent * );
|
||||
void savingSession(QPIConfig & conf);
|
||||
void loadingSession(QPIConfig & conf);
|
||||
|
||||
void buildDumpSection(QTreeWidgetItem * pi, PIString & str);
|
||||
void showInfo();
|
||||
EVENT_HANDLER(void, reqProcPIEvents) {QMetaObject::invokeMethod(this, "procPIEvents", Qt::QueuedConnection);}
|
||||
QString durationStr(PISystemTime t);
|
||||
|
||||
EVENT_HANDLER2(void, peerReceived, const PIString &, from, const PIByteArray &, data);
|
||||
EVENT_HANDLER1(void, peersChanged, const PIString &, name);
|
||||
|
||||
PIString cur_server;
|
||||
PIIntrospection::ProcessInfo info;
|
||||
PIIntrospection::ProcessStat stat;
|
||||
PIPeer peer;
|
||||
int request_timer;
|
||||
|
||||
private slots:
|
||||
void procPIEvents() {callQueuedEvents();}
|
||||
void buildTree(QByteArray d);
|
||||
void procRequestTimer();
|
||||
void on_listApp_currentRowChanged(int r);
|
||||
void on_buttonRequest_clicked();
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // PIINTROSPECTOR_H
|
||||
284
utils/piintrospector/piintrospector.ui
Normal file
284
utils/piintrospector/piintrospector.ui
Normal file
@@ -0,0 +1,284 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QPIIntrospector</class>
|
||||
<widget class="QMainWindow" name="QPIIntrospector">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>824</width>
|
||||
<height>597</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>PIP introspector</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Select application</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QListWidget" name="listApp">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Request</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QWidget" name="widgetRequestFlags" native="true">
|
||||
<layout class="QVBoxLayout" name="layoutRequestFlags">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonRequest">
|
||||
<property name="text">
|
||||
<string>Request</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkRequestTimer">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Timer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="spinRequestTimerHz">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> Hz</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.500000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidgetMain">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Info</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelInfo">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Threads:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="treeStat">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>#</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>id</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>uptime</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>kernel, %</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>user, %</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Containers</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="ContainersView" name="widgetContainers" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_4">
|
||||
<attribute name="title">
|
||||
<string>Objects</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="ObjectsView" name="widgetObjects" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_3">
|
||||
<attribute name="title">
|
||||
<string>Threads</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="ThreadsView" name="widgetThreads" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ObjectsView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>objects_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ContainersView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>containers_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ThreadsView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>threads_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>checkRequestTimer</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>QPIIntrospector</receiver>
|
||||
<slot>procRequestTimer()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>65</x>
|
||||
<y>552</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>6</x>
|
||||
<y>546</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinRequestTimerHz</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>QPIIntrospector</receiver>
|
||||
<slot>procRequestTimer()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>150</x>
|
||||
<y>552</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>140</x>
|
||||
<y>605</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>procRequestTimer()</slot>
|
||||
</slots>
|
||||
</ui>
|
||||
13
utils/piintrospector/piintrospector_main.cpp
Normal file
13
utils/piintrospector/piintrospector_main.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <QApplication>
|
||||
#include "piintrospector.h"
|
||||
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
QApplication a(argc, argv);
|
||||
#if QT_VERSION >= 0x050000
|
||||
a.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
|
||||
#endif
|
||||
QPIIntrospector w;
|
||||
w.show();
|
||||
return a.exec();
|
||||
}
|
||||
230
utils/piintrospector/threads_view.cpp
Normal file
230
utils/piintrospector/threads_view.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
#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) {
|
||||
state_names[e.value] = PI2QString(e.name.mid(1));
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
81
utils/piintrospector/threads_view.h
Normal file
81
utils/piintrospector/threads_view.h
Normal file
@@ -0,0 +1,81 @@
|
||||
#ifndef THREADS_VIEW_H
|
||||
#define THREADS_VIEW_H
|
||||
|
||||
#include "ui_threads_view.h"
|
||||
#include <QDebug>
|
||||
#include <QWidget>
|
||||
#include <QHash>
|
||||
#include <QTreeView>
|
||||
#include <QAbstractItemModel>
|
||||
#include <QStyledItemDelegate>
|
||||
#include "piqt.h"
|
||||
#include "pisystemmonitor.h"
|
||||
#include "piintrospection_threads_p.h"
|
||||
|
||||
|
||||
class ThreadsModel: public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ThreadsModel();
|
||||
|
||||
void update(const PIVector<PIIntrospectionThreads::ThreadInfo> & t);
|
||||
void setStat(const PIVector<PISystemMonitor::ThreadStats> & s);
|
||||
void clear();
|
||||
|
||||
int rowCount(const QModelIndex & parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex & parent = QModelIndex()) const;
|
||||
QModelIndex parent(const QModelIndex & child) const {return QModelIndex();}
|
||||
QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const;
|
||||
bool hasChildren(const QModelIndex & parent = QModelIndex()) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
QVariant data(const QModelIndex & index, int role) const;
|
||||
Qt::ItemFlags flags(const QModelIndex & index) const;
|
||||
|
||||
protected:
|
||||
PIVector<PIIntrospectionThreads::ThreadInfo> threads;
|
||||
PIVector<PISystemMonitor::ThreadStats> stat;
|
||||
QHash<int, QString> state_names;
|
||||
QHash<int, QColor> state_colors;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
class ContainersDelegate: public QStyledItemDelegate {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ContainersDelegate(QAbstractItemModel * m) {model = m;}
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem & option, const QModelIndex &index) const override;
|
||||
QAbstractItemModel * model;
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
class ThreadsView: public QWidget, private Ui::ThreadsView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ThreadsView(QWidget * parent = 0);
|
||||
~ThreadsView();
|
||||
|
||||
void setStat(const PIVector<PISystemMonitor::ThreadStats> & stat);
|
||||
void showThreads(const PIVector<PIIntrospectionThreads::ThreadInfo> & threads);
|
||||
void clear();
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent * e);
|
||||
|
||||
ThreadsModel * model;
|
||||
|
||||
private slots:
|
||||
void sessionSave(QByteArray * data) {*data = treeThreads->header()->saveState();}
|
||||
void sessionLoad(QByteArray * data) {treeThreads->header()->restoreState(*data);}
|
||||
void updateHidden();
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // CONTAINERS_VIEW_H
|
||||
51
utils/piintrospector/threads_view.ui
Normal file
51
utils/piintrospector/threads_view.ui
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ThreadsView</class>
|
||||
<widget class="QWidget" name="ThreadsView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>513</width>
|
||||
<height>365</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkHideStopped">
|
||||
<property name="text">
|
||||
<string>Hide stopped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="treeThreads">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Reference in New Issue
Block a user