diff --git a/playground/invoker/Callback.cpp b/playground/invoker/Callback.cpp new file mode 100644 index 00000000..cfa8f846 --- /dev/null +++ b/playground/invoker/Callback.cpp @@ -0,0 +1,40 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * This file may be used under the terms of the QSkinny License, Version 1.0 + *****************************************************************************/ + +#include "Callback.h" +#include + +Callback::Callback(): + m_context( nullptr ) +{ +} + +Callback::Callback( const QObject* context, const QMetaMethod& method ): + m_context( const_cast< QObject* >( context ) ), + m_invokable( method ) +{ +} + +Callback::Callback( const QObject* context, const char* methodName ): + Callback( context, qskMetaMethod( context, methodName ) ) +{ +} + +Callback::Callback( const QObject* context, const QMetaProperty& property ): + m_context( const_cast< QObject* >( context ) ), + m_invokable( property ) +{ +} + +Callback::Callback( const QObject* context, const QskMetaFunction& function ): + m_context( const_cast< QObject* >( context ) ), + m_invokable( function ) +{ +} + +void Callback::invoke( void* args[], Qt::ConnectionType connectionType ) +{ + m_invokable.invoke( m_context, args, connectionType ); +} diff --git a/playground/invoker/Callback.h b/playground/invoker/Callback.h new file mode 100644 index 00000000..32fa2b3c --- /dev/null +++ b/playground/invoker/Callback.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * This file may be used under the terms of the QSkinny License, Version 1.0 + *****************************************************************************/ + +#ifndef CALLBACK_H +#define CALLBACK_H 1 + +#include + +class QObject; + +class Callback +{ +public: + Callback(); + + Callback( const QObject*, const QskMetaFunction& ); + Callback( const QObject*, const QMetaMethod& ); + Callback( const QObject*, const QMetaProperty& ); + + Callback( const QObject*, const char* methodName ); + + void invoke( void* args[], Qt::ConnectionType ); + + const QObject* context() const; + const QskMetaInvokable& invokable() const; + +private: + QObject* m_context; + QskMetaInvokable m_invokable; +}; + +inline const QObject* Callback::context() const +{ + return m_context; +} + +inline const QskMetaInvokable& Callback::invokable() const +{ + return m_invokable; +} + +#endif diff --git a/playground/invoker/Invoker.cpp b/playground/invoker/Invoker.cpp index 3befea8d..72105e65 100644 --- a/playground/invoker/Invoker.cpp +++ b/playground/invoker/Invoker.cpp @@ -16,21 +16,22 @@ Invoker::Invoker( QObject* parent ): void Invoker::addFunctionCall( const QObject* object, const QskMetaFunction& function ) { - m_callbacks.append( QskMetaCallback( object, function ) ); + m_callbacks.append( Callback( object, function ) ); } void Invoker::addMethodCall( const QObject* object, const char* methodName ) { - m_callbacks.append( QskMetaCallback( object, methodName ) ); + m_callbacks.append( Callback( object, methodName ) ); } void Invoker::addPropertyCall( const QObject* object, const char* property ) { - const auto* mo = object->metaObject(); - auto metaProperty = mo->property( mo->indexOfProperty( property ) ); - m_callbacks.append( QskMetaCallback( object, metaProperty ) ); + const auto metaProperty = object->metaObject()->property( + object->metaObject()->indexOfProperty( property ) ); + + m_callbacks.append( Callback( object, metaProperty ) ); } void Invoker::invoke( qreal realValue, int intValue, @@ -69,27 +70,25 @@ void Invoker::invoke( qreal realValue, int intValue, } } - callback.setConnectionType( connectionType ); - - const int callType = connectionType & 0x3; - switch( callType ) + switch( connectionType & 0x3 ) { case Qt::DirectConnection: { - callback.invoke( args ); + callback.invoke( args, connectionType ); break; } case Qt::QueuedConnection: { - if ( callback.object() ) - callback.invoke( args ); + if ( callback.context() ) + callback.invoke( args, connectionType ); + break; } case Qt::BlockingQueuedConnection: { - const auto receiver = callback.object(); + const auto receiver = callback.context(); if ( receiver && receiver->thread() != QThread::currentThread() ) - callback.invoke( args ); + callback.invoke( args, connectionType ); break; } diff --git a/playground/invoker/Invoker.h b/playground/invoker/Invoker.h index fe6fbb7b..3cbe7bef 100644 --- a/playground/invoker/Invoker.h +++ b/playground/invoker/Invoker.h @@ -6,8 +6,8 @@ #ifndef INVOKER_H #define INVOKER_H 1 +#include "Callback.h" #include -#include #include #include @@ -26,7 +26,7 @@ public: void invoke( qreal d, int i, Qt::ConnectionType ); private: - QVector< QskMetaCallback > m_callbacks; + QVector< Callback > m_callbacks; }; inline void Invoker::addFunctionCall( const QskMetaFunction& function ) diff --git a/playground/invoker/invoker.pro b/playground/invoker/invoker.pro index 8f484ec3..a5175491 100644 --- a/playground/invoker/invoker.pro +++ b/playground/invoker/invoker.pro @@ -5,8 +5,10 @@ QMAKE_MOC_OPTIONS += -nw # disable warning about missing READ TARGET = invoker HEADERS += \ + Callback.h \ Invoker.h SOURCES += \ + Callback.cpp \ Invoker.cpp \ main.cpp diff --git a/src/common/QskMetaCallback.cpp b/src/common/QskMetaCallback.cpp deleted file mode 100644 index 4c4bb03c..00000000 --- a/src/common/QskMetaCallback.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * This file may be used under the terms of the QSkinny License, Version 1.0 - *****************************************************************************/ - -#include "QskMetaCallback.h" -#include "QskMetaMethod.h" - -QskMetaCallback::QskMetaCallback( const QObject* object, - const QMetaMethod& method, Qt::ConnectionType connectionType ): - m_object( const_cast< QObject* >( object ) ), - m_invokable( method ), - m_hasObject( object != nullptr ), - m_connectionType( static_cast< ushort >( connectionType & 0x3 ) ) -{ -} - -QskMetaCallback::QskMetaCallback( const QObject* object, - const char* methodName, Qt::ConnectionType connectionType ): - QskMetaCallback( object, QskMetaMethod::method( object, methodName ), connectionType ) -{ -} - -QskMetaCallback::QskMetaCallback( const QObject* object, - const QMetaProperty& property, Qt::ConnectionType connectionType ): - m_object( const_cast< QObject* >( object ) ), - m_invokable( property ), - m_hasObject( object != nullptr ), - m_connectionType( static_cast< ushort >( connectionType & 0x3 ) ) -{ -} - -QskMetaCallback::QskMetaCallback( const QObject* object, - const QskMetaFunction& function, Qt::ConnectionType connectionType ): - m_object( const_cast< QObject* >( object ) ), - m_invokable( function ), - m_hasObject( object != nullptr ), - m_connectionType( static_cast< ushort >( connectionType & ~Qt::UniqueConnection ) ) -{ -} - -QskMetaCallback::~QskMetaCallback() -{ -} - -bool QskMetaCallback::isValid() const -{ - if ( m_hasObject && m_object.isNull() ) - return false; - - return !m_invokable.isNull(); -} - -void QskMetaCallback::setInvokable( const QskMetaInvokable& invokable ) -{ - // type checking is m_object matches ??? - m_invokable = invokable; -} - -void QskMetaCallback::setConnectionType( Qt::ConnectionType connectionType ) -{ - m_connectionType = connectionType; -} - -void QskMetaCallback::invoke( void* args[] ) -{ - if ( isValid() ) - m_invokable.invoke( m_object, args, connectionType() ); -} diff --git a/src/common/QskMetaCallback.h b/src/common/QskMetaCallback.h deleted file mode 100644 index f456eeff..00000000 --- a/src/common/QskMetaCallback.h +++ /dev/null @@ -1,77 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * This file may be used under the terms of the QSkinny License, Version 1.0 - *****************************************************************************/ - -#ifndef QSK_META_CALLBACK_H -#define QSK_META_CALLBACK_H 1 - -#include "QskGlobal.h" -#include "QskMetaInvokable.h" - -#include -#include - -class QSK_EXPORT QskMetaCallback -{ -public: - QskMetaCallback(); - - QskMetaCallback( const QObject*, const QskMetaFunction&, - Qt::ConnectionType = Qt::AutoConnection ); - - QskMetaCallback( const QObject*, const QMetaMethod&, - Qt::ConnectionType = Qt::AutoConnection ); - - QskMetaCallback( const QObject*, const QMetaProperty&, - Qt::ConnectionType = Qt::AutoConnection ); - - QskMetaCallback( const QObject*, const char* methodName, - Qt::ConnectionType = Qt::AutoConnection ); - - ~QskMetaCallback(); - - bool isValid() const; - bool isStale() const; - - const QObject* object() const { return m_object; } - - void setInvokable( const QskMetaInvokable& ); - const QskMetaInvokable& invokable() const; - - void setConnectionType( Qt::ConnectionType ); - Qt::ConnectionType connectionType() const; - - void invoke( void* args[] ); - -private: - QPointer< QObject > m_object; - QskMetaInvokable m_invokable; - - bool m_hasObject : 1; - ushort m_connectionType : 3; -}; - -inline QskMetaCallback::QskMetaCallback(): - m_hasObject( false ) -{ -} - -inline bool QskMetaCallback::isStale() const -{ - return m_hasObject && m_object.isNull(); -} - -inline const QskMetaInvokable& QskMetaCallback::invokable() const -{ - return m_invokable; -} - -inline Qt::ConnectionType QskMetaCallback::connectionType() const -{ - return static_cast< Qt::ConnectionType >( m_connectionType ); -} - -Q_DECLARE_METATYPE( QskMetaCallback ) - -#endif diff --git a/src/common/QskMetaInvokable.cpp b/src/common/QskMetaInvokable.cpp index ec03ae1a..7304e480 100644 --- a/src/common/QskMetaInvokable.cpp +++ b/src/common/QskMetaInvokable.cpp @@ -5,15 +5,25 @@ #include "QskMetaInvokable.h" #include "QskMetaFunction.h" -#include "QskMetaMethod.h" #include +#include + #include #include + #include +#include +#include + +QSK_QT_PRIVATE_BEGIN +#include +QSK_QT_PRIVATE_END namespace { + using CallFunction = QObjectPrivate::StaticMetaCallFunction; + class Function : public QskMetaFunction { public: @@ -34,33 +44,270 @@ namespace static_cast< FunctionCall* >( functionCall )->destroyIfLastRef(); } }; + + class MetaCallEvent final : public QMetaCallEvent + { + public: + MetaCallEvent( QMetaObject::Call call, CallFunction callFunction, + ushort offset, ushort index, + int nargs, int* types, void* args[], QSemaphore* semaphore = nullptr ): + QMetaCallEvent( offset, index, callFunction, nullptr, -1, + nargs, types, args, semaphore ), + m_call( call ), + m_callFunction( callFunction ), + m_index( index ) + { + } + + virtual void placeMetaCall( QObject* object ) override final + { + m_callFunction( object, m_call, m_index, args() ); + } + + private: + const QMetaObject::Call m_call; + + // as those members from QMetaCallEvent are not accessible + CallFunction m_callFunction; + const ushort m_index; + }; } -static void qskInvokeSetProperty( QObject* object, - const QMetaObject* metaObject, int propertyIndex, - void* args[], Qt::ConnectionType connectionType ) +static inline void qskInvokeMetaCallQueued( QObject* object, + QMetaObject::Call call, ushort offset, ushort index, + int nargs, int* types, void* args[], QSemaphore* semaphore = nullptr ) { + const auto callFunction = object->metaObject()->d.static_metacall; + + auto event = new MetaCallEvent( call, callFunction, + offset, index, nargs, types, args, semaphore ); + + QCoreApplication::postEvent( object, event ); +} + +QMetaMethod qskMetaMethod( const QObject* object, const char* methodName ) +{ + return object ? qskMetaMethod( object->metaObject(), methodName ) : QMetaMethod(); +} + +QMetaMethod qskMetaMethod( const QMetaObject* metaObject, const char* methodName ) +{ + if ( metaObject == nullptr || methodName == nullptr ) + return QMetaMethod(); + + constexpr char signalIndicator = '0' + QSIGNAL_CODE; + constexpr char slotIndicator = '0' + QSLOT_CODE; + + int index = -1; + + if( methodName[0] == signalIndicator ) + { + auto signature = QMetaObject::normalizedSignature( methodName + 1 ); + index = metaObject->indexOfSignal( signature ); + } + else if ( methodName[0] == slotIndicator ) + { + auto signature = QMetaObject::normalizedSignature( methodName + 1 ); + index = metaObject->indexOfSlot( signature ); + } + else + { + auto signature = QMetaObject::normalizedSignature( methodName ); + index = metaObject->indexOfMethod( signature ); + } + + return ( index >= 0 ) ? metaObject->method( index ) : QMetaMethod(); +} + +QMetaMethod qskNotifySignal( const QObject* object, const char* propertyName ) +{ + return object ? qskNotifySignal( object->metaObject(), propertyName ) : QMetaMethod(); +} + +QMetaMethod qskNotifySignal( const QMetaObject* metaObject, const char* propertyName ) +{ + if ( metaObject == nullptr || propertyName == nullptr ) + return QMetaMethod(); + + const int propertyIndex = metaObject->indexOfProperty( propertyName ); + if ( propertyIndex ) + { + const auto property = metaObject->property( propertyIndex ); + return property.notifySignal(); + } + + return QMetaMethod(); +} + +static void qskInvokeMetaCall( QObject* object, + const QMetaObject* metaObject, QMetaObject::Call call, + int offset, int index, void* argv[], Qt::ConnectionType connectionType ) +{ + QPointer< QObject > receiver( object ); + int invokeType = connectionType & 0x3; if ( invokeType == Qt::AutoConnection ) { - invokeType = ( object->thread() != QThread::currentThread() ) + invokeType = ( object && object->thread() != QThread::currentThread() ) ? Qt::QueuedConnection : Qt::DirectConnection; } -#if 1 - if ( invokeType != Qt::DirectConnection ) - return; // TODO ... -#endif - - if ( propertyIndex >= 0 && object->metaObject() == metaObject ) + switch( invokeType ) { - int status = -1; - int flags = 0; - void* argv[] = { args[1], nullptr, &status, &flags }; + case Qt::DirectConnection: + { + if ( receiver.isNull() ) + { +#if 1 + // do we really always need an object, what about Q_GADGET ??? + return; +#endif + } - QMetaObject::metacall( object, - QMetaObject::WriteProperty, propertyIndex, argv ); + /* + QMetaObject::metacall seems to be made for situations we don't have. + Need to dive deeper into the Qt code to be 100% sure TODO ... + */ + + metaObject->d.static_metacall( receiver, call, index, argv ); + break; + } + case Qt::BlockingQueuedConnection: + { + if ( receiver.isNull() + || ( receiver->thread() == QThread::currentThread() ) ) + { + // We would end up in a deadlock, better do nothing + return; + } + + QSemaphore semaphore; + + qskInvokeMetaCallQueued( receiver, call, offset, index, + 0, nullptr, argv, &semaphore ); + + semaphore.acquire(); + + break; + } + case Qt::QueuedConnection: + { + if ( receiver == nullptr ) + return; + + int* types = nullptr; + void** arguments = nullptr; + int argc = 0; + + if ( call == QMetaObject::InvokeMetaMethod ) + { +#if 1 + // should be doable without QMetaMethod. TODO ... + const auto method = metaObject->method( offset + index ); +#endif + argc = method.parameterCount() + 1; + + types = static_cast< int* >( malloc( argc * sizeof( int ) ) ); + arguments = static_cast< void** >( malloc( argc * sizeof( void* ) ) ); + + /* + The first one is the return type, one that is always + invalid for Queued Connections. + */ + + types[0] = QMetaType::UnknownType; + arguments[0] = nullptr; + + for ( int i = 1; i < argc; i++ ) + { + if ( argv[i] == nullptr ) + { + Q_ASSERT( argv[i] != nullptr ); + receiver = nullptr; + break; + } + + types[i] = method.parameterType( i - 1 ); + arguments[i] = QMetaType::create( types[i], argv[i] ); + } + } + else + { + // should be doable without QMetaMethod. TODO ... + const auto property = metaObject->property( offset + index ); + + argc = 1; + + types = static_cast< int* >( malloc( argc * sizeof( int ) ) ); + arguments = static_cast< void** >( malloc( argc * sizeof( void* ) ) ); + + types[0] = property.userType(); + arguments[0] = QMetaType::create( types[0], argv[0] ); + } + + if ( receiver.isNull() ) + { + // object might have died in the meantime + free( types ); + free( arguments ); + + return; + } + + qskInvokeMetaCallQueued( object, call, + offset, index, argc, types, arguments ); + + break; + } + } +} + +void qskInvokeMetaPropertyWrite( QObject* context, + const QMetaProperty& property, void* args[], Qt::ConnectionType connectionType ) +{ + qskInvokeMetaPropertyWrite( context, property.enclosingMetaObject(), + property.propertyIndex(), args, connectionType ); +} + +void qskInvokeMetaPropertyWrite( QObject* context, + const QMetaObject* metaObject, int propertyIndex, + void* args[], Qt::ConnectionType connectionType ) +{ + // check for is writable ??? + + if ( metaObject && ( propertyIndex >= 0 ) + && ( propertyIndex < metaObject->propertyCount() ) ) + { + const auto offset = metaObject->propertyOffset(); + const auto index = propertyIndex - offset; + + qskInvokeMetaCall( context, metaObject, QMetaObject::WriteProperty, + offset, index, args + 1, connectionType ); + } +} + +void qskInvokeMetaMethod( QObject* object, + const QMetaMethod& method, void* args[], + Qt::ConnectionType connectionType ) +{ + qskInvokeMetaMethod( object, method.enclosingMetaObject(), + method.methodIndex(), args, connectionType ); +} + +void qskInvokeMetaMethod( QObject* object, + const QMetaObject* metaObject, int methodIndex, void* argv[], + Qt::ConnectionType connectionType ) +{ + if ( metaObject && ( methodIndex >= 0 ) + && ( methodIndex < metaObject->methodCount() ) ) + { + + const auto offset = metaObject->methodOffset(); + const auto index = methodIndex - offset; + + qskInvokeMetaCall( object, metaObject, QMetaObject::InvokeMetaMethod, + offset, index, argv, connectionType ); } } @@ -71,12 +318,12 @@ QskMetaInvokable::QskMetaInvokable( const QMetaMethod& method ): } QskMetaInvokable::QskMetaInvokable( const QObject* object, const char* methodName ): - QskMetaInvokable( QskMetaMethod::method( object, methodName ) ) + QskMetaInvokable( qskMetaMethod( object, methodName ) ) { } QskMetaInvokable::QskMetaInvokable( const QMetaObject* metaObject, const char* methodName ): - QskMetaInvokable( QskMetaMethod::method( metaObject, methodName ) ) + QskMetaInvokable( qskMetaMethod( metaObject, methodName ) ) { } @@ -353,14 +600,14 @@ void QskMetaInvokable::invoke( QObject* object, void* args[], { case MetaMethod: { - QskMetaMethod::invoke( object, m_metaData.metaObject, + qskInvokeMetaMethod( object, m_metaData.metaObject, m_metaData.index, args, connectionType ); break; } case MetaProperty: { - qskInvokeSetProperty( object, + qskInvokeMetaPropertyWrite( object, m_metaData.metaObject, m_metaData.index, args, connectionType ); diff --git a/src/common/QskMetaInvokable.h b/src/common/QskMetaInvokable.h index a6d82e53..320193a9 100644 --- a/src/common/QskMetaInvokable.h +++ b/src/common/QskMetaInvokable.h @@ -115,6 +115,30 @@ inline QskMetaInvokable::Type QskMetaInvokable::type() const return static_cast< Type >( m_type ); } +QSK_EXPORT QMetaMethod qskMetaMethod( const QMetaObject*, const char* methodName ); +QSK_EXPORT QMetaMethod qskMetaMethod( const QObject*, const char* methodName ); + +QSK_EXPORT void qskInvokeMetaMethod( + QObject*, const QMetaObject*, int methodIndex, void* args[], + Qt::ConnectionType = Qt::AutoConnection ); + +QSK_EXPORT void qskInvokeMetaMethod( + QObject*, const QMetaMethod&, void* args[], + Qt::ConnectionType = Qt::AutoConnection ); + +QSK_EXPORT void qskInvokeMetaPropertyWrite( + QObject*, const QMetaObject*, int propertyIndex, + void* args[], Qt::ConnectionType = Qt::AutoConnection ); + +QSK_EXPORT void qskInvokeMetaPropertyWrite( + const QObject* object, const QMetaProperty&, + void* args[], Qt::ConnectionType = Qt::AutoConnection ); + + +QSK_EXPORT QMetaMethod qskNotifySignal( const QMetaObject*, const char* propertyName ); +QSK_EXPORT QMetaMethod qskNotifySignal( const QObject*, const char* propertyName ); + + Q_DECLARE_METATYPE( QskMetaInvokable ) #endif diff --git a/src/common/QskMetaMethod.cpp b/src/common/QskMetaMethod.cpp deleted file mode 100644 index 745a5ef0..00000000 --- a/src/common/QskMetaMethod.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * This file may be used under the terms of the QSkinny License, Version 1.0 - *****************************************************************************/ - -#include "QskMetaMethod.h" - -#include -#include -#include -#include -#include -#include - -QSK_QT_PRIVATE_BEGIN -#include -QSK_QT_PRIVATE_END - -static inline void qskInvokeMethodQueued( QObject* object, - const QMetaObject* metaObject, ushort methodIndex, - int nargs, int* types, void* args[], QSemaphore* semaphore = nullptr ) -{ - constexpr QObject* sender = nullptr; - constexpr int signalId = -1; - - const int methodOffset = metaObject->methodOffset(); - - auto event = new QMetaCallEvent( - methodOffset, methodIndex - methodOffset, - metaObject->d.static_metacall, - sender, signalId, nargs, types, args, semaphore ); - - QCoreApplication::postEvent( object, event ); -} - -void QskMetaMethod::invoke( QObject* object, - const QMetaMethod& method, void* args[], - Qt::ConnectionType connectionType ) -{ - auto metaObject = method.enclosingMetaObject(); - if ( metaObject == nullptr ) - return; - - const int methodIndex = method.methodIndex() - metaObject->methodOffset(); - invoke( object, metaObject, methodIndex, args, connectionType ); -} - -void QskMetaMethod::invoke( QObject* object, - const QMetaObject* metaObject, int methodIndex, void* argv[], - Qt::ConnectionType connectionType ) -{ - if ( ( metaObject == nullptr ) || ( methodIndex < 0 ) - || ( methodIndex >= metaObject->methodCount() ) ) - { - return; - } - - QPointer< QObject > receiver( object ); - - int invokeType = connectionType & 0x3; - - if ( invokeType == Qt::AutoConnection ) - { - invokeType = ( object && object->thread() != QThread::currentThread() ) - ? Qt::QueuedConnection : Qt::DirectConnection; - } - - switch( invokeType ) - { - case Qt::DirectConnection: - { -#if 1 - if ( receiver.isNull() ) - return; // do we really always need an object here ??? -#endif - - const int index = methodIndex - metaObject->methodOffset(); - - if ( metaObject->d.static_metacall ) - { - metaObject->d.static_metacall( receiver, - QMetaObject::InvokeMetaMethod, index, argv ); - } - else - { - QMetaObject::metacall( receiver, - QMetaObject::InvokeMetaMethod, index, argv ); - } - break; - } - case Qt::BlockingQueuedConnection: - { - if ( receiver.isNull() - || ( receiver->thread() == QThread::currentThread() ) ) - { - // We would end up in a deadlock, better do nothing - return; - } - - QSemaphore semaphore; - - qskInvokeMethodQueued( receiver, metaObject, - methodIndex, 0, nullptr, argv, &semaphore ); - - semaphore.acquire(); - - break; - } - case Qt::QueuedConnection: - { - if ( receiver == nullptr ) - return; - -#if 1 - // should be doable without QMetaMethod. TODO ... - const auto method = metaObject->method( methodIndex ); -#endif - const int argc = method.parameterCount() + 1; - - auto types = static_cast< int* >( malloc( argc * sizeof( int ) ) ); - auto arguments = static_cast< void** >( malloc( argc * sizeof( void* ) ) ); - - /* - The first one is the return type, one that is always - invalid for Queued Connections. - */ - - types[0] = QMetaType::UnknownType; - arguments[0] = nullptr; - - for ( int i = 1; i < argc; i++ ) - { - if ( argv[i] == nullptr ) - { - Q_ASSERT( argv[i] != nullptr ); - receiver = nullptr; - break; - } - - types[i] = method.parameterType( i - 1 ); - arguments[i] = QMetaType::create( types[i], argv[i] ); - } - - if ( receiver.isNull() ) - { - // object might have died in the meantime - free( types ); - free( arguments ); - - return; - } - - qskInvokeMethodQueued( object, - metaObject, methodIndex, argc, types, arguments ); - - break; - } - } -} - -QMetaMethod QskMetaMethod::method( - const QMetaObject* metaObject, const char* methodName ) -{ - if ( metaObject == nullptr || methodName == nullptr ) - return QMetaMethod(); - - constexpr char signalIndicator = '0' + QSIGNAL_CODE; - constexpr char slotIndicator = '0' + QSLOT_CODE; - - int index = -1; - - if( methodName[0] == signalIndicator ) - { - auto signature = QMetaObject::normalizedSignature( methodName + 1 ); - index = metaObject->indexOfSignal( signature ); - } - else if ( methodName[0] == slotIndicator ) - { - auto signature = QMetaObject::normalizedSignature( methodName + 1 ); - index = metaObject->indexOfSlot( signature ); - } - else - { - auto signature = QMetaObject::normalizedSignature( methodName ); - index = metaObject->indexOfMethod( signature ); - } - - return ( index >= 0 ) ? metaObject->method( index ) : QMetaMethod(); -} - -QMetaMethod QskMetaMethod::notifySignal( - const QMetaObject* metaObject, const char* propertyName ) -{ - if ( metaObject == nullptr || propertyName == nullptr ) - return QMetaMethod(); - - const int propertyIndex = metaObject->indexOfProperty( propertyName ); - if ( propertyIndex ) - { - const auto property = metaObject->property( propertyIndex ); - return property.notifySignal(); - } - - return QMetaMethod(); -} diff --git a/src/common/QskMetaMethod.h b/src/common/QskMetaMethod.h deleted file mode 100644 index f1f703b1..00000000 --- a/src/common/QskMetaMethod.h +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * This file may be used under the terms of the QSkinny License, Version 1.0 - *****************************************************************************/ - -#ifndef QSK_META_METHOD_H -#define QSK_META_FUNCTION_H 1 - -#include "QskGlobal.h" - -#include -#include - -class QObject; -class QMetaMethod; -class QMetaObject; - -namespace QskMetaMethod -{ - QSK_EXPORT void invoke( - QObject* object, const QMetaMethod&, void* args[], - Qt::ConnectionType = Qt::AutoConnection ); - - QSK_EXPORT void invoke( - QObject*, const QMetaObject*, int methodIndex, void* args[], - Qt::ConnectionType = Qt::AutoConnection ); - - QSK_EXPORT QMetaMethod method( const QMetaObject*, const char* methodName ); - QSK_EXPORT QMetaMethod method( const QObject*, const char* methodName ); - - QSK_EXPORT QMetaMethod notifySignal( const QMetaObject*, const char* propertyName ); - QSK_EXPORT QMetaMethod notifySignal( const QObject*, const char* propertyName ); -} - -inline QMetaMethod QskMetaMethod::method( - const QObject* object, const char* methodName ) -{ - return object ? method( object->metaObject(), methodName ) : QMetaMethod(); -} - -inline QMetaMethod QskMetaMethod::notifySignal( - const QObject* object, const char* propertyName ) -{ - return object ? notifySignal( object->metaObject(), propertyName ) : QMetaMethod(); -} - -#endif diff --git a/src/src.pro b/src/src.pro index 64ce6471..828b7a41 100644 --- a/src/src.pro +++ b/src/src.pro @@ -40,11 +40,9 @@ HEADERS += \ common/QskGlobal.h \ common/QskGradient.h \ common/QskMargins.h \ - common/QskMetaCallback.h \ common/QskMetaFunction.h \ common/QskMetaFunction.hpp \ common/QskMetaInvokable.h \ - common/QskMetaMethod.h \ common/QskModule.h \ common/QskNamespace.h \ common/QskObjectCounter.h \ @@ -61,10 +59,8 @@ SOURCES += \ common/QskFunctions.cpp \ common/QskGradient.cpp \ common/QskMargins.cpp \ - common/QskMetaCallback.cpp \ common/QskMetaFunction.cpp \ common/QskMetaInvokable.cpp \ - common/QskMetaMethod.cpp \ common/QskModule.cpp \ common/QskObjectCounter.cpp \ common/QskSizePolicy.cpp \