#include "qtdebugger.h" #include "ui_debugwindow.h" #include #include #include #include #include #include #include #include #include "resourceexplorer.h" QtDebugger::QtDebugger(QObject* parent) : QObject(parent), debugWindow( new QMainWindow() ), ui( new Ui::DebugWindow() ) { this->ui->setupUi( debugWindow ); debugWindow->show(); QList sizes; sizes << 40 << 150 << 490; this->ui->splitter->setSizes( sizes ); QObject::connect( this->ui->refreshButton, &QPushButton::clicked, this, &QtDebugger::refresh ); QObject::connect( this->ui->objectTree, &QTreeWidget::currentItemChanged, this, &QtDebugger::currentObjectChanged ); QObject::connect( this->ui->resourceExplorerButton, &QPushButton::clicked, this, &QtDebugger::openResourceExplorer ); this->refresh(); } QtDebugger::~QtDebugger() { delete this->debugWindow; delete this->ui; } void QtDebugger::refresh() { this->resetStyleSheet(); this->ui->objectTree->clear(); this->ui->propertiesTree->clear(); // update object tree std::function walkTree = [&](const QObject* obj, uint32_t maxdepth, uint32_t currentDepth, QTreeWidgetItem* root) { if ( !obj ) { return; } QTreeWidgetItem* item = new QTreeWidgetItem( ); item->setText(0, obj->metaObject()->className() ); item->setText(1, obj->objectName() ); item->setData(0, Qt::UserRole, QVariant((unsigned long long) obj)); root->addChild( item ); if( currentDepth < maxdepth ) { const QObjectList& childs = obj->children(); for( const QObject* child : childs ) { walkTree( child, maxdepth, currentDepth+1, item ); } } }; QTreeWidgetItem* root = new QTreeWidgetItem( ); root->setText( 0, "root" ); this->ui->objectTree->insertTopLevelItem( 0, root ); walkTree( qApp, 128, 0, root); // get windows QWidgetList tlWidgets = qApp->topLevelWidgets(); for ( QWidget* wdg : tlWidgets ) { walkTree( wdg, 128, 0, root); } } void QtDebugger::currentObjectChanged( QTreeWidgetItem* new_, QTreeWidgetItem* old ) { Q_UNUSED( old ); this->ui->propertiesTree->clear(); this->resetStyleSheet(); if ( !new_ ) { qWarning() << "invalid row"; return; } // find the object QVariant variant = new_->data(0, Qt::UserRole); QObject* obj = (QObject*) variant.toULongLong(); if( !obj ) { qWarning() << "invalid Object"; return; } QWidget* widget = qobject_cast( obj ); if ( widget ) { this->oldStyleSheet = widget->styleSheet(); this->oldStyleSheetValid = true; widget->setStyleSheet( "background-color: black;" ); } // update the tree std::function readProperties = [&] (const QMetaObject* meta) { if (!meta) { return; } QTreeWidgetItem* item = new QTreeWidgetItem(); item->setText(0, meta->className()); this->ui->propertiesTree->insertTopLevelItem( 0, item ); item->setExpanded( true ); // read superclass properties readProperties(meta->superClass()); for( int32_t i = meta->propertyOffset(); i < meta->propertyCount(); ++i ) { QMetaProperty prop = meta->property(i); QString propName = prop.name(); QVariant propVal = prop.read(obj); // QString value = propVal.canConvert() ? propVal.value() : ""; QTreeWidgetItem* propItem = new QTreeWidgetItem(); propItem->setText(0, prop.typeName()); propItem->setText(1, propName); propItem->setData(2, Qt::DisplayRole, propVal); item->addChild( propItem ); } }; readProperties( obj->metaObject() ); } void QtDebugger::openResourceExplorer() { ResourceExplorer* re = new ResourceExplorer( debugWindow ); re->show(); } void QtDebugger::resetStyleSheet() { // get currently selected item QList items = this->ui->objectTree->selectedItems(); if ( this->oldStyleSheetValid && items.size() == 1 ) { QTreeWidgetItem* item = items.at(0); QVariant var = item->data(0, Qt::UserRole); QObject* obj = (QObject*) var.toULongLong(); QWidget* widget = qobject_cast( obj ); if ( widget ) { widget->setStyleSheet( this->oldStyleSheet ); } this->oldStyleSheetValid = false; this->oldStyleSheet.clear(); } }