#include "piintrospector.h" #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; } 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 //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); //startTimer(100); session.addEntry(this); 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 * ) { } 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(); 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); }