154 lines
4.2 KiB
C++
154 lines
4.2 KiB
C++
#include "qtdebugger.h"
|
|
#include "ui_debugwindow.h"
|
|
|
|
#include <QApplication>
|
|
#include <QDebug>
|
|
#include <QMetaProperty>
|
|
#include <QMainWindow>
|
|
#include <QSplitter>
|
|
#include <QWindow>
|
|
|
|
#include <functional>
|
|
#include <set>
|
|
|
|
#include "resourceexplorer.h"
|
|
|
|
QtDebugger::QtDebugger(QObject* parent) : QObject(parent), debugWindow( new QMainWindow() ), ui( new Ui::DebugWindow() ) {
|
|
this->ui->setupUi( debugWindow );
|
|
debugWindow->show();
|
|
|
|
QList<int> 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<void(const QObject*, uint32_t, uint32_t, QTreeWidgetItem*)> 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<QWidget*>( obj );
|
|
if ( widget ) {
|
|
this->oldStyleSheet = widget->styleSheet();
|
|
this->oldStyleSheetValid = true;
|
|
widget->setStyleSheet( "background-color: black;" );
|
|
}
|
|
|
|
// update the tree
|
|
std::function<void(const QMetaObject*)> 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<QString>() ? propVal.value<QString>() : "<unconvertable>";
|
|
|
|
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<QTreeWidgetItem*> 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<QWidget*>( obj );
|
|
if ( widget ) {
|
|
widget->setStyleSheet( this->oldStyleSheet );
|
|
}
|
|
|
|
this->oldStyleSheetValid = false;
|
|
this->oldStyleSheet.clear();
|
|
}
|
|
}
|