Qml inspection, eventFilter
-
I want to build a documentation lookup/help system for my Qml interface elements. My interface has different "active" items like buttons, input fileds and "inactive" items like labels.
My idea is to give every ui element an doc-Id as property (or function return value) which acts as document lookup value.
The idea is to switch to a help mode and activate my event filter. The event filter should filter mouse-clicks and find the doc-Id of the clicked item.
I was able to implement a cusomized event-filter but when I dump the source object I cannot see my component nor get the property...virtual bool eventFilter(QObject *watched, QEvent *event) override { if (event->type() == QEvent::Type::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) { qDebug() << __FUNCTION__ << ":" << watched << watched->property("docId") << " - " << event->type(); // auto count = watched->metaObject()->propertyCount(); // for (int i = 0; i<count; ++i) { // qDebug() << QString::fromUtf8(watched->metaObject()->property(i).name()); // } // QMetaObject::invokeMethod(watched, "getDocId"); } return QObject::eventFilter(watched, event); }
Better ideas
-
I'll check back tomorrow or Tuesday to see if I can better explain the code that I am about to share.
I'm in a hurry today, so I'm just going to paste this and hope that anyone reading it can make use of it :)
#include <QQmlComponent> #include <QQmlProperty> #include <QQuickItem> void dumpRecursive( int level, QObject* object ) { if( object ) { QByteArray buf; buf.fill( ' ', level / 2 * 8 ); if( level % 2 ) buf += " "; QString name = object->objectName(); QVariant propv = QQmlProperty::read( object, "visible" ); if( propv.isNull() ) { fprintf( stderr, "%s\n", "IS_NULL visible prop" ); } else { QQmlProperty prop( object, "visible" ); fprintf( stderr, "hasNotifySignal %d\n", static_cast<int>( prop.hasNotifySignal() ) ); fprintf( stderr, "isResettable %d\n", static_cast<int>( prop.isResettable() ) ); fprintf( stderr, "isSignalProperty %d\n", static_cast<int>( prop.isSignalProperty() ) ); fprintf( stderr, "isValid %d\n", static_cast<int>( prop.isValid() ) ); fprintf( stderr, "isWritable %d\n", static_cast<int>( prop.isWritable() ) ); fprintf( stderr, "propertyTypeName %s\n", prop.propertyTypeName() ); fprintf( stderr, "needsNotifySignal %d\n", static_cast<int>( prop.needsNotifySignal() ) ); // bool QQmlProperty::needsNotifySignal() const // QMetaMethod m = prop.method(); } QVariant prop = QQmlProperty::read( object, "testtest" ); if( !prop.isNull() ) { if( !prop.canConvert<QList<QVariant>>() ) { fprintf( stderr, "%s\n", "whoooooooooooooooooooooooooops ! ! !" ); } else { QList<QVariant> list = prop.toList(); fprintf( stderr, "wheeeeeeeeeeeeeeeee %p\n", reinterpret_cast<void*>( &list ) ); for( const auto& state : list ) { fprintf( stderr, "got one %p\n", reinterpret_cast<void*>( &list ) ); if( state.canConvert<QQuickItem*>() ) { QQuickItem* t = state.value<QQuickItem*>(); fprintf( stderr, "converts one %p\n", reinterpret_cast<void*>( t ) ); } } } } qDebug( "%s%s::%s", reinterpret_cast<const char*>( buf.data() ), object->metaObject()->className(), name.toLocal8Bit().data() ); QObjectList children = object->children(); if( !children.isEmpty() ) { for( int i = 0; i < children.size(); ++i ) dumpRecursive( level + 1, children.at( i ) ); } } } void localDump( QObject* object ) { dumpRecursive( 0, object ); } // return true if the event should be filtered (i.e. stopped) bool EventFilter::eventFilter( QObject* obj, QEvent* event ) { localDump( obj ); return QObject::eventFilter( obj, event ); }