diff --git a/piqt_utils/piintrospector/CMakeLists.txt b/piqt_utils/piintrospector/CMakeLists.txt index 3b2f127..7cfc432 100644 --- a/piqt_utils/piintrospector/CMakeLists.txt +++ b/piqt_utils/piintrospector/CMakeLists.txt @@ -3,7 +3,7 @@ file(GLOB SRC "*.h" "*.cpp" "*.ui" "*.qrc" "lang/*.ts") find_qt(${QtVersions} Core Gui) qt_wrap(${SRC} HDRS out_HDR CPPS out_CPP QMS out_QM) qt_add_executable(${PROJECT_NAME} WIN32 out_CPP) -qt_target_link_libraries(${PROJECT_NAME} pip qad_utils qad_widgets piqt_utils) +qt_target_link_libraries(${PROJECT_NAME} pip qad_utils qad_widgets qad_application piqt_utils) message(STATUS "Building ${PROJECT_NAME}") if(LIB) if(WIN32) diff --git a/piqt_utils/piintrospector/piintrospector.cpp b/piqt_utils/piintrospector/piintrospector.cpp index 3f7fdb3..e27832d 100644 --- a/piqt_utils/piintrospector/piintrospector.cpp +++ b/piqt_utils/piintrospector/piintrospector.cpp @@ -2,23 +2,65 @@ #include "pifile.h" #include "pitime.h" #include "pidir.h" +#include "pichunkstream.h" #include +#include + +#include +const QString demangle(const char * name) { + int status = -4; + char * res = abi::__cxa_demangle(name, NULL, NULL, &status); + QString ret((status == 0) ? res : name); + free(res); + return ret; +} -QPIIntrospector::QPIIntrospector(QWidget * parent): QMainWindow(parent), peer("__introspection_client__") { +enum ColumnContainers { + ccType, + ccCount, + ccItems, + ccBytesAllocated, + ccBytesUsed, +}; + +enum ColumnObjects { + coClassName, + coName, + coParents, + coQueuedEvents, +}; + + +QPIIntrospector::QPIIntrospector(QWidget * parent): EMainWindow(parent), peer("__introspection_client__") { setupUi(this); + session.setFile("qpiintrospector_session.conf"); #if QT_VERSION >= 0x050000 - tree->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + //treeContainers->header()->setSectionResizeMode(QHeaderView::ResizeToContents); #else - tree->header()->setResizeMode(QHeaderView::ResizeToContents); + //treeContainers->header()->setResizeMode(QHeaderView::ResizeToContents); #endif - CONNECTU(&peer, dataReceivedEvent, this, peerReceived) - startTimer(100); + 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); + //startTimer(100); + session.addEntry(this); + session.load(); + peer.start(); +} + + +QPIIntrospector::~QPIIntrospector() { + session.save(); + peer.stop(); } void QPIIntrospector::changeEvent(QEvent * e) { - QMainWindow::changeEvent(e); + EMainWindow::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: retranslateUi(this); @@ -30,6 +72,124 @@ void QPIIntrospector::changeEvent(QEvent * e) { void QPIIntrospector::timerEvent(QTimerEvent * ) { +} + + +void QPIIntrospector::buildTree(QByteArray d) { + /*PIVector 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::buildDumpSection(QTreeWidgetItem * pi, PIString & str) { +} + + +void QPIIntrospector::showInfo(const PIIntrospection::ProcessInfo & info) { + 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(", "); + labelInfo->setText(PI2QString(s)); +} + + +void QPIIntrospector::showContainers(const PIMap & data, const PIMap & typenames) { + int vpos = treeContainers->verticalScrollBar()->value(); + treeContainers->clear(); + for (auto i = data.constBegin(); i != data.constEnd(); ++i) { + QTreeWidgetItem * ti = new QTreeWidgetItem(); + ti->setText(ccType, demangle(typenames.value(i.key(), PIString::fromNumber(i.key())).dataAscii())); + ti->setText(ccCount, QString::number(i.value().count)); + ti->setText(ccItems, QString::number(i.value().items)); + ti->setText(ccBytesAllocated, PI2QString(PIString::readableSize(i.value().bytes_allocated))); + ti->setText(ccBytesUsed, PI2QString(PIString::readableSize(i.value().bytes_used))); + treeContainers->addTopLevelItem(ti); + } + treeContainers->verticalScrollBar()->setValue(vpos); +} + + +void QPIIntrospector::showObjects(const PIVector & objects) { + QHash 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 (auto 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); +} + + +void QPIIntrospector::on_listApp_currentRowChanged(int r) { + if (r < 0) cur_server.clear(); + else cur_server = Q2PIString(listApp->item(r)->text()); +} + + +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 1: { + cs.get(pba); + PIIntrospection::ProcessInfo info; + PIIntrospection::unpackInfo(pba, info); + showInfo(info); + } break; + case 2: { + cs.get(pba); + PIMap data; + PIMap typenames; + PIIntrospection::unpackContainers(pba, data, typenames); + showContainers(data, typenames); + } break; + case 4: { + cs.get(pba); + PIVector objects; + PIIntrospection::unpackObjects(pba, objects); + showObjects(objects); + } break; + default: break; + } + } +} + + +void QPIIntrospector::peersChanged(const PIString & name) { listApp->blockSignals(true); QString cs = listApp->currentItem() ? listApp->currentItem()->text() : ""; listApp->clear(); @@ -43,41 +203,3 @@ void QPIIntrospector::timerEvent(QTimerEvent * ) { peer.unlock(); listApp->blockSignals(false); } - - -void QPIIntrospector::buildTree(QByteArray d) { - PIVector threads; - PIByteArray pd = Q2PIByteArray(d); - pd >> threads; - tree->clear(); - piForeachC (PIIntrospectionThreads::ThreadInfo & t, threads) { - QTreeWidgetItem * ti = new QTreeWidgetItem(); - ti->setText(0, QString(PI2QString(t.name) + " (%1)").arg(t.id)); - tree->addTopLevelItem(ti); - } -} - - -void QPIIntrospector::buildDumpSection(QTreeWidgetItem * pi, PIString & str) { -} - - -void QPIIntrospector::on_listApp_currentRowChanged(int r) { - if (r < 0) cur_server.clear(); - else cur_server = Q2PIString(listApp->item(r)->text()); -} - - -void QPIIntrospector::peerReceived(const PIString & from, const PIByteArray & data) { - if (from != cur_server) return; - PIString appname; - PIIntrospectionContainers cont; - PIByteArray ba(data); - ba >> appname >> cont;// >> threads.threads; - /*QMetaObject::invokeMethod(labelAppname, "setText", Qt::QueuedConnection, Q_ARG(QString, PI2QString(appname))); - QMetaObject::invokeMethod(labelCount, "setText", Qt::QueuedConnection, Q_ARG(QString, QString::number(cont.count))); - QMetaObject::invokeMethod(labelAlloc, "setText", Qt::QueuedConnection, Q_ARG(QString, PI2QString(PIString::readableSize(cont.bytes_allocated)))); - QMetaObject::invokeMethod(labelUsed, "setText", Qt::QueuedConnection, Q_ARG(QString, PI2QString(PIString::readableSize(cont.bytes_used)))); - QMetaObject::invokeMethod(this, "buildTree", Qt::QueuedConnection, Q_ARG(QByteArray, PI2QByteArray(ba)));*/ - //piCout << appname; -} diff --git a/piqt_utils/piintrospector/piintrospector.h b/piqt_utils/piintrospector/piintrospector.h index e6708d0..da7bc86 100644 --- a/piqt_utils/piintrospector/piintrospector.h +++ b/piqt_utils/piintrospector/piintrospector.h @@ -6,30 +6,38 @@ #include #include #include +#include #include "piqt.h" #include "pipeer.h" -#include "piintrospection_containers_p.h" -#include "piintrospection_threads_p.h" +#include "piintrospection_server_p.h" -class QPIIntrospector: public QMainWindow, private Ui::QPIIntrospector, public PIObject +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 buildDumpSection(QTreeWidgetItem * pi, PIString & str); + void showInfo(const PIIntrospection::ProcessInfo & info); + void showContainers(const PIMap & data, const PIMap & typenames); + void showObjects(const PIVector & objects); + + EVENT_HANDLER(void, reqProcPIEvents) {QMetaObject::invokeMethod(this, "procPIEvents", Qt::QueuedConnection);} EVENT_HANDLER2(void, peerReceived, const PIString &, from, const PIByteArray &, data); + EVENT_HANDLER1(void, peersChanged, const PIString &, name); PIString cur_server; PIPeer peer; private slots: + void procPIEvents() {callQueuedEvents();} void buildTree(QByteArray d); void on_listApp_currentRowChanged(int r); diff --git a/piqt_utils/piintrospector/piintrospector.ui b/piqt_utils/piintrospector/piintrospector.ui index 48a7a83..6aac872 100644 --- a/piqt_utils/piintrospector/piintrospector.ui +++ b/piqt_utils/piintrospector/piintrospector.ui @@ -6,8 +6,8 @@ 0 0 - 923 - 661 + 824 + 597 @@ -40,91 +40,155 @@ - + - - - + + + 2 - - Qt::AlignCenter - - - - - - - Containers - - - - QFormLayout::AllNonFixedFieldsGrow - - - QFormLayout::DontWrapRows - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - count: - - - - - - - 0 - - - - - - - allocated: - - - - - - - 0 - - - - - - - used: - - - - - - - 0 - - - - - - - - - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::ScrollPerPixel - - - - - - + + + Info + + + + + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + Containers + + + + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::ScrollPerPixel + + + + type + + + + + count + + + + + items + + + + + bytes_allocated + + + + + bytes_used + + + + + + + + + Objects + + + + + + 1 + + + + List + + + + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::ScrollPerPixel + + + + class + + + + + name + + + + + parents + + + + + queued_events + + + + + + + + + Statictic + + + + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::ScrollPerPixel + + + + class + + + + + count + + + + + + + + + + + + + Threads + +