QskMetaInvokable introduced
This commit is contained in:
parent
b5a5b56a1d
commit
6c9d78c532
@ -32,7 +32,7 @@ void Invoker::invoke( qreal realValue, int intValue,
|
|||||||
{
|
{
|
||||||
void* args[4] = { nullptr };
|
void* args[4] = { nullptr };
|
||||||
|
|
||||||
const auto types = callback.parameterTypes();
|
const auto types = callback.invokable().parameterTypes();
|
||||||
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
for ( auto type : types )
|
for ( auto type : types )
|
||||||
|
@ -4,41 +4,12 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "QskMetaCallback.h"
|
#include "QskMetaCallback.h"
|
||||||
#include "QskMetaFunction.h"
|
|
||||||
#include "QskMetaMethod.h"
|
#include "QskMetaMethod.h"
|
||||||
|
|
||||||
#include <QMetaMethod>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
class Function: public QskMetaFunction
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inline Function( void* functionCall ):
|
|
||||||
QskMetaFunction( static_cast< FunctionCall* >( functionCall ) )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ref( void* functionCall )
|
|
||||||
{
|
|
||||||
if ( functionCall )
|
|
||||||
static_cast< FunctionCall* >( functionCall )->ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void deref( void* functionCall )
|
|
||||||
{
|
|
||||||
if ( functionCall )
|
|
||||||
static_cast< FunctionCall* >( functionCall )->destroyIfLastRef();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QskMetaCallback::QskMetaCallback( const QObject* object,
|
QskMetaCallback::QskMetaCallback( const QObject* object,
|
||||||
const QMetaMethod& method, Qt::ConnectionType connectionType ):
|
const QMetaMethod& method, Qt::ConnectionType connectionType ):
|
||||||
m_object( const_cast< QObject* >( object ) ),
|
m_object( const_cast< QObject* >( object ) ),
|
||||||
m_methodData { method.enclosingMetaObject(), method.methodIndex() },
|
m_invokable( method ),
|
||||||
m_type( MetaMethod ),
|
|
||||||
m_hasObject( object != nullptr ),
|
m_hasObject( object != nullptr ),
|
||||||
m_connectionType( static_cast< ushort >( connectionType & 0x3 ) )
|
m_connectionType( static_cast< ushort >( connectionType & 0x3 ) )
|
||||||
{
|
{
|
||||||
@ -53,88 +24,14 @@ QskMetaCallback::QskMetaCallback( const QObject* object,
|
|||||||
QskMetaCallback::QskMetaCallback( const QObject* object,
|
QskMetaCallback::QskMetaCallback( const QObject* object,
|
||||||
const QskMetaFunction& function, Qt::ConnectionType connectionType ):
|
const QskMetaFunction& function, Qt::ConnectionType connectionType ):
|
||||||
m_object( const_cast< QObject* >( object ) ),
|
m_object( const_cast< QObject* >( object ) ),
|
||||||
m_functionData { function.functionCall(), function.parameterTypes() },
|
m_invokable( function ),
|
||||||
m_type( MetaFunction ),
|
|
||||||
m_hasObject( object != nullptr ),
|
m_hasObject( object != nullptr ),
|
||||||
m_connectionType( static_cast< ushort >( connectionType & ~Qt::UniqueConnection ) )
|
m_connectionType( static_cast< ushort >( connectionType & ~Qt::UniqueConnection ) )
|
||||||
{
|
{
|
||||||
Function::ref( m_functionData.functionCall );
|
|
||||||
}
|
|
||||||
|
|
||||||
QskMetaCallback::QskMetaCallback( const QskMetaCallback& other ):
|
|
||||||
m_object( other.m_object ),
|
|
||||||
m_type( other.m_type ),
|
|
||||||
m_hasObject( other.m_hasObject ),
|
|
||||||
m_connectionType( other.m_connectionType )
|
|
||||||
{
|
|
||||||
switch( m_type )
|
|
||||||
{
|
|
||||||
case MetaMethod:
|
|
||||||
{
|
|
||||||
m_methodData.metaObject = other.m_methodData.metaObject;
|
|
||||||
m_methodData.methodIndex = other.m_methodData.methodIndex;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MetaFunction:
|
|
||||||
{
|
|
||||||
m_functionData.functionCall = other.m_functionData.functionCall;
|
|
||||||
Function::ref( m_functionData.functionCall );
|
|
||||||
|
|
||||||
m_functionData.parameterTypes = other.m_functionData.parameterTypes;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QskMetaCallback::~QskMetaCallback()
|
QskMetaCallback::~QskMetaCallback()
|
||||||
{
|
{
|
||||||
if ( m_type == MetaFunction )
|
|
||||||
Function::deref( m_functionData.functionCall );
|
|
||||||
}
|
|
||||||
|
|
||||||
QskMetaCallback& QskMetaCallback::operator=( const QskMetaCallback& other )
|
|
||||||
{
|
|
||||||
m_object = other.m_object;
|
|
||||||
m_hasObject = other.m_hasObject;
|
|
||||||
|
|
||||||
m_connectionType = other.m_connectionType;
|
|
||||||
|
|
||||||
switch( other.m_type )
|
|
||||||
{
|
|
||||||
case MetaMethod:
|
|
||||||
{
|
|
||||||
if ( m_type == MetaFunction )
|
|
||||||
Function::deref( m_functionData.functionCall );
|
|
||||||
|
|
||||||
m_methodData.metaObject = other.m_methodData.metaObject;
|
|
||||||
m_methodData.methodIndex = other.m_methodData.methodIndex;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MetaFunction:
|
|
||||||
{
|
|
||||||
if ( m_type == MetaFunction )
|
|
||||||
Function::deref( m_functionData.functionCall );
|
|
||||||
|
|
||||||
m_functionData.functionCall = other.m_functionData.functionCall;
|
|
||||||
Function::ref( m_functionData.functionCall );
|
|
||||||
|
|
||||||
m_functionData.parameterTypes = other.m_functionData.parameterTypes;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
if ( m_type == MetaFunction )
|
|
||||||
Function::deref( m_functionData.functionCall );
|
|
||||||
}
|
|
||||||
|
|
||||||
m_type = other.m_type;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QskMetaCallback::isValid() const
|
bool QskMetaCallback::isValid() const
|
||||||
@ -142,28 +39,13 @@ bool QskMetaCallback::isValid() const
|
|||||||
if ( m_hasObject && m_object.isNull() )
|
if ( m_hasObject && m_object.isNull() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
switch( m_type )
|
return !m_invokable.isNull();
|
||||||
{
|
}
|
||||||
case MetaMethod:
|
|
||||||
{
|
|
||||||
const auto& d = m_methodData;
|
|
||||||
if ( d.metaObject && ( d.methodIndex >= 0 )
|
|
||||||
&& ( d.methodIndex < d.metaObject->methodCount() ) )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
void QskMetaCallback::setInvokable( const QskMetaInvokable& invokable )
|
||||||
}
|
{
|
||||||
|
// type checking is m_object matches ???
|
||||||
case MetaFunction:
|
m_invokable = invokable;
|
||||||
{
|
|
||||||
return m_functionData.functionCall != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskMetaCallback::setConnectionType( Qt::ConnectionType connectionType )
|
void QskMetaCallback::setConnectionType( Qt::ConnectionType connectionType )
|
||||||
@ -171,88 +53,8 @@ void QskMetaCallback::setConnectionType( Qt::ConnectionType connectionType )
|
|||||||
m_connectionType = connectionType;
|
m_connectionType = connectionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskMetaCallback::reset()
|
|
||||||
{
|
|
||||||
m_object = nullptr;
|
|
||||||
m_hasObject = false;
|
|
||||||
|
|
||||||
if ( m_type == MetaFunction )
|
|
||||||
Function::deref( m_functionData.functionCall );
|
|
||||||
|
|
||||||
m_functionData = { nullptr, nullptr }; // for the debugger
|
|
||||||
m_type = Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector< int > QskMetaCallback::parameterTypes() const
|
|
||||||
{
|
|
||||||
QVector< int > paramTypes;
|
|
||||||
|
|
||||||
switch( m_type )
|
|
||||||
{
|
|
||||||
case MetaMethod:
|
|
||||||
{
|
|
||||||
const auto& d = m_methodData;
|
|
||||||
if ( m_methodData.metaObject )
|
|
||||||
{
|
|
||||||
#if 1
|
|
||||||
// should be doable without QMetaMethod. TODO ...
|
|
||||||
const auto method = d.metaObject->method( d.methodIndex );
|
|
||||||
#endif
|
|
||||||
const int paramCount = method.parameterCount();
|
|
||||||
|
|
||||||
paramTypes.reserve( paramCount );
|
|
||||||
for ( int i = 0; i < paramCount; i++ )
|
|
||||||
paramTypes += method.parameterType( i );
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MetaFunction:
|
|
||||||
{
|
|
||||||
auto types = m_functionData.parameterTypes;
|
|
||||||
if ( types )
|
|
||||||
{
|
|
||||||
while ( *types )
|
|
||||||
paramTypes += *types++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return paramTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QskMetaCallback::invoke( void* args[] )
|
void QskMetaCallback::invoke( void* args[] )
|
||||||
{
|
{
|
||||||
if ( !isValid() )
|
if ( isValid() )
|
||||||
return;
|
m_invokable.invoke( m_object, args, connectionType() );
|
||||||
|
|
||||||
auto object = const_cast< QObject* >( m_object.data() );
|
|
||||||
|
|
||||||
switch( m_type )
|
|
||||||
{
|
|
||||||
case MetaMethod:
|
|
||||||
{
|
|
||||||
QskMetaMethod::invoke( object, m_methodData.metaObject,
|
|
||||||
m_methodData.methodIndex, args, connectionType() );
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MetaFunction:
|
|
||||||
{
|
|
||||||
if ( m_functionData.functionCall )
|
|
||||||
{
|
|
||||||
Function function( m_functionData.functionCall );
|
|
||||||
function.invoke( object, args, connectionType() );
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,29 +7,14 @@
|
|||||||
#define QSK_META_CALLBACK_H 1
|
#define QSK_META_CALLBACK_H 1
|
||||||
|
|
||||||
#include "QskGlobal.h"
|
#include "QskGlobal.h"
|
||||||
|
#include "QskMetaInvokable.h"
|
||||||
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QVector>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
class QskMetaFunction;
|
|
||||||
class QMetaObject;
|
|
||||||
class QMetaMethod;
|
|
||||||
|
|
||||||
class QSK_EXPORT QskMetaCallback
|
class QSK_EXPORT QskMetaCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Type
|
|
||||||
{
|
|
||||||
Invalid = 0,
|
|
||||||
|
|
||||||
// A QMetaMethod
|
|
||||||
MetaMethod,
|
|
||||||
|
|
||||||
// A function pointer, for what Qt calls "functor based" callbacks
|
|
||||||
MetaFunction
|
|
||||||
};
|
|
||||||
|
|
||||||
QskMetaCallback();
|
QskMetaCallback();
|
||||||
|
|
||||||
QskMetaCallback( const QObject*, const QskMetaFunction&,
|
QskMetaCallback( const QObject*, const QskMetaFunction&,
|
||||||
@ -41,61 +26,42 @@ public:
|
|||||||
QskMetaCallback( const QObject*, const char* methodName,
|
QskMetaCallback( const QObject*, const char* methodName,
|
||||||
Qt::ConnectionType = Qt::AutoConnection );
|
Qt::ConnectionType = Qt::AutoConnection );
|
||||||
|
|
||||||
QskMetaCallback( const QskMetaCallback& );
|
|
||||||
|
|
||||||
~QskMetaCallback();
|
~QskMetaCallback();
|
||||||
|
|
||||||
QskMetaCallback& operator=( const QskMetaCallback& );
|
|
||||||
|
|
||||||
Type type() const;
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
bool isStale() const;
|
||||||
|
|
||||||
const QObject* object() const { return m_object; }
|
const QObject* object() const { return m_object; }
|
||||||
|
|
||||||
|
void setInvokable( const QskMetaInvokable& );
|
||||||
|
const QskMetaInvokable& invokable() const;
|
||||||
|
|
||||||
void setConnectionType( Qt::ConnectionType );
|
void setConnectionType( Qt::ConnectionType );
|
||||||
Qt::ConnectionType connectionType() const;
|
Qt::ConnectionType connectionType() const;
|
||||||
|
|
||||||
QVector< int > parameterTypes() const;
|
|
||||||
|
|
||||||
void invoke( void* args[] );
|
void invoke( void* args[] );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void reset();
|
QPointer< QObject > m_object;
|
||||||
|
QskMetaInvokable m_invokable;
|
||||||
|
|
||||||
QPointer< const QObject > m_object;
|
|
||||||
|
|
||||||
struct FunctionData
|
|
||||||
{
|
|
||||||
void* functionCall;
|
|
||||||
const int* parameterTypes;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MethodData
|
|
||||||
{
|
|
||||||
const QMetaObject* metaObject;
|
|
||||||
int methodIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
FunctionData m_functionData;
|
|
||||||
MethodData m_methodData;
|
|
||||||
};
|
|
||||||
|
|
||||||
int m_type : 3;
|
|
||||||
bool m_hasObject : 1;
|
bool m_hasObject : 1;
|
||||||
ushort m_connectionType : 3;
|
ushort m_connectionType : 3;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline QskMetaCallback::QskMetaCallback():
|
inline QskMetaCallback::QskMetaCallback():
|
||||||
m_type( Invalid ),
|
|
||||||
m_hasObject( false )
|
m_hasObject( false )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QskMetaCallback::Type QskMetaCallback::type() const
|
inline bool QskMetaCallback::isStale() const
|
||||||
{
|
{
|
||||||
return static_cast< Type >( m_type );
|
return m_hasObject && m_object.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const QskMetaInvokable& QskMetaCallback::invokable() const
|
||||||
|
{
|
||||||
|
return m_invokable;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Qt::ConnectionType QskMetaCallback::connectionType() const
|
inline Qt::ConnectionType QskMetaCallback::connectionType() const
|
||||||
|
@ -123,6 +123,34 @@ QskMetaFunction& QskMetaFunction::operator=( const QskMetaFunction& other )
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QskMetaFunction::operator==( const QskMetaFunction& other ) const
|
||||||
|
{
|
||||||
|
if ( m_functionCall == other.m_functionCall )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
There is no way to compmare functors/members without
|
||||||
|
std::type_info, what we don't want to use as it is
|
||||||
|
another template creating symbols.
|
||||||
|
|
||||||
|
So this implementation can't do much more than finding
|
||||||
|
out if one instance is a copy from another.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( m_functionCall && other.m_functionCall )
|
||||||
|
{
|
||||||
|
if ( m_functionCall->typeInfo() == Function &&
|
||||||
|
other.m_functionCall->typeInfo() == Function )
|
||||||
|
{
|
||||||
|
// only static functions can be compared
|
||||||
|
return m_functionCall->compare(
|
||||||
|
reinterpret_cast< void** >( other.m_functionCall ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
size_t QskMetaFunction::parameterCount() const
|
size_t QskMetaFunction::parameterCount() const
|
||||||
{
|
{
|
||||||
if ( auto types = parameterTypes() )
|
if ( auto types = parameterTypes() )
|
||||||
|
@ -70,6 +70,11 @@ public:
|
|||||||
QskMetaFunction& operator=( const QskMetaFunction& );
|
QskMetaFunction& operator=( const QskMetaFunction& );
|
||||||
QskMetaFunction& operator=( QskMetaFunction&& );
|
QskMetaFunction& operator=( QskMetaFunction&& );
|
||||||
|
|
||||||
|
bool operator==( const QskMetaFunction& ) const;
|
||||||
|
bool operator!=( const QskMetaFunction& ) const;
|
||||||
|
|
||||||
|
explicit operator bool() const;
|
||||||
|
|
||||||
const int* parameterTypes() const;
|
const int* parameterTypes() const;
|
||||||
|
|
||||||
// including the return type !
|
// including the return type !
|
||||||
@ -79,6 +84,7 @@ public:
|
|||||||
Qt::ConnectionType = Qt::AutoConnection );
|
Qt::ConnectionType = Qt::AutoConnection );
|
||||||
|
|
||||||
Type functionType() const;
|
Type functionType() const;
|
||||||
|
bool isNull() const;
|
||||||
|
|
||||||
class FunctionCall;
|
class FunctionCall;
|
||||||
FunctionCall* functionCall() const;
|
FunctionCall* functionCall() const;
|
||||||
@ -90,13 +96,28 @@ private:
|
|||||||
FunctionCall* m_functionCall;
|
FunctionCall* m_functionCall;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "QskMetaFunction.hpp"
|
inline bool QskMetaFunction::operator!=( const QskMetaFunction& other ) const
|
||||||
|
{
|
||||||
|
return !( *this == other );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QskMetaFunction::operator bool() const
|
||||||
|
{
|
||||||
|
return !isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool QskMetaFunction::isNull() const
|
||||||
|
{
|
||||||
|
return m_functionCall == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
inline QskMetaFunction::FunctionCall* QskMetaFunction::functionCall() const
|
inline QskMetaFunction::FunctionCall* QskMetaFunction::functionCall() const
|
||||||
{
|
{
|
||||||
return m_functionCall;
|
return m_functionCall;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "QskMetaFunction.hpp"
|
||||||
|
|
||||||
inline const int* QskMetaFunction::parameterTypes() const
|
inline const int* QskMetaFunction::parameterTypes() const
|
||||||
{
|
{
|
||||||
return m_functionCall ? m_functionCall->parameterTypes() : nullptr;
|
return m_functionCall ? m_functionCall->parameterTypes() : nullptr;
|
||||||
|
@ -63,7 +63,7 @@ namespace QskMetaFunctionCall
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void invoke(int which, QSlotObjectBase* functionCall,
|
static void invoke(int which, QSlotObjectBase* functionCall,
|
||||||
QObject* object, void** args, bool* )
|
QObject* object, void** args, bool* ret )
|
||||||
{
|
{
|
||||||
switch ( which )
|
switch ( which )
|
||||||
{
|
{
|
||||||
@ -80,6 +80,13 @@ namespace QskMetaFunctionCall
|
|||||||
static_cast< MetaCall* >( functionCall )->m_function, object, args );
|
static_cast< MetaCall* >( functionCall )->m_function, object, args );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Compare:
|
||||||
|
{
|
||||||
|
*ret = reinterpret_cast< MetaCall* >( args )->m_function
|
||||||
|
== static_cast< MetaCall* >( functionCall )->m_function;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case TypeInfo:
|
case TypeInfo:
|
||||||
{
|
{
|
||||||
*reinterpret_cast< int* >( args ) = QskMetaFunction::Function;
|
*reinterpret_cast< int* >( args ) = QskMetaFunction::Function;
|
||||||
@ -148,14 +155,14 @@ namespace QskMetaFunctionCall
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void invoke( int which, QSlotObjectBase* slotObject,
|
static void invoke( int which, QSlotObjectBase* functionCall,
|
||||||
QObject* object, void** args, bool* )
|
QObject* object, void** args, bool* )
|
||||||
{
|
{
|
||||||
switch (which)
|
switch (which)
|
||||||
{
|
{
|
||||||
case Destroy:
|
case Destroy:
|
||||||
{
|
{
|
||||||
delete static_cast< MetaCall* >( slotObject );
|
delete static_cast< MetaCall* >( functionCall );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Call:
|
case Call:
|
||||||
@ -163,7 +170,7 @@ namespace QskMetaFunctionCall
|
|||||||
typedef Functor< Function, N > FuncType;
|
typedef Functor< Function, N > FuncType;
|
||||||
|
|
||||||
FuncType::template call< Args, R >(
|
FuncType::template call< Args, R >(
|
||||||
static_cast< MetaCall* >( slotObject )->m_function, object, args );
|
static_cast< MetaCall* >( functionCall )->m_function, object, args );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
251
src/common/QskMetaInvokable.cpp
Normal file
251
src/common/QskMetaInvokable.cpp
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "QskMetaInvokable.h"
|
||||||
|
#include "QskMetaFunction.h"
|
||||||
|
#include "QskMetaMethod.h"
|
||||||
|
|
||||||
|
#include <QMetaMethod>
|
||||||
|
#include <QVector>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class Function : public QskMetaFunction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline Function( void* functionCall ):
|
||||||
|
QskMetaFunction( static_cast< FunctionCall* >( functionCall ) )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ref( void* functionCall )
|
||||||
|
{
|
||||||
|
if ( functionCall )
|
||||||
|
static_cast< FunctionCall* >( functionCall )->ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void deref( void* functionCall )
|
||||||
|
{
|
||||||
|
if ( functionCall )
|
||||||
|
static_cast< FunctionCall* >( functionCall )->destroyIfLastRef();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QskMetaInvokable::QskMetaInvokable( const QMetaMethod& method ):
|
||||||
|
m_methodData { method.enclosingMetaObject(), method.methodIndex() },
|
||||||
|
m_type( MetaMethod )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QskMetaInvokable::QskMetaInvokable( const QObject* object, const char* methodName ):
|
||||||
|
QskMetaInvokable( QskMetaMethod::method( object, methodName ) )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QskMetaInvokable::QskMetaInvokable( const QMetaObject* metaObject, const char* methodName ):
|
||||||
|
QskMetaInvokable( QskMetaMethod::method( metaObject, methodName ) )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QskMetaInvokable::QskMetaInvokable( const QskMetaFunction& function ):
|
||||||
|
m_functionData { function.functionCall() },
|
||||||
|
m_type( MetaFunction )
|
||||||
|
{
|
||||||
|
Function::ref( m_functionData.functionCall );
|
||||||
|
}
|
||||||
|
|
||||||
|
QskMetaInvokable::QskMetaInvokable( const QskMetaInvokable& other ):
|
||||||
|
m_type( other.m_type )
|
||||||
|
{
|
||||||
|
switch( m_type )
|
||||||
|
{
|
||||||
|
case MetaMethod:
|
||||||
|
{
|
||||||
|
m_methodData.metaObject = other.m_methodData.metaObject;
|
||||||
|
m_methodData.methodIndex = other.m_methodData.methodIndex;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MetaFunction:
|
||||||
|
{
|
||||||
|
m_functionData.functionCall = other.m_functionData.functionCall;
|
||||||
|
Function::ref( m_functionData.functionCall );
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QskMetaInvokable::~QskMetaInvokable()
|
||||||
|
{
|
||||||
|
if ( m_type == MetaFunction )
|
||||||
|
Function::deref( m_functionData.functionCall );
|
||||||
|
}
|
||||||
|
|
||||||
|
QskMetaInvokable& QskMetaInvokable::operator=( const QskMetaInvokable& other )
|
||||||
|
{
|
||||||
|
switch( other.m_type )
|
||||||
|
{
|
||||||
|
case MetaMethod:
|
||||||
|
{
|
||||||
|
if ( m_type == MetaFunction )
|
||||||
|
Function::deref( m_functionData.functionCall );
|
||||||
|
|
||||||
|
m_methodData.metaObject = other.m_methodData.metaObject;
|
||||||
|
m_methodData.methodIndex = other.m_methodData.methodIndex;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MetaFunction:
|
||||||
|
{
|
||||||
|
if ( m_type == MetaFunction )
|
||||||
|
Function::deref( m_functionData.functionCall );
|
||||||
|
|
||||||
|
m_functionData.functionCall = other.m_functionData.functionCall;
|
||||||
|
Function::ref( m_functionData.functionCall );
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if ( m_type == MetaFunction )
|
||||||
|
Function::deref( m_functionData.functionCall );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_type = other.m_type;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QskMetaInvokable::operator==( const QskMetaInvokable& other ) const
|
||||||
|
{
|
||||||
|
if ( m_type == other.m_type )
|
||||||
|
{
|
||||||
|
if ( m_type == MetaMethod )
|
||||||
|
{
|
||||||
|
return ( m_methodData.metaObject == other.m_methodData.metaObject )
|
||||||
|
&& ( m_methodData.methodIndex == other.m_methodData.methodIndex );
|
||||||
|
}
|
||||||
|
if ( m_type == MetaFunction )
|
||||||
|
{
|
||||||
|
return m_functionData.functionCall == other.m_functionData.functionCall;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QskMetaInvokable::isNull() const
|
||||||
|
{
|
||||||
|
switch( m_type )
|
||||||
|
{
|
||||||
|
case MetaMethod:
|
||||||
|
{
|
||||||
|
const auto& d = m_methodData;
|
||||||
|
if ( d.metaObject && ( d.methodIndex >= 0 )
|
||||||
|
&& ( d.methodIndex < d.metaObject->methodCount() ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MetaFunction:
|
||||||
|
{
|
||||||
|
return m_functionData.functionCall == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskMetaInvokable::reset()
|
||||||
|
{
|
||||||
|
if ( m_type == MetaFunction )
|
||||||
|
Function::deref( m_functionData.functionCall );
|
||||||
|
|
||||||
|
m_type = Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector< int > QskMetaInvokable::parameterTypes() const
|
||||||
|
{
|
||||||
|
QVector< int > paramTypes;
|
||||||
|
|
||||||
|
switch( m_type )
|
||||||
|
{
|
||||||
|
case MetaMethod:
|
||||||
|
{
|
||||||
|
const auto& d = m_methodData;
|
||||||
|
if ( m_methodData.metaObject )
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
// should be doable without QMetaMethod. TODO ...
|
||||||
|
const auto method = d.metaObject->method( d.methodIndex );
|
||||||
|
#endif
|
||||||
|
const int paramCount = method.parameterCount();
|
||||||
|
|
||||||
|
paramTypes.reserve( paramCount );
|
||||||
|
for ( int i = 0; i < paramCount; i++ )
|
||||||
|
paramTypes += method.parameterType( i );
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MetaFunction:
|
||||||
|
{
|
||||||
|
auto types = Function( m_functionData.functionCall ).parameterTypes();
|
||||||
|
if ( types )
|
||||||
|
{
|
||||||
|
while ( *types )
|
||||||
|
paramTypes += *types++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return paramTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QskMetaInvokable::invoke( QObject* object, void* args[],
|
||||||
|
Qt::ConnectionType connectionType )
|
||||||
|
{
|
||||||
|
if ( isNull() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch( m_type )
|
||||||
|
{
|
||||||
|
case MetaMethod:
|
||||||
|
{
|
||||||
|
QskMetaMethod::invoke( object, m_methodData.metaObject,
|
||||||
|
m_methodData.methodIndex, args, connectionType );
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MetaFunction:
|
||||||
|
{
|
||||||
|
if ( m_functionData.functionCall )
|
||||||
|
{
|
||||||
|
Function function( m_functionData.functionCall );
|
||||||
|
function.invoke( object, args, connectionType );
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
106
src/common/QskMetaInvokable.h
Normal file
106
src/common/QskMetaInvokable.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QSK_META_INVOKABLE_H
|
||||||
|
#define QSK_META_INVOKABLE_H 1
|
||||||
|
|
||||||
|
#include "QskGlobal.h"
|
||||||
|
|
||||||
|
#include <QMetaType>
|
||||||
|
#include <Qt>
|
||||||
|
|
||||||
|
template< typename T > class QVector;
|
||||||
|
|
||||||
|
class QskMetaFunction;
|
||||||
|
class QMetaObject;
|
||||||
|
class QMetaMethod;
|
||||||
|
class QObject;
|
||||||
|
|
||||||
|
class QSK_EXPORT QskMetaInvokable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
Invalid = 0,
|
||||||
|
|
||||||
|
// A QMetaMethod
|
||||||
|
MetaMethod,
|
||||||
|
|
||||||
|
// A function pointer, for what Qt calls "functor based" callbacks
|
||||||
|
MetaFunction
|
||||||
|
};
|
||||||
|
|
||||||
|
QskMetaInvokable();
|
||||||
|
|
||||||
|
QskMetaInvokable( const QskMetaFunction& );
|
||||||
|
QskMetaInvokable( const QMetaMethod& );
|
||||||
|
QskMetaInvokable( const QObject*, const char* methodName );
|
||||||
|
QskMetaInvokable( const QMetaObject*, const char* methodName );
|
||||||
|
|
||||||
|
QskMetaInvokable( const QskMetaInvokable& );
|
||||||
|
|
||||||
|
~QskMetaInvokable();
|
||||||
|
|
||||||
|
QskMetaInvokable& operator=( const QskMetaInvokable& );
|
||||||
|
|
||||||
|
bool operator==( const QskMetaInvokable& ) const;
|
||||||
|
bool operator!=( const QskMetaInvokable& ) const;
|
||||||
|
|
||||||
|
explicit operator bool() const;
|
||||||
|
|
||||||
|
Type type() const;
|
||||||
|
bool isNull() const;
|
||||||
|
|
||||||
|
QVector< int > parameterTypes() const;
|
||||||
|
|
||||||
|
void invoke( QObject*, void* args[],
|
||||||
|
Qt::ConnectionType = Qt::AutoConnection );
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct FunctionData
|
||||||
|
{
|
||||||
|
void* functionCall;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MethodData
|
||||||
|
{
|
||||||
|
const QMetaObject* metaObject;
|
||||||
|
int methodIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FunctionData m_functionData;
|
||||||
|
MethodData m_methodData;
|
||||||
|
};
|
||||||
|
|
||||||
|
int m_type : 3;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QskMetaInvokable::QskMetaInvokable():
|
||||||
|
m_type( Invalid )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool QskMetaInvokable::operator!=( const QskMetaInvokable& other ) const
|
||||||
|
{
|
||||||
|
return !( *this == other );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QskMetaInvokable::operator bool() const
|
||||||
|
{
|
||||||
|
return !isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QskMetaInvokable::Type QskMetaInvokable::type() const
|
||||||
|
{
|
||||||
|
return static_cast< Type >( m_type );
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE( QskMetaInvokable )
|
||||||
|
|
||||||
|
#endif
|
@ -43,6 +43,7 @@ HEADERS += \
|
|||||||
common/QskMetaCallback.h \
|
common/QskMetaCallback.h \
|
||||||
common/QskMetaFunction.h \
|
common/QskMetaFunction.h \
|
||||||
common/QskMetaFunction.hpp \
|
common/QskMetaFunction.hpp \
|
||||||
|
common/QskMetaInvokable.h \
|
||||||
common/QskMetaMethod.h \
|
common/QskMetaMethod.h \
|
||||||
common/QskModule.h \
|
common/QskModule.h \
|
||||||
common/QskNamespace.h \
|
common/QskNamespace.h \
|
||||||
@ -62,6 +63,7 @@ SOURCES += \
|
|||||||
common/QskMargins.cpp \
|
common/QskMargins.cpp \
|
||||||
common/QskMetaCallback.cpp \
|
common/QskMetaCallback.cpp \
|
||||||
common/QskMetaFunction.cpp \
|
common/QskMetaFunction.cpp \
|
||||||
|
common/QskMetaInvokable.cpp \
|
||||||
common/QskMetaMethod.cpp \
|
common/QskMetaMethod.cpp \
|
||||||
common/QskModule.cpp \
|
common/QskModule.cpp \
|
||||||
common/QskObjectCounter.cpp \
|
common/QskObjectCounter.cpp \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user