diff --git a/playground/invoker/Invoker.cpp b/playground/invoker/Invoker.cpp index 72105e65..83a60441 100644 --- a/playground/invoker/Invoker.cpp +++ b/playground/invoker/Invoker.cpp @@ -43,26 +43,26 @@ void Invoker::invoke( qreal realValue, int intValue, { void* args[4] = { nullptr }; - const auto types = callback.invokable().parameterTypes(); + void **a = args + 1; + const auto& invokable = callback.invokable(); - int i = 1; - for ( auto type : types ) + for ( int i = 0; i < invokable.parameterCount(); i++ ) { - switch ( type ) + switch ( invokable.parameterType( i ) ) { case QMetaType::Int: { - args[i++] = reinterpret_cast< void* >( &intValue ); + *a++ = reinterpret_cast< void* >( &intValue ); break; } case QMetaType::Double: { - args[i++] = reinterpret_cast< void* >( &realValue ); + *a++ = reinterpret_cast< void* >( &realValue ); break; } case QMetaType::QString: { - args[i++] = reinterpret_cast< void* >( &s ); + *a++ = reinterpret_cast< void* >( &s ); break; } default: diff --git a/src/common/QskMetaInvokable.cpp b/src/common/QskMetaInvokable.cpp index 7304e480..80761313 100644 --- a/src/common/QskMetaInvokable.cpp +++ b/src/common/QskMetaInvokable.cpp @@ -467,55 +467,55 @@ void QskMetaInvokable::reset() m_type = Invalid; } -QVector< int > QskMetaInvokable::parameterTypes() const +int QskMetaInvokable::parameterCount() const { - QVector< int > paramTypes; - switch( m_type ) { case MetaMethod: { // should be doable without QMetaMethod. TODO ... const auto method = QskMetaInvokable::method(); - - const int paramCount = method.parameterCount(); - if ( paramCount > 0 ) - { - paramTypes.reserve( paramCount ); - - for ( int i = 0; i < paramCount; i++ ) - paramTypes += method.parameterType( i ); - } - - break; + return method.parameterCount(); } case MetaProperty: { - // should be doable without QMetaProperty. TODO ... - const auto property = QskMetaInvokable::property(); - if ( property.isWritable() ) - { - paramTypes.reserve( 1 ); - paramTypes += property.userType(); - } - - break; + return 1; } case MetaFunction: { - auto types = function().parameterTypes(); - if ( types ) - { - while ( *types ) - paramTypes += *types++; - } - break; + return function().parameterCount(); } default: break; } - return paramTypes; + return 0; +} + +int QskMetaInvokable::parameterType( int index ) const +{ + switch( m_type ) + { + case MetaMethod: + { + const auto method = QskMetaInvokable::method(); + return method.parameterType( index ); + } + case MetaProperty: + { + const auto property = QskMetaInvokable::property(); + return property.userType(); + } + case MetaFunction: + { + auto types = function().parameterTypes(); + return types[index]; + } + default: + { + return QMetaType::UnknownType; + } + } } int QskMetaInvokable::returnType() const @@ -531,6 +531,9 @@ int QskMetaInvokable::returnType() const return function().returnType(); } case MetaProperty: + { + return QMetaType::Void; + } default: { return QMetaType::Void; @@ -560,7 +563,6 @@ QByteArray QskMetaInvokable::name() const return QByteArray(); } } - } QMetaMethod QskMetaInvokable::method() const diff --git a/src/common/QskMetaInvokable.h b/src/common/QskMetaInvokable.h index 320193a9..beff91ce 100644 --- a/src/common/QskMetaInvokable.h +++ b/src/common/QskMetaInvokable.h @@ -11,8 +11,6 @@ #include #include -template< typename T > class QVector; - class QskMetaFunction; class QMetaObject; class QMetaMethod; @@ -60,7 +58,9 @@ public: Type type() const; bool isNull() const; - QVector< int > parameterTypes() const; + int parameterCount() const; + int parameterType( int index ) const; + int returnType() const; void invoke( QObject*, void* args[], diff --git a/src/controls/QskShortcutMap.cpp b/src/controls/QskShortcutMap.cpp index 69e9b0af..88b1b117 100644 --- a/src/controls/QskShortcutMap.cpp +++ b/src/controls/QskShortcutMap.cpp @@ -5,9 +5,9 @@ #include "QskShortcutMap.h" #include "QskControl.h" +#include "QskMetaInvokable.h" #include -#include #include #include #include @@ -24,11 +24,8 @@ class QskShortcutHandler final : public QObject public: QskShortcutHandler(); - int add( QQuickItem*, const QKeySequence&, - const QObject* receiver, const char* method ); - - int add( QQuickItem*, const QKeySequence&, - const QObject* receiver, QtPrivate::QSlotObjectBase* ); + int insert( QQuickItem*, const QKeySequence&, bool autoRepeat, + const QObject*, const QskMetaInvokable& ); void remove( int id ); @@ -38,8 +35,6 @@ public: virtual bool eventFilter( QObject*, QEvent* ) override final; private: - int insert( QQuickItem*, const QKeySequence&, - const QObject* receiver, const QMetaMethod&, QtPrivate::QSlotObjectBase* ); void cleanUp( QObject* ); @@ -48,21 +43,13 @@ private: public: InvokeData(): item( nullptr ), - receiver( nullptr ), - slotObject( nullptr ) + receiver( nullptr ) { } - ~InvokeData() - { - if ( slotObject ) - slotObject->destroyIfLastRef(); - } - QQuickItem* item; const QObject* receiver; - QMetaMethod method; - QtPrivate::QSlotObjectBase* slotObject; + QskMetaInvokable invokable; }; std::map< int, InvokeData > m_invokeDataMap; @@ -82,7 +69,7 @@ static bool qskContextMatcher( QObject* object, Qt::ShortcutContext context ) { /* Unfortunatley there is no way to have to know about - the contextItem without making it the receiver of + the contextItem without making it the receiver of the following QShortcutEvent. So we have to install an event handler to process and swallow it in QskShortcutHandler. */ @@ -101,39 +88,25 @@ QskShortcutHandler::QskShortcutHandler() installEventFilter( this ); } -int QskShortcutHandler::add( QQuickItem* item, const QKeySequence& sequence, - const QObject* receiver, const char* method ) +int QskShortcutHandler::insert( + QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, + const QObject* receiver, const QskMetaInvokable& invokable ) { - int id = 0; - - if ( receiver ) + if ( sequence.isEmpty() ) { - const QMetaObject* metaObject = receiver->metaObject(); - - const int methodIndex = metaObject->indexOfMethod( - QMetaObject::normalizedSignature( method ).constData() + 1 ); - - if ( methodIndex >= 0 ) - { - id = insert( item, sequence, - receiver, metaObject->method( methodIndex ), nullptr ); - } + qDebug() << "QskShortcutMap: invalid shortcut key sequence"; + return 0; } - return id; -} +#if 1 + // should be a compile time check for functor based slots + if ( invokable.parameterCount() > 0 ) + { + qDebug() << "QskShortcutMap: invalid slot parameter count"; + return 0; + } +#endif -int QskShortcutHandler::add( QQuickItem* item, const QKeySequence& sequence, - const QObject* receiver, QtPrivate::QSlotObjectBase* slotObj ) -{ - return insert( item, sequence, receiver, QMetaMethod(), slotObj ); -} - -int QskShortcutHandler::insert( - QQuickItem* item, const QKeySequence& sequence, - const QObject* receiver, const QMetaMethod& method, - QtPrivate::QSlotObjectBase* slotObject ) -{ if ( receiver ) { connect( receiver, &QObject::destroyed, @@ -163,11 +136,10 @@ int QskShortcutHandler::insert( data.item = item; data.receiver = receiver; + data.invokable = invokable; - if ( slotObject ) - data.slotObject = slotObject; - else - data.method = method; + if ( !autoRepeat ) + setAutoRepeat( id, false ); return id; } @@ -266,30 +238,14 @@ bool QskShortcutHandler::eventFilter( QObject* object, QEvent* event ) const auto it = m_invokeDataMap.find( se->shortcutId() ); if ( it != m_invokeDataMap.end() ) { - const auto& invokeData = it->second; + auto& data = it->second; - Q_ASSERT( invokeData.item == nullptr || invokeData.item == object ); + Q_ASSERT( data.item == nullptr || data.item == object ); - auto receiver = const_cast< QObject* >( invokeData.receiver ); + auto receiver = const_cast< QObject* > ( data.receiver ); + void* args[] = { nullptr }; - if ( invokeData.slotObject ) - { - void* args[] = { 0 }; - - if ( receiver && receiver->thread() != thread() ) - { - QCoreApplication::postEvent( receiver, - new QMetaCallEvent( invokeData.slotObject, nullptr, 0, 0, nullptr, args ) ); - } - else - { - invokeData.slotObject->call( receiver, args ); - } - } - else - { - invokeData.method.invoke( receiver, Qt::AutoConnection ); - } + data.invokable.invoke( receiver, args, Qt::AutoConnection ); return true; } @@ -303,24 +259,26 @@ int QskShortcutMap::addMethod( QQuickItem* item, const QKeySequence& sequence, { if ( receiver == nullptr ) { + qDebug() << "QskShortcutMap: bad receiver for shortcut:" << sequence; return 0; } - int id = qskShortcutHandler->add( item, sequence, receiver, method ); - if ( id && !autoRepeat ) - qskShortcutHandler->setAutoRepeat( id, false ); - - return id; + return qskShortcutHandler->insert( + item, sequence, autoRepeat, receiver, qskMetaMethod( receiver, method ) ); } -int QskShortcutMap::addSlotObject( QQuickItem* item, const QKeySequence& sequence, - bool autoRepeat, const QObject* receiver, QtPrivate::QSlotObjectBase* slotObject ) +int QskShortcutMap::addFunction( QQuickItem* item, const QKeySequence& sequence, + bool autoRepeat, const QObject* receiver, const QskMetaFunction& function ) { - int id = qskShortcutHandler->add( item, sequence, receiver, slotObject ); - if ( id && !autoRepeat ) - qskShortcutHandler->setAutoRepeat( id, false ); + if ( ( receiver == nullptr ) + && ( function.functionType() == QskMetaFunction::Member ) ) + { + qDebug() << "QskShortcutMap: bad receiver for shortcut:" << sequence; + return 0; + } - return id; + return qskShortcutHandler->insert( + item, sequence, autoRepeat, receiver, function ); } void QskShortcutMap::setAutoRepeat( int id, bool on ) diff --git a/src/controls/QskShortcutMap.h b/src/controls/QskShortcutMap.h index d6c5c569..fd4a611f 100644 --- a/src/controls/QskShortcutMap.h +++ b/src/controls/QskShortcutMap.h @@ -7,6 +7,8 @@ #define QSK_SHORTCUT_MAP_H #include "QskGlobal.h" +#include "QskMetaFunction.h" + #include class QQuickItem; @@ -20,51 +22,34 @@ public: static void removeShortcut( int ); - // -- traditional slots - static int addShortcut( const QKeySequence&, bool autoRepeat, - const QObject* receiver, const char* method ); + // string based slots + static int addShortcut( const QKeySequence&, + bool autoRepeat, const QObject* receiver, const char* method ); - static int addShortcut( QQuickWindow*, const QKeySequence&, bool autoRepeat, - const QObject* receiver, const char* method ); + static int addShortcut( QQuickWindow*, const QKeySequence&, + bool autoRepeat, const QObject* receiver, const char* method ); - static int addShortcut( QQuickItem*, const QKeySequence&, bool autoRepeat, - const QObject* receiver, const char* method ); + static int addShortcut( QQuickItem*, const QKeySequence&, + bool autoRepeat, const QObject* receiver, const char* method ); - // -- calling a QObject method - template< typename Func1 > - static int addShortcut( const QKeySequence&, bool autoRepeat, - const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot ); + // functor based slots + static int addShortcut( const QKeySequence&, + bool autoRepeat, const QskMetaFunction& ); - template< typename Func1 > - static int addShortcut( QQuickWindow*, const QKeySequence&, bool autoRepeat, - const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot ); + static int addShortcut( const QKeySequence&, + bool autoRepeat, const QObject* context, const QskMetaFunction& ); - template< typename Func1 > - static int addShortcut( QQuickItem*, const QKeySequence&, bool autoRepeat, - const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot ); + static int addShortcut( QQuickItem*, const QKeySequence&, + bool autoRepeat, const QskMetaFunction& ); - // -- calling a functor or function pointer inside a thread context - template< typename Func1 > - static int addShortcut( const QKeySequence&, bool autoRepeat, - const QObject* context, Func1 slot ); + static int addShortcut( QQuickItem*, const QKeySequence&, + bool autoRepeat, const QObject* context, const QskMetaFunction& ); - template< typename Func1 > - static int addShortcut( QQuickWindow*, const QKeySequence&, bool autoRepeat, - const QObject* context, Func1 slot ); + static int addShortcut( QQuickWindow*, const QKeySequence&, + bool autoRepeat, const QskMetaFunction& ); - template< typename Func1 > - static int addShortcut( QQuickItem*, const QKeySequence&, bool autoRepeat, - const QObject* context, Func1 slot ); - - // -- calling a functor or function pointer - template< typename Func1 > - static int addShortcut( const QKeySequence&, bool autoRepeat, Func1 slot ); - - template< typename Func1 > - static int addShortcut( QQuickWindow*, const QKeySequence&, bool autoRepeat, Func1 slot ); - - template< typename Func1 > - static int addShortcut( QQuickItem*, const QKeySequence&, bool autoRepeat, Func1 slot ); + static int addShortcut( QQuickWindow*, const QKeySequence&, + bool autoRepeat, const QObject* context, const QskMetaFunction& ); static bool contextMatcher( const QQuickItem*, Qt::ShortcutContext ); @@ -72,66 +57,15 @@ private: QskShortcutMap() = delete; ~QskShortcutMap() = delete; - static int addMethod( QQuickItem*, const QKeySequence&, bool autoRepeat, - const QObject* receiver, const char* method ); - - template< typename Func1 > - static int addMemberSlot( QQuickItem*, const QKeySequence&, bool autoRepeat, - const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot ); - - template< typename Func1 > - static int addFunctorSlot( QQuickItem*, const QKeySequence&, - bool autoRepeat, const QObject* context, Func1 slot ); - - static int addSlotObject( + static int addFunction( QQuickItem* item, const QKeySequence&, bool autoRepeat, - const QObject* receiver, QtPrivate::QSlotObjectBase* ); + const QObject* receiver, const QskMetaFunction& ); + + static int addMethod( + QQuickItem* item, const QKeySequence&, bool autoRepeat, + const QObject* receiver, const char* ); }; -template< typename Func1 > -inline int QskShortcutMap::addMemberSlot( - QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, - const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot ) -{ - using namespace QtPrivate; - typedef FunctionPointer< Func1 > SlotType; - - Q_STATIC_ASSERT_X( int( SlotType::ArgumentCount ) == 0, - "The slot must not have any arguments."); - - return addSlotObject( item, sequence, autoRepeat, receiver, - new QSlotObject< Func1, typename SlotType::Arguments, void >( slot ) ); -} - -template< typename Func1 > -inline int QskShortcutMap::addFunctorSlot( - QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, - const QObject* context, Func1 slot ) -{ - using namespace QtPrivate; - typedef FunctionPointer< Func1 > SlotType; - - Q_STATIC_ASSERT_X( int( SlotType::ArgumentCount ) <= 0, - "The slot must not have any arguments."); - - Q_STATIC_ASSERT_X( !SlotType::IsPointerToMemberFunction, - "The slot must be no member function." ); - - using Args = List_Left< void, 0 >::Value; - - return addSlotObject( item, sequence, autoRepeat, context, - new QFunctorSlotObject< Func1, 0, Args, void >( slot ) ); -} - -// -- traditional slots - -inline int QskShortcutMap::addShortcut( - QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, - const QObject* receiver, const char* method ) -{ - return addMethod( item, sequence, autoRepeat, receiver, method ); -} - inline int QskShortcutMap::addShortcut( const QKeySequence& sequence, bool autoRepeat, const QObject* receiver, const char* method ) @@ -140,89 +74,55 @@ inline int QskShortcutMap::addShortcut( } inline int QskShortcutMap::addShortcut( - QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat, - const QObject* receiver, const char* method ) + QQuickWindow* window, const QKeySequence& sequence, + bool autoRepeat, const QObject* receiver, const char* method ) { auto item = window ? window->contentItem() : nullptr; return addMethod( item, sequence, autoRepeat, receiver, method ); } -// -- calling a QObject method - -template< typename Func1 > -inline int QskShortcutMap::addShortcut( - QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, - const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot ) -{ - return addMemberSlot( item, sequence, autoRepeat, receiver, slot ); -} - - -template< typename Func1 > -inline int QskShortcutMap::addShortcut( - QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat, - const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot ) -{ - auto item = window ? window->contentItem() : nullptr; - return addMemberSlot( item, sequence, autoRepeat, receiver, slot ); -} - -template< typename Func1 > inline int QskShortcutMap::addShortcut( const QKeySequence& sequence, bool autoRepeat, - const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot ) + const QskMetaFunction& function ) { - return addMemberSlot( nullptr, sequence, autoRepeat, receiver, slot ); + return addFunction( nullptr, sequence, autoRepeat, nullptr, function ); } -// -- calling a functor or function pointer with context +inline int QskShortcutMap::addShortcut( + const QKeySequence& sequence, bool autoRepeat, + const QObject* context, const QskMetaFunction& function ) +{ + return addFunction( nullptr, sequence, autoRepeat, context, function ); +} -template< typename Func1 > inline int QskShortcutMap::addShortcut( QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, - const QObject* context, Func1 slot ) + const QskMetaFunction& function ) { - return addFunctorSlot( item, sequence, autoRepeat, context, slot ); + return addFunction( item, sequence, autoRepeat, nullptr, function ); +} + +inline int QskShortcutMap::addShortcut( + QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, + const QObject* context, const QskMetaFunction& function ) +{ + return addFunction( item, sequence, autoRepeat, context, function ); } -template< typename Func1 > inline int QskShortcutMap::addShortcut( QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat, - const QObject* context, Func1 slot ) + const QskMetaFunction& function ) { auto item = window ? window->contentItem() : nullptr; - return addFunctorSlot( item, sequence, autoRepeat, context, slot ); + return addFunction( item, sequence, autoRepeat, nullptr, function ); } -template< typename Func1 > -inline int QskShortcutMap::addShortcut( const QKeySequence& sequence, bool autoRepeat, - const QObject* context, Func1 slot ) -{ - return addFunctorSlot( nullptr, sequence, autoRepeat, context, slot ); -} - -// -- calling a functor or function pointer - -template< typename Func1 > inline int QskShortcutMap::addShortcut( - QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, Func1 slot ) -{ - return addFunctorSlot( item, sequence, autoRepeat, nullptr, slot ); -} - -template< typename Func1 > -inline int QskShortcutMap::addShortcut( - QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat, Func1 slot ) + QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat, + const QObject* context, const QskMetaFunction& function ) { auto item = window ? window->contentItem() : nullptr; - return addFunctorSlot( item, sequence, autoRepeat, nullptr, autoRepeat, slot ); -} - -template< typename Func1 > -int QskShortcutMap::addShortcut( - const QKeySequence& sequence, bool autoRepeat, Func1 slot ) -{ - return addFunctorSlot( nullptr, sequence, autoRepeat, nullptr, slot ); + return addFunction( item, sequence, autoRepeat, context, function ); } #endif