2018-02-26 08:09:21 +00:00
|
|
|
/******************************************************************************
|
|
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include "QskMetaCallback.h"
|
2018-02-28 15:48:46 +00:00
|
|
|
#include "QskMetaFunction.h"
|
2018-03-02 13:58:43 +00:00
|
|
|
#include "QskMetaMethod.h"
|
2018-02-28 09:43:15 +00:00
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
#include <QMetaMethod>
|
2018-02-28 09:43:15 +00:00
|
|
|
|
2018-02-26 08:09:21 +00:00
|
|
|
QskMetaCallback::QskMetaCallback( const QObject* object,
|
2018-02-27 16:47:23 +00:00
|
|
|
const QMetaMethod& method, Qt::ConnectionType connectionType ):
|
2018-02-26 08:09:21 +00:00
|
|
|
m_object( const_cast< QObject* >( object ) ),
|
2018-03-01 11:18:58 +00:00
|
|
|
m_methodData { method.enclosingMetaObject(), method.methodIndex() },
|
2018-02-26 08:09:21 +00:00
|
|
|
m_type( MetaMethod ),
|
2018-02-28 15:48:46 +00:00
|
|
|
m_hasObject( object != nullptr ),
|
|
|
|
m_connectionType( static_cast< ushort >( connectionType & 0x3 ) )
|
2018-02-26 08:09:21 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-03-02 13:58:43 +00:00
|
|
|
QskMetaCallback::QskMetaCallback( const QObject* object,
|
|
|
|
const char* methodName, Qt::ConnectionType connectionType ):
|
|
|
|
QskMetaCallback( object, QskMetaMethod::method( object, methodName ), connectionType )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-02-26 08:09:21 +00:00
|
|
|
QskMetaCallback::QskMetaCallback( const QObject* object,
|
|
|
|
const QskMetaFunction& function, Qt::ConnectionType connectionType ):
|
|
|
|
m_object( const_cast< QObject* >( object ) ),
|
2018-02-28 15:48:46 +00:00
|
|
|
m_functionData { function.invokable(), function.parameterTypes() },
|
2018-02-26 08:09:21 +00:00
|
|
|
m_type( MetaFunction ),
|
2018-02-28 15:48:46 +00:00
|
|
|
m_hasObject( object != nullptr ),
|
2018-02-26 08:09:21 +00:00
|
|
|
m_connectionType( static_cast< ushort >( connectionType & ~Qt::UniqueConnection ) )
|
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
if ( m_functionData.invokable )
|
|
|
|
m_functionData.invokable->ref();
|
2018-02-26 08:09:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QskMetaCallback::QskMetaCallback( const QskMetaCallback& other ):
|
|
|
|
m_object( other.m_object ),
|
2018-02-28 15:48:46 +00:00
|
|
|
m_type( other.m_type ),
|
|
|
|
m_hasObject( other.m_hasObject ),
|
2018-02-26 08:09:21 +00:00
|
|
|
m_connectionType( other.m_connectionType )
|
|
|
|
{
|
|
|
|
switch( m_type )
|
|
|
|
{
|
|
|
|
case MetaMethod:
|
2018-02-28 15:48:46 +00:00
|
|
|
{
|
|
|
|
m_methodData.metaObject = other.m_methodData.metaObject;
|
|
|
|
m_methodData.methodIndex = other.m_methodData.methodIndex;
|
2018-02-26 08:09:21 +00:00
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
break;
|
|
|
|
}
|
2018-02-26 08:09:21 +00:00
|
|
|
case MetaFunction:
|
2018-02-28 15:48:46 +00:00
|
|
|
{
|
|
|
|
m_functionData.invokable = other.m_functionData.invokable;
|
|
|
|
if ( m_functionData.invokable )
|
|
|
|
m_functionData.invokable->ref();
|
|
|
|
|
|
|
|
m_functionData.parameterTypes = other.m_functionData.parameterTypes;
|
2018-02-26 08:09:21 +00:00
|
|
|
break;
|
2018-02-28 15:48:46 +00:00
|
|
|
}
|
2018-02-26 08:09:21 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QskMetaCallback::~QskMetaCallback()
|
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
if ( ( m_type == MetaFunction ) && m_functionData.invokable )
|
|
|
|
m_functionData.invokable->destroyIfLastRef();
|
2018-02-26 08:09:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QskMetaCallback& QskMetaCallback::operator=( const QskMetaCallback& other )
|
|
|
|
{
|
|
|
|
m_object = other.m_object;
|
2018-02-28 15:48:46 +00:00
|
|
|
m_hasObject = other.m_hasObject;
|
|
|
|
|
2018-02-26 08:09:21 +00:00
|
|
|
m_connectionType = other.m_connectionType;
|
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
switch( other.m_type )
|
2018-02-26 08:09:21 +00:00
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
case MetaMethod:
|
|
|
|
{
|
|
|
|
if ( m_type == MetaFunction && m_functionData.invokable )
|
|
|
|
m_functionData.invokable->destroyIfLastRef();
|
2018-03-01 11:18:58 +00:00
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
m_methodData.metaObject = other.m_methodData.metaObject;
|
|
|
|
m_methodData.methodIndex = other.m_methodData.methodIndex;
|
2018-02-26 08:09:21 +00:00
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MetaFunction:
|
|
|
|
{
|
|
|
|
if ( ( m_type == MetaFunction ) && m_functionData.invokable )
|
|
|
|
m_functionData.invokable->destroyIfLastRef();
|
|
|
|
|
|
|
|
m_functionData.invokable = other.m_functionData.invokable;
|
|
|
|
|
|
|
|
if ( m_functionData.invokable )
|
|
|
|
m_functionData.invokable->ref();
|
|
|
|
|
|
|
|
m_functionData.parameterTypes = other.m_functionData.parameterTypes;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
if ( ( m_type == MetaFunction ) && m_functionData.invokable )
|
|
|
|
m_functionData.invokable->destroyIfLastRef();
|
2018-02-26 08:09:21 +00:00
|
|
|
}
|
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
m_type = other.m_type;
|
|
|
|
|
2018-02-26 08:09:21 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
bool QskMetaCallback::isValid() const
|
2018-02-27 16:47:23 +00:00
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
if ( m_hasObject && m_object.isNull() )
|
|
|
|
return false;
|
2018-02-27 16:47:23 +00:00
|
|
|
|
2018-02-26 08:09:21 +00:00
|
|
|
switch( m_type )
|
|
|
|
{
|
|
|
|
case MetaMethod:
|
2018-02-28 15:48:46 +00:00
|
|
|
{
|
|
|
|
const auto& d = m_methodData;
|
|
|
|
if ( d.metaObject && ( d.methodIndex >= 0 )
|
|
|
|
&& ( d.methodIndex < d.metaObject->methodCount() ) )
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2018-02-26 08:09:21 +00:00
|
|
|
|
|
|
|
case MetaFunction:
|
2018-02-28 15:48:46 +00:00
|
|
|
{
|
|
|
|
return m_functionData.invokable != nullptr;
|
|
|
|
}
|
2018-02-26 08:09:21 +00:00
|
|
|
|
|
|
|
default:
|
2018-02-28 15:48:46 +00:00
|
|
|
return false;
|
2018-02-26 08:09:21 +00:00
|
|
|
}
|
2018-02-28 15:48:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskMetaCallback::setConnectionType( Qt::ConnectionType connectionType )
|
|
|
|
{
|
|
|
|
m_connectionType = connectionType;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskMetaCallback::reset()
|
|
|
|
{
|
|
|
|
m_object = nullptr;
|
|
|
|
m_hasObject = false;
|
|
|
|
|
|
|
|
if ( m_type == MetaFunction && m_functionData.invokable )
|
|
|
|
m_functionData.invokable->destroyIfLastRef();
|
2018-02-26 08:09:21 +00:00
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
m_functionData = { nullptr, nullptr }; // for the debugger
|
2018-02-26 08:09:21 +00:00
|
|
|
m_type = Invalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVector< int > QskMetaCallback::parameterTypes() const
|
|
|
|
{
|
|
|
|
QVector< int > paramTypes;
|
|
|
|
|
|
|
|
switch( m_type )
|
|
|
|
{
|
|
|
|
case MetaMethod:
|
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
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 );
|
|
|
|
}
|
2018-02-26 08:09:21 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MetaFunction:
|
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
auto types = m_functionData.parameterTypes;
|
2018-02-26 08:09:21 +00:00
|
|
|
if ( types )
|
|
|
|
{
|
|
|
|
while ( *types )
|
|
|
|
paramTypes += *types++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return paramTypes;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void QskMetaCallback::invoke( void* args[] )
|
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
if ( !isValid() )
|
|
|
|
return;
|
|
|
|
|
2018-02-26 08:09:21 +00:00
|
|
|
auto object = const_cast< QObject* >( m_object.data() );
|
|
|
|
|
|
|
|
switch( m_type )
|
|
|
|
{
|
|
|
|
case MetaMethod:
|
|
|
|
{
|
2018-03-02 13:58:43 +00:00
|
|
|
QskMetaMethod::invoke( object, m_methodData.metaObject,
|
2018-02-28 15:48:46 +00:00
|
|
|
m_methodData.methodIndex, args, connectionType() );
|
|
|
|
|
2018-02-26 08:09:21 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MetaFunction:
|
|
|
|
{
|
2018-03-02 05:57:08 +00:00
|
|
|
QskMetaFunction function( m_functionData.invokable );
|
2018-02-28 15:48:46 +00:00
|
|
|
function.invoke( object, args, connectionType() );
|
|
|
|
|
2018-02-26 08:09:21 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|